StringUtil { public static List<CharSequence> unescapeCsvFields(CharSequence value) { List<CharSequence> unescaped = new ArrayList<CharSequence>(2); StringBuilder current = InternalThreadLocalMap.get().stringBuilder(); boolean quoted = false; int last = value.length() - 1; for (int i = 0; i <= last; i++) { char c = value.charAt(i); if (quoted) { switch (c) { case DOUBLE_QUOTE: if (i == last) { unescaped.add(current.toString()); return unescaped; } char next = value.charAt(++i); if (next == DOUBLE_QUOTE) { current.append(DOUBLE_QUOTE); break; } if (next == COMMA) { quoted = false; unescaped.add(current.toString()); current.setLength(0); break; } throw newInvalidEscapedCsvFieldException(value, i - 1); default: current.append(c); } } else { switch (c) { case COMMA: unescaped.add(current.toString()); current.setLength(0); break; case DOUBLE_QUOTE: if (current.length() == 0) { quoted = true; break; } case LINE_FEED: case CARRIAGE_RETURN: throw newInvalidEscapedCsvFieldException(value, i); default: current.append(c); } } } if (quoted) { throw newInvalidEscapedCsvFieldException(value, last); } unescaped.add(current.toString()); return unescaped; } private  StringUtil(); static String substringAfter(String value, char delim); static boolean commonSuffixOfLength(String s, String p, int len); static String byteToHexStringPadded(int value); static T byteToHexStringPadded(T buf, int value); static String toHexStringPadded(byte[] src); static String toHexStringPadded(byte[] src, int offset, int length); static T toHexStringPadded(T dst, byte[] src); static T toHexStringPadded(T dst, byte[] src, int offset, int length); static String byteToHexString(int value); static T byteToHexString(T buf, int value); static String toHexString(byte[] src); static String toHexString(byte[] src, int offset, int length); static T toHexString(T dst, byte[] src); static T toHexString(T dst, byte[] src, int offset, int length); static int decodeHexNibble(final char c); static byte decodeHexByte(CharSequence s, int pos); static byte[] decodeHexDump(CharSequence hexDump, int fromIndex, int length); static byte[] decodeHexDump(CharSequence hexDump); static String simpleClassName(Object o); static String simpleClassName(Class<?> clazz); static CharSequence escapeCsv(CharSequence value); static CharSequence escapeCsv(CharSequence value, boolean trimWhiteSpace); static CharSequence unescapeCsv(CharSequence value); static List<CharSequence> unescapeCsvFields(CharSequence value); static int length(String s); static boolean isNullOrEmpty(String s); static int indexOfNonWhiteSpace(CharSequence seq, int offset); static boolean isSurrogate(char c); static boolean endsWith(CharSequence s, char c); static CharSequence trimOws(CharSequence value); static final String EMPTY_STRING; static final String NEWLINE; static final char DOUBLE_QUOTE; static final char COMMA; static final char LINE_FEED; static final char CARRIAGE_RETURN; static final char TAB; static final char SPACE; }
@Test public void testUnescapeCsvFields() { assertEquals(Arrays.asList(""), unescapeCsvFields("")); assertEquals(Arrays.asList("", ""), unescapeCsvFields(",")); assertEquals(Arrays.asList("a", ""), unescapeCsvFields("a,")); assertEquals(Arrays.asList("", "a"), unescapeCsvFields(",a")); assertEquals(Arrays.asList("\""), unescapeCsvFields("\"\"\"\"")); assertEquals(Arrays.asList("\"", "\""), unescapeCsvFields("\"\"\"\",\"\"\"\"")); assertEquals(Arrays.asList("netty"), unescapeCsvFields("netty")); assertEquals(Arrays.asList("hello", "netty"), unescapeCsvFields("hello,netty")); assertEquals(Arrays.asList("hello,netty"), unescapeCsvFields("\"hello,netty\"")); assertEquals(Arrays.asList("hello", "netty"), unescapeCsvFields("\"hello\",\"netty\"")); assertEquals(Arrays.asList("a\"b", "c\"d"), unescapeCsvFields("\"a\"\"b\",\"c\"\"d\"")); assertEquals(Arrays.asList("a\rb", "c\nd"), unescapeCsvFields("\"a\rb\",\"c\nd\"")); }
@Test(expected = IllegalArgumentException.class) public void unescapeCsvFieldsWithCRWithoutQuote() { unescapeCsvFields("a,\r"); }
@Test(expected = IllegalArgumentException.class) public void unescapeCsvFieldsWithLFWithoutQuote() { unescapeCsvFields("a,\r"); }
@Test(expected = IllegalArgumentException.class) public void unescapeCsvFieldsWithQuote() { unescapeCsvFields("a,\""); }
@Test(expected = IllegalArgumentException.class) public void unescapeCsvFieldsWithQuote2() { unescapeCsvFields("\",a"); }
@Test(expected = IllegalArgumentException.class) public void unescapeCsvFieldsWithQuote3() { unescapeCsvFields("a\"b,a"); }