com.lti.utils.StringUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fmj Show documentation
Show all versions of fmj Show documentation
Freedom for Media in Java
package com.lti.utils;
import net.iharder.*;
/**
* String utilties. TODO: move to src.utils/com.lti.utils.
*
* @author Ken Larson
*
*/
public final class StringUtils
{
private static final int MAX_STANDARD_ASCII = 255;
private static final int RADIX_16 = 16;
public static String byteArrayToBase64String(byte[] value)
{
return Base64.encodeBytes(value);
}
public static String byteArrayToHexString(byte[] array)
{
return byteArrayToHexString(array, array.length);
}
public static String byteArrayToHexString(byte[] array, int len)
{
return byteArrayToHexString(array, len, 0);
}
public static String byteArrayToHexString(byte[] array, int len, int offset)
{
StringBuffer b = new StringBuffer();
for (int i = 0; i < len; ++i)
{
String byteStr = Integer.toHexString(UnsignedUtils
.uByteToInt(array[offset + i]));
if (byteStr.length() == 1)
byteStr = "0" + byteStr;
b.append(byteStr);
}
return b.toString();
}
public static String byteToHexString_ZeroPad(byte b)
{
String s = Integer.toHexString(UnsignedUtils.uByteToInt(b));
if (s.length() == 1)
s = "0" + s;
return s;
}
/**
* Dump to string using a debugger-like format - both hex and ascii. Bytes
* dumped will be byteslen - offset.
*/
public static String dump(byte[] bytes, int offset, int byteslen)
{
final StringBuffer b = new StringBuffer();
final int width = 32;
int len = width;
while (offset < byteslen)
{
int remainder = 0;
if (offset + len > byteslen)
{
len = byteslen - offset;
remainder = width - len;
}
b.append(StringUtils.byteArrayToHexString(bytes, len, offset));
for (int i = 0; i < remainder; ++i)
{
b.append(" ");
}
b.append(" | ");
for (int i = 0; i < len; ++i)
{
byte c = bytes[offset + i];
if (c >= ' ' && c <= '~')
{
b.append((char) c);
} else
b.append('.');
}
b.append('\n');
offset += len;
}
return b.toString();
}
/**
*
* @throws NumberFormatException
*/
public static byte hexStringToByte(String s)
{
return (byte) Integer.parseInt(s, RADIX_16);
}
/**
*
* @throws NumberFormatException
*/
public static byte[] hexStringToByteArray(String s)
{
byte[] array = new byte[s.length() / 2];
for (int i = 0; i < array.length; ++i)
{
array[i] = hexStringToByte(s.substring(i * 2, i * 2 + 2));
}
return array;
}
public static String replaceSpecialUrlChars(final String raw)
{
return replaceSpecialUrlChars(raw, false);
}
// see http://en.wikipedia.org/wiki/Query_string
public static String replaceSpecialUrlChars(final String raw,
final boolean isPath)
{
if (raw == null)
{
return null;
}
final StringBuffer buf = new StringBuffer();
for (int i = 0; i < raw.length(); ++i)
{
char c = raw.charAt(i);
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
|| (c >= '0' && c <= '9')
|| (c == '.' || c == '-' || c == '_' || c == '~')
|| (isPath && (c == '/' || c == ':' || c == '\\')))
{
buf.append(c);
} else
{
if (i > MAX_STANDARD_ASCII)
throw new IllegalArgumentException(); // TODO: unicode?
buf.append('%');
buf.append(byteToHexString_ZeroPad((byte) c));
}
}
return buf.toString();
}
public static String replaceSpecialXMLChars(String raw)
{
return replaceSpecialXMLChars_Core(raw, true);
}
/*
* Replace &, <, >, ", and ', in passed raw String with their XML/HTML
* entity representation.
*/
private static String replaceSpecialXMLChars_Core(String raw, boolean apos)
{
if (raw == null)
{
return null;
}
StringBuilder buf = new StringBuilder();
for (int i = 0; i < raw.length(); ++i)
{
char c = raw.charAt(i);
if (c == '&')
{
buf.append("&");
} else if (c == '<')
{
buf.append("<");
} else if (c == '>')
{
buf.append(">");
} else if (c == '"')
{
buf.append(""");
}
// apos seems useful for XML, but not HTML.
else if (apos && c == '\'')
{
buf.append("'");
} else
{
buf.append(c);
}
}
// TODO: handle invalid chars somehow:
//
// if (c < 0x20 && c != 0xa && c != 0xd && c != 0x9)
// Debug.trace("replaceXML_SpecialChars: Skipping bad character ("+
// (int) c +") in input string " + s ); // bad characters - ignore
//
return buf.toString();
}
public static String restoreSpecialURLChars(String cooked)
{
if (cooked == null)
{
return null;
}
StringBuffer buf = new StringBuffer();
StringBuffer hexValueBuf = new StringBuffer();
int state = 0;
for (int i = 0; i < cooked.length(); ++i)
{
char c = cooked.charAt(i);
if (state == 0)
{
if (c == '%')
{
state = 1;
hexValueBuf = new StringBuffer();
} else
{
buf.append(c);
}
} else
{
hexValueBuf.append(c);
if (hexValueBuf.length() == 2)
{
String token = hexValueBuf.toString();
int value = Integer.parseInt(token, 16); // TODO: what to do
// with num format
// except?
buf.append((char) value);
state = 0;
} else if (hexValueBuf.length() == 1
&& hexValueBuf.charAt(0) == '%')
{
buf.append('%');
state = 0;
}
}
}
if (state == 1)
{
buf.append("&" + hexValueBuf.toString()); // incomplete
}
return buf.toString();
}
public static String restoreSpecialXMLChars(String cooked)
{
return restoreSpecialXMLChars_Core(cooked, true);
}
private static String restoreSpecialXMLChars_Core(String cooked,
boolean apos)
{
if (cooked == null)
{
return null;
}
StringBuilder buf = new StringBuilder();
StringBuilder entityNameBuf = new StringBuilder();
int state = 0;
for (int i = 0; i < cooked.length(); ++i)
{
char c = cooked.charAt(i);
if (state == 0)
{
if (c == '&')
{
state = 1;
entityNameBuf = new StringBuilder();
} else
{
buf.append(c);
}
} else
{
if (c == ';')
{
String token = entityNameBuf.toString();
if (token.equals("amp"))
buf.append('&');
else if (token.equals("lt"))
buf.append('<');
else if (token.equals("gt"))
buf.append('>');
else if (token.equals("quot"))
buf.append('"');
else if (apos & token.equals("apos"))
buf.append('\'');
else
buf.append("&" + token + ';'); // unknown
state = 0;
} else
{
entityNameBuf.append(c);
}
}
}
if (state == 1)
{
buf.append("&" + entityNameBuf.toString()); // incomplete
}
return buf.toString();
}
}