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

com.firefly.utils.json.io.JsonStringReader Maven / Gradle / Ivy

There is a newer version: 5.0.2
Show newest version
package com.firefly.utils.json.io;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;

import com.firefly.utils.VerifyUtils;
import com.firefly.utils.json.JsonReader;
import com.firefly.utils.json.exception.JsonException;

public class JsonStringReader extends JsonReader {
	private char[] chars;
	private int pos = 0;
	private final int limit;
	private int mark = 0;

	public JsonStringReader(String str) {
		chars = str.toCharArray();
		limit = chars.length;
	}
	
	@Override
	public void increasePosition() {
		pos++;
	}
	
	@Override
	public void decreasePosition() {
		pos--;
	}
	
	@Override
	public int position() {
		return pos;
	}
	
	@Override
	public boolean isEnd() {
//		System.out.println("end pos and limit --> " + pos + "|" + limit);
		return pos >= limit;
	}
	
	@Override
	public void mark(int readAheadLimit) {
		mark = pos;
	}
	
	@Override
	public void reset() {
		pos = mark;
	}
	
	@Override
	public boolean isEndFlag(char ch) {
		switch (ch) {
		case ',':
		case '}':
		case ']':
		case ' ':
		case ':':
			return true;
		}
		return false;
	}
	
	@Override
	public boolean isString() {
		char c = readAndSkipBlank();
		return c == '"';
	}

	@Override
	public boolean isArray() {
		char c = readAndSkipBlank();
		return c == '[';
	}
	
	@Override
	public boolean isEmptyArray() {
		mark(1024);
		char c = readAndSkipBlank();
		
		if(c == ']')
			return true;
		
		reset();
		return false;
	}

	@Override
	public boolean isObject() {
		char c = readAndSkipBlank();
		return c == '{';
	}
	
	@Override
	public boolean isEmptyObject() {
		mark(1024);
		char c = readAndSkipBlank();
		
		if(c == '}')
			return true;
		
		reset();
		return false;
	}
	
	@Override
	public boolean isColon() {
		char c = readAndSkipBlank();
		return c == ':';
	}
	
	@Override
	public boolean isComma() {
		char c = readAndSkipBlank();
		return c == ',';
	}
	
	@Override
	public boolean isNull() {
		mark(1024);
		char ch = readAndSkipBlank();
		if(pos + 3 > limit) {
			reset();
			return false;
		}
		
		if(ch == 'n' && 'u' == read() && 'l' == read() && 'l' == read()) {
			if(pos >= limit)
				return true;
			
			ch = readAndSkipBlank();
			if(isEndFlag(ch)) {
				pos--;
				return true;
			} else {
				reset();
				return false;
			}
		} else {
			reset();
			return false;
		}
	}

	@Override
	public int read() {
		return chars[pos++];
	}

	@Override
	public char readAndSkipBlank() {
		char c = (char)read();
		if (c > ' ')
			return c;
		for (;;) {
			c = (char)read();
			if (c > ' ')
				return c;
		}
	}
	
	@Override
	public boolean readBoolean() {
		boolean ret = false;
		
		if(isNull())
			return ret;
		
		char ch = readAndSkipBlank();
		boolean isString = (ch == '"');
		if(isString)
			ch = readAndSkipBlank();
		
		if(ch == 't' && 'r' == read() && 'u' == read() && 'e' == read())
			ret = true;
		else if (ch == 'f' && 'a' == read() && 'l' == read() && 's' == read() && 'e' == read())
			ret = false;
		
		if(isString) {
			ch = readAndSkipBlank();
			if(ch != '"')
				throw new JsonException("read boolean error, the position is " + pos);
		}
		
		return ret;
	}
	
	@Override
	public int readInt() {
		int value = 0;

		if(isNull())
			return value;
		
		char ch = readAndSkipBlank();
		boolean isString = (ch == '"');
		if(isString)
			ch = readAndSkipBlank();
		boolean negative = (ch == '-');
		
		if(!negative) {
			if(VerifyUtils.isDigit(ch))
				value = (value << 3) + (value << 1) + (ch - '0');
			else
				throw new JsonException("read int error, charactor \"" + ch + "\" is not integer, the position is " + pos);
		}
		
		for(;;) {
			ch = (char)read();
			if(VerifyUtils.isDigit(ch))
				value = (value << 3) + (value << 1) + (ch - '0');
			else {
				if(isString) {
					if(ch == '"')
						break;
				} else {
					if (isEndFlag(ch)) {
						pos--;
						break;
					} else
						throw new JsonException("read int error, charactor \"" + ch + "\" is not integer, the position is " + pos);
				}
			}
			
			if(pos >= limit)
				break;
		}
		return negative ? -value : value;
	}
	
