/* * CsvReader.java * * Copyright (C) 2009-12 by RStudio, Inc. * * Unless you have received this program directly from RStudio pursuant * to the terms of a commercial license agreement with RStudio, then * this program is licensed to you under the terms of version 3 of the * GNU Affero General Public License. This program is distributed WITHOUT * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT, * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details. * */ package org.rstudio.core.client; import java.util.ArrayList; import java.util.Iterator; public class CsvReader implements Iterable<String[]> { public CsvReader(String data) { data_ = data; } public Iterator<String[]> iterator() { return new Iterator<String[]>() { private int pos = 0; public boolean hasNext() { return pos < data_.length(); } public String[] next() { ArrayList<String> list = new ArrayList<String>(); StringBuilder chunk = new StringBuilder(); final int START = 0; final int IN_UNQUOTED = 1; final int IN_QUOTE = 2; final int QUOTE_ENDED = 3; int state = START; for ( ; pos < data_.length(); pos++) { char c = data_.charAt(pos); if (c == '\n' && state != IN_QUOTE) { pos++; break; } if (c == ',' && state != IN_QUOTE) { if (state != QUOTE_ENDED) list.add(chunk.toString()); chunk = new StringBuilder(); state = START; continue; } if (c == '"' && state == START) { state = IN_QUOTE; continue; } if (c == '"' && state == IN_QUOTE) { int lookahead = (pos < data_.length() - 1) ? data_.charAt(pos+1) : -1; if (lookahead == '"') { chunk.append((char)lookahead); pos++; continue; } list.add(chunk.toString()); chunk = new StringBuilder(); state = QUOTE_ENDED; continue; } if (state == START) state = IN_UNQUOTED; chunk.append(c); } if (state != QUOTE_ENDED) { list.add(chunk.toString()); } return list.toArray(new String[0]); } public void remove() { throw new UnsupportedOperationException(); } }; } private final String data_; }