
org.boon.json.implementation.JsonBaseByteArrayParser Maven / Gradle / Ivy
/*
* Copyright 2013-2014 Richard M. Hightower
* 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.
*
* __________ _____ __ .__
* \______ \ ____ ____ ____ /\ / \ _____ | | _|__| ____ ____
* | | _// _ \ / _ \ / \ \/ / \ / \\__ \ | |/ / |/ \ / ___\
* | | ( <_> | <_> ) | \ /\ / Y \/ __ \| <| | | \/ /_/ >
* |______ /\____/ \____/|___| / \/ \____|__ (____ /__|_ \__|___| /\___ /
* \/ \/ \/ \/ \/ \//_____/
* ____. ___________ _____ ______________.___.
* | |____ ___ _______ \_ _____/ / _ \ / _____/\__ | |
* | \__ \\ \/ /\__ \ | __)_ / /_\ \ \_____ \ / | |
* /\__| |/ __ \\ / / __ \_ | \/ | \/ \ \____ |
* \________(____ /\_/ (____ / /_______ /\____|__ /_______ / / ______|
* \/ \/ \/ \/ \/ \/
*/
package org.boon.json.implementation;
import org.boon.IO;
import org.boon.core.Typ;
import org.boon.core.reflection.MapObjectConversion;
import org.boon.json.JsonException;
import org.boon.collections.LazyMap;
import org.boon.primitive.Byt;
import org.boon.primitive.ByteScanner;
import org.boon.primitive.CharBuf;
import org.boon.primitive.InMemoryInputStream;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.*;
import static org.boon.primitive.ByteScanner.skipWhiteSpaceFast;
/**
* Created by rick on 12/15/13.
*/
public abstract class JsonBaseByteArrayParser extends BaseJsonParser {
protected byte[] charArray;
protected int __index;
protected int __currentChar;
protected static final int NEW_LINE = '\n';
protected static final int RETURN = '\r';
protected static final int SPACE = ' ';
protected static final int TAB = '\t';
protected static final int BELL = '\b';
protected static final int FORM_FEED = '\f';
protected static final int COLON = ':';
protected static final int OPEN_CURLY = '{';
protected static final int OPEN_BRACKET = '[';
protected static final int LETTER_N = 'n';
protected static final int LETTER_U = 'u';
protected static final int LETTER_L = 'l';
protected static final int LETTER_T = 't';
protected static final int LETTER_R = 'r';
protected static final int LETTER_F = 'f';
protected static final int LETTER_A = 'a';
protected static final int LETTER_S = 's';
protected final CharBuf builder = CharBuf.create( 20 );
protected final boolean hasMore() {
return __index < lastIndex;
}
protected final boolean hasCurrent() {
return __index <= lastIndex;
}
protected final void skipWhiteSpaceIfNeeded() {
int ix = __index;
if (hasCurrent ()) {
this.__currentChar = this.charArray[ix];
}
if (__currentChar <= 32) {
ix = skipWhiteSpaceFast ( this.charArray, ix );
this.__currentChar = this.charArray[ix];
__index = ix;
}
}
protected final int nextChar() {
try {
if ( hasMore() ) {
__index++;
return __currentChar = charArray[ __index ];
} else {
return '\u0000';
}
} catch ( Exception ex ) {
throw new JsonException( exceptionDetails( "unable to advance character" ), ex );
}
}
protected String exceptionDetails( String message ) {
return ByteScanner.errorDetails(message, charArray, __index, __currentChar);
}
private static int skipWhiteSpaceFastBytes( byte [] array, int index ) {
int c;
for (; index< array.length; index++ ) {
c = array [index];
if ( c > 32 ) {
return index;
}
}
return index-1;
}
protected final void skipWhiteSpace() {
__index = skipWhiteSpaceFastBytes ( this.charArray, __index );
this.__currentChar = this.charArray[__index];
}
protected int lastIndex;
private Object decode( byte[] cs ) {
lastIndex = cs.length -1;
charArray = cs;
__index = 0;
return decodeValue();
}
public T parse( Class type, String str ) {
return this.parse( type, str.getBytes( charset ) );
}
public T parse( Class type, byte[] bytes ) {
if ( type == Map.class || type == List.class || Typ.isBasicType (type) ) {
return ( T ) this.decode( bytes );
} else {
Map objectMap = ( Map ) this.decode( bytes );
return MapObjectConversion.fromMap ( objectMap, type );
}
}
@Override
public Object parse ( byte[] bytes ) {
return this.decode ( bytes );
}
public T parse( Class type, InputStream input ) {
return parse( type, IO.input( input ) );
}
public T parse( Class type, CharSequence charSequence ) {
return parse( type, charSequence.toString() );
}
public T parse( Class type, char[] chars ) {
return parse( type, new String( chars ) );
}
protected void complain( String complaint ) {
throw new JsonException( exceptionDetails( complaint ) );
}
protected final Object decodeJsonObject() {
if ( __currentChar == OPEN_CURLY ) {
__index++;
}
LazyMap map = new LazyMap ();
for (; __index < this.charArray.length; __index++ ) {
skipWhiteSpaceIfNeeded ();
if ( __currentChar == DOUBLE_QUOTE ) {
String key =
decodeString();
if ( internKeys ) {
String keyPrime = internedKeysCache.get( key );
if ( keyPrime == null ) {
key = key.intern();
internedKeysCache.put( key, key );
} else {
key = keyPrime;
}
}
skipWhiteSpaceIfNeeded ();
if ( __currentChar != COLON ) {
complain( "expecting current character to be " + charDescription( __currentChar ) + "\n" );
}
__index++;
skipWhiteSpaceIfNeeded ();
Object value = decodeValue();
skipWhiteSpaceIfNeeded ();
map.put( key, value );
}
if ( __currentChar == CLOSED_CURLY ) {
__index++;
break;
} else if ( __currentChar == COMMA) {
continue;
} else {
complain(
"expecting '}' or ',' but got current char " + charDescription( __currentChar ) );
}
}
return map;
}
protected final Object decodeValue() {
Object value = null;
done:
for (; __index < this.charArray.length; __index++ ) {
__currentChar = charArray[ __index ];
switch ( __currentChar ) {
case NEW_LINE:
break;
case RETURN:
case SPACE:
case TAB:
case BELL:
case FORM_FEED:
break;
case DOUBLE_QUOTE:
value = decodeString ();
break done;
case LETTER_T:
value = decodeTrue();
break done;
case LETTER_F:
value = decodeFalse();
break done;
case LETTER_N:
value = decodeNull();
break done;
case OPEN_BRACKET:
value = decodeJsonArray();
break done;
case OPEN_CURLY:
value = decodeJsonObject();
break done;
case ALPHA_1:
case ALPHA_2:
case ALPHA_3:
case ALPHA_4:
case ALPHA_5:
case ALPHA_6:
case ALPHA_7:
case ALPHA_8:
case ALPHA_9:
case ALPHA_0:
value = decodeNumber();
break done;
case MINUS:
value = decodeNumber();
break done;
default:
throw new JsonException( exceptionDetails( "Unable to determine the " +
"current character, it is not a string, number, array, or object" ) );
}
}
return value;
}
int[] endIndex = new int[1];
private final Object decodeNumber() {
Number num = ByteScanner.parseJsonNumber( charArray, __index, charArray.length, endIndex );
__index = endIndex[0];
return num;
}
protected final static byte[] NULL = Byt.bytes( "null" );
protected final Object decodeNull() {
if ( __index + NULL.length <= charArray.length ) {
if ( charArray[ __index ] == LETTER_N &&
charArray[ ++__index ] == LETTER_U &&
charArray[ ++__index ] == LETTER_L &&
charArray[ ++__index ] == LETTER_L ) {
nextChar();
return null;
}
}
throw new JsonException( exceptionDetails( "null not parsed properly" ) );
}
protected final static byte[] TRUE = Byt.bytes( "true" );
protected final boolean decodeTrue() {
if ( __index + TRUE.length <= charArray.length ) {
if ( charArray[ __index ] == LETTER_T &&
charArray[ ++__index ] == LETTER_R &&
charArray[ ++__index ] == LETTER_U &&
charArray[ ++__index ] == LETTER_E ) {
nextChar();
return true;
}
}
throw new JsonException( exceptionDetails( "true not parsed properly" ) );
}
protected final static byte[] FALSE = Byt.bytes( "false" );
protected final boolean decodeFalse() {
if ( __index + FALSE.length <= charArray.length ) {
if ( charArray[ __index ] == LETTER_F &&
charArray[ ++__index ] == LETTER_A &&
charArray[ ++__index ] == LETTER_L &&
charArray[ ++__index ] == LETTER_S &&
charArray[ ++__index ] == LETTER_E ) {
nextChar();
return false;
}
}
throw new JsonException( exceptionDetails( "false not parsed properly" ) );
}
protected abstract String decodeString();
protected final List decodeJsonArray() {
ArrayList
© 2015 - 2025 Weber Informatics LLC | Privacy Policy