package hugo.weaving.internal; import java.util.Arrays; import java.util.HashSet; import java.util.Locale; import java.util.Set; final class Strings { static String toString(Object obj) { if (obj == null) { return "null"; } if (obj instanceof CharSequence) { return '"' + printableToString(obj.toString()) + '"'; } Class<?> cls = obj.getClass(); if (Byte.class == cls) { return byteToString((Byte) obj); } if (cls.isArray()) { return arrayToString(cls.getComponentType(), obj); } return obj.toString(); } private static String printableToString(String string) { int length = string.length(); StringBuilder builder = new StringBuilder(length); for (int i = 0; i < length;) { int codePoint = string.codePointAt(i); switch (Character.getType(codePoint)) { case Character.CONTROL: case Character.FORMAT: case Character.PRIVATE_USE: case Character.SURROGATE: case Character.UNASSIGNED: switch (codePoint) { case '\n': builder.append("\\n"); break; case '\r': builder.append("\\r"); break; case '\t': builder.append("\\t"); break; case '\f': builder.append("\\f"); break; case '\b': builder.append("\\b"); break; default: builder.append("\\u").append(String.format("%04x", codePoint).toUpperCase(Locale.US)); break; } break; default: builder.append(Character.toChars(codePoint)); break; } i += Character.charCount(codePoint); } return builder.toString(); } private static String arrayToString(Class<?> cls, Object obj) { if (byte.class == cls) { return byteArrayToString((byte[]) obj); } if (short.class == cls) { return Arrays.toString((short[]) obj); } if (char.class == cls) { return Arrays.toString((char[]) obj); } if (int.class == cls) { return Arrays.toString((int[]) obj); } if (long.class == cls) { return Arrays.toString((long[]) obj); } if (float.class == cls) { return Arrays.toString((float[]) obj); } if (double.class == cls) { return Arrays.toString((double[]) obj); } if (boolean.class == cls) { return Arrays.toString((boolean[]) obj); } return arrayToString((Object[]) obj); } /** A more human-friendly version of Arrays#toString(byte[]) that uses hex representation. */ private static String byteArrayToString(byte[] bytes) { StringBuilder builder = new StringBuilder("["); for (int i = 0; i < bytes.length; i++) { if (i > 0) { builder.append(", "); } builder.append(byteToString(bytes[i])); } return builder.append(']').toString(); } private static String byteToString(Byte b) { if (b == null) { return "null"; } return "0x" + String.format("%02x", b).toUpperCase(Locale.US); } private static String arrayToString(Object[] array) { StringBuilder buf = new StringBuilder(); arrayToString(array, buf, new HashSet<Object[]>()); return buf.toString(); } private static void arrayToString(Object[] array, StringBuilder builder, Set<Object[]> seen) { if (array == null) { builder.append("null"); return; } seen.add(array); builder.append('['); for (int i = 0; i < array.length; i++) { if (i > 0) { builder.append(", "); } Object element = array[i]; if (element == null) { builder.append("null"); } else { Class elementClass = element.getClass(); if (elementClass.isArray() && elementClass.getComponentType() == Object.class) { Object[] arrayElement = (Object[]) element; if (seen.contains(arrayElement)) { builder.append("[...]"); } else { arrayToString(arrayElement, builder, seen); } } else { builder.append(toString(element)); } } } builder.append(']'); seen.remove(array); } private Strings() { throw new AssertionError("No instances."); } }