	@Override
	public long readLong() {
		long value = 0;

		if(isNull())
			return value;
		
		char ch = readAndSkipBlank();
		boolean isString = (ch == '"');
		if(isString)
			ch = readAndSkipBlank();
		boolean negative = (ch == '-');
		
		if(!negative) {
			if(VerifyUtils.isDigit(ch))
				value = (value << 3) + (value << 1) + (ch - '0');
			else
				throw new JsonException("read int error, charactor \"" + ch + "\" is not integer, the position is " + pos);
		}
		
		for(;;) {
			ch = (char)read();
			if(VerifyUtils.isDigit(ch))
				value = (value << 3) + (value << 1) + (ch - '0');
			else {
				if(isString) {
					if(ch == '"')
						break;
				} else {
					if (isEndFlag(ch)) {
						pos--;
						break;
					} else
						throw new JsonException("read int error, charactor \"" + ch + "\" is not integer, the position is " + pos);
				}
			}
			
			if(pos >= limit)
				break;
		}
		return negative ? -value : value;
	}
	
	@Override
	public String readValueAsString() {
		int start = pos;
		int startBlankLength = 0;
		int endBlankLength = 0;
		boolean hasChar = false;
		for(;;) {
			char ch = (char)read();
			if(ch <= ' ') {
				if(!hasChar) {
					startBlankLength++;
				} else {
					endBlankLength++;
				}
				continue;
			}
			
			if(!hasChar) {
				hasChar = true;
			}
			
			if (isEndFlag(ch)) {
				pos--;
				break;
			}
		}
		start = start + startBlankLength;
		int end = pos - endBlankLength;
		int len = end - start;
//		System.out.println("str len --> " + len + "|" + start + "|" + new String(chars, start, len));
		return new String(chars, start, len);
	}
	
	@Override
	public BigInteger readBigInteger() {
		String value = "0";
		
		if(isNull())
			return new BigInteger(value);
		
		char ch = readAndSkipBlank();
		boolean isString = (ch == '"');
		if(isString)
			ch = readAndSkipBlank();
		pos--;
		
		int start = pos;
		for(;;) {
			ch = (char)read();
			if(isString) {
				if(ch == '"')
					break;
			} else {
				if (isEndFlag(ch)) {
					pos--;
					break;
				}
			}
		}
		
		int len = isString ? pos - start - 1 : pos - start;
		String temp = new String(chars, start, len);
		return new BigInteger(temp);
	}
	
	@Override
	public BigDecimal readBigDecimal() {
		String value = "0.0";
		
		if(isNull())
			return new BigDecimal(value);
		
		char ch = readAndSkipBlank();
		boolean isString = (ch == '"');
		if(isString)
			ch = readAndSkipBlank();
		pos--;
		
		int start = pos;
		for(;;) {
			ch = (char)read();
			if(isString) {
				if(ch == '"')
					break;
			} else {
				if (isEndFlag(ch)) {
					pos--;
					break;
				}
			}
		}
		
		int len = isString ? pos - start - 1 : pos - start;
		String temp = new String(chars, start, len);
		return new BigDecimal(temp);
	}
	
	@Override
	public double readDouble() {
		double value = 0.0;

		if(isNull())
			return value;
		
		char ch = readAndSkipBlank();
		boolean isString = (ch == '"');
		if(isString)
			ch = readAndSkipBlank();
		pos--;
		
		int start = pos;
		for(;;) {
			ch = (char)read();
			if(isString) {
				if(ch == '"')
					break;
			} else {
				if (isEndFlag(ch)) {
					pos--;
					break;
				}
			}
		}
		
		int len = isString ? pos - start - 1 : pos - start;
		String temp = new String(chars, start, len);
		return Double.parseDouble(temp);
	}
	
	@Override
	public float readFloat() {
		float value = 0.0F;

		if(isNull())
			return value;
		
		char ch = readAndSkipBlank();
		boolean isString = (ch == '"');
		if(isString)
			ch = readAndSkipBlank();
		pos--;
		
		int start = pos;
		for(;;) {
			ch = (char)read();
			if(isString) {
				if(ch == '"')
					break;
			} else {
				if (isEndFlag(ch)) {
					pos--;
					break;
				}
			}
		}
		
		int len = isString ? pos - start - 1 : pos - start;
		String temp = new String(chars, start, len);
		return Float.parseFloat(temp);
	}

