All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sfm.csv.parser.CharConsumer Maven / Gradle / Ivy

package org.sfm.csv.parser;


/**
 * Consume the charbuffer.
 */
public final class CharConsumer {

	public static final int IN_QUOTE = 4;
	public static final int IN_CR = 2;
	public static final int QUOTE = 1;
	public static final int NONE = 0;

	public static final int TURN_OFF_IN_CR_MASK = ~IN_CR;
	public static final int ALL_QUOTES = QUOTE | IN_QUOTE;

	
	private int currentState = NONE;


	public void parseFull(CharBuffer csvBuffer, CellConsumer cellConsumer) {
		while(csvBuffer.hasContent()) {
			char c = csvBuffer.getNextChar();
			switch (c) {
			case ',':
				newCellIfNotInQuote(csvBuffer, cellConsumer);
				break;
			case '"':
				quote(csvBuffer);
				break;
			case '\n':
				handleEndOfLineLF(csvBuffer, cellConsumer);
				break;
			case '\r':
				handleEndOfLineCR(csvBuffer, cellConsumer);
				break;
			default:
				turnOffCrFlag();
			}
		}
	}

	public boolean nextLine(CharBuffer csvBuffer, CellConsumer cellConsumer) {
		while(csvBuffer.hasContent()) {
			char c = csvBuffer.getNextChar();
			switch (c) {
				case ',':
					newCellIfNotInQuote(csvBuffer, cellConsumer);
					break;
				case '"':
					quote(csvBuffer);
					break;
				case '\n':
					if (handleEndOfLineLF(csvBuffer, cellConsumer)) {
						return true;
					}
					break;
				case '\r':
					if (handleEndOfLineCR(csvBuffer, cellConsumer)) {
						return true;
					}
					break;
				default:
					turnOffCrFlag();
			}
		}

		return false;
	}

	/**
	 * use bit mask to testing if == IN_CR
	 */
	private void turnOffCrFlag() {
		currentState = currentState & TURN_OFF_IN_CR_MASK;
	}

	private void newCellIfNotInQuote(CharBuffer csvBuffer, CellConsumer cellConsumer) {
		if (isInQuote())
			return;

		newCell(csvBuffer, 1, cellConsumer);
		turnOffCrFlag();
	}



	private boolean isInQuote() {
		return currentState == IN_QUOTE;
	}

	/**
	 *
	 * @param csvBuffer
	 * @return true if endOfLine
	 */
	private boolean handleEndOfLineLF(CharBuffer csvBuffer, CellConsumer cellConsumer) {
		if (!isInQuote()) {
			if (currentState != IN_CR) {
				endOfRow(csvBuffer, cellConsumer);
				return true;
			} else {
				// we had a preceding cr so shift the marl
				csvBuffer.mark();
			}
		}
		turnOffCrFlag();
		return false;
	}

	private boolean handleEndOfLineCR(CharBuffer csvBuffer, CellConsumer cellConsumer) {
		if (!isInQuote()) {
			endOfRow(csvBuffer, cellConsumer);
			currentState = IN_CR;
			return true;
		}
		return false;
	}

	private void endOfRow(CharBuffer csvBuffer, CellConsumer cellConsumer) {
		newCell(csvBuffer, 1, cellConsumer);
		cellConsumer.endOfRow();
	}

	private void quote(CharBuffer csvBuffer) {
		if (csvBuffer.isAllConsumed()) {
			currentState = IN_QUOTE;
		} else {
			currentState = currentState ^ ALL_QUOTES;
		}
		turnOffCrFlag();
	}

	private void newCell(CharBuffer csvBuffer, int shift, CellConsumer cellConsumer) {;
		cellConsumer.newCell(csvBuffer.getCharBuffer(), csvBuffer.getMark(), csvBuffer.getLengthFromMark() - shift);
		csvBuffer.mark();
		currentState = NONE;
	}

	public void finish(CharBuffer csvBuffer, CellConsumer cellConsumer) {
		if (!csvBuffer.isAllConsumed()) {
			newCell(csvBuffer, 0, cellConsumer);
		}
		cellConsumer.end();
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy