/**
   * Creates a new FSTObjectOutput stream to write data to the specified underlying output stream.
   * The counter <code>written</code> is set to zero. Don't create a FSTConfiguration with each
   * stream, just create one global static configuration and reuse it. FSTConfiguration is
   * threadsafe.
   *
   * @param out the underlying output stream, to be saved for later use.
   */
  public FSTObjectOutput(OutputStream out, FSTConfiguration conf) {
    this.conf = conf;
    codec = conf.createStreamEncoder();
    codec.setOutstream(out);

    objects = (FSTObjectRegistry) conf.getCachedObject(FSTObjectRegistry.class);
    if (objects == null) {
      objects = new FSTObjectRegistry(conf);
      objects.disabled = !conf.isShareReferences();
    } else {
      objects.clearForWrite();
    }
  }
 @Override
 public void close() throws IOException {
   flush();
   closed = true;
   codec.close();
   resetAndClearRefs();
   conf.returnObject(objects);
 }
 public void writeObject(Object obj, Class... possibles) throws IOException {
   curDepth++;
   if (conf.isCrossPlatform()) {
     writeObjectInternal(obj, null); // not supported cross platform
   }
   if (possibles != null && possibles.length > 1) {
     for (int i = 0; i < possibles.length; i++) {
       Class possible = possibles[i];
       codec.registerClass(possible);
     }
   }
   writeObjectInternal(obj, possibles);
 }
 // incoming array is already registered
 protected void writeArray(FSTClazzInfo.FSTFieldInfo referencee, Object array) throws IOException {
   if (array == null) {
     codec.writeClass(Object.class);
     codec.writeFInt(-1);
     return;
   }
   final int len = Array.getLength(array);
   Class<?> componentType = array.getClass().getComponentType();
   codec.writeClass(array.getClass());
   codec.writeFInt(len);
   if (!componentType.isArray()) {
     if (codec.isPrimitiveArray(array, componentType)) {
       codec.writePrimitiveArray(array, 0, len);
     } else { // objects
       Object arr[] = (Object[]) array;
       for (int i = 0; i < len; i++) {
         Object toWrite = arr[i];
         writeObjectWithContext(referencee, toWrite);
       }
     }
   } else { // multidim array. FIXME shared refs to subarrays are not tested !!!
     Object[] arr = (Object[]) array;
     FSTClazzInfo.FSTFieldInfo ref1 =
         new FSTClazzInfo.FSTFieldInfo(
             referencee.getPossibleClasses(),
             null,
             conf.getCLInfoRegistry().isIgnoreAnnotations());
     for (int i = 0; i < len; i++) {
       Object subArr = arr[i];
       boolean needsWrite = true;
       if (codec.isTagMultiDimSubArrays()) {
         if (subArr == null) {
           needsWrite = !codec.writeTag(NULL, null, 0, null);
         } else {
           needsWrite = !codec.writeTag(ARRAY, subArr, 0, subArr);
         }
       }
       if (needsWrite) writeArray(ref1, subArr);
     }
   }
 }
 public FSTClazzInfoRegistry getClassInfoRegistry() {
   return conf.getCLInfoRegistry();
 }
 /**
  * Creates a new FSTObjectOutput stream to write data to the specified underlying output stream.
  * uses Default Configuration singleton
  */
 public FSTObjectOutput(OutputStream out) {
   this(out, FSTConfiguration.getDefaultConfiguration());
 }
 /**
  * serialize without an underlying stream, the resulting byte array of writing to this
  * FSTObjectOutput can be accessed using getBuffer(), the size using getWritten(). Note once you
  * call close or flush, the tmp byte array is lost. (grab array before flushing/closing)
  *
  * <p>uses default configuration singleton
  *
  * @throws IOException
  */
 public FSTObjectOutput() {
   this(null, FSTConfiguration.getDefaultConfiguration());
   codec.setOutstream(null);
 }