	@Override
	public char[] readField(char[] chs) {
		if(!isString())
			throw new JsonException("read field error, the position is " + pos);
			
		int cur = pos;
		int len = chs.length;
		boolean skip = true;
		
		int next = pos + len;
		if(next < limit && chars[next] == '"') {
			for (int i = 0; i < len; i++) {
				if (chs[i] != chars[cur++]) {
					skip = false;
					break;
				}
			}
		} else {
			skip = false;
		}

		if (skip) {
			pos = cur + 1;
			return null;
		} else {
			char[] field = null;
			int start = pos;
			for(;;) {
				char c = (char)read();
				if(c == '"')
					break;
			}
			int fieldLen = pos - 1 - start;
			field = new char[fieldLen];
			System.arraycopy(chars, start, field, 0, fieldLen);
			return field;
		}
	}
	
	@Override
	public char[] readChars() {
		if(!isString())
			throw new JsonException("read field error, the position is " + pos);
		
		int start = pos;
		for(;;) {
			char c = (char)read();
			if(c == '"')
				break;
		}
		int fieldLen = pos - 1 - start;
		char[] c = new char[fieldLen];
		System.arraycopy(chars, start, c, 0, fieldLen);
		return c;
	}
	
	@Override
	public void skipValue() {
		char ch = readAndSkipBlank();
		switch (ch) {
		case '"': // 跳过字符串
			for(;;) {
				ch = (char)read();
				if(ch == '"')
					break;
				else if(ch == '\\')
					pos++;
			}
			break;
		case '[': // 跳过数组
			for(;;) {
				if(isEmptyArray())
					break;
				
				skipValue();
				ch = readAndSkipBlank();
				if(ch == ']')
					break;
				
				if(ch != ',')
					throw new JsonException("json string array format error, the position is " + pos);
			}
			break;
		case '{': // 跳过对象
			for(;;) {
				if(isEmptyObject())
					break;
				
				readChars();
				if(!isColon())
					throw new JsonException("json string object format error, the position is " + pos);
				
				skipValue();
				ch = readAndSkipBlank();
				if(ch == '}')
					break;
				
				if(ch != ',')
					throw new JsonException("json string object format error, the position is " + pos);
			}
			break;

		default: // 跳过数字或者null
			for(;;) {
				ch = (char)read();
				if(isEndFlag(ch)) {
					pos--;
					break;
				}
			}
			break;
		}
	}
	
	@Override
	public String readString() {
		if(isNull())
			return null;
		
		if(!isString())
			throw new JsonException("read string error, the position is " + pos);
		
		JsonStringWriter writer = new JsonStringWriter();
		String ret = null;
		
		int cur = pos;
		int len = 0;
		for(;;) {
			char ch = chars[cur++];
			if(ch == '"') {
				len = cur - pos - 1;
				writer.write(chars, pos, len);
				pos = cur;
				break;
			} else if(ch == '\\') {
				char c0 = chars[cur++];
				len = cur - 2 - pos;
				writer.write(chars, pos, len);
				switch (c0) {
				case 'b':
					writer.write('\b');
					break;
				case 'n':
					writer.write('\n');
					break;
				case 'r':
					writer.write('\r');
					break;
				case 'f':
					writer.write('\f');
					break;
				case '\\':
					writer.write('\\');
					break;
				case '/':
					writer.write('/');
					break;
				case '"':
					writer.write('"');
					break;
				case 't':
					writer.write('\t');
					break;
				case 'u': // unicode char parse
					char[] controlChars = new char[4];
					for (int i = 0; i < controlChars.length; i++) {
						controlChars[i] = chars[cur++];
					}
					char tmp = (char)Integer.parseInt(String.valueOf(controlChars), 16);
					writer.write(tmp);
					break;
				}
				pos = cur;
			}
			
		}
		try {
			ret = writer.toString();
		} finally {
			writer.close();
		}
		return ret;
	}

	@Override
	public int read(char[] cbuf, int off, int len) throws IOException {
		throw new JsonException("method not implements!");
	}
	
	@Override
	public void close() throws IOException {
		
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy