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

org.bimserver.utils.Tokenizer Maven / Gradle / Ivy

Go to download

Shared libraries, common parent for both BIMserver and BimServerClientLib

There is a newer version: 2.0.0
Show newest version
package org.bimserver.utils;

/******************************************************************************
 * Copyright (C) 2009-2016  BIMserver.org
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program 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 Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see {@literal}.
 *****************************************************************************/

import java.util.Stack;

public class Tokenizer {

	private static class Pair {
		public int oldRight;
		public String rightChar;

		public Pair(String rightChar, int oldRight) {
			this.rightChar = rightChar;
			this.oldRight = oldRight;
		}
	}
	
	private final String input;
	private int leftPositionInclude;
	private int rightPositionInclude;
	private Stack zoomStack = new Stack();
	
	public Tokenizer(String input) {
		this.input = input;
		leftPositionInclude = 0;
		rightPositionInclude = input.length() - 1;
	}
	
	@Override
	public String toString() {
		return input.substring(leftPositionInclude, rightPositionInclude + 1);
	}

	public Tokenizer zoomIn(String startChar, String endChar) throws TokenizeException {
		String trimmed = toString().trim();
		if (!trimmed.startsWith(startChar)) {
			throw new TokenizeException("No " + startChar + " found in " + input.substring(leftPositionInclude, rightPositionInclude));
		}
		String specialChar = "'";
		int leftIndex = input.indexOf(startChar, leftPositionInclude);
		int rightIndex = -1;
		int depth = 0;
		int altDepth = 0;
		for (int i=leftIndex + 1; i<=rightPositionInclude; i++) {
			String c = input.substring(i, i + endChar.length());
			if (c.equals(endChar)) {
				if (depth == 0 && altDepth == 0) {
					rightIndex = i;
					break;
				} else {
					if (altDepth == 0) {
						depth--;
					}
				}
			} else if (c.equals(specialChar)) {
				altDepth = 1 - altDepth;
			} else if (c.equals(startChar) && altDepth == 0) {
				depth++;
			}
		}
		if (rightIndex == -1 || rightIndex < leftPositionInclude) {
			throw new TokenizeException("No " + endChar + " found in " + input.substring(leftPositionInclude, rightPositionInclude));
		}
		zoomStack.push(new Pair(endChar, this.rightPositionInclude));
		this.leftPositionInclude = leftIndex + startChar.length();
		this.rightPositionInclude = rightIndex - endChar.length();
		return this;
	}

	public Tokenizer readComma() throws TokenizeException {
		String toString = toString();
		String x = toString.trim();
		if (!x.startsWith(",")) {
			throw new TokenizeException("No comma at starting index in " + x);
		}
		int offset = toString.indexOf(",");
		this.leftPositionInclude += offset + 1;
		return this;
	}

	public String readSingleQuoted() throws TokenizeException {
		String toString = toString();
		String trimmed = toString.trim();
		if (!trimmed.startsWith("'")) {
			throw new TokenizeException("No opening \"'\" found in " + trimmed);
		}
		int add = toString.indexOf("'");
		int endIndex = trimmed.indexOf("'", 1);

		// Never ending loop protection, can probably be done by changing the loop condition to something smarter...
		int lastEndIndex = -2;
		
		while (trimmed.length() > endIndex + 1 && trimmed.charAt(endIndex + 1) == '\'') {
			// Two quotes
			endIndex = trimmed.indexOf("'", endIndex + 2);
			if (lastEndIndex != -2 && lastEndIndex == endIndex) {
				throw new TokenizeException("No closing \"'\" found in " + trimmed);
			}
			lastEndIndex = endIndex;
		}
		if (endIndex == -1) {
			throw new TokenizeException("No closing \"'\" found in " + trimmed);
		}
		this.leftPositionInclude += endIndex + add + 1;
		return trimmed.substring(1, endIndex);
	}

	public void shouldBeFinished() throws TokenizeException {
//		if (leftPosition != rightPosition) {
//			throw new TokenizeException("");
//		}
	}

	public void zoomOut() throws TokenizeException {
		Pair pair = zoomStack.pop();
		String trimmed = input.substring(this.leftPositionInclude, pair.oldRight + 1).trim();
		String x = trimmed.substring(0, pair.rightChar.length());
		int offset = input.indexOf(pair.rightChar, this.leftPositionInclude);
		if (!x.equals(pair.rightChar)) {
			throw new TokenizeException(pair.rightChar + " expected, got " + x);
		}
		this.leftPositionInclude = offset + pair.rightChar.length();
		this.rightPositionInclude = pair.oldRight;
	}

	public String readAll() {
		String substring = input.substring(leftPositionInclude, rightPositionInclude + 1);
		leftPositionInclude = rightPositionInclude + 1;
		return substring;
	}

	public boolean isEmpty() {
		return toString().trim().isEmpty();
	}
	
	public boolean nextIsAComma() throws TokenizeException {
		String toString = toString();
		String x = toString.trim();
		return x.startsWith(",");
	}

	public boolean startsWith(String string) {
		return toString().trim().startsWith(string);
	}

	public boolean nextIsDollar() {
		String toString = toString();
		String x = toString.trim();
		return x.startsWith("$");
	}

	public Tokenizer readDollar() throws TokenizeException {
		String toString = toString();
		String x = toString.trim();
		if (!x.startsWith("$")) {
			throw new TokenizeException("No dollar at starting index in " + x);
		}
		int offset = toString.indexOf("$");
		this.leftPositionInclude += offset + 1;
		return this;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy