net.minidev.json.parser.JSONParserBase Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of json-smart Show documentation
Show all versions of json-smart Show documentation
JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. It is based on a subset of the JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999. JSON is a text format that is completely language independent but uses conventions that are familiar to programmers of the C-family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, and many others. These properties make JSON an ideal data-interchange language.
package net.minidev.json.parser;
/*
* Copyright 2011 JSON-SMART authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_CHAR;
import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_DUPLICATE_KEY;
import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_EOF;
import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_LEADING_0;
import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_TOKEN;
import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_UNICODE;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
/**
* JSONParserBase is the common code between {@link JSONParserString} and
* {@link JSONParserReader}
*
* @see JSONParserMemory
* @see JSONParserStream
*
* @author Uriel Chemouni
*/
abstract class JSONParserBase {
protected char c;
public final static byte EOI = 0x1A;
protected static final char MAX_STOP = 126; // '}' -> 125
//
protected static boolean[] stopAll = new boolean[MAX_STOP];
protected static boolean[] stopArray = new boolean[MAX_STOP];
protected static boolean[] stopKey = new boolean[MAX_STOP];
protected static boolean[] stopValue = new boolean[MAX_STOP];
protected static boolean[] stopX = new boolean[MAX_STOP];
static {
stopKey[':'] = stopKey[EOI] = true;
stopValue[','] = stopValue['}'] = stopValue[EOI] = true;
stopArray[','] = stopArray[']'] = stopArray[EOI] = true;
stopX[EOI] = true;
stopAll[','] = stopAll[':'] = true;
stopAll[']'] = stopAll['}'] = stopAll[EOI] = true;
}
/*
* End of static declaration
*/
protected ContainerFactory containerFactory;
protected ContentHandler handler;
protected final MSB sb = new MSB(15);
protected Object xo;
protected String xs;
protected int pos;
/*
* Parsing flags
*/
protected final boolean acceptLeadinZero;
protected final boolean acceptNaN;
protected final boolean acceptNonQuote;
protected final boolean acceptSimpleQuote;
protected final boolean acceptUselessComma;
protected final boolean checkTaillingData;
protected final boolean checkTaillingSpace;
protected final boolean ignoreControlChar;
protected final boolean useHiPrecisionFloat;
protected final boolean useIntegerStorage;
public JSONParserBase(int permissiveMode) {
this.acceptNaN = (permissiveMode & JSONParser.ACCEPT_NAN) > 0;
this.acceptNonQuote = (permissiveMode & JSONParser.ACCEPT_NON_QUOTE) > 0;
this.acceptSimpleQuote = (permissiveMode & JSONParser.ACCEPT_SIMPLE_QUOTE) > 0;
this.ignoreControlChar = (permissiveMode & JSONParser.IGNORE_CONTROL_CHAR) > 0;
this.useIntegerStorage = (permissiveMode & JSONParser.USE_INTEGER_STORAGE) > 0;
this.acceptLeadinZero = (permissiveMode & JSONParser.ACCEPT_LEADING_ZERO) > 0;
this.acceptUselessComma = (permissiveMode & JSONParser.ACCEPT_USELESS_COMMA) > 0;
this.useHiPrecisionFloat = (permissiveMode & JSONParser.USE_HI_PRECISION_FLOAT) > 0;
this.checkTaillingData = (permissiveMode & (JSONParser.ACCEPT_TAILLING_DATA | JSONParser.ACCEPT_TAILLING_SPACE)) != (JSONParser.ACCEPT_TAILLING_DATA | JSONParser.ACCEPT_TAILLING_SPACE);
this.checkTaillingSpace = (permissiveMode & JSONParser.ACCEPT_TAILLING_SPACE) == 0;
}
public void checkControleChar() throws ParseException {
if (ignoreControlChar)
return;
int l = xs.length();
for (int i = 0; i < l; i++) {
char c = xs.charAt(i);
if (c < 0)
continue;
if (c <= 31)
throw new ParseException(pos + i, ParseException.ERROR_UNEXPECTED_CHAR, c);
if (c == 127)
throw new ParseException(pos + i, ParseException.ERROR_UNEXPECTED_CHAR, c);
}
}
public void checkLeadinZero() throws ParseException {
int len = xs.length();
if (len == 1)
return;
if (len == 2) {
if (xs.equals("00"))
throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, xs);
return;
}
char c1 = xs.charAt(0);
char c2 = xs.charAt(1);
if (c1 == '-') {
char c3 = xs.charAt(2);
if (c2 == '0' && c3 >= '0' && c3 <= '9')
throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, xs);
return;
}
if (c1 == '0' && c2 >= '0' && c2 <= '9')
throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, xs);
}
protected Number extractFloat() throws ParseException {
if (!acceptLeadinZero)
checkLeadinZero();
try {
if (!useHiPrecisionFloat)
return Float.parseFloat(xs);
if (xs.length() > 18) // follow JSonIJ parsing method
return new BigDecimal(xs);
return Double.parseDouble(xs);
} catch(NumberFormatException e) {
throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
}
}
/**
* use to return Primitive Type, or String, Or JsonObject or JsonArray
* generated by a ContainerFactory
*/
protected Object parse(ContainerFactory containerFactory, ContentHandler handler) throws ParseException {
this.containerFactory = containerFactory;
this.handler = handler;
// this.pos = -1;
Object result;
try {
read();
handler.startJSON();
result = readMain(stopX);
handler.endJSON();
if (checkTaillingData) {
if (!checkTaillingSpace)
skipSpace();
if (c != EOI)
throw new ParseException(pos - 1, ERROR_UNEXPECTED_TOKEN, c);
}
} catch (IOException e) {
throw new ParseException(pos, e);
}
xs = null;
xo = null;
return result;
}
protected Number parseNumber(String s) throws ParseException {
// pos
int p = 0;
// len
int l = s.length();
// max pos long base 10 len
int max = 19;
boolean neg;
if (s.charAt(0) == '-') {
p++;
max++;
neg = true;
if (!acceptLeadinZero && l >= 3 && s.charAt(1) == '0')
throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, s);
} else {
neg = false;
if (!acceptLeadinZero && l >= 2 && s.charAt(0) == '0')
throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, s);
}
boolean mustCheck;
if (l < max) {
max = l;
mustCheck = false;
} else if (l > max) {
return new BigInteger(s, 10);
} else {
max = l - 1;
mustCheck = true;
}
long r = 0;
while (p < max) {
r = (r * 10L) + ('0' - s.charAt(p++));
}
if (mustCheck) {
boolean isBig;
if (r > -922337203685477580L) {
isBig = false;
} else if (r < -922337203685477580L) {
isBig = true;
} else {
if (neg)
isBig = (s.charAt(p) > '8');
else
isBig = (s.charAt(p) > '7');
}
if (isBig)
return new BigInteger(s, 10);
r = r * 10L + ('0' - s.charAt(p));
}
if (neg) {
if (this.useIntegerStorage && r >= Integer.MIN_VALUE)
return (int) r;
return r;
}
r = -r;
if (this.useIntegerStorage && r <= Integer.MAX_VALUE)
return (int) r;
return r;
}
/**
* Read one char in this.c
*
* @throws IOException
*/
abstract protected void read() throws IOException;
protected List