Fix to last known bug with Smile (turned out to be wrong offset when skipping double values)
diff --git a/src/java/org/codehaus/jackson/impl/JsonWriteContext.java b/src/java/org/codehaus/jackson/impl/JsonWriteContext.java
index 5b3d330..61e42c5 100644
--- a/src/java/org/codehaus/jackson/impl/JsonWriteContext.java
+++ b/src/java/org/codehaus/jackson/impl/JsonWriteContext.java
@@ -29,9 +29,9 @@
/**********************************************************
*/
- JsonWriteContext _childArray = null;
+ protected JsonWriteContext _childArray = null;
- JsonWriteContext _childObject = null;
+ protected JsonWriteContext _childObject = null;
/*
/**********************************************************
diff --git a/src/perf/TestJsonPerf.java b/src/perf/TestJsonPerf.java
index dfe49ee..2d951bb 100644
--- a/src/perf/TestJsonPerf.java
+++ b/src/perf/TestJsonPerf.java
@@ -169,6 +169,7 @@
jp.close();
jg.close();
byte[] smileBytes = out.toByteArray();
+ System.out.println("Written as "+smileBytes.length+" Smile bytes from "+json.length+" JSON bytes; will verify correctness");
// One more thing: let's actually verify correctness!
JsonParser sp = _smileFactory.createJsonParser(new ByteArrayInputStream(smileBytes));
diff --git a/src/smile/java/org/codehaus/jackson/smile/SmileGenerator.java b/src/smile/java/org/codehaus/jackson/smile/SmileGenerator.java
index 5f42aff..ddeebcb 100644
--- a/src/smile/java/org/codehaus/jackson/smile/SmileGenerator.java
+++ b/src/smile/java/org/codehaus/jackson/smile/SmileGenerator.java
@@ -205,6 +205,14 @@
*/
protected final int _outputEnd;
+ /**
+ * Let's keep track of how many bytes have been output, may prove useful
+ * when debugging. This does <b>not</b> include bytes buffered in
+ * the output buffer, just bytes that have been written using underlying
+ * stream writer.
+ */
+ protected int _bytesWritten;
+
/*
/**********************************************************
/* Shared String detection
@@ -1425,6 +1433,7 @@
protected final void _flushBuffer() throws IOException
{
if (_outputTail > 0) {
+ _bytesWritten += _outputTail;
_out.write(_outputBuffer, 0, _outputTail);
_outputTail = 0;
}
@@ -1493,6 +1502,14 @@
/* Internal methods, error reporting
/**********************************************************
*/
+
+ /**
+ * Method for accessing offset of the next byte within the whole output
+ * stream that this generator has produced.
+ */
+ protected long outputOffset() {
+ return _bytesWritten + _outputTail;
+ }
protected UnsupportedOperationException _notSupported() {
return new UnsupportedOperationException();
diff --git a/src/smile/java/org/codehaus/jackson/smile/SmileParser.java b/src/smile/java/org/codehaus/jackson/smile/SmileParser.java
index b844aec..fc2ad46 100644
--- a/src/smile/java/org/codehaus/jackson/smile/SmileParser.java
+++ b/src/smile/java/org/codehaus/jackson/smile/SmileParser.java
@@ -258,7 +258,7 @@
if (_parsingContext.inObject() && _currToken != JsonToken.FIELD_NAME) {
return (_currToken = _handleFieldName());
}
-
+
switch ((ch >> 5) & 0x7) {
case 0: // short shared string value reference
case 1: // misc literals
@@ -333,10 +333,10 @@
{
int subtype = typeBits & 0x3;
if (subtype <= 0x2) { // 0x3 reserved (should never occur)
- _tokenIncomplete = true;
- _numTypesValid = 0;
- _got32BitFloat = (subtype == 0);
- return (_currToken = JsonToken.VALUE_NUMBER_FLOAT);
+ _tokenIncomplete = true;
+ _numTypesValid = 0;
+ _got32BitFloat = (subtype == 0);
+ return (_currToken = JsonToken.VALUE_NUMBER_FLOAT);
}
}
break;
@@ -581,7 +581,7 @@
}
_sharedNames[_sharedNameCount++] = name;
}
- _parsingContext.setCurrentName(name);
+ _parsingContext.setCurrentName(name);
}
return JsonToken.FIELD_NAME;
case 3: // short Unicode
@@ -993,16 +993,16 @@
private final void _finishDouble()
throws IOException, JsonParseException
{
- // ok; let's take two sets of 4 bytes (each is int)
+ // ok; let's take two sets of 4 bytes (each is int)
long hi = _fourBytesToInt();
long value = (hi << 28) + (long) _fourBytesToInt();
// and then remaining 2 bytes
if (_inputPtr >= _inputEnd) {
- loadMoreGuaranteed();
+ loadMoreGuaranteed();
}
value = (value << 7) + _inputBuffer[_inputPtr++];
if (_inputPtr >= _inputEnd) {
- loadMoreGuaranteed();
+ loadMoreGuaranteed();
}
value = (value << 7) + _inputBuffer[_inputPtr++];
_numberDouble = Double.longBitsToDouble(value);
@@ -1389,7 +1389,7 @@
_skipBytes(5);
return;
case 1: // double
- _skipBytes(11);
+ _skipBytes(10);
return;
case 2: // big-decimal
// first, skip scale
diff --git a/src/test/org/codehaus/jackson/smile/TestSmileGeneratorNumbers.java b/src/test/org/codehaus/jackson/smile/TestSmileGeneratorNumbers.java
index e0bdbbf..ccf9094 100644
--- a/src/test/org/codehaus/jackson/smile/TestSmileGeneratorNumbers.java
+++ b/src/test/org/codehaus/jackson/smile/TestSmileGeneratorNumbers.java
@@ -104,5 +104,25 @@
gen.close();
assertEquals(11, out.toByteArray().length);
}
-
+
+ public void testFloats() throws Exception
+ {
+ // float length is fixed, 6 bytes
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ SmileGenerator gen = _generator(out, false);
+ gen.writeNumber(0.125f);
+ gen.close();
+ assertEquals(6, out.toByteArray().length);
+ }
+
+ public void testDoubles() throws Exception
+ {
+ // double length is fixed, 11 bytes
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ SmileGenerator gen = _generator(out, false);
+ gen.writeNumber(0.125);
+ gen.close();
+ assertEquals(11, out.toByteArray().length);
+ }
+
}
diff --git a/src/test/org/codehaus/jackson/smile/TestSmileParserNumbers.java b/src/test/org/codehaus/jackson/smile/TestSmileParserNumbers.java
index a31ad60..81ba537 100644
--- a/src/test/org/codehaus/jackson/smile/TestSmileParserNumbers.java
+++ b/src/test/org/codehaus/jackson/smile/TestSmileParserNumbers.java
@@ -200,6 +200,43 @@
assertToken(JsonToken.END_ARRAY, p.nextToken());
}
+ public void testObjectWithDoubles() throws IOException
+ {
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ SmileGenerator g = _generator(bo, false);
+ g.writeStartObject();
+ g.writeNumberField("x", 0.5);
+ g.writeNumberField("y", 0.01338);
+ g.writeEndObject();
+ g.close();
+
+ byte[] data = bo.toByteArray();
+
+ // first let's just skip
+ SmileParser p = _parser(data);
+ assertToken(JsonToken.START_OBJECT, p.nextToken());
+ assertToken(JsonToken.FIELD_NAME, p.nextToken());
+ assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
+ assertToken(JsonToken.FIELD_NAME, p.nextToken());
+ assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
+ assertToken(JsonToken.END_OBJECT, p.nextToken());
+ p.close();
+
+ // and then check data too (skip codepath distinct)
+ p = _parser(data);
+ assertToken(JsonToken.START_OBJECT, p.nextToken());
+ assertToken(JsonToken.FIELD_NAME, p.nextToken());
+ assertEquals("x", p.getText());
+ assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
+ assertEquals(0.5, p.getDoubleValue());
+ assertToken(JsonToken.FIELD_NAME, p.nextToken());
+ assertEquals("y", p.getText());
+ assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
+ assertEquals(0.01338, p.getDoubleValue());
+ assertToken(JsonToken.END_OBJECT, p.nextToken());
+ p.close();
+ }
+
public void testBigInteger() throws IOException
{
ByteArrayOutputStream bo = new ByteArrayOutputStream();