Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   package com.fasterxml.jackson.databind.util;
   
   import java.io.*;
   import java.math.BigDecimal;
   import java.math.BigInteger;
   import java.util.TreeMap;
   
Utility class used for efficient storage of com.fasterxml.jackson.core.JsonToken sequences, needed for temporary buffering. Space efficient for different sequence lengths (especially so for smaller ones; but not significantly less efficient for larger), highly efficient for linear iteration and appending. Implemented as segmented/chunked linked list of tokens; only modifications are via appends.

Note that before version 2.0, this class was located in the "core" bundle, not data-binding; but since it was only used by data binding, was moved here to reduce size of core package

  
  public class TokenBuffer
  /* Won't use JsonGeneratorBase, to minimize overhead for validity
   * checking
   */
      extends JsonGenerator
  {
      protected final static int DEFAULT_GENERATOR_FEATURES = JsonGenerator.Feature.collectDefaults();
  
      /*
      /**********************************************************
      /* Configuration
      /**********************************************************
       */

    
Object codec to use for stream-based object conversion through parser/generator interfaces. If null, such methods can not be used.
  
      protected ObjectCodec _objectCodec;

    
Bit flag composed of bits that indicate which com.fasterxml.jackson.core.JsonGenerator.Features are enabled.

NOTE: most features have no effect on this class

  
      protected int _generatorFeatures;
  
      protected boolean _closed;

    

Since:
2.3
  
      protected boolean _hasNativeTypeIds;

    

Since:
2.3
  
      protected boolean _hasNativeObjectIds;

    

Since:
2.3
  
      protected boolean _mayHaveNativeIds;
      
      /*
      /**********************************************************
      /* Token buffering state
      /**********************************************************
       */

    
First segment, for contents this buffer has
  
      protected Segment _first;

    
Last segment of this buffer, one that is used for appending more tokens
  
      protected Segment _last;
    
    
Offset within last segment,
  
      protected int _appendOffset;

    
If native type ids supported, this is the id for following value (or first token of one) to be written.
  
     protected Object _typeId;

    
If native object ids supported, this is the id for following value (or first token of one) to be written.
 
     protected Object _objectId;

    
Do we currnetly have a native type or object id buffered?
 
     protected boolean _hasNativeId = false;
 
     /*
     /**********************************************************
     /* Output state
     /**********************************************************
      */
 
     protected JsonWriteContext _writeContext;
 
     /*
     /**********************************************************
     /* Life-cycle
     /**********************************************************
      */

    

Deprecated:
since 2.3 preferred variant is one that takes com.fasterxml.jackson.core.JsonParser or additional boolean parameter.
Parameters:
codec Object codec to use for stream-based object conversion through parser/generator interfaces. If null, such methods can not be used.
 
     @Deprecated
     public TokenBuffer(ObjectCodec codec) {
         this(codecfalse);
     }

    

Parameters:
codec Object codec to use for stream-based object conversion through parser/generator interfaces. If null, such methods can not be used.
hasNativeIds Whether resulting com.fasterxml.jackson.core.JsonParser (if created) is considered to support native type and object ids
 
     public TokenBuffer(ObjectCodec codecboolean hasNativeIds)
     {
          = codec;
          = JsonWriteContext.createRootContext(null);
         // at first we have just one segment
          =  = new Segment();
          = 0;
          = hasNativeIds;
          = hasNativeIds;
 
     }

    

Since:
2.3
 
     public TokenBuffer(JsonParser jp)
     {
          = jp.getCodec();
          = JsonWriteContext.createRootContext(null);
         // at first we have just one segment
          =  = new Segment();
          = 0;
          = jp.canReadTypeId();
          = jp.canReadObjectId();
     }
     
     @Override
     public Version version() {
     }

    
Method used to create a com.fasterxml.jackson.core.JsonParser that can read contents stored in this buffer. Will use default _objectCodec for object conversions.

Note: instances are not synchronized, that is, they are not thread-safe if there are concurrent appends to the underlying buffer.

Returns:
Parser that can be used for reading contents stored in this buffer
 
     public JsonParser asParser()
     {
         return asParser();
     }

    
Method used to create a com.fasterxml.jackson.core.JsonParser that can read contents stored in this buffer.

Note: instances are not synchronized, that is, they are not thread-safe if there are concurrent appends to the underlying buffer.

Parameters:
codec Object codec to use for stream-based object conversion through parser/generator interfaces. If null, such methods can not be used.
Returns:
Parser that can be used for reading contents stored in this buffer
 
     public JsonParser asParser(ObjectCodec codec)
     {
         return new Parser(codec);
     }

    

Parameters:
src Parser to use for accessing source information like location, configured codec
 
     public JsonParser asParser(JsonParser src)
     {
         Parser p = new Parser(src.getCodec(), );
         p.setLocation(src.getTokenLocation());
         return p;
     }
     
     /*
     /**********************************************************
     /* Additional accessors
     /**********************************************************
      */
 
     public JsonToken firstToken() {
         if ( != null) {
             return .type(0);
         }
         return null;
     }
     
     /*
     /**********************************************************
     /* Other custom methods not needed for implementing interfaces
     /**********************************************************
      */

    
Helper method that will append contents of given buffer into this buffer. Not particularly optimized; can be made faster if there is need.

Returns:
This buffer
 
     @SuppressWarnings("resource")
     public TokenBuffer append(TokenBuffer other)
         throws IOExceptionJsonGenerationException
     {
         // Important? If source has native ids, need to store
         if (!) {  
              = other.canWriteTypeId();
         }
         if (!) {
              = other.canWriteObjectId();
         }
         
         JsonParser jp = other.asParser();
         while (jp.nextToken() != null) {
             copyCurrentStructure(jp);
         }
         return this;
     }
    
    
Helper method that will write all contents of this buffer using given com.fasterxml.jackson.core.JsonGenerator.

Note: this method would be enough to implement JsonSerializer for TokenBuffer type; but we can not have upwards references (from core to mapper package); and as such we also can not take second argument.

 
     public void serialize(JsonGenerator jgen)
         throws IOExceptionJsonGenerationException
     {
         Segment segment = ;
         int ptr = -1;
 
         final boolean checkIds = ;
         boolean hasIds = checkIds && (segment.hasIds());
 
         while (true) {
             if (++ptr >= .) {
                 ptr = 0;
                 segment = segment.next();
                 if (segment == nullbreak;
                 hasIds = checkIds && (segment.hasIds());
             }
             JsonToken t = segment.type(ptr);
             if (t == nullbreak;
 
             if (hasIds) {
                 Object id = segment.findObjectId(ptr);
                 if (id != null) {
                     jgen.writeObjectId(id);
                 }
                 id = segment.findTypeId(ptr);
                 if (id != null) {
                     jgen.writeTypeId(id);
                 }
             }
             
             // Note: copied from 'copyCurrentEvent'...
             switch (t) {
             case :
                 jgen.writeStartObject();
                 break;
             case :
                 jgen.writeEndObject();
                 break;
             case :
                 jgen.writeStartArray();
                 break;
             case :
                 jgen.writeEndArray();
                 break;
             case :
             {
                 // 13-Dec-2010, tatu: Maybe we should start using different type tokens to reduce casting?
                 Object ob = segment.get(ptr);
                 if (ob instanceof SerializableString) {
                     jgen.writeFieldName((SerializableStringob);
                 } else {
                     jgen.writeFieldName((Stringob);
                 }
             }
                 break;
             case :
                 {
                     Object ob = segment.get(ptr);
                     if (ob instanceof SerializableString) {
                         jgen.writeString((SerializableStringob);
                     } else {
                         jgen.writeString((Stringob);
                     }
                 }
                 break;
             case :
                 {
                     Object n = segment.get(ptr);
                     if (n instanceof Integer) {
                         jgen.writeNumber((Integern);
                     } else if (n instanceof BigInteger) {
                         jgen.writeNumber((BigIntegern);
                     } else if (n instanceof Long) {
                         jgen.writeNumber((Longn);
                     } else if (n instanceof Short) {
                         jgen.writeNumber((Shortn);
                     } else {
                         jgen.writeNumber(((Numbern).intValue());
                     }
                 }
                 break;
             case :
                 {
                     Object n = segment.get(ptr);
                     if (n instanceof Double) {
                         jgen.writeNumber(((Doublen).doubleValue());
                     } else if (n instanceof BigDecimal) {
                         jgen.writeNumber((BigDecimaln);
                     } else if (n instanceof Float) {
                         jgen.writeNumber(((Floatn).floatValue());
                     } else if (n == null) {
                         jgen.writeNull();
                     } else if (n instanceof String) {
                         jgen.writeNumber((Stringn);
                     } else {
                         throw new JsonGenerationException("Unrecognized value type for VALUE_NUMBER_FLOAT: "+n.getClass().getName()+", can not serialize");
                     }
                 }
                 break;
             case :
                 jgen.writeBoolean(true);
                 break;
             case :
                 jgen.writeBoolean(false);
                 break;
             case :
                 jgen.writeNull();
                 break;
             case :
                 jgen.writeObject(segment.get(ptr));
                 break;
             default:
                 throw new RuntimeException("Internal error: should never end up through this code path");
             }
         }
     }

    
Helper method used by standard deserializer.

Since:
2.3
 
         throws IOExceptionJsonProcessingException
     {
         copyCurrentStructure(jp);
         return this;
     }
     
     @Override
     @SuppressWarnings("resource")
     public String toString()
     {
         // Let's print up to 100 first tokens...
         final int MAX_COUNT = 100;
 
         StringBuilder sb = new StringBuilder();
         sb.append("[TokenBuffer: ");
 
         /*
 sb.append("NativeTypeIds=").append(_hasNativeTypeIds).append(",");
 sb.append("NativeObjectIds=").append(_hasNativeObjectIds).append(",");
 */
         
         JsonParser jp = asParser();
         int count = 0;
         final boolean hasNativeIds =  || ;
 
         while (true) {
             JsonToken t;
             try {
                 t = jp.nextToken();
                 if (t == nullbreak;
 
                 if (hasNativeIds) {
                     _appendNativeIds(sb);
                 }
                         
                 if (count < MAX_COUNT) {
                     if (count > 0) {
                         sb.append(", ");
                     }
                     sb.append(t.toString());
                     if (t == .) {
                         sb.append('(');
                         sb.append(jp.getCurrentName());
                         sb.append(')');
                     }
                 }
             } catch (IOException ioe) { // should never occur
                 throw new IllegalStateException(ioe);
             }
             ++count;
         }
 
         if (count >= MAX_COUNT) {
             sb.append(" ... (truncated ").append(count-MAX_COUNT).append(" entries)");
         }
         sb.append(']');
         return sb.toString();
     }
 
     private final void _appendNativeIds(StringBuilder sb)
     {
         Object objectId = .findObjectId(-1);
         if (objectId != null) {
             sb.append("[objectId=").append(String.valueOf(objectId)).append(']');
         }
         Object typeId = .findTypeId(-1);
         if (typeId != null) {
             sb.append("[typeId=").append(String.valueOf(typeId)).append(']');
         }
     }
     
     /*
     /**********************************************************
     /* JsonGenerator implementation: configuration
     /**********************************************************
      */
 
     @Override
     public JsonGenerator enable(Feature f) {
          |= f.getMask();
         return this;
     }
 
     @Override
     public JsonGenerator disable(Feature f) {
          &= ~f.getMask();
         return this;
     }
 
     //public JsonGenerator configure(SerializationFeature f, boolean state) { }
 
     @Override
     public boolean isEnabled(Feature f) {
         return ( & f.getMask()) != 0;
     }
 
     @Override
     public int getFeatureMask() {
         return ;
     }
 
     @Override
     public JsonGenerator setFeatureMask(int mask) {
          = mask;
         return this;
     }
     
     @Override
         // No-op: we don't indent
         return this;
     }
 
     @Override
     public JsonGenerator setCodec(ObjectCodec oc) {
          = oc;
         return this;
     }
 
     @Override
     public ObjectCodec getCodec() { return ; }
 
     @Override
     public final JsonWriteContext getOutputContext() { return ; }
 
     /*
     /**********************************************************
     /* JsonGenerator implementation: capability introspection
     /**********************************************************
      */
    
    
Since we can efficiently store byte[], yes.
 
     @Override
     public boolean canWriteBinaryNatively() {
         return true;
     }
     
     /*
     /**********************************************************
     /* JsonGenerator implementation: low-level output handling
     /**********************************************************
      */
 
     @Override
     public void flush() throws IOException { /* NOP */ }
 
     @Override
     public void close() throws IOException {
          = true;
     }
 
     @Override
     public boolean isClosed() { return ; }
 
     /*
     /**********************************************************
     /* JsonGenerator implementation: write methods, structural
     /**********************************************************
      */
 
     @Override
     public final void writeStartArray()
         throws IOExceptionJsonGenerationException
     {
         _append(.);
     }
 
     @Override
     public final void writeEndArray()
         throws IOExceptionJsonGenerationException
     {
         _append(.);
         // Let's allow unbalanced tho... i.e. not run out of root level, ever
         JsonWriteContext c = .getParent();
         if (c != null) {
              = c;
         }
     }
 
     @Override
     public final void writeStartObject()
         throws IOExceptionJsonGenerationException
     {
         _append(.);
     }
 
     @Override
     public final void writeEndObject()
         throws IOExceptionJsonGenerationException
     {
         _append(.);
         // Let's allow unbalanced tho... i.e. not run out of root level, ever
         JsonWriteContext c = .getParent();
         if (c != null) {
              = c;
         }
     }
 
     @Override
     public final void writeFieldName(String name)
         throws IOExceptionJsonGenerationException
     {
         _append(.name);
         .writeFieldName(name);
     }
 
     @Override
     public void writeFieldName(SerializableString name)
         throws IOExceptionJsonGenerationException
     {
         _append(.name);
         .writeFieldName(name.getValue());
     }
     
     /*
     /**********************************************************
     /* JsonGenerator implementation: write methods, textual
     /**********************************************************
      */
 
     @Override
     public void writeString(String textthrows IOException,JsonGenerationException {
         if (text == null) {
             writeNull();
         } else {
             _append(.text);
         }
     }
 
     @Override
     public void writeString(char[] textint offsetint lenthrows IOExceptionJsonGenerationException {
         writeString(new String(textoffsetlen));
     }
 
     @Override
     public void writeString(SerializableString textthrows IOExceptionJsonGenerationException {
         if (text == null) {
             writeNull();
         } else {
             _append(.text);
         }
     }
     
     @Override
     public void writeRawUTF8String(byte[] textint offsetint length)
         throws IOExceptionJsonGenerationException
     {
         // could add support for buffering if we really want it...
         _reportUnsupportedOperation();
     }
 
     @Override
     public void writeUTF8String(byte[] textint offsetint length)
         throws IOExceptionJsonGenerationException
     {
         // could add support for buffering if we really want it...
         _reportUnsupportedOperation();
     }
 
     @Override
     public void writeRaw(String textthrows IOExceptionJsonGenerationException {
         _reportUnsupportedOperation();
     }
 
     @Override
     public void writeRaw(String textint offsetint lenthrows IOExceptionJsonGenerationException {
         _reportUnsupportedOperation();
     }
 
     @Override
     public void writeRaw(SerializableString textthrows IOExceptionJsonGenerationException {
         _reportUnsupportedOperation();
     }
     
     @Override
     public void writeRaw(char[] textint offsetint lenthrows IOExceptionJsonGenerationException {
         _reportUnsupportedOperation();
     }
 
     @Override
     public void writeRaw(char cthrows IOExceptionJsonGenerationException {
         _reportUnsupportedOperation();
     }
 
     @Override
     public void writeRawValue(String textthrows IOExceptionJsonGenerationException {
         _reportUnsupportedOperation();
     }
 
     @Override
     public void writeRawValue(String textint offsetint lenthrows IOExceptionJsonGenerationException {
         _reportUnsupportedOperation();
     }
 
     @Override
     public void writeRawValue(char[] textint offsetint lenthrows IOExceptionJsonGenerationException {
         _reportUnsupportedOperation();
     }
 
     /*
     /**********************************************************
     /* JsonGenerator implementation: write methods, primitive types
     /**********************************************************
      */
 
     @Override
     public void writeNumber(short ithrows IOExceptionJsonGenerationException {
         _append(., Short.valueOf(i));
     }
 
     @Override
     public void writeNumber(int ithrows IOExceptionJsonGenerationException {
         _append(., Integer.valueOf(i));
     }
 
     @Override
     public void writeNumber(long lthrows IOExceptionJsonGenerationException {
         _append(., Long.valueOf(l));
     }
 
     @Override
     public void writeNumber(double dthrows IOException,JsonGenerationException {
         _append(., Double.valueOf(d));
     }
 
     @Override
     public void writeNumber(float fthrows IOExceptionJsonGenerationException {
         _append(., Float.valueOf(f));
     }
 
     @Override
     public void writeNumber(BigDecimal decthrows IOException,JsonGenerationException {
         if (dec == null) {
             writeNull();
         } else {
             _append(.dec);
         }
     }
 
     @Override
     public void writeNumber(BigInteger vthrows IOExceptionJsonGenerationException {
         if (v == null) {
             writeNull();
         } else {
             _append(.v);
         }
     }
 
     @Override
     public void writeNumber(String encodedValuethrows IOExceptionJsonGenerationException {
         /* 03-Dec-2010, tatu: related to [JACKSON-423], should try to keep as numeric
          *   identity as long as possible
          */
         _append(.encodedValue);
     }
 
     @Override
     public void writeBoolean(boolean statethrows IOException,JsonGenerationException {
         _append(state ? . : .);
     }
 
     @Override
     public void writeNull() throws IOExceptionJsonGenerationException {
         _append(.);
     }
 
     /*
     /***********************************************************
     /* JsonGenerator implementation: write methods for POJOs/trees
     /***********************************************************
      */
 
     @Override
     public void writeObject(Object value)
         throws IOExceptionJsonProcessingException
     {
         // embedded means that no conversions should be done...
         _append(.value);
     }
 
     @Override
     public void writeTree(TreeNode rootNode)
         throws IOExceptionJsonProcessingException
     {
         /* 31-Dec-2009, tatu: no need to convert trees either is there?
          *  (note: may need to re-evaluate at some point)
          */
         _append(.rootNode);
     }
 
     /*
     /***********************************************************
     /* JsonGenerator implementation; binary
     /***********************************************************
      */
 
     @Override
     public void writeBinary(Base64Variant b64variantbyte[] dataint offsetint len)
         throws IOExceptionJsonGenerationException
     {
         /* 31-Dec-2009, tatu: can do this using multiple alternatives; but for
          *   now, let's try to limit number of conversions.
          *   The only (?) tricky thing is that of whether to preserve variant,
          *   seems pointless, so let's not worry about it unless there's some
          *   compelling reason to.
          */
         byte[] copy = new byte[len];
         System.arraycopy(dataoffsetcopy, 0, len);
         writeObject(copy);
     }

    
Although we could support this method, it does not necessarily make sense: we can not make good use of streaming because buffer must hold all the data. Because of this, currently this will simply throw java.lang.UnsupportedOperationException
 
     @Override
     public int writeBinary(Base64Variant b64variantInputStream dataint dataLength) {
         throw new UnsupportedOperationException();
     }
 
     /*
     /***********************************************************
     /* JsonGenerator implementation: native ids
     /***********************************************************
      */
 
     @Override
     public boolean canWriteTypeId() {
         return ;
     }
 
     @Override
     public boolean canWriteObjectId() {
         return ;
     }
     
     @Override
     public void writeTypeId(Object id) {
          = id;
          = true;
     }
     
     @Override
     public void writeObjectId(Object id) {
          = id;
          = true;
     }
 
     /*
     /**********************************************************
     /* JsonGenerator implementation; pass-through copy
     /**********************************************************
      */
 
     @Override
     public void copyCurrentEvent(JsonParser jpthrows IOExceptionJsonProcessingException
     {
         if () {
             _checkNativeIds(jp);
         }
         switch (jp.getCurrentToken()) {
         case :
             writeStartObject();
             break;
         case :
             writeEndObject();
             break;
         case :
             writeStartArray();
             break;
         case :
             writeEndArray();
             break;
         case :
             writeFieldName(jp.getCurrentName());
             break;
         case :
             if (jp.hasTextCharacters()) {
                 writeString(jp.getTextCharacters(), jp.getTextOffset(), jp.getTextLength());
             } else {
                 writeString(jp.getText());
             }
             break;
         case :
             switch (jp.getNumberType()) {
             case :
                 writeNumber(jp.getIntValue());
                 break;
             case :
                 writeNumber(jp.getBigIntegerValue());
                 break;
             default:
                 writeNumber(jp.getLongValue());
             }
             break;
         case :
             switch (jp.getNumberType()) {
             case :
                 writeNumber(jp.getDecimalValue());
                 break;
             case :
                 writeNumber(jp.getFloatValue());
                 break;
             default:
                 writeNumber(jp.getDoubleValue());
             }
             break;
         case :
             writeBoolean(true);
             break;
         case :
             writeBoolean(false);
             break;
         case :
             writeNull();
             break;
         case :
             writeObject(jp.getEmbeddedObject());
             break;
         default:
             throw new RuntimeException("Internal error: should never end up through this code path");
         }
     }
     
     @Override
     {
         JsonToken t = jp.getCurrentToken();
 
         // Let's handle field-name separately first
         if (t == .) {
             if () {
                 _checkNativeIds(jp);
             }
             writeFieldName(jp.getCurrentName());
             t = jp.nextToken();
             // fall-through to copy the associated value
         }
 
         if () {
             _checkNativeIds(jp);
         }
         
         switch (t) {
         case :
             writeStartArray();
             while (jp.nextToken() != .) {
                 copyCurrentStructure(jp);
             }
             writeEndArray();
             break;
         case :
             writeStartObject();
             while (jp.nextToken() != .) {
                 copyCurrentStructure(jp);
             }
             writeEndObject();
             break;
         default// others are simple:
             copyCurrentEvent(jp);
         }
     }
 
     
     private final void _checkNativeIds(JsonParser jpthrows IOExceptionJsonProcessingException
     {
         if (( = jp.getTypeId()) != null) {
              = true;
         }
         if (( = jp.getObjectId()) != null) {
              = true;
         }
     }
     
     /*
     /**********************************************************
     /* Internal methods
     /**********************************************************
      */
 
     protected final void _append(JsonToken type)
     {
         Segment next = 
                 ? .append(type)
                 : .append(type);
         if (next == null) {
             ++;
         } else {
              = next;
              = 1; // since we added first at 0
        }
    }
    protected final void _append(JsonToken typeObject value)
    {
        Segment next = 
                ? .append(typevalue)
                : .append(typevalue);
        if (next == null) {
            ++;
        } else {
             = next;
             = 1;
        }
    }
    protected final void _appendRaw(int rawTypeObject value)
    {
        Segment next = 
                ? .appendRaw(rawTypevalue)
                : .appendRaw(rawTypevalue);
        if (next == null) {
            ++;
        } else {
             = next;
             = 1;
        }
    }
    protected void _reportUnsupportedOperation() {
        throw new UnsupportedOperationException("Called operation not supported for TokenBuffer");
    }
    
    /*
    /**********************************************************
    /* Supporting classes
    /**********************************************************
     */
    protected final static class Parser
        extends ParserMinimalBase
    {
        /*
        /**********************************************************
        /* Configuration
        /**********************************************************
         */
        protected ObjectCodec _codec;

        

Since:
2.3
        protected final boolean _hasNativeTypeIds;

        

Since:
2.3
        protected final boolean _hasNativeObjectIds;
        protected final boolean _hasNativeIds;
        
        /*
        /**********************************************************
        /* Parsing state
        /**********************************************************
         */

        
Currently active segment
        protected Segment _segment;

        
Pointer to current token within current segment
        protected int _segmentPtr;

        
Information about parser context, context in which the next token is to be parsed (root, array, object).
        protected JsonReadContext _parsingContext;
        
        protected boolean _closed;
        protected transient ByteArrayBuilder _byteBuilder;
        protected JsonLocation _location = null;
        
        /*
        /**********************************************************
        /* Construction, init
        /**********************************************************
         */
        @Deprecated // since 2.3
        protected Parser(Segment firstSegObjectCodec codec) {
            this(firstSegcodecfalsefalse);
        }

        

Since:
2.3
        public Parser(Segment firstSegObjectCodec codec,
                boolean hasNativeTypeIds,
                boolean hasNativeObjectIds)
        {
            super(0);
             = firstSeg;
             = -1; // not yet read
             = codec;
             = JsonReadContext.createRootContext(null);
             = hasNativeTypeIds;
             = hasNativeObjectIds;
             = (hasNativeTypeIds | hasNativeObjectIds);
        }
        public void setLocation(JsonLocation l) {
             = l;
        }
        
        @Override
        public ObjectCodec getCodec() { return ; }
        @Override
        public void setCodec(ObjectCodec c) {  = c; }
        @Override
        public Version version() {
            return ......;
        }
        /*
        /**********************************************************
        /* Extended API beyond JsonParser
        /**********************************************************
         */
        
        public JsonToken peekNextToken()
            throws IOExceptionJsonParseException
        {
            // closed? nothing more to peek, either
            if (return null;
            Segment seg = ;
            int ptr = +1;
            if (ptr >= .) {
                ptr = 0;
                seg = (seg == null) ? null : seg.next();
            }
            return (seg == null) ? null : seg.type(ptr);
        }
        
        /*
        /**********************************************************
        /* Closeable implementation
        /**********************************************************
         */
        @Override
        public void close() throws IOException {
            if (!) {
                 = true;
            }
        }
        /*
        /**********************************************************
        /* Public API, traversal
        /**********************************************************
         */
        
        @Override
        public JsonToken nextToken() throws IOExceptionJsonParseException
        {
            // If we are closed, nothing more to do
            if ( || ( == null)) return null;
            // Ok, then: any more tokens?
            if (++ >= .) {
                 = 0;
                 = .next();
                if ( == null) {
                    return null;
                }
            }