/** * * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see <http://www.gnu.org/licenses/>. * **/ package lucee.runtime.text.csv; import java.util.ArrayList; import java.util.List; import lucee.commons.lang.StringUtil; public class CSVString { private static final char LF=10; private static final char CR=13; 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>>(); List<String> line = new ArrayList<String>(); 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 == LF || c == CR ) { if(c == CR && isNext(LF)) next(); line.add( sb.toString().trim() ); sb = new StringBuilder(); if ( isValidLine( line ) ) result.add( line ); line = new ArrayList<String>(); } else if ( c == delim ) { line.add( sb.toString().trim() ); sb = new StringBuilder(); } else sb.append( c ); next(); } while ( pos < buffer.length ); line.add( sb.toString() ); 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; } }