package railo.runtime.text.csv; import java.util.ArrayList; import java.util.List; import railo.commons.lang.StringUtil; public class CSVString { private char[] buffer; private int pos; private char delim; public CSVString( String input, char delim ) { this.buffer = input.toCharArray(); this.delim = delim; } public List<List<String>> parse() { List<List<String>> result = new ArrayList(); List<String> line = new ArrayList(); if ( buffer.length == 0 ) return result; StringBuilder sb = new StringBuilder(); char c; do { c = buffer[ pos ]; if ( c == '"' || c == '\'' ) { sb.append( fwdQuote( c ) ); } else if ( c == '\n' ) { line.add( sb.toString().trim() ); sb = new StringBuilder(); if ( isValidLine( line ) ) result.add( line ); line = new ArrayList(); } else if ( c == delim ) { line.add( sb.toString().trim() ); sb = new StringBuilder(); } else sb.append( c ); next(); } while ( hasNext() ); sb.append( buffer[ pos ] ); line.add( sb.toString().trim() ); if ( isValidLine( line ) ) result.add( line ); return result; } /** forward pos until the end of quote */ StringBuilder fwdQuote( char q ) { StringBuilder sb = new StringBuilder(); while ( hasNext() ) { next(); sb.append( buffer[ pos ] ); if ( isCurr( q ) ) { if ( isNext( q ) ) { // consecutive quote sign next(); } else { break; } } } if ( sb.length() > 0 ) sb.setLength( sb.length() - 1 ); // remove closing quote sign return sb; } void next() { pos++; } boolean hasNext() { return pos < ( buffer.length - 1 ); } boolean isNext( char c ) { if ( !hasNext() ) return false; return buffer[ pos + 1 ] == c; } boolean isCurr( char c ) { if ( !isValidPos() ) return false; return buffer[ pos ] == c; } boolean isValidPos() { return pos >= 0 && pos < buffer.length - 1; } boolean isValidLine( List<String> line ) { for ( String s : line ) { if ( !StringUtil.isEmpty( s, true ) ) return true; } return false; } }