package dk.socketmud.util;
public class Format
{
private static final String AnsiCodes = "unrRgGpPcCdDwWbByY";
private static final String ReplaceCodes = "#";
public static String cprintf(String fmt, Object ... varargs)
{
return cprintf(fmt.toCharArray(), varargs);
}
public static String cprintf(char[] fmt, Object ... varargs)
{
StringBuffer buf = new StringBuffer();
int i = 0;
int len = fmt.length;
int argc = 0;
while (i < len)
{
boolean reverse = false;
int size = 0;
int maxSize = 0;
switch (fmt[i])
{
default:
buf.append(fmt[i++]);
break;
case '%':
// should we align this in reverse?
if (fmt[i + 1] == '-')
{
i++;
reverse = true;
}
// get the size, if any
while (Character.isDigit(fmt[i + 1]))
{
i++;
size *= 10;
size += fmt[i] - '0';
}
// any size restrictions?
if (fmt[i + 1] == '.')
{
i++;
while (Character.isDigit(fmt[i + 1]))
{
i++;
maxSize *= 10;
maxSize += fmt[i] - '0';
}
}
i++;
switch (fmt[i])
{
default:
buf.append('%');
break;
case 's':
String s = (String) getVarArg(fmt[i], argc, varargs);
if (maxSize > 0)
s = restrictString(s, maxSize);
size -= colourLength(s);
argc++;
if (!reverse)
{
while(size-- > 0)
buf.append(' ');
}
buf.append(s);
if (reverse)
{
while(size-- > 0)
buf.append(' ');
}
i++;
break;
case 'd':
int value = (Integer) getVarArg(fmt[i], argc, varargs);
argc++;
// a little trick to see how long the number is
String tmp = "" + value;
size -= tmp.length();
if (!reverse)
{
while(size-- > 0)
buf.append(' ');
}
buf.append(tmp);
if (reverse)
{
while(size-- > 0)
buf.append(' ');
}
i++;
break;
}
break;
}
}
return buf.toString();
}
private static Object getVarArg(char type, int num, Object ... varargs) throws IllegalArgumentException
{
if (varargs.length < (num + 1))
throw new IllegalArgumentException("Not enough variable arguments");
Object o = varargs[num];
switch (type)
{
default:
throw new IllegalArgumentException("Unknown type '" + type + "'");
case 's':
if (o instanceof String)
break;
else
throw new IllegalArgumentException("variable argument " + (num + 1) + " not of type String");
case 'd':
if (o instanceof Integer)
break;
else
throw new IllegalArgumentException("variable argument " + (num + 1) + " not of type Integer");
}
return o;
}
public static String restrictString(String s, int maxSize)
{
StringBuffer buf = new StringBuffer();
char[] c = s.toCharArray();
boolean done = false;
int size = s.length();
int len = 0;
int i = 0;
while (i < size && !done)
{
boolean found = false;
switch (c[i])
{
default:
if (++len > maxSize)
{
done = true;
break;
}
buf.append(c[i]);
i++;
break;
case '#':
i++;
if (AnsiCodes.indexOf(c[i]) > -1)
{
buf.append('#');
buf.append(c[i]);
i++;
found = true;
}
if (!found && ReplaceCodes.indexOf(c[i]) > - 1)
{
if (++len > maxSize)
{
done = true;
break;
}
buf.append('#');
buf.append(c[i]);
found = true;
}
if (!found)
{
if (++len > maxSize)
{
done = true;
break;
}
buf.append('#');
}
break;
}
}
return buf.toString();
}
private static int colourLength(String s)
{
char[] c = s.toCharArray();
int len = 0;
int max = s.length();
int i = 0;
while (i < max)
{
boolean found = false;
switch(c[i])
{
default:
len++;
i++;
break;
case '#':
i++;
if (AnsiCodes.indexOf(c[i]) > -1)
{
i++;
found = true;
}
if (!found && ReplaceCodes.indexOf(c[i]) > - 1)
{
len++;
i++;
found = true;
}
if (!found)
len++;
break;
}
}
return len;
}
}