diff --git a/pom.xml b/pom.xml
index 01bf1721..4840503f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.jsoniter
- 0.9.22
+ 0.9.24-SNAPSHOT
jsoniter
json iterator
jsoniter (json-iterator) is fast and flexible JSON parser available in Java and Go
@@ -46,25 +46,25 @@
org.javassist
javassist
- 3.21.0-GA
+ 3.22.0-GA
true
com.fasterxml.jackson.core
jackson-annotations
- 2.8.5
+ 2.9.5
true
com.fasterxml.jackson.core
jackson-databind
- 2.8.5
+ 2.9.5
true
com.google.code.gson
gson
- 2.2.4
+ 2.8.3
true
@@ -119,7 +119,7 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.6.0
+ 3.7.0
1.6
1.6
@@ -129,7 +129,7 @@
org.apache.maven.plugins
maven-source-plugin
- 2.2.1
+ 3.0.1
attach-sources
@@ -142,7 +142,7 @@
org.apache.maven.plugins
maven-javadoc-plugin
- 2.9.1
+ 3.0.0
attach-javadocs
@@ -158,7 +158,7 @@
org.apache.maven.plugins
maven-gpg-plugin
- 1.5
+ 1.6
sign-artifacts
@@ -172,7 +172,7 @@
org.sonatype.plugins
nexus-staging-maven-plugin
- 1.6.7
+ 1.6.8
true
ossrh
@@ -194,7 +194,7 @@
org.apache.maven.plugins
maven-surefire-plugin
- 2.19.1
+ 2.21.0
methods
1
diff --git a/src/main/java/com/jsoniter/Codegen.java b/src/main/java/com/jsoniter/Codegen.java
index ad2013d5..7cf7318d 100644
--- a/src/main/java/com/jsoniter/Codegen.java
+++ b/src/main/java/com/jsoniter/Codegen.java
@@ -96,16 +96,12 @@ private static void addPlaceholderDecoderToSupportRecursiveStructure(final Strin
public Object decode(JsonIterator iter) throws IOException {
Decoder decoder = JsoniterSpi.getDecoder(cacheKey);
if (this == decoder) {
- for(int i = 0; i < 30; i++) {
+ for(int i = 0; (i < 30) && (this == decoder); i++) {
decoder = JsoniterSpi.getDecoder(cacheKey);
- if (this == decoder) {
- try {
- Thread.sleep(1000);
+ try {
+ Thread.sleep(1000);
} catch (InterruptedException e) {
throw new JsonException(e);
- }
- } else {
- break;
}
}
if (this == decoder) {
diff --git a/src/main/java/com/jsoniter/IterImpl.java b/src/main/java/com/jsoniter/IterImpl.java
index 65563134..ad779fd8 100644
--- a/src/main/java/com/jsoniter/IterImpl.java
+++ b/src/main/java/com/jsoniter/IterImpl.java
@@ -59,7 +59,7 @@ final static void skipArray(JsonIterator iter) throws IOException {
case '[': // If open symbol, increase level
level++;
break;
- case ']': // If close symbol, increase level
+ case ']': // If close symbol, decrease level
level--;
// If we have returned to the original level, we're done
@@ -85,7 +85,7 @@ final static void skipObject(JsonIterator iter) throws IOException {
case '{': // If open symbol, increase level
level++;
break;
- case '}': // If close symbol, increase level
+ case '}': // If close symbol, decrease level
level--;
// If we have returned to the original level, we're done
@@ -393,10 +393,6 @@ static final int readInt(final JsonIterator iter, final byte c) throws IOExcepti
static final long readLong(final JsonIterator iter, final byte c) throws IOException {
long ind = IterImplNumber.intDigits[c];
- if (ind == 0) {
- IterImplForStreaming.assertNotLeadingZero(iter);
- return 0;
- }
if (ind == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
throw iter.reportError("readLong", "expect 0~9");
}
diff --git a/src/main/java/com/jsoniter/IterImplForStreaming.java b/src/main/java/com/jsoniter/IterImplForStreaming.java
index 7e29f770..2cef3a16 100644
--- a/src/main/java/com/jsoniter/IterImplForStreaming.java
+++ b/src/main/java/com/jsoniter/IterImplForStreaming.java
@@ -71,7 +71,7 @@ final static void skipArray(JsonIterator iter) throws IOException {
case '[': // If open symbol, increase level
level++;
break;
- case ']': // If close symbol, increase level
+ case ']': // If close symbol, decrease level
level--;
// If we have returned to the original level, we're done
@@ -101,7 +101,7 @@ final static void skipObject(JsonIterator iter) throws IOException {
case '{': // If open symbol, increase level
level++;
break;
- case '}': // If close symbol, increase level
+ case '}': // If close symbol, decrease level
level--;
// If we have returned to the original level, we're done
@@ -147,7 +147,8 @@ final static void skipString(JsonIterator iter) throws IOException {
throw iter.reportError("skipString", "incomplete string");
}
if (escaped) {
- iter.head = 1; // skip the first char as last char is \
+ // TODO add unit test to prove/verify bug
+ iter.head += 1; // skip the first char as last char is \
}
} else {
iter.head = end;
@@ -274,19 +275,19 @@ public final static boolean loadMore(JsonIterator iter) throws IOException {
}
private static boolean keepSkippedBytesThenRead(JsonIterator iter) throws IOException {
- int n;
- int offset;
- if (iter.skipStartedAt == 0 || iter.skipStartedAt < iter.tail / 2) {
- byte[] newBuf = new byte[iter.buf.length * 2];
- offset = iter.tail - iter.skipStartedAt;
- System.arraycopy(iter.buf, iter.skipStartedAt, newBuf, 0, offset);
- iter.buf = newBuf;
- n = iter.in.read(iter.buf, offset, iter.buf.length - offset);
- } else {
- offset = iter.tail - iter.skipStartedAt;
- System.arraycopy(iter.buf, iter.skipStartedAt, iter.buf, 0, offset);
- n = iter.in.read(iter.buf, offset, iter.buf.length - offset);
- }
+ int offset = iter.tail - iter.skipStartedAt;
+ byte[] srcBuffer = iter.buf;
+ // Check there is no unused buffer capacity
+ if ((getUnusedBufferByteCount(iter)) == 0) {
+ // If auto expand buffer enabled, then create larger buffer
+ if (iter.autoExpandBufferStep > 0) {
+ iter.buf = new byte[iter.buf.length + iter.autoExpandBufferStep];
+ } else {
+ throw iter.reportError("loadMore", String.format("buffer is full and autoexpansion is disabled. tail: [%s] skipStartedAt: [%s]", iter.tail, iter.skipStartedAt));
+ }
+ }
+ System.arraycopy(srcBuffer, iter.skipStartedAt, iter.buf, 0, offset);
+ int n = iter.in.read(iter.buf, offset, iter.buf.length - offset);
iter.skipStartedAt = 0;
if (n < 1) {
if (n == -1) {
@@ -301,6 +302,11 @@ private static boolean keepSkippedBytesThenRead(JsonIterator iter) throws IOExce
return true;
}
+ private static int getUnusedBufferByteCount(JsonIterator iter) {
+ // Get bytes from 0 to skipStart + from tail till end
+ return iter.buf.length - iter.tail + iter.skipStartedAt;
+ }
+
final static byte readByte(JsonIterator iter) throws IOException {
if (iter.head == iter.tail) {
if (!loadMore(iter)) {
@@ -540,6 +546,16 @@ static int readIntSlowPath(final JsonIterator iter, int value) throws IOExceptio
public static final double readDoubleSlowPath(final JsonIterator iter) throws IOException {
try {
numberChars numberChars = readNumber(iter);
+ if (numberChars.charsLength == 0 && iter.whatIsNext() == ValueType.STRING) {
+ String possibleInf = iter.readString();
+ if ("infinity".equals(possibleInf)) {
+ return Double.POSITIVE_INFINITY;
+ }
+ if ("-infinity".equals(possibleInf)) {
+ return Double.NEGATIVE_INFINITY;
+ }
+ throw iter.reportError("readDoubleSlowPath", "expect number but found string: " + possibleInf);
+ }
return Double.valueOf(new String(numberChars.chars, 0, numberChars.charsLength));
} catch (NumberFormatException e) {
throw iter.reportError("readDoubleSlowPath", e.toString());
@@ -633,8 +649,7 @@ static final int readInt(final JsonIterator iter, final byte c) throws IOExcepti
static void assertNotLeadingZero(JsonIterator iter) throws IOException {
try {
- byte nextByte = IterImpl.readByte(iter);
- iter.unreadByte();
+ byte nextByte = iter.buf[iter.head];
int ind2 = IterImplNumber.intDigits[nextByte];
if (ind2 == IterImplNumber.INVALID_CHAR_FOR_NUMBER) {
return;
diff --git a/src/main/java/com/jsoniter/IterImplNumber.java b/src/main/java/com/jsoniter/IterImplNumber.java
index adc2bf69..c521cdd5 100644
--- a/src/main/java/com/jsoniter/IterImplNumber.java
+++ b/src/main/java/com/jsoniter/IterImplNumber.java
@@ -91,8 +91,17 @@ public static final int readInt(final JsonIterator iter) throws IOException {
public static final long readLong(JsonIterator iter) throws IOException {
byte c = IterImpl.nextToken(iter);
if (c == '-') {
- return IterImpl.readLong(iter, IterImpl.readByte(iter));
+ c = IterImpl.readByte(iter);
+ if (IterImplNumber.intDigits[c] == 0) {
+ IterImplForStreaming.assertNotLeadingZero(iter);
+ return 0;
+ }
+ return IterImpl.readLong(iter, c);
} else {
+ if (IterImplNumber.intDigits[c] == 0) {
+ IterImplForStreaming.assertNotLeadingZero(iter);
+ return 0;
+ }
long val = IterImpl.readLong(iter, c);
if (val == Long.MIN_VALUE) {
throw iter.reportError("readLong", "value is too large for long");
diff --git a/src/main/java/com/jsoniter/JsonIterator.java b/src/main/java/com/jsoniter/JsonIterator.java
index 33f224d3..c198540b 100644
--- a/src/main/java/com/jsoniter/JsonIterator.java
+++ b/src/main/java/com/jsoniter/JsonIterator.java
@@ -21,6 +21,9 @@ public class JsonIterator implements Closeable {
final static ValueType[] valueTypes = new ValueType[256];
InputStream in;
byte[] buf;
+ // Whenever buf is not large enough new one is created with size of
+ // buf.length + autoExpandBufferStep. Set to < 1 to disable auto expanding.
+ int autoExpandBufferStep;
int head;
int tail;
int skipStartedAt = -1; // skip should keep bytes starting at this pos
@@ -60,13 +63,22 @@ private JsonIterator(InputStream in, byte[] buf, int head, int tail) {
this.tail = tail;
}
+ private JsonIterator(InputStream in, byte[] buf, int autoExpandBufferStep) {
+ this(in, buf, 0, 0);
+ this.autoExpandBufferStep = autoExpandBufferStep;
+ }
+
public JsonIterator() {
this(null, new byte[0], 0, 0);
}
public static JsonIterator parse(InputStream in, int bufSize) {
+ return parse(in, bufSize, bufSize);
+ }
+
+ public static JsonIterator parse(InputStream in, int bufSize, int autoExpandBufferStep) {
enableStreamingSupport();
- return new JsonIterator(in, new byte[bufSize], 0, 0);
+ return new JsonIterator(in, new byte[bufSize], autoExpandBufferStep);
}
public static JsonIterator parse(byte[] buf) {
@@ -292,13 +304,14 @@ public final Object read() throws IOException {
return readString();
case NUMBER:
IterImplForStreaming.numberChars numberChars = IterImplForStreaming.readNumber(this);
- Double number = Double.valueOf(new String(numberChars.chars, 0, numberChars.charsLength));
+ String numberStr = new String(numberChars.chars, 0, numberChars.charsLength);
+ Double number = Double.valueOf(numberStr);
if (numberChars.dotFound) {
return number;
}
double doubleNumber = number;
if (doubleNumber == Math.floor(doubleNumber) && !Double.isInfinite(doubleNumber)) {
- long longNumber = (long) doubleNumber;
+ long longNumber = Long.valueOf(numberStr);
if (longNumber <= Integer.MAX_VALUE && longNumber >= Integer.MIN_VALUE) {
return (int) longNumber;
}
diff --git a/src/main/java/com/jsoniter/JsonIteratorPool.java b/src/main/java/com/jsoniter/JsonIteratorPool.java
index 00f88e63..f0324d02 100644
--- a/src/main/java/com/jsoniter/JsonIteratorPool.java
+++ b/src/main/java/com/jsoniter/JsonIteratorPool.java
@@ -22,6 +22,7 @@ public static JsonIterator borrowJsonIterator() {
public static void returnJsonIterator(JsonIterator iter) {
iter.configCache = null;
+ iter.existingObject = null;
if (slot1.get() == null) {
slot1.set(iter);
return;
diff --git a/src/main/java/com/jsoniter/MapKeyDecoders.java b/src/main/java/com/jsoniter/MapKeyDecoders.java
index 4fa3d0cf..0bb75a30 100644
--- a/src/main/java/com/jsoniter/MapKeyDecoders.java
+++ b/src/main/java/com/jsoniter/MapKeyDecoders.java
@@ -22,11 +22,14 @@ private static Decoder createMapKeyDecoder(Type mapKeyType) {
if (String.class == mapKeyType) {
return new StringKeyDecoder();
}
+ if (mapKeyType instanceof Class && ((Class) mapKeyType).isEnum()) {
+ return new EnumKeyDecoder((Class) mapKeyType);
+ }
Decoder decoder = CodegenImplNative.NATIVE_DECODERS.get(mapKeyType);
if (decoder != null) {
return new NumberKeyDecoder(decoder);
}
- throw new JsonException("can not encode map key type: " + mapKeyType);
+ throw new JsonException("can not decode map key type: " + mapKeyType);
}
private static class StringKeyDecoder implements Decoder {
@@ -37,6 +40,20 @@ public Object decode(JsonIterator iter) throws IOException {
}
}
+ private static class EnumKeyDecoder implements Decoder {
+
+ private final Class enumClass;
+
+ private EnumKeyDecoder(Class enumClass) {
+ this.enumClass = enumClass;
+ }
+
+ @Override
+ public Object decode(JsonIterator iter) throws IOException {
+ return iter.read(enumClass);
+ }
+ }
+
private static class NumberKeyDecoder implements Decoder {
private final Decoder decoder;
diff --git a/src/main/java/com/jsoniter/any/ArrayLazyAny.java b/src/main/java/com/jsoniter/any/ArrayLazyAny.java
index 2205f71c..13983641 100644
--- a/src/main/java/com/jsoniter/any/ArrayLazyAny.java
+++ b/src/main/java/com/jsoniter/any/ArrayLazyAny.java
@@ -206,7 +206,11 @@ private class LazyIterator implements Iterator {
public LazyIterator() {
index = 0;
- next = fillCacheUntil(index);
+ try {
+ next = fillCacheUntil(index);
+ } catch (IndexOutOfBoundsException e) {
+ next = null;
+ }
}
@Override
diff --git a/src/main/java/com/jsoniter/any/LazyAny.java b/src/main/java/com/jsoniter/any/LazyAny.java
index 246fca76..d088241e 100644
--- a/src/main/java/com/jsoniter/any/LazyAny.java
+++ b/src/main/java/com/jsoniter/any/LazyAny.java
@@ -68,7 +68,7 @@ public final T as(TypeLiteral typeLiteral) {
}
public String toString() {
- return new String(data, head, tail - head);
+ return new String(data, head, tail - head).trim();
}
protected final JsonIterator parse() {
diff --git a/src/main/java/com/jsoniter/extra/Base64Support.java b/src/main/java/com/jsoniter/extra/Base64Support.java
index 16c60dfb..676178f7 100644
--- a/src/main/java/com/jsoniter/extra/Base64Support.java
+++ b/src/main/java/com/jsoniter/extra/Base64Support.java
@@ -11,7 +11,7 @@
import java.io.IOException;
/**
- * byte[] <=> base64
+ * byte[] <=> base64
*/
public class Base64Support {
private static boolean enabled;
diff --git a/src/main/java/com/jsoniter/output/CodegenImplMap.java b/src/main/java/com/jsoniter/output/CodegenImplMap.java
index 52250efd..006817d3 100644
--- a/src/main/java/com/jsoniter/output/CodegenImplMap.java
+++ b/src/main/java/com/jsoniter/output/CodegenImplMap.java
@@ -51,11 +51,6 @@ public static CodegenResult genMap(String cacheKey, ClassInfo classInfo) {
ctx.append("stream.writeMore();");
}
genWriteMapKey(ctx, keyType, noIndention);
- if (noIndention) {
- ctx.append("stream.write(':');");
- } else {
- ctx.append("stream.write((byte)':', (byte)' ');");
- }
if (isCollectionValueNullable) {
ctx.append("if (entry.getValue() == null) { stream.writeNull(); } else {");
CodegenImplNative.genWriteOp(ctx, "entry.getValue()", valueType, true);
diff --git a/src/main/java/com/jsoniter/output/JsonStream.java b/src/main/java/com/jsoniter/output/JsonStream.java
index 88f77077..7886bc05 100644
--- a/src/main/java/com/jsoniter/output/JsonStream.java
+++ b/src/main/java/com/jsoniter/output/JsonStream.java
@@ -442,52 +442,59 @@ public static void serialize(TypeLiteral typeLiteral, Object obj, OutputStream o
}
public static void serialize(Type type, Object obj, OutputStream out) {
- JsonStream stream = JsonStreamPool.borrowJsonStream();
- try {
- try {
- stream.reset(out);
- stream.writeVal(type, obj);
- } finally {
- stream.close();
- }
- } catch (IOException e) {
- throw new JsonException(e);
- } finally {
- JsonStreamPool.returnJsonStream(stream);
- }
+ serialize(type, obj, out, false);
}
public static String serialize(Config config, Object obj) {
- JsoniterSpi.setCurrentConfig(config);
- try {
- return serialize(config.escapeUnicode(), obj.getClass(), obj);
- } finally {
- JsoniterSpi.clearCurrentConfig();
- }
+ return serialize(config, obj.getClass(), obj);
}
public static String serialize(Object obj) {
- return serialize(JsoniterSpi.getCurrentConfig().escapeUnicode(), obj.getClass(), obj);
+ return serialize(obj.getClass(), obj);
}
public static String serialize(Config config, TypeLiteral typeLiteral, Object obj) {
+ return serialize(config, typeLiteral.getType(), obj);
+ }
+
+ private static String serialize(Config config, Type type, Object obj) {
+ final Config configBackup = JsoniterSpi.getCurrentConfig();
+ // Set temporary config
JsoniterSpi.setCurrentConfig(config);
try {
- return serialize(config.escapeUnicode(), typeLiteral.getType(), obj);
+ return serialize(type, obj);
} finally {
- JsoniterSpi.clearCurrentConfig();
+ // Revert old config
+ JsoniterSpi.setCurrentConfig(configBackup);
}
}
public static String serialize(TypeLiteral typeLiteral, Object obj) {
- return serialize(JsoniterSpi.getCurrentConfig().escapeUnicode(), typeLiteral.getType(), obj);
+ return serialize(typeLiteral.getType(), obj);
}
public static String serialize(boolean escapeUnicode, Type type, Object obj) {
- JsonStream stream = JsonStreamPool.borrowJsonStream();
+ final Config currentConfig = JsoniterSpi.getCurrentConfig();
+ return serialize(currentConfig.copyBuilder().escapeUnicode(escapeUnicode).build(), type, obj);
+ }
+
+ private static String serialize(Type type, Object obj) {
+ return serialize(type, obj, null, true);
+ }
+
+ private static String serialize(Type type, Object obj, OutputStream out, boolean returnObjAsString) {
+ final JsonStream stream = JsonStreamPool.borrowJsonStream();
+ final boolean escapeUnicode = JsoniterSpi.getCurrentConfig().escapeUnicode();
try {
- stream.reset(null);
- stream.writeVal(type, obj);
+ try {
+ stream.reset(out);
+ stream.writeVal(type, obj);
+ } finally {
+ stream.close();
+ }
+ if (!returnObjAsString) {
+ return "";
+ }
if (escapeUnicode) {
return new String(stream.buf, 0, stream.count);
} else {
diff --git a/src/main/java/com/jsoniter/output/MapKeyEncoders.java b/src/main/java/com/jsoniter/output/MapKeyEncoders.java
index 443aa291..401ebfbe 100644
--- a/src/main/java/com/jsoniter/output/MapKeyEncoders.java
+++ b/src/main/java/com/jsoniter/output/MapKeyEncoders.java
@@ -29,6 +29,9 @@ private static Encoder createDefaultEncoder(Type mapKeyType) {
if (mapKeyType instanceof WildcardType) {
return new DynamicKeyEncoder();
}
+ if (mapKeyType instanceof Class && ((Class) mapKeyType).isEnum()) {
+ return new StringKeyEncoder();
+ }
Encoder.ReflectionEncoder encoder = CodegenImplNative.NATIVE_ENCODERS.get(mapKeyType);
if (encoder != null) {
return new NumberKeyEncoder(encoder);
diff --git a/src/main/java/com/jsoniter/output/StreamImplNumber.java b/src/main/java/com/jsoniter/output/StreamImplNumber.java
index cf6ef68e..54e039c6 100644
--- a/src/main/java/com/jsoniter/output/StreamImplNumber.java
+++ b/src/main/java/com/jsoniter/output/StreamImplNumber.java
@@ -212,10 +212,18 @@ public static final void writeLong(final JsonStream stream, long value) throws I
public static final void writeFloat(JsonStream stream, float val) throws IOException {
if (val < 0) {
+ if (val == Float.NEGATIVE_INFINITY) {
+ stream.writeVal("-Infinity");
+ return;
+ }
stream.write('-');
val = -val;
}
if (val > 0x4ffffff) {
+ if (val == Float.POSITIVE_INFINITY) {
+ stream.writeVal("Infinity");
+ return;
+ }
stream.writeRaw(Float.toString(val));
return;
}
@@ -240,10 +248,18 @@ public static final void writeFloat(JsonStream stream, float val) throws IOExcep
public static final void writeDouble(JsonStream stream, double val) throws IOException {
if (val < 0) {
+ if (val == Double.NEGATIVE_INFINITY) {
+ stream.writeVal("-Infinity");
+ return;
+ }
val = -val;
stream.write('-');
}
if (val > 0x4ffffff) {
+ if (val == Double.POSITIVE_INFINITY) {
+ stream.writeVal("Infinity");
+ return;
+ }
stream.writeRaw(Double.toString(val));
return;
}
diff --git a/src/main/java/com/jsoniter/output/StreamImplString.java b/src/main/java/com/jsoniter/output/StreamImplString.java
index 7116f359..7c4a27a7 100644
--- a/src/main/java/com/jsoniter/output/StreamImplString.java
+++ b/src/main/java/com/jsoniter/output/StreamImplString.java
@@ -48,7 +48,7 @@ class StreamImplString {
static {
for (int i = 0; i < CAN_DIRECT_WRITE.length; i++) {
- if (i > 31 && i < 126 && i != '"' && i != '\\') {
+ if (i > 31 && i <= 126 && i != '"' && i != '\\') {
CAN_DIRECT_WRITE[i] = true;
}
}
@@ -132,7 +132,7 @@ private static void writeStringSlowPath(JsonStream stream, String val, int i, in
if (escapeUnicode) {
for (; i < valLen; i++) {
int c = val.charAt(i);
- if (c > 125) {
+ if (c > 127) {
writeAsSlashU(stream, c);
} else {
writeAsciiChar(stream, c);
@@ -147,7 +147,7 @@ private static void writeStringSlowPathWithoutEscapeUnicode(JsonStream stream, S
int _surrogate;
for (; i < valLen; i++) {
int c = val.charAt(i);
- if (c > 125) {
+ if (c > 127) {
if (c < 0x800) { // 2-byte
stream.write(
(byte) (0xc0 | (c >> 6)),
diff --git a/src/main/java/com/jsoniter/spi/JsoniterSpi.java b/src/main/java/com/jsoniter/spi/JsoniterSpi.java
index 7f505e1a..4b40e77e 100644
--- a/src/main/java/com/jsoniter/spi/JsoniterSpi.java
+++ b/src/main/java/com/jsoniter/spi/JsoniterSpi.java
@@ -43,6 +43,7 @@ public static void setCurrentConfig(Config val) {
currentConfig.set(val);
}
+ // TODO usage of this method leads to potentially unexpected side effects. All usage should be checked.
public static void clearCurrentConfig() {
currentConfig.set(defaultConfig);
}
diff --git a/src/test/java/com/jsoniter/IterImplForStreamingTest.java b/src/test/java/com/jsoniter/IterImplForStreamingTest.java
index c190d469..e0432d39 100644
--- a/src/test/java/com/jsoniter/IterImplForStreamingTest.java
+++ b/src/test/java/com/jsoniter/IterImplForStreamingTest.java
@@ -1,6 +1,13 @@
package com.jsoniter;
+import com.jsoniter.any.Any;
+import com.jsoniter.spi.JsonException;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
import junit.framework.TestCase;
+import org.junit.experimental.categories.Category;
+import sun.reflect.generics.reflectiveObjects.NotImplementedException;
public class IterImplForStreamingTest extends TestCase {
@@ -11,4 +18,76 @@ public void testReadMaxDouble() throws Exception {
String number = new String(numberChars.chars, 0, numberChars.charsLength);
assertEquals(maxDouble, number);
}
-}
\ No newline at end of file
+
+ @Category(StreamingCategory.class)
+ public void testLoadMore() throws IOException {
+ final String originalContent = "1234567890";
+ final byte[] src = ("{\"a\":\"" + originalContent + "\"}").getBytes();
+
+ int initialBufferSize;
+ Any parsedString;
+ // Case #1: Data fits into initial buffer, autoresizing on
+ // Input must definitely fit into such large buffer
+ initialBufferSize = src.length * 2;
+ JsonIterator jsonIterator = JsonIterator.parse(getSluggishInputStream(src), initialBufferSize, 512);
+ jsonIterator.readObject();
+ parsedString = jsonIterator.readAny();
+ assertEquals(originalContent, parsedString.toString());
+ // Check buffer was not expanded
+ assertEquals(initialBufferSize, jsonIterator.buf.length);
+
+ // Case #2: Data does not fit into initial buffer, autoresizing off
+ initialBufferSize = originalContent.length() / 2;
+ jsonIterator = JsonIterator.parse(getSluggishInputStream(src), initialBufferSize, 0);
+ jsonIterator.readObject();
+ try {
+ jsonIterator.readAny();
+ fail("Expect to fail because buffer is too small.");
+ } catch (JsonException e) {
+ if (!e.getMessage().startsWith("loadMore")) {
+ throw e;
+ }
+ }
+ // Check buffer was not expanded
+ assertEquals(initialBufferSize, jsonIterator.buf.length);
+
+ // Case #3: Data does fit into initial buffer, autoresizing on
+ initialBufferSize = originalContent.length() / 2;
+ int autoExpandBufferStep = initialBufferSize * 3;
+ jsonIterator = JsonIterator.parse(getSluggishInputStream(src), initialBufferSize, autoExpandBufferStep);
+ jsonIterator.readObject();
+ parsedString = jsonIterator.readAny();
+ assertEquals(originalContent, parsedString.toString());
+ // Check buffer was expanded exactly once
+ assertEquals(initialBufferSize + autoExpandBufferStep, jsonIterator.buf.length);
+
+ // Case #4: Data does not fit (but largest string does) into initial buffer, autoresizing on
+ initialBufferSize = originalContent.length() + 2;
+ jsonIterator = JsonIterator.parse(new ByteArrayInputStream(src), initialBufferSize, 0);
+ jsonIterator.readObject();
+ parsedString = jsonIterator.readAny();
+ assertEquals(originalContent, parsedString.toString());
+ // Check buffer was expanded exactly once
+ assertEquals(initialBufferSize, jsonIterator.buf.length);
+ }
+
+ private static InputStream getSluggishInputStream(final byte[] src) {
+ return new InputStream() {
+ int position = 0;
+
+ @Override
+ public int read() throws IOException {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ if (position < src.length) {
+ b[off] = src[position++];
+ return 1;
+ }
+ return -1;
+ }
+ };
+ }
+}
diff --git a/src/test/java/com/jsoniter/TestFloat.java b/src/test/java/com/jsoniter/TestFloat.java
index b1e9d82c..5fc0f851 100644
--- a/src/test/java/com/jsoniter/TestFloat.java
+++ b/src/test/java/com/jsoniter/TestFloat.java
@@ -1,6 +1,5 @@
package com.jsoniter;
-import com.fasterxml.jackson.databind.ObjectMapper;
import junit.framework.TestCase;
import org.junit.experimental.categories.Category;
@@ -90,4 +89,12 @@ public void testChooseDouble() {
number = JsonIterator.deserialize("1.0", Object.class);
assertEquals(1.0, number);
}
+
+ public void testInfinity() {
+ assertTrue(JsonIterator.deserialize("\"-infinity\"", Double.class) == Double.NEGATIVE_INFINITY);
+ assertTrue(JsonIterator.deserialize("\"-infinity\"", Float.class) == Float.NEGATIVE_INFINITY);
+ assertTrue(JsonIterator.deserialize("\"infinity\"", Double.class) == Double.POSITIVE_INFINITY);
+ assertTrue(JsonIterator.deserialize("\"infinity\"", Float.class) == Float.POSITIVE_INFINITY);
+ }
+
}
diff --git a/src/test/java/com/jsoniter/TestMap.java b/src/test/java/com/jsoniter/TestMap.java
index f9becb56..487b646d 100644
--- a/src/test/java/com/jsoniter/TestMap.java
+++ b/src/test/java/com/jsoniter/TestMap.java
@@ -41,6 +41,18 @@ public void test_integer_key() throws IOException {
}}, map);
}
+ public static enum EnumKey {
+ KeyA, KeyB
+ }
+
+ public void test_enum_key() {
+ Map map = JsonIterator.deserialize("{\"KeyA\":null}", new TypeLiteral