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();