
com.tangosol.io.pof.PofBufferReader Maven / Gradle / Ivy
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
package com.tangosol.io.pof;
import com.tangosol.io.ReadBuffer;
import com.tangosol.io.SerializationSupport;
import com.tangosol.io.SerializerAware;
import com.tangosol.util.Binary;
import com.tangosol.util.ExternalizableHelper;
import com.tangosol.util.ImmutableArrayList;
import com.tangosol.util.LongArray;
import com.tangosol.util.SparseArray;
import java.io.IOException;
import java.io.StreamCorruptedException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.function.IntFunction;
/**
* {@link PofReader} implementation that reads POF-encoded data from a
* {@link com.tangosol.io.ReadBuffer.BufferInput BufferInput}.
*
* @author cp 2006.07.14
*
* @since Coherence 3.2
*/
public class PofBufferReader
extends PofHelper
implements PofReader
{
// ----- constructors ---------------------------------------------------
/**
* Construct a new PofBufferReader that will read a POF stream from the
* passed BufferInput object.
*
* @param in a BufferInput object
* @param ctx the PofContext
*/
public PofBufferReader(ReadBuffer.BufferInput in, PofContext ctx)
{
m_in = in;
m_ctx = ctx;
}
protected PofBufferReader()
{
}
// ----- PofReader interface --------------------------------------------
/**
* {@inheritDoc}
*/
public boolean readBoolean(int iProp)
throws IOException
{
return readInt(iProp) != 0;
}
/**
* {@inheritDoc}
*/
public byte readByte(int iProp)
throws IOException
{
return (byte) readInt(iProp);
}
/**
* {@inheritDoc}
*/
public char readChar(int iProp)
throws IOException
{
return (char) readInt(iProp);
}
/**
* {@inheritDoc}
*/
public short readShort(int iProp)
throws IOException
{
return (short) readInt(iProp);
}
/**
* {@inheritDoc}
*/
public int readInt(int iProp)
throws IOException
{
int n = 0;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
n = readInt(iProp);
registerIdentity(nId, Integer.valueOf(n));
}
break;
case T_REFERENCE:
Number number = (Number) lookupIdentity(in.readPackedInt());
if (number != null)
{
n = number.intValue();
}
break;
case V_REFERENCE_NULL:
case V_INT_0:
break;
default:
n = readAsInt(in, nType);
break;
}
}
complete(iProp);
return n;
}
/**
* {@inheritDoc}
*/
public long readLong(int iProp)
throws IOException
{
long n = 0L;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
n = readLong(iProp);
registerIdentity(nId, Long.valueOf(n));
}
break;
case T_REFERENCE:
Number number = (Number) lookupIdentity(in.readPackedInt());
if (number != null)
{
n = number.longValue();
}
break;
case V_REFERENCE_NULL:
case V_INT_0:
break;
default:
n = readAsLong(in, nType);
break;
}
}
complete(iProp);
return n;
}
/**
* {@inheritDoc}
*/
public float readFloat(int iProp)
throws IOException
{
float fl = 0.0F;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
fl = readFloat(iProp);
registerIdentity(nId, Float.valueOf(fl));
}
break;
case T_REFERENCE:
Number number = (Number) lookupIdentity(in.readPackedInt());
if (number != null)
{
fl = number.floatValue();
}
break;
case V_REFERENCE_NULL:
case V_INT_0:
break;
default:
fl = readAsFloat(in, nType);
break;
}
}
complete(iProp);
return fl;
}
/**
* {@inheritDoc}
*/
public double readDouble(int iProp)
throws IOException
{
double dfl = 0.0;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
dfl = readDouble(iProp);
registerIdentity(nId, Double.valueOf(dfl));
}
break;
case T_REFERENCE:
Number number = (Number) lookupIdentity(in.readPackedInt());
if (number != null)
{
dfl = number.doubleValue();
}
break;
case V_REFERENCE_NULL:
case V_INT_0:
break;
default:
dfl = readAsDouble(in, nType);
break;
}
}
complete(iProp);
return dfl;
}
/**
* {@inheritDoc}
*/
public boolean[] readBooleanArray(int iProp)
throws IOException
{
boolean[] af = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
af = readBooleanArray(iProp);
registerIdentity(nId, af);
}
break;
case T_REFERENCE:
af = (boolean[]) lookupIdentity(in.readPackedInt());
break;
case V_REFERENCE_NULL:
break;
case V_STRING_ZERO_LENGTH:
case V_COLLECTION_EMPTY:
af = BOOLEAN_ARRAY_EMPTY;
break;
case T_COLLECTION:
case T_ARRAY:
{
int cElements = in.readPackedInt();
af = new boolean[cElements];
for (int i = 0; i < cElements; ++i)
{
af[i] = readAsInt(in, in.readPackedInt()) != 0;
}
}
break;
case T_UNIFORM_COLLECTION:
case T_UNIFORM_ARRAY:
{
int nElementType = in.readPackedInt();
int cElements = in.readPackedInt();
af = new boolean[cElements];
switch (nElementType)
{
case T_BOOLEAN:
case T_INT16:
case T_INT32:
case T_INT64:
case T_INT128:
for (int i = 0; i < cElements; ++i)
{
af[i] = in.readPackedInt() != 0;
}
break;
default:
for (int i = 0; i < cElements; ++i)
{
af[i] = readAsInt(in, nElementType) != 0;
}
break;
}
}
break;
case T_SPARSE_ARRAY:
{
int cElements = in.readPackedInt();
af = new boolean[cElements];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
af[iElement] = readAsInt(in, in.readPackedInt()) != 0;
}
while (--cElements >= 0);
}
break;
case T_UNIFORM_SPARSE_ARRAY:
{
int nElementType = in.readPackedInt();
int cElements = in.readPackedInt();
af = new boolean[cElements];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
af[iElement] = readAsInt(in, nElementType) != 0;
}
while (--cElements >= 0);
}
break;
default:
throw new IOException("unable to convert type " + nType
+ " to an array type");
}
}
complete(iProp);
return af;
}
/**
* {@inheritDoc}
*/
public byte[] readByteArray(int iProp)
throws IOException
{
byte[] ab = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
ab = readByteArray(iProp);
registerIdentity(nId, ab);
}
break;
case T_REFERENCE:
{
Object o = lookupIdentity(in.readPackedInt());
ab = o instanceof Binary
? ((Binary) o).toByteArray()
: (byte[]) o;
}
break;
case V_REFERENCE_NULL:
break;
case V_STRING_ZERO_LENGTH:
case V_COLLECTION_EMPTY:
ab = BYTE_ARRAY_EMPTY;
break;
case T_OCTET_STRING:
ab = new byte[in.readPackedInt()];
in.readFully(ab);
break;
case T_COLLECTION:
case T_ARRAY:
{
int cElements = in.readPackedInt();
ab = new byte[cElements];
for (int i = 0; i < cElements; ++i)
{
ab[i] = (byte) readAsInt(in, in.readPackedInt());
}
}
break;
case T_UNIFORM_COLLECTION:
case T_UNIFORM_ARRAY:
{
int nElementType = in.readPackedInt();
int cElements = in.readPackedInt();
ab = new byte[cElements];
if (nElementType == T_OCTET)
{
in.readFully(ab);
}
else
{
for (int i = 0; i < cElements; ++i)
{
ab[i] = (byte) readAsInt(in, nElementType);
}
}
}
break;
case T_SPARSE_ARRAY:
{
int cElements = in.readPackedInt();
ab = new byte[cElements];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
ab[iElement] = (byte) readAsInt(in, in.readPackedInt());
}
while (--cElements >= 0);
}
break;
case T_UNIFORM_SPARSE_ARRAY:
{
int nElementType = in.readPackedInt();
int cElements = in.readPackedInt();
ab = new byte[cElements];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
ab[iElement] = nElementType == T_OCTET
? in.readByte()
: (byte) readAsInt(in, nElementType);
}
while (--cElements >= 0);
}
break;
default:
throw new IOException("unable to convert type " + nType
+ " to an array type");
}
}
complete(iProp);
return ab;
}
/**
* {@inheritDoc}
*/
public char[] readCharArray(int iProp)
throws IOException
{
char[] ach = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
ach = readCharArray(iProp);
registerIdentity(nId, ach);
}
break;
case T_REFERENCE:
{
Object o = lookupIdentity(in.readPackedInt());
ach = o instanceof String
? ((String) o).toCharArray()
: (char[]) o;
}
break;
case V_REFERENCE_NULL:
break;
case V_STRING_ZERO_LENGTH:
case V_COLLECTION_EMPTY:
ach = CHAR_ARRAY_EMPTY;
break;
case T_OCTET_STRING:
{
int cb = in.readPackedInt();
byte[] ab = new byte[cb];
in.readFully(ab);
ach = new char[cb];
for (int of = 0; of < cb; ++cb)
{
ach[of] = (char) (ab[of] & 0xFF);
}
}
break;
case T_CHAR_STRING:
ach = in.readSafeUTF().toCharArray();
break;
case T_COLLECTION:
case T_ARRAY:
{
int cElements = in.readPackedInt();
ach = new char[cElements];
for (int i = 0; i < cElements; ++i)
{
ach[i] = (char) readAsInt(in, in.readPackedInt());
}
}
break;
case T_UNIFORM_COLLECTION:
case T_UNIFORM_ARRAY:
{
int nElementType = in.readPackedInt();
int cElements = in.readPackedInt();
ach = new char[cElements];
for (int i = 0; i < cElements; ++i)
{
ach[i] = nElementType == T_CHAR
? readChar(in)
: (char) readAsInt(in, nElementType);
}
}
break;
case T_SPARSE_ARRAY:
{
int cElements = in.readPackedInt();
ach = new char[cElements];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
ach[iElement] = (char) readAsInt(in, in.readPackedInt());
}
while (--cElements >= 0);
}
break;
case T_UNIFORM_SPARSE_ARRAY:
{
int nElementType = in.readPackedInt();
int cElements = in.readPackedInt();
ach = new char[cElements];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
ach[iElement] = nElementType == T_CHAR
? readChar(in)
: (char) readAsInt(in, nElementType);
}
while (--cElements >= 0);
}
break;
default:
throw new IOException("unable to convert type " + nType
+ " to an array type");
}
}
complete(iProp);
return ach;
}
/**
* {@inheritDoc}
*/
public short[] readShortArray(int iProp)
throws IOException
{
short[] an = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
an = readShortArray(iProp);
registerIdentity(nId, an);
}
break;
case T_REFERENCE:
an = (short[]) lookupIdentity(in.readPackedInt());
break;
case V_REFERENCE_NULL:
break;
case V_COLLECTION_EMPTY:
an = SHORT_ARRAY_EMPTY;
break;
case T_COLLECTION:
case T_ARRAY:
{
int cElements = in.readPackedInt();
an = new short[cElements];
for (int i = 0; i < cElements; ++i)
{
an[i] = (short) readAsInt(in, in.readPackedInt());
}
}
break;
case T_UNIFORM_COLLECTION:
case T_UNIFORM_ARRAY:
{
int nElementType = in.readPackedInt();
int cElements = in.readPackedInt();
an = new short[cElements];
switch (nElementType)
{
case T_INT16:
case T_INT32:
case T_INT64:
case T_INT128:
for (int i = 0; i < cElements; ++i)
{
an[i] = (short) in.readPackedInt();
}
break;
default:
for (int i = 0; i < cElements; ++i)
{
an[i] = (short) readAsInt(in, nElementType);
}
break;
}
}
break;
case T_SPARSE_ARRAY:
{
int cElements = in.readPackedInt();
an = new short[cElements];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
an[iElement] = (short) readAsInt(in, in.readPackedInt());
}
while (--cElements >= 0);
}
break;
case T_UNIFORM_SPARSE_ARRAY:
{
int nElementType = in.readPackedInt();
int cElements = in.readPackedInt();
an = new short[cElements];
switch (nElementType)
{
case T_INT16:
case T_INT32:
case T_INT64:
case T_INT128:
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
an[iElement] = (short) in.readPackedInt();
}
while (--cElements >= 0);
break;
default:
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
an[iElement] = (short) readAsInt(in, nElementType);
}
while (--cElements >= 0);
break;
}
}
break;
default:
throw new IOException("unable to convert type " + nType
+ " to an array type");
}
}
complete(iProp);
return an;
}
/**
* {@inheritDoc}
*/
public int[] readIntArray(int iProp)
throws IOException
{
int[] an = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
an = readIntArray(iProp);
registerIdentity(nId, an);
}
break;
case T_REFERENCE:
an = (int[]) lookupIdentity(in.readPackedInt());
break;
case V_REFERENCE_NULL:
break;
case V_COLLECTION_EMPTY:
an = INT_ARRAY_EMPTY;
break;
case T_COLLECTION:
case T_ARRAY:
{
int cElements = in.readPackedInt();
an = new int[cElements];
for (int i = 0; i < cElements; ++i)
{
an[i] = readAsInt(in, in.readPackedInt());
}
}
break;
case T_UNIFORM_COLLECTION:
case T_UNIFORM_ARRAY:
{
int nElementType = in.readPackedInt();
int cElements = in.readPackedInt();
an = new int[cElements];
switch (nElementType)
{
case T_INT16:
case T_INT32:
case T_INT64:
case T_INT128:
for (int i = 0; i < cElements; ++i)
{
an[i] = in.readPackedInt();
}
break;
default:
for (int i = 0; i < cElements; ++i)
{
an[i] = readAsInt(in, nElementType);
}
break;
}
}
break;
case T_SPARSE_ARRAY:
{
int cElements = in.readPackedInt();
an = new int[cElements];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
an[iElement] = readAsInt(in, in.readPackedInt());
}
while (--cElements >= 0);
}
break;
case T_UNIFORM_SPARSE_ARRAY:
{
int nElementType = in.readPackedInt();
int cElements = in.readPackedInt();
an = new int[cElements];
switch (nElementType)
{
case T_INT16:
case T_INT32:
case T_INT64:
case T_INT128:
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
an[iElement] = in.readPackedInt();
}
while (--cElements >= 0);
break;
default:
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
an[iElement] = readAsInt(in, nElementType);
}
while (--cElements >= 0);
break;
}
}
break;
default:
throw new IOException("unable to convert type " + nType
+ " to an array type");
}
}
complete(iProp);
return an;
}
/**
* {@inheritDoc}
*/
public long[] readLongArray(int iProp)
throws IOException
{
long[] an = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
an = readLongArray(iProp);
registerIdentity(nId, an);
}
break;
case T_REFERENCE:
an = (long[]) lookupIdentity(in.readPackedInt());
break;
case V_REFERENCE_NULL:
break;
case V_COLLECTION_EMPTY:
an = LONG_ARRAY_EMPTY;
break;
case T_COLLECTION:
case T_ARRAY:
{
int cElements = in.readPackedInt();
an = new long[cElements];
for (int i = 0; i < cElements; ++i)
{
an[i] = readAsLong(in, in.readPackedInt());
}
}
break;
case T_UNIFORM_COLLECTION:
case T_UNIFORM_ARRAY:
{
int nElementType = in.readPackedInt();
int cElements = in.readPackedInt();
an = new long[cElements];
switch (nElementType)
{
case T_INT16:
case T_INT32:
case T_INT64:
case T_INT128:
for (int i = 0; i < cElements; ++i)
{
an[i] = in.readPackedLong();
}
break;
default:
for (int i = 0; i < cElements; ++i)
{
an[i] = readAsLong(in, nElementType);
}
break;
}
}
break;
case T_SPARSE_ARRAY:
{
int cElements = in.readPackedInt();
an = new long[cElements];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
an[iElement] = readAsLong(in, in.readPackedInt());
}
while (--cElements >= 0);
}
break;
case T_UNIFORM_SPARSE_ARRAY:
{
int nElementType = in.readPackedInt();
int cElements = in.readPackedInt();
an = new long[cElements];
switch (nElementType)
{
case T_INT16:
case T_INT32:
case T_INT64:
case T_INT128:
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
an[iElement] = in.readPackedLong();
}
while (--cElements >= 0);
break;
default:
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
an[iElement] = readAsLong(in, nElementType);
}
while (--cElements >= 0);
break;
}
}
break;
default:
throw new IOException("unable to convert type " + nType
+ " to an array type");
}
}
complete(iProp);
return an;
}
/**
* {@inheritDoc}
*/
public float[] readFloatArray(int iProp)
throws IOException
{
float[] afl = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
afl = readFloatArray(iProp);
registerIdentity(nId, afl);
}
break;
case T_REFERENCE:
afl = (float[]) lookupIdentity(in.readPackedInt());
break;
case V_REFERENCE_NULL:
break;
case V_COLLECTION_EMPTY:
afl = FLOAT_ARRAY_EMPTY;
break;
case T_COLLECTION:
case T_ARRAY:
{
int cElements = in.readPackedInt();
afl = new float[cElements];
for (int i = 0; i < cElements; ++i)
{
afl[i] = readAsFloat(in, in.readPackedInt());
}
}
break;
case T_UNIFORM_COLLECTION:
case T_UNIFORM_ARRAY:
{
int nElementType = in.readPackedInt();
int cElements = in.readPackedInt();
afl = new float[cElements];
for (int i = 0; i < cElements; ++i)
{
afl[i] = nElementType == T_FLOAT32
? in.readFloat()
: readAsFloat(in, nElementType);
}
}
break;
case T_SPARSE_ARRAY:
{
int cElements = in.readPackedInt();
afl = new float[cElements];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
afl[iElement] = readAsFloat(in, in.readPackedInt());
}
while (--cElements >= 0);
}
break;
case T_UNIFORM_SPARSE_ARRAY:
{
int nElementType = in.readPackedInt();
int cElements = in.readPackedInt();
afl = new float[cElements];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
afl[iElement] = nElementType == T_FLOAT32
? in.readFloat()
: readAsFloat(in, nElementType);
}
while (--cElements >= 0);
}
break;
default:
throw new IOException("unable to convert type " + nType
+ " to an array type");
}
}
complete(iProp);
return afl;
}
/**
* {@inheritDoc}
*/
public double[] readDoubleArray(int iProp)
throws IOException
{
double[] adfl = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
adfl = readDoubleArray(iProp);
registerIdentity(nId, adfl);
}
break;
case T_REFERENCE:
adfl = (double[]) lookupIdentity(in.readPackedInt());
break;
case V_REFERENCE_NULL:
break;
case V_COLLECTION_EMPTY:
adfl = DOUBLE_ARRAY_EMPTY;
break;
case T_COLLECTION:
case T_ARRAY:
{
int cElements = in.readPackedInt();
adfl = new double[cElements];
for (int i = 0; i < cElements; ++i)
{
adfl[i] = readAsDouble(in, in.readPackedInt());
}
}
break;
case T_UNIFORM_COLLECTION:
case T_UNIFORM_ARRAY:
{
int nElementType = in.readPackedInt();
int cElements = in.readPackedInt();
adfl = new double[cElements];
for (int i = 0; i < cElements; ++i)
{
adfl[i] = nElementType == T_FLOAT64
? in.readDouble()
: readAsDouble(in, nElementType);
}
}
break;
case T_SPARSE_ARRAY:
{
int cElements = in.readPackedInt();
adfl = new double[cElements];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
adfl[iElement] = readAsDouble(in, in.readPackedInt());
}
while (--cElements >= 0);
}
break;
case T_UNIFORM_SPARSE_ARRAY:
{
int nElementType = in.readPackedInt();
int cElements = in.readPackedInt();
adfl = new double[cElements];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
adfl[iElement] = nElementType == T_FLOAT64
? in.readDouble()
: readAsDouble(in, nElementType);
}
while (--cElements >= 0);
}
break;
default:
throw new IOException("unable to convert type " + nType
+ " to an array type");
}
}
complete(iProp);
return adfl;
}
/**
* {@inheritDoc}
*/
public BigInteger readBigInteger(int iProp)
throws IOException
{
BigInteger n = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
n = readBigInteger(iProp);
registerIdentity(nId, n);
}
break;
case T_REFERENCE:
{
Number number = (Number) lookupIdentity(in.readPackedInt());
n = (BigInteger) convertNumber(number, J_BIG_INTEGER);
}
break;
case V_REFERENCE_NULL:
break;
case V_INT_0:
n = BigInteger.ZERO;
break;
default:
n = readAsBigInteger(in, nType);
break;
}
}
complete(iProp);
return n;
}
/**
* {@inheritDoc}
*/
public RawQuad readRawQuad(int iProp)
throws IOException
{
RawQuad qfl = RawQuad.ZERO;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
qfl = readRawQuad(iProp);
registerIdentity(nId, qfl);
}
break;
case T_REFERENCE:
{
Number number = (Number) lookupIdentity(in.readPackedInt());
qfl = (RawQuad) convertNumber(number, J_QUAD);
}
break;
case V_REFERENCE_NULL:
qfl = null;
break;
case V_INT_0:
break;
default:
qfl = readAsQuad(in, nType);
break;
}
}
complete(iProp);
return qfl;
}
/**
* {@inheritDoc}
*/
public BigDecimal readBigDecimal(int iProp)
throws IOException
{
BigDecimal dec = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
dec = readBigDecimal(iProp);
registerIdentity(nId, dec);
}
break;
case T_REFERENCE:
{
Number number = (Number) lookupIdentity(in.readPackedInt());
dec = (BigDecimal) convertNumber(number, J_BIG_DECIMAL);
}
break;
case V_REFERENCE_NULL:
break;
case V_INT_0:
dec = BigDecimal.ZERO;
break;
default:
dec = readAsBigDecimal(in, nType);
break;
}
}
complete(iProp);
return dec;
}
/**
* {@inheritDoc}
*/
public Binary readBinary(int iProp)
throws IOException
{
Binary bin = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
bin = readBinary(iProp);
registerIdentity(nId, bin);
}
break;
case T_REFERENCE:
{
Object o = lookupIdentity(in.readPackedInt());
bin = o instanceof byte[]
? new Binary((byte[]) o)
: (Binary) o;
}
break;
case V_REFERENCE_NULL:
break;
case V_STRING_ZERO_LENGTH:
case V_COLLECTION_EMPTY:
bin = BINARY_EMPTY;
break;
case T_OCTET_STRING:
bin = readBinary(in);
break;
case T_COLLECTION:
case T_ARRAY:
{
int cb = in.readPackedInt();
byte[] ab = new byte[cb];
for (int i = 0; i < cb; ++i)
{
ab[i] = (byte) readAsInt(in, in.readPackedInt());
}
bin = new Binary(ab);
}
break;
case T_UNIFORM_COLLECTION:
case T_UNIFORM_ARRAY:
{
int nElementType = in.readPackedInt();
int cb = in.readPackedInt();
byte[] ab = new byte[cb];
if (nElementType == T_OCTET)
{
in.readFully(ab);
}
else
{
for (int i = 0; i < cb; ++i)
{
ab[i] = (byte) readAsInt(in, nElementType);
}
}
bin = new Binary(ab);
}
break;
case T_SPARSE_ARRAY:
{
int cb = in.readPackedInt();
byte[] ab = new byte[cb];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
ab[iElement] = (byte) readAsInt(in, in.readPackedInt());
}
while (--cb >= 0);
bin = new Binary(ab);
}
break;
case T_UNIFORM_SPARSE_ARRAY:
{
int nElementType = in.readPackedInt();
int cb = in.readPackedInt();
byte[] ab = new byte[cb];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
ab[iElement] = nElementType == T_OCTET
? in.readByte()
: (byte) readAsInt(in, nElementType);
}
while (--cb >= 0);
bin = new Binary(ab);
}
break;
default:
throw new IOException("unable to convert type " + nType
+ " to a Binary type");
}
}
complete(iProp);
return bin;
}
/**
* {@inheritDoc}
*/
public String readString(int iProp)
throws IOException
{
String s = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
s = readString(iProp);
registerIdentity(nId, s);
}
break;
case T_REFERENCE:
{
Object o = lookupIdentity(in.readPackedInt());
if (o instanceof byte[])
{
s = new String((byte[]) o, 0);
}
else if (o instanceof Binary)
{
s = new String(((Binary) o).toByteArray(), 0);
}
else
{
s = (String) o;
}
}
break;
case V_REFERENCE_NULL:
break;
case V_STRING_ZERO_LENGTH:
case V_COLLECTION_EMPTY:
s = "";
break;
case T_OCTET_STRING:
{
int cb = in.readPackedInt();
int of = in.getOffset();
ReadBuffer buf = in.getBuffer();
if (buf == null)
{
s = new String(in.readBuffer(cb).toByteArray(), 0);
}
else
{
in.skipBytes(cb);
Binary bin = in.getBuffer().toBinary(of, cb);
s = new String(bin.toByteArray(), 0);
}
}
break;
case T_CHAR_STRING:
s = in.readSafeUTF();
break;
case T_COLLECTION:
case T_ARRAY:
{
int cch = in.readPackedInt();
char[] ach = new char[cch];
for (int i = 0; i < cch; ++i)
{
ach[i] = readAsChar(in, in.readPackedInt());
}
s = new String(ach);
}
break;
case T_UNIFORM_COLLECTION:
case T_UNIFORM_ARRAY:
{
int nElementType = in.readPackedInt();
int cch = in.readPackedInt();
char[] ach = new char[cch];
for (int i = 0; i < cch; ++i)
{
ach[i] = readAsChar(in, nElementType);
}
s = new String(ach);
}
break;
case T_SPARSE_ARRAY:
{
int cch = in.readPackedInt();
char[] ach = new char[cch];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
ach[iElement] = readAsChar(in, in.readPackedInt());
}
while (--cch >= 0);
s = new String(ach);
}
break;
case T_UNIFORM_SPARSE_ARRAY:
{
int nElementType = in.readPackedInt();
int cch = in.readPackedInt();
char[] ach = new char[cch];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
ach[iElement] = readAsChar(in, nElementType);
}
while (--cch >= 0);
s = new String(ach);
}
break;
default:
throw new IOException("unable to convert type " + nType
+ " to a String type");
}
}
complete(iProp);
return s;
}
/**
* {@inheritDoc}
*/
public Date readDate(int iProp)
throws IOException
{
Date date = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
date = readDate(iProp);
registerIdentity(nId, date);
}
break;
case T_REFERENCE:
date = convertToDate(lookupIdentity(in.readPackedInt()));
break;
case V_REFERENCE_NULL:
break;
case T_DATE:
date = convertToDate(readRawDate(in));
break;
case T_TIME:
date = convertToDate(readRawTime(in));
break;
case T_DATETIME:
date = convertToDate(new RawDateTime(readRawDate(in), readRawTime(in)));
break;
default:
throw new IOException("unable to convert type " + nType
+ " to a Java Date type");
}
}
complete(iProp);
return date;
}
@Override
public LocalDate readLocalDate(int iProp) throws IOException
{
LocalDate date = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
date = readLocalDate(iProp);
registerIdentity(nId, date);
}
break;
case T_REFERENCE:
date = (LocalDate) lookupIdentity(in.readPackedInt());
break;
case V_REFERENCE_NULL:
break;
case T_DATE:
date = readLocalDate(in);
break;
default:
throw new IOException("unable to convert type " + nType
+ " to a Java LocalDate type");
}
}
complete(iProp);
return date;
}
@Override
public LocalDateTime readLocalDateTime(int iProp) throws IOException
{
LocalDateTime dt = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
dt = readLocalDateTime(iProp);
registerIdentity(nId, dt);
}
break;
case T_REFERENCE:
dt = (LocalDateTime) lookupIdentity(in.readPackedInt());
break;
case V_REFERENCE_NULL:
break;
case T_DATETIME:
dt = readLocalDateTime(in);
break;
default:
throw new IOException("unable to convert type " + nType
+ " to a Java LocalDateTime type");
}
}
complete(iProp);
return dt;
}
@Override
public LocalTime readLocalTime(int iProp) throws IOException
{
LocalTime time = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
time = readLocalTime(iProp);
registerIdentity(nId, time);
}
break;
case T_REFERENCE:
time = (LocalTime) lookupIdentity(in.readPackedInt());
break;
case V_REFERENCE_NULL:
break;
case T_TIME:
time = readLocalTime(in);
break;
default:
throw new IOException("unable to convert type " + nType
+ " to a Java LocalTime type");
}
}
complete(iProp);
return time;
}
@Override
public OffsetDateTime readOffsetDateTime(int iProp) throws IOException
{
OffsetDateTime dt = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
dt = readOffsetDateTime(iProp);
registerIdentity(nId, dt);
}
break;
case T_REFERENCE:
dt = (OffsetDateTime) lookupIdentity(in.readPackedInt());
break;
case V_REFERENCE_NULL:
break;
case T_DATETIME:
dt = readOffsetDateTime(in);
break;
default:
throw new IOException("unable to convert type " + nType
+ " to a Java OffsetDateTime type");
}
}
complete(iProp);
return dt;
}
@Override
public OffsetTime readOffsetTime(int iProp) throws IOException
{
OffsetTime time = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
time = readOffsetTime(iProp);
registerIdentity(nId, time);
}
break;
case T_REFERENCE:
time = (OffsetTime) lookupIdentity(in.readPackedInt());
break;
case V_REFERENCE_NULL:
break;
case T_TIME:
time = readOffsetTime(in);
break;
default:
throw new IOException("unable to convert type " + nType
+ " to a Java OffsetTime type");
}
}
complete(iProp);
return time;
}
/**
* {@inheritDoc}
*/
public RawDate readRawDate(int iProp)
throws IOException
{
RawDate date = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
date = readRawDate(iProp);
registerIdentity(nId, date);
}
break;
case T_REFERENCE:
{
Object o = lookupIdentity(in.readPackedInt());
if (o instanceof Date)
{
Calendar calendar = Calendar.getInstance();
calendar.setTime((Date) o);
date = new RawDate(
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH) + 1,
calendar.get(Calendar.DAY_OF_MONTH));
}
else if (o instanceof RawDateTime)
{
date = ((RawDateTime) o).getRawDate();
}
else
{
date = (RawDate) o;
}
}
break;
case V_REFERENCE_NULL:
break;
case T_DATE:
date = readRawDate(in);
break;
case T_DATETIME:
{
// read the date portion
date = readRawDate(in);
// skip the time portion
skipPackedInts(in, 4);
int nZoneType = in.readPackedInt();
if (nZoneType == 2)
{
skipPackedInts(in, 2);
}
}
break;
default:
throw new IOException("unable to convert type " + nType
+ " to a RawDate type");
}
}
complete(iProp);
return date;
}
/**
* {@inheritDoc}
*/
public RawTime readRawTime(int iProp)
throws IOException
{
RawTime time = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
time = readRawTime(iProp);
registerIdentity(nId, time);
}
break;
case T_REFERENCE:
{
Object o = lookupIdentity(in.readPackedInt());
if (o instanceof Date)
{
Calendar calendar = Calendar.getInstance();
calendar.setTime((Date) o);
time = new RawTime(
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
calendar.get(Calendar.SECOND),
calendar.get(Calendar.MILLISECOND) * 1000000,
false);
}
else if (o instanceof RawDateTime)
{
time = ((RawDateTime) o).getRawTime();
}
else
{
time = (RawTime) o;
}
}
break;
case V_REFERENCE_NULL:
break;
case T_DATETIME:
// skip the date portion
skipPackedInts(in, 3);
// fall through
case T_TIME:
time = readRawTime(in);
break;
default:
throw new IOException("unable to convert type " + nType
+ " to a RawTime type");
}
}
complete(iProp);
return time;
}
/**
* {@inheritDoc}
*/
public RawDateTime readRawDateTime(int iProp)
throws IOException
{
RawDateTime dt = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
dt = readRawDateTime(iProp);
registerIdentity(nId, dt);
}
break;
case T_REFERENCE:
{
Object o = lookupIdentity(in.readPackedInt());
if (o instanceof Date)
{
Calendar calendar = Calendar.getInstance();
calendar.setTime((Date) o);
dt = new RawDateTime(
new RawDate(
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH) + 1,
calendar.get(Calendar.DAY_OF_MONTH)),
new RawTime(
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
calendar.get(Calendar.SECOND),
calendar.get(Calendar.MILLISECOND) * 1000000,
false));
}
else if (o instanceof RawDate)
{
dt = new RawDateTime((RawDate) o, new RawTime(0, 0, 0, 0, false));
}
else
{
dt = (RawDateTime) o;
}
}
break;
case V_REFERENCE_NULL:
break;
case T_DATE:
dt = new RawDateTime(readRawDate(in), new RawTime(0, 0, 0, 0, false));
break;
case T_DATETIME:
dt = new RawDateTime(readRawDate(in), readRawTime(in));
break;
default:
throw new IOException("unable to convert type " + nType
+ " to a RawDateTime type");
}
}
complete(iProp);
return dt;
}
/**
* {@inheritDoc}
*/
public RawYearMonthInterval readRawYearMonthInterval(int iProp)
throws IOException
{
RawYearMonthInterval interval = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
interval = readRawYearMonthInterval(iProp);
registerIdentity(nId, interval);
}
break;
case T_REFERENCE:
interval = (RawYearMonthInterval) lookupIdentity(in.readPackedInt());
break;
case V_REFERENCE_NULL:
break;
case T_YEAR_MONTH_INTERVAL:
{
int cYears = in.readPackedInt();
int cMonths = in.readPackedInt();
interval = new RawYearMonthInterval(cYears, cMonths);
}
break;
default:
throw new IOException("unable to convert type " + nType
+ " to a RawYearMonthInterval type");
}
}
complete(iProp);
return interval;
}
/**
* {@inheritDoc}
*/
public RawTimeInterval readRawTimeInterval(int iProp)
throws IOException
{
RawTimeInterval interval = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
interval = readRawTimeInterval(iProp);
registerIdentity(nId, interval);
}
break;
case T_REFERENCE:
interval = (RawTimeInterval) lookupIdentity(in.readPackedInt());
break;
case V_REFERENCE_NULL:
break;
case T_TIME_INTERVAL:
int cHours = in.readPackedInt();
int cMinutes = in.readPackedInt();
int cSeconds = in.readPackedInt();
int cNanos = in.readPackedInt();
interval = new RawTimeInterval(cHours, cMinutes, cSeconds, cNanos);
break;
default:
throw new IOException("unable to convert type " + nType
+ " to a RawTimeInterval type");
}
}
complete(iProp);
return interval;
}
/**
* {@inheritDoc}
*/
public RawDayTimeInterval readRawDayTimeInterval(int iProp)
throws IOException
{
RawDayTimeInterval interval = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
interval = readRawDayTimeInterval(iProp);
registerIdentity(nId, interval);
}
break;
case T_REFERENCE:
interval = (RawDayTimeInterval) lookupIdentity(in.readPackedInt());
break;
case V_REFERENCE_NULL:
break;
case T_DAY_TIME_INTERVAL:
int cDays = in.readPackedInt();
int cHours = in.readPackedInt();
int cMinutes = in.readPackedInt();
int cSeconds = in.readPackedInt();
int cNanos = in.readPackedInt();
interval = new RawDayTimeInterval(
cDays, cHours, cMinutes, cSeconds, cNanos);
break;
default:
throw new IOException("unable to convert type " + nType
+ " to a RawDayTimeInterval type");
}
}
complete(iProp);
return interval;
}
/**
* {@inheritDoc}
*/
public Object[] readObjectArray(int iProp, Object[] ao)
throws IOException
{
Object[] aoResult = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
aoResult = readObjectArray(iProp, ao);
registerIdentity(nId, aoResult);
}
break;
case T_REFERENCE:
{
Object o = lookupIdentity(in.readPackedInt());
if (o instanceof Collection)
{
aoResult = ((Collection) o).toArray(ao);
}
else if (o instanceof LongArray)
{
LongArray array = (LongArray) o;
long cElements = array.getLastIndex() + 1;
if (array.getFirstIndex() < 0L)
{
throw new ArrayIndexOutOfBoundsException(
"index=" + array.getFirstIndex());
}
if (cElements > Integer.MAX_VALUE)
{
throw new ArrayIndexOutOfBoundsException(
"index=" + array.getLastIndex());
}
aoResult = resizeArray(ao, (int) cElements);
for (LongArray.Iterator iter = array.iterator(); iter.hasNext(); )
{
Object oValue = iter.next();
aoResult[(int) iter.getIndex()] = oValue;
}
}
else
{
aoResult = (Object[]) o;
}
}
break;
case V_REFERENCE_NULL:
break;
case V_STRING_ZERO_LENGTH:
case V_COLLECTION_EMPTY:
aoResult = OBJECT_ARRAY_EMPTY;
break;
default:
aoResult = readAsObjectArray(nType, ao);
break;
}
}
complete(iProp);
return aoResult;
}
/**
* {@inheritDoc}
*/
public T[] readArray(int iProp, IntFunction supplier)
throws IOException
{
T[] aoResult = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
aoResult = readArray(iProp, supplier);
registerIdentity(nId, aoResult);
}
break;
case T_REFERENCE:
{
Object o = lookupIdentity(in.readPackedInt());
if (o instanceof Collection)
{
Collection col = (Collection) o;
aoResult = col.toArray(supplier.apply(col.size()));
}
else if (o instanceof LongArray)
{
LongArray array = (LongArray) o;
long cElements = array.getLastIndex() + 1;
if (array.getFirstIndex() < 0L)
{
throw new ArrayIndexOutOfBoundsException(
"index=" + array.getFirstIndex());
}
if (cElements > Integer.MAX_VALUE)
{
throw new ArrayIndexOutOfBoundsException(
"index=" + array.getLastIndex());
}
aoResult = supplier.apply((int) cElements);
for (LongArray.Iterator iter = array.iterator(); iter.hasNext(); )
{
T value = (T) iter.next();
aoResult[(int) iter.getIndex()] = value;
}
}
else
{
aoResult = (T[]) o;
}
}
break;
case V_REFERENCE_NULL:
break;
case V_STRING_ZERO_LENGTH:
case V_COLLECTION_EMPTY:
aoResult = (T[]) OBJECT_ARRAY_EMPTY;
break;
default:
aoResult = readAsTypedObjectArray(nType, supplier);
break;
}
}
complete(iProp);
return aoResult;
}
/**
* {@inheritDoc}
*/
public LongArray readLongArray(int iProp, LongArray array)
throws IOException
{
// do not default to null, since the caller is passing in a mutable
// LongArray
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
array = readLongArray(iProp, array);
registerIdentity(nId, array);
}
break;
case T_REFERENCE:
{
Object o = lookupIdentity(in.readPackedInt());
if (o instanceof Collection)
{
if (array == null)
{
array = new SparseArray();
}
int i = 0;
for (Iterator iter = ((Collection) o).iterator(); iter.hasNext(); )
{
array.set(++i, iter.next());
}
}
else
{
array = (LongArray) o;
}
}
break;
case V_REFERENCE_NULL:
case V_STRING_ZERO_LENGTH:
case V_COLLECTION_EMPTY:
break;
case T_COLLECTION:
case T_ARRAY:
{
if (array == null)
{
array = new SparseArray();
}
int co = in.readPackedInt();
for (int i = 0; i < co; ++i)
{
array.set(i, readAsObject(in.readPackedInt()));
}
}
break;
case T_UNIFORM_COLLECTION:
case T_UNIFORM_ARRAY:
{
if (array == null)
{
array = new SparseArray();
}
int nElementType = in.readPackedInt();
int co = in.readPackedInt();
for (int i = 0; i < co; ++i)
{
array.set(i, readAsUniformObject(nElementType));
}
}
break;
case T_SPARSE_ARRAY:
{
if (array == null)
{
array = new SparseArray();
}
int co = in.readPackedInt();
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
array.set(iElement, readAsObject(in.readPackedInt()));
}
while (--co >= 0);
}
break;
case T_UNIFORM_SPARSE_ARRAY:
{
if (array == null)
{
array = new SparseArray();
}
int nElementType = in.readPackedInt();
int co = in.readPackedInt();
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
array.set(iElement, readAsUniformObject(nElementType));
}
while (--co >= 0);
}
break;
default:
throw new IOException("unable to convert type " + nType
+ " to an array type");
}
}
complete(iProp);
return array;
}
/**
* {@inheritDoc}
*/
public > C readCollection(int iProp, C coll)
throws IOException
{
// do not default to null, since the caller is passing in a mutable
// Collection
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
coll = readCollection(iProp, coll);
registerIdentity(nId, coll);
}
break;
case T_REFERENCE:
{
Object o = lookupIdentity(in.readPackedInt());
if (o instanceof Object[])
{
Collection collData =
new ImmutableArrayList((Object[]) o).getList();
if (coll == null)
{
coll = (C) collData;
}
else
{
coll.addAll(collData);
}
}
else
{
coll = (C) o;
}
}
break;
case V_REFERENCE_NULL:
case V_STRING_ZERO_LENGTH:
case V_COLLECTION_EMPTY:
break;
case T_COLLECTION:
case T_ARRAY:
{
if (coll == null)
{
Object[] ao = readAsObjectArray(nType, null);
coll = (C) new ImmutableArrayList(ao).getList();
}
else
{
int co = in.readPackedInt();
for (int i = 0; i < co; ++i)
{
coll.add((T) readAsObject(in.readPackedInt()));
}
}
}
break;
case T_UNIFORM_COLLECTION:
case T_UNIFORM_ARRAY:
{
if (coll == null)
{
Object[] ao = readAsObjectArray(nType, null);
coll = (C) new ImmutableArrayList(ao).getList();
}
else
{
int nElementType = in.readPackedInt();
int co = in.readPackedInt();
for (int i = 0; i < co; ++i)
{
coll.add((T) readAsUniformObject(nElementType));
}
}
}
break;
case T_SPARSE_ARRAY:
{
int co = in.readPackedInt();
if (coll == null)
{
coll = (C) new ArrayList<>(co);
}
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
coll.add((T) readAsObject(in.readPackedInt()));
}
while (--co >= 0);
}
break;
case T_UNIFORM_SPARSE_ARRAY:
{
int nElementType = in.readPackedInt();
int co = in.readPackedInt();
if (coll == null)
{
coll = (C) new ArrayList<>(co);
}
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
coll.add((T) readAsUniformObject(nElementType));
}
while (--co >= 0);
}
break;
default:
throw new IOException("unable to convert type " + nType
+ " to a Collection type");
}
}
complete(iProp);
return coll;
}
/**
* {@inheritDoc}
*/
public > M readMap(int iProp, M map)
throws IOException
{
// do not default to null, since the caller is passing in a mutable
// Map
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
map = readMap(iProp, map);
registerIdentity(nId, map);
}
break;
case T_REFERENCE:
map = (M) lookupIdentity(in.readPackedInt());
break;
case V_REFERENCE_NULL:
case V_STRING_ZERO_LENGTH:
case V_COLLECTION_EMPTY:
break;
case T_MAP:
{
int cEntries = in.readPackedInt();
if (map == null)
{
map = (M) new HashMap(cEntries);
}
for (int i = 0; i < cEntries; ++i)
{
K key = (K) readAsObject(in.readPackedInt());
V val = (V) readAsObject(in.readPackedInt());
map.put(key, val);
}
}
break;
case T_UNIFORM_KEYS_MAP:
{
int nKeyType = in.readPackedInt();
int cEntries = in.readPackedInt();
if (map == null)
{
map = (M) new HashMap(cEntries);
}
for (int i = 0; i < cEntries; ++i)
{
K key = (K) readAsUniformObject(nKeyType);
V val = (V) readAsObject(in.readPackedInt());
map.put(key, val);
}
}
break;
case T_UNIFORM_MAP:
{
int nKeyType = in.readPackedInt();
int nValType = in.readPackedInt();
int cEntries = in.readPackedInt();
if (map == null)
{
map = (M) new HashMap(cEntries);
}
for (int i = 0; i < cEntries; ++i)
{
K key = (K) readAsUniformObject(nKeyType);
V val = (V) readAsUniformObject(nValType);
map.put(key, val);
}
}
break;
default:
throw new IOException("unable to convert type " + nType
+ " to a Map type");
}
}
complete(iProp);
return map;
}
/**
* {@inheritDoc}
*/
public PofContext getPofContext()
{
return m_ctx;
}
/**
* {@inheritDoc}
*/
public void setPofContext(PofContext ctx)
{
if (ctx == null)
{
throw new IllegalArgumentException("PofContext cannot be null");
}
m_ctx = ctx;
}
/**
* {@inheritDoc}
*/
public T readObject(int iProp)
throws IOException
{
T o = null;
if (advanceTo(iProp))
{
ReadBuffer.BufferInput in = m_in;
int nType = in.readPackedInt();
switch (nType)
{
case T_IDENTITY:
{
int nId = in.readPackedInt();
IdentityHolder.set(this, nId);
o = readObject(iProp);
IdentityHolder.reset(this, nId, o);
}
break;
case T_REFERENCE:
o = (T) lookupIdentity(in.readPackedInt());
break;
case V_REFERENCE_NULL:
break;
default:
o = (T) readAsObject(nType);
break;
}
}
complete(iProp);
return o;
}
/**
* {@inheritDoc}
*/
public int getUserTypeId()
{
return -1;
}
/**
* {@inheritDoc}
*/
public int getVersionId()
{
throw new IllegalStateException("not in a user type");
}
/**
* {@inheritDoc}
*/
public void registerIdentity(Object o)
{
throw new IllegalStateException("not in a user type");
}
/**
* {@inheritDoc}
*/
public PofReader createNestedPofReader(int iProp)
throws IOException
{
throw new IllegalStateException("not in a user type");
}
/**
* {@inheritDoc}
*/
public Binary readRemainder()
throws IOException
{
throw new IllegalStateException("not in a user type");
}
// ----- internal methods -----------------------------------------------
/**
* Advance through the POF stream until the specified property is found.
* If the property is found, return true, otherwise return false and
* advance to the first property that follows the specified property.
*
* @param iProp the index of the property to advance to
*
* @return true if the property is found
*
* @throws IllegalStateException if the POF stream has already advanced
* past the desired property
* @throws IOException if an I/O error occurs
*/
protected boolean advanceTo(int iProp)
throws IOException
{
if (iProp > 0)
{
throw new IllegalStateException();
}
return true;
}
/**
* Register the completion of the parsing of a value.
*
* @param iProp the property index
*
* @throws IOException if an I/O error occurs
*/
protected void complete(int iProp)
throws IOException
{
}
/**
* If this parser is contextually within a user type, obtain the parser
* which created this parser in order to parse the user type.
*
* @return the parser for the context within which this parser is
* operating
*/
protected PofBufferReader getParentParser()
{
return null;
}
/**
* Obtain the registry for identity-reference pairs, creating it if
* necessary.
*
* @return the identity-reference registry, never null
*/
protected LongArray ensureReferenceRegistry()
{
LongArray array = m_arrayRefs;
if (array == null)
{
PofBufferReader parent = getParentParser();
m_arrayRefs = array = parent == null
? new SparseArray()
: parent.ensureReferenceRegistry();
}
return array;
}
/**
* Register the passed value with the passed identity.
*
* @param nId the identity within the POF stream of the object
* @param oValue the object to associate with the passed identity
*
* @throws IllegalArgumentException if the specified identity is already
* registered with a different object
*/
protected void registerIdentity(int nId, Object oValue)
{
if (nId >= 0)
{
LongArray array = ensureReferenceRegistry();
Object o = array.get(nId);
if (o != null && o != oValue)
{
throw new IllegalArgumentException("duplicate identity: " + nId);
}
array.set(nId, oValue);
}
}
/**
* Look up the specified identity and return the object to which it
* refers.
*
* @param nId the identity
*
* @return the object registered under that identity
*
* @throws IOException if the requested identity is not registered
*/
protected Object lookupIdentity(int nId)
throws IOException
{
LongArray array = ensureReferenceRegistry();
if (!array.exists(nId))
{
throw new IOException("missing identity: " + nId);
}
return array.get(nId);
}
/**
* Read a POF value as an Object.
*
* @param nType the type identifier of the value
*
* @return an Object value
*
* @throws IOException if an I/O error occurs
*/
protected Object readAsObject(int nType)
throws IOException
{
Object o = null;
ReadBuffer.BufferInput in = m_in;
switch (nType)
{
case T_INT16:
o = Short.valueOf((short) in.readPackedInt());
break;
case T_INT32:
case V_INT_NEG_1:
case V_INT_0:
case V_INT_1:
case V_INT_2:
case V_INT_3:
case V_INT_4:
case V_INT_5:
case V_INT_6:
case V_INT_7:
case V_INT_8:
case V_INT_9:
case V_INT_10:
case V_INT_11:
case V_INT_12:
case V_INT_13:
case V_INT_14:
case V_INT_15:
case V_INT_16:
case V_INT_17:
case V_INT_18:
case V_INT_19:
case V_INT_20:
case V_INT_21:
case V_INT_22:
o = Integer.valueOf(readAsInt(in, nType));
break;
case T_INT64:
o = Long.valueOf(in.readPackedLong());
break;
case T_INT128:
o = readBigInteger(in);
break;
case T_FLOAT32:
o = Float.valueOf(in.readFloat());
break;
case T_FLOAT64:
o = Double.valueOf(in.readDouble());
break;
case T_FLOAT128:
o = readQuad(in);
break;
case V_FP_POS_INFINITY:
o = Double.POSITIVE_INFINITY;
break;
case V_FP_NEG_INFINITY:
o = Double.NEGATIVE_INFINITY;
break;
case V_FP_NAN:
o = Double.NaN;
break;
case T_DECIMAL32:
o = readBigDecimal(in, 4);
break;
case T_DECIMAL64:
o = readBigDecimal(in, 8);
break;
case T_DECIMAL128:
o = readBigDecimal(in, 16);
break;
case T_BOOLEAN:
o = in.readPackedInt() == 0 ? Boolean.FALSE : Boolean.TRUE;
break;
case T_OCTET:
o = Byte.valueOf(in.readByte());
break;
case T_OCTET_STRING:
o = readBinary(in);
break;
case T_CHAR:
o = Character.valueOf(readChar(in));
break;
case T_CHAR_STRING:
o = in.readSafeUTF();
break;
case T_DATE:
{
RawDate rawDate = readRawDate(in);
o = getPofContext().isPreferJavaTime()
? rawDate.toLocalDate()
: rawDate.toSqlDate();
}
break;
case T_TIME:
{
RawTime rawTime = readRawTime(in);
o = getPofContext().isPreferJavaTime()
? rawTime.hasTimezone() ? rawTime.toOffsetTime() : rawTime.toLocalTime()
: rawTime.toSqlTime();
}
break;
case T_DATETIME:
{
RawDateTime rawDateTime = new RawDateTime(readRawDate(in), readRawTime(in));
o = getPofContext().isPreferJavaTime()
? rawDateTime.getRawTime().hasTimezone()
? rawDateTime.toOffsetDateTime() : rawDateTime.toLocalDateTime()
: rawDateTime.toSqlTimestamp();
}
break;
case T_YEAR_MONTH_INTERVAL:
{
int cYears = in.readPackedInt();
int dMonths = in.readPackedInt();
o = new RawYearMonthInterval(cYears, dMonths);
}
break;
case T_TIME_INTERVAL:
{
int cHours = in.readPackedInt();
int cMinutes = in.readPackedInt();
int cSeconds = in.readPackedInt();
int cNanos = in.readPackedInt();
o = new RawTimeInterval(cHours, cMinutes, cSeconds, cNanos);
}
break;
case T_DAY_TIME_INTERVAL:
{
int cDays = in.readPackedInt();
int cHours = in.readPackedInt();
int cMinutes = in.readPackedInt();
int cSeconds = in.readPackedInt();
int cNanos = in.readPackedInt();
o = new RawDayTimeInterval(cDays, cHours, cMinutes, cSeconds, cNanos);
}
break;
case T_COLLECTION:
case T_UNIFORM_COLLECTION:
o = new ImmutableArrayList(readAsObjectArray(nType, null)).getList();
break;
case T_ARRAY:
o = readAsObjectArray(nType, null);
break;
case T_UNIFORM_ARRAY:
{
int nElementType = in.readPackedInt();
int cElements = in.readPackedInt();
switch (nElementType)
{
case T_BOOLEAN:
{
boolean[] af = new boolean[cElements];
for (int i = 0; i < cElements; ++i)
{
af[i] = in.readPackedInt() != 0;
}
o = af;
}
break;
case T_OCTET:
{
byte[] ab = new byte[cElements];
in.readFully(ab);
o = ab;
}
break;
case T_CHAR:
{
char[] ach = new char[cElements];
for (int i = 0; i < cElements; ++i)
{
ach[i] = readChar(in);
}
o = ach;
}
break;
case T_INT16:
{
short[] an = new short[cElements];
for (int i = 0; i < cElements; ++i)
{
an[i] = (short) in.readPackedInt();
}
o = an;
}
break;
case T_INT32:
{
int[] an = new int[cElements];
for (int i = 0; i < cElements; ++i)
{
an[i] = in.readPackedInt();
}
o = an;
}
break;
case T_INT64:
{
long[] an = new long[cElements];
for (int i = 0; i < cElements; ++i)
{
an[i] = in.readPackedLong();
}
o = an;
}
break;
case T_FLOAT32:
{
float[] afl = new float[cElements];
for (int i = 0; i < cElements; ++i)
{
afl[i] = in.readFloat();
}
o = afl;
}
break;
case T_FLOAT64:
{
double[] adfl = new double[cElements];
for (int i = 0; i < cElements; ++i)
{
adfl[i] = in.readDouble();
}
o = adfl;
}
break;
default:
{
Object[] ao = new Object[cElements];
for (int i = 0; i < cElements; ++i)
{
ao[i] = readAsUniformObject(nElementType);
}
o = ao;
}
}
}
break;
case T_SPARSE_ARRAY:
{
LongArray array = new SparseArray();
int cElements = in.readPackedInt();
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
array.set(iElement, readAsObject(in.readPackedInt()));
}
while (--cElements >= 0);
o = array;
}
break;
case T_UNIFORM_SPARSE_ARRAY:
{
int nElementType = in.readPackedInt();
int cElements = in.readPackedInt();
switch (nElementType)
{
case T_BOOLEAN:
{
boolean[] af = new boolean[cElements];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
af[iElement] = in.readPackedInt() != 0;
}
while (--cElements >= 0);
o = af;
}
break;
case T_OCTET:
{
byte[] ab = new byte[cElements];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
ab[iElement] = in.readByte();
}
while (--cElements >= 0);
o = ab;
}
break;
case T_CHAR:
{
char[] ach = new char[cElements];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
ach[iElement] = readChar(in);
}
while (--cElements >= 0);
o = ach;
}
break;
case T_INT16:
{
short[] an = new short[cElements];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
an[iElement] = (short) in.readPackedInt();
}
while (--cElements >= 0);
o = an;
}
break;
case T_INT32:
{
int[] an = new int[cElements];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
an[iElement] = in.readPackedInt();
}
while (--cElements >= 0);
o = an;
}
break;
case T_INT64:
{
long[] an = new long[cElements];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
an[iElement] = in.readPackedLong();
}
while (--cElements >= 0);
o = an;
}
break;
case T_FLOAT32:
{
float[] afl = new float[cElements];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
afl[iElement] = in.readFloat();
}
while (--cElements >= 0);
o = afl;
}
break;
case T_FLOAT64:
{
double[] adfl = new double[cElements];
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
adfl[iElement] = in.readDouble();
}
while (--cElements >= 0);
o = adfl;
}
break;
default:
{
LongArray array = new SparseArray();
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
array.set(iElement, readAsUniformObject(nElementType));
}
while (--cElements >= 0);
o = array;
}
}
}
break;
case T_MAP:
{
Map map = new HashMap();
int cEntries = in.readPackedInt();
for (int i = 0; i < cEntries; ++i)
{
Object oKey = readAsObject(in.readPackedInt());
Object oVal = readAsObject(in.readPackedInt());
map.put(oKey, oVal);
}
o = map;
}
break;
case T_UNIFORM_KEYS_MAP:
{
Map map = new HashMap();
int nKeyType = in.readPackedInt();
int cEntries = in.readPackedInt();
for (int i = 0; i < cEntries; ++i)
{
Object oKey = readAsUniformObject(nKeyType);
Object oVal = readAsObject(in.readPackedInt());
map.put(oKey, oVal);
}
o = map;
}
break;
case T_UNIFORM_MAP:
{
Map map = new HashMap();
int nKeyType = in.readPackedInt();
int nValType = in.readPackedInt();
int cEntries = in.readPackedInt();
for (int i = 0; i < cEntries; ++i)
{
Object oKey = readAsUniformObject(nKeyType);
Object oVal = readAsUniformObject(nValType);
map.put(oKey, oVal);
}
o = map;
}
break;
case T_IDENTITY:
{
int nId = in.readPackedInt();
nType = in.readPackedInt();
IdentityHolder.set(this, nId);
o = readAsObject(nType);
IdentityHolder.reset(this, nId, o);
}
break;
case T_REFERENCE:
o = lookupIdentity(in.readPackedInt());
break;
case V_BOOLEAN_FALSE:
o = Boolean.FALSE;
break;
case V_BOOLEAN_TRUE:
o = Boolean.TRUE;
break;
case V_STRING_ZERO_LENGTH:
o = "";
break;
case V_COLLECTION_EMPTY:
o = COLLECTION_EMPTY;
break;
case V_REFERENCE_NULL:
break;
default:
{
if (nType < 0)
{
throw new StreamCorruptedException("illegal type " + nType);
}
PofContext ctx = getPofContext();
PofSerializer ser;
try
{
ser = ctx.getPofSerializer(nType);
}
catch (IllegalArgumentException e)
{
throw new StreamCorruptedException(e.getMessage());
}
PofReader reader = new PofBufferReader.UserTypeReader(
this, in, ctx, nType, in.readPackedInt());
o = ExternalizableHelper.realize(ser.deserialize(reader), m_ctx);
}
break;
}
return o;
}
/**
* Read a POF value in a uniform array/map as an Object.
*
* @param nType the type identifier of the value
*
* @return an Object value
*
* @throws IOException if an I/O error occurs
*/
protected Object readAsUniformObject(int nType)
throws IOException
{
if (nType < 0)
{
return readAsObject(nType);
}
ReadBuffer.BufferInput in = m_in;
int of = in.getOffset();
int nId = -1;
if (of == 0)
{
return readAsObject(nType);
}
int nValue = in.readPackedInt();
if (nValue == T_IDENTITY)
{
nId = in.readPackedInt();
IdentityHolder.set(this, nId);
}
else
{
// it can only be reference if its data type supports reference
// (a user defined object)
if (nValue > 0 && nType >= 0)
{
Object o = ensureReferenceRegistry().get(nValue);
if (o != null)
{
// double check the object type
int nTypeId = PofHelper.getPofTypeId(o.getClass(), getPofContext());
if (nTypeId == nType)
{
return o;
}
}
}
in.setOffset(of);
}
Object o = readAsObject(nType);
if (nValue == T_IDENTITY)
{
IdentityHolder.reset(this, nId, o);
}
return o;
}
/**
* Read a POF value as an Object array.
*
* @param nType the type identifier of the value
* @param ao the optional array to use to store the values, or to use
* as a typed template for creating an array to store the
* values, following the documentation for
* {@link java.util.Collection#toArray(Object[]) Collection.toArray()}
*
* @return an Object array
*
* @throws IOException if an I/O error occurs
*/
protected Object[] readAsObjectArray(int nType, Object[] ao)
throws IOException
{
Object[] aoResult = null;
ReadBuffer.BufferInput in = m_in;
switch (nType)
{
case V_REFERENCE_NULL:
break;
case V_STRING_ZERO_LENGTH:
case V_COLLECTION_EMPTY:
aoResult = OBJECT_ARRAY_EMPTY;
break;
case T_COLLECTION:
case T_ARRAY:
{
int co = in.readPackedInt();
aoResult = resizeArray(ao, co);
for (int i = 0; i < co; ++i)
{
aoResult[i] = readAsObject(in.readPackedInt());
}
}
break;
case T_UNIFORM_COLLECTION:
case T_UNIFORM_ARRAY:
{
int nElementType = in.readPackedInt();
int co = in.readPackedInt();
aoResult = resizeArray(ao, co);
for (int i = 0; i < co; ++i)
{
aoResult[i] = readAsUniformObject(nElementType);
}
}
break;
case T_SPARSE_ARRAY:
{
int co = in.readPackedInt();
aoResult = resizeArray(ao, co);
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
aoResult[iElement] = readAsObject(in.readPackedInt());
}
while (--co >= 0);
}
break;
case T_UNIFORM_SPARSE_ARRAY:
{
int nElementType = in.readPackedInt();
int co = in.readPackedInt();
aoResult = resizeArray(ao, co);
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
aoResult[iElement] = readAsUniformObject(nElementType);
}
while (--co >= 0);
}
break;
default:
throw new IOException("unable to convert type " + nType
+ " to an array type");
}
return aoResult;
}
/**
* Read a POF value as an Object array.
*
* @param the identifier type
* @param nType the type identifier of the value
* @param factory the optional factory to use to initialize the array
*
* @return an Object array
*
* @throws IOException if an I/O error occurs
*/
protected T[] readAsTypedObjectArray(int nType, IntFunction factory)
throws IOException
{
T[] aoResult = null;
ReadBuffer.BufferInput in = m_in;
switch (nType)
{
case V_REFERENCE_NULL:
break;
case V_STRING_ZERO_LENGTH:
case V_COLLECTION_EMPTY:
aoResult = (T[]) OBJECT_ARRAY_EMPTY;
break;
case T_COLLECTION:
case T_ARRAY:
{
int co = in.readPackedInt();
aoResult = factory.apply(co);
for (int i = 0; i < co; ++i)
{
aoResult[i] = (T) readAsObject(in.readPackedInt());
}
}
break;
case T_UNIFORM_COLLECTION:
case T_UNIFORM_ARRAY:
{
int nElementType = in.readPackedInt();
int co = in.readPackedInt();
aoResult = factory.apply(co);
for (int i = 0; i < co; ++i)
{
aoResult[i] = (T) readAsUniformObject(nElementType);
}
}
break;
case T_SPARSE_ARRAY:
{
int co = in.readPackedInt();
aoResult = factory.apply(co);
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
aoResult[iElement] = (T) readAsObject(in.readPackedInt());
}
while (--co >= 0);
}
break;
case T_UNIFORM_SPARSE_ARRAY:
{
int nElementType = in.readPackedInt();
int co = in.readPackedInt();
aoResult = factory.apply(co);
do
{
int iElement = in.readPackedInt();
if (iElement < 0)
{
break;
}
aoResult[iElement] = (T) readAsUniformObject(nElementType);
}
while (--co >= 0);
}
break;
default:
throw new IOException("unable to convert type " + nType
+ " to an array type");
}
return aoResult;
}
/**
* Read a Binary object from the specified BufferInput in an optimal way,
* depending on the existence of an enclosing ReadBuffer.
*
* @param in a BufferInput to read from
*
* @return a Binary object
*
* @throws IOException if an I/O error occurs
*/
protected static Binary readBinary(ReadBuffer.BufferInput in)
throws IOException
{
int cb = in.readPackedInt();
ReadBuffer buf = in.getBuffer();
if (buf == null)
{
return in.readBuffer(cb).toBinary();
}
else
{
int of = in.getOffset();
Binary bin = buf.toBinary(of, cb);
in.skipBytes(cb); // skip after read to prevent pre-destruction
return bin;
}
}
// ----- inner class: UserTypeReader ------------------------------------
/**
* The UserTypeReader implementation is a contextually-aware PofReader
* whose purpose is to advance through the properties of a value of a
* specified user type. The "contextual awareness" refers to the fact that
* the UserTypeReader maintains state about the type identifier and
* version of the user type, the parser's property index position within
* the user type value, and a PofContext that may differ from the
* PofContext that provided the PofSerializer which is using this
* UserTypeReader to parse a user type.
*/
public static class UserTypeReader
extends PofBufferReader
{
// ----- constructors -------------------------------------------
/**
* Construct a parser for parsing the property values of a user type.
*
* @param in the BufferInput that contains the user type
* data, except for the user type id itself (which
* is passed passed as a constructor argument)
* @param ctx the PofContext to use for parsing the user type
* property values within the user type that this
* parser will be parsing
* @param nTypeId the type id of the user type
* @param nVersionId the version id of the user type
*
* @throws IOException if an I/O error occurs
*/
public UserTypeReader(
ReadBuffer.BufferInput in, PofContext ctx,
int nTypeId, int nVersionId)
throws IOException
{
this(null, in, ctx, nTypeId, nVersionId);
}
/**
* Construct a parser for parsing the property values of a user type.
*
* @param parent the parent (ie the containing) PofBufferReader
* @param in the BufferInput that contains the user type
* data, except for the user type id itself (which
* is passed passed as a constructor argument)
* @param ctx the PofContext to use for parsing the user type
* property values within the user type that this
* parser will be parsing
* @param nTypeId the type id of the user type
* @param nVersionId the version id of the user type
*
* @throws IOException if an I/O error occurs
*/
public UserTypeReader(PofBufferReader parent,
ReadBuffer.BufferInput in, PofContext ctx,
int nTypeId, int nVersionId)
throws IOException
{
super(in, ctx);
assert nTypeId >= 0;
assert nVersionId >= 0;
m_parent = parent;
m_nTypeId = nTypeId;
m_nVersionId = nVersionId;
// prime the property reader by knowing the offset of index of
// the next property to read
m_ofNextProp = in.getOffset();
int iProp = in.readPackedInt();
m_iNextProp = iProp < 0 ? EOPS : iProp;
}
/**
* Create a nested UserTypeReader, which will be initiated with the
* information found in the nested buffer.
*
* @param parent the parent (ie the containing) PofBufferReader
* @param in the BufferInput that contains the user type data
* @param ctx the PofContext to use for parsing the user type property
* values within the user type that this parser will be
* parsing
*
* @throws IOException if an I/O error occurs
*/
private UserTypeReader(PofBufferReader parent,
ReadBuffer.BufferInput in, PofContext ctx) throws IOException
{
super(in, ctx);
m_parent = parent;
// read the type and version directly from the buffer
m_nTypeId = in.readPackedInt();
m_nVersionId = in.readPackedInt();
// prime the property reader by knowing the offset of index of
// the next property to read
m_ofNextProp = in.getOffset();
int iProp = in.readPackedInt();
m_iNextProp = iProp < 0 ? EOPS : iProp;
}
/**
* Construct a parser for parsing a nested property that does not exist.
* In other words, this is a "no-op" user type reader.
*
* @param parent the parent (ie the containing) PofBufferReader
* @param in the BufferInput that contains the user type
* data, except for the user type id itself (which
* is passed passed as a constructor argument)
* @param ctx the PofContext to use for parsing the user type
* property values within the user type that this
* parser will be parsing
* @param nTypeId the type id of the user type
*
* @throws IOException if an I/O error occurs
*/
private UserTypeReader(PofBufferReader parent, ReadBuffer.BufferInput in,
PofContext ctx, int nTypeId)
throws IOException
{
super(in, ctx);
assert nTypeId >= 0;
m_parent = parent;
m_nTypeId = nTypeId;
m_nVersionId = 0;
// prime the property reader by knowing the offset of index of
// the next property to read
m_ofNextProp = in.getOffset();
m_iNextProp = EOPS;
}
// ----- PofReader interface ------------------------------------
/**
* {@inheritDoc}
*/
@Override public int getUserTypeId()
{
return m_nTypeId;
}
/**
* {@inheritDoc}
*/
@Override public int getVersionId()
{
return m_nVersionId;
}
/**
* {@inheritDoc}
*/
@Override public void registerIdentity(Object o)
{
PofBufferReader.IdentityHolder.reset(this, -1, o);
}
/**
* {@inheritDoc}
*/
@Override public PofReader createNestedPofReader(int iProp)
throws IOException
{
UserTypeReader reader;
if (advanceTo(iProp))
{
reader = new PofBufferReader.UserTypeReader(this, m_in,
getPofContext());
// note: there is no complete() call at this point, since the
// property has yet to be read
}
else
{
// nothing to read for that property
complete(iProp);
// return a "fake" reader that contains no data
reader = new PofBufferReader.UserTypeReader(this, m_in,
getPofContext(), getUserTypeId());
}
m_readerNested = reader;
m_iNestedProp = iProp;
return reader;
}
/**
* {@inheritDoc}
*/
@Override public Binary readRemainder()
throws IOException
{
// close nested buffer if it exists
closeNested();
// check if the property stream is already exhausted
int iNextProp = m_iNextProp;
if (iNextProp == EOPS)
{
return null;
}
// skip over all the remaining properties
ReadBuffer.BufferInput in = m_in;
ReadBuffer buf = in.getBuffer();
if (buf == null)
{
// if the BufferInput does not have an underlying ReadBuffer,
// we must use mark() and reset() to read the remaining
// properties; in this case, assume we need to reread as much
// data as theoretically possible
in.mark(Integer.MAX_VALUE);
}
int ofBegin = m_ofNextProp;
int ofEnd;
do
{
skipValue(in);
ofEnd = in.getOffset();
iNextProp = in.readPackedInt();
}
while (iNextProp != -1);
m_iNextProp = EOPS;
m_ofNextProp = ofEnd;
// return all the properties that were skipped
int cb = ofEnd - ofBegin;
if (buf == null)
{
in.reset();
return in.readBuffer(cb).toBinary();
}
else
{
return buf.toBinary(ofBegin, cb);
}
}
// ----- internal methods ---------------------------------------
/**
* Return the index of the most recent property read or (if it were
* missing) requested.
*
* @return the index of the most recent property read
*/
public int getPreviousPropertyIndex()
{
return m_iPrevProp;
}
/**
* Return the index of the next property in the POF stream.
*
* @return the index of the next property in the POF stream
*
* @throws IOException if an I/O error occurs
*/
public int getNextPropertyIndex()
throws IOException
{
closeNested();
return m_iNextProp == EOPS ? -1 : m_iNextProp;
}
/**
* {@inheritDoc}
*/
@Override protected boolean advanceTo(int iProp)
throws IOException
{
// if a nested writer is still open, then "end" that property
closeNested();
// the terminating index is -1; if searching for -1, re-order the
// goal to come after all other properties (which assumes that
// there is no valid property index Integer.MAX_VALUE)
if (iProp == -1)
{
iProp = EOPS;
}
// check for backwards movement
if (iProp <= m_iPrevProp)
{
throw new IllegalStateException("previous property index="
+ m_iPrevProp + ", requested property index=" + iProp
+ " while reading user type " + getUserTypeId());
}
// check if the stream is already in the correct location
// (common case)
int iNextProp = m_iNextProp;
if (iProp == iNextProp)
{
return true;
}
ReadBuffer.BufferInput in = m_in;
int ofNextProp = m_ofNextProp;
while (iNextProp != EOPS && iNextProp < iProp)
{
skipValue(in);
ofNextProp = in.getOffset();
iNextProp = in.readPackedInt();
if (iNextProp < 0)
{
iNextProp = EOPS;
}
}
m_ofNextProp = ofNextProp;
m_iNextProp = iNextProp;
return iProp == iNextProp;
}
/**
* {@inheritDoc}
*/
@Override protected void complete(int iProp)
throws IOException
{
if (m_iNextProp == iProp)
{
ReadBuffer.BufferInput in = m_in;
m_ofNextProp = in.getOffset();
int iNextProp = in.readPackedInt();
m_iNextProp = iNextProp < 0 ? EOPS : iNextProp;
}
m_iPrevProp = iProp;
}
/**
* Notify the UserTypeReader that it is being "closed".
*
* @throws IOException if an I/O error occurs
*/
protected void closeNested()
throws IOException
{
// check if a nested PofReader is open
UserTypeReader readerNested = m_readerNested;
if (readerNested != null)
{
// check if there is some remainder that haven't been skipped
if (readerNested.m_iNextProp != EOPS)
{
readerNested.readRemainder();
}
// close it
readerNested.closeNested();
// finish reading the property that the nested PofReader was
// reading from; this is the "complete()" call that was
// deferred when the nested stream was opened
complete(m_iNestedProp);
m_readerNested = null;
m_iNestedProp = -1;
}
}
/**
* {@inheritDoc}
*/
@Override protected PofBufferReader getParentParser()
{
return m_parent;
}
// ----- constants ----------------------------------------------
/**
* Fake End-Of-Property-Stream indicator.
*/
private static final int EOPS = Integer.MAX_VALUE;
// ----- data members -------------------------------------------
/**
* The parent (ie containing) PofBufferReader.
*/
private PofBufferReader m_parent;
/**
* The type identifier of the user type that is being parsed.
*/
private int m_nTypeId;
/**
* The version identifier of the user type that is being parsed.
*/
private int m_nVersionId;
/**
* Most recent property read or (if it were missing) requested. This
* is used to determine if the client is attempting to read properties
* in the wrong order.
*/
private int m_iPrevProp = -1;
/**
* The index of the next property in the POF stream.
*/
private int m_iNextProp;
/**
* The offset of the index of the next property to read.
*/
private int m_ofNextProp;
/**
* The currently open nested reader, if any.
*/
private UserTypeReader m_readerNested;
/**
* The property index of the property from which the currently open
* nested reader is reading from.
*/
private int m_iNestedProp;
}
// ----- inner class: IdentityHolder ------------------------------------
public static class IdentityHolder
{
private static ThreadLocal s_mapId = new ThreadLocal()
{
@Override protected synchronized Object initialValue()
{
return new HashMap();
}
};
public static void set(PofBufferReader reader, int nId)
{
Map mapId = (Map) s_mapId.get();
mapId.put(reader, Integer.valueOf(nId));
}
public static void reset(PofBufferReader reader, int nId, Object o)
{
Map mapId = (Map) s_mapId.get();
if (!mapId.isEmpty())
{
while (reader != null)
{
Object oValue = mapId.get(reader);
if (oValue != null)
{
int nValue = ((Integer) oValue).intValue();
if (nId == -1 || nValue == nId)
{
reader.registerIdentity(nValue, o);
mapId.remove(reader);
}
break;
}
reader = reader.getParentParser();
}
}
}
}
// ----- data members ---------------------------------------------------
/**
* The BufferInput containing the POF stream.
*/
protected ReadBuffer.BufferInput m_in;
/**
* The PofContext to use to realize user data types as Java objects.
*/
protected PofContext m_ctx;
/**
* Lazily-constructed mapping of identities to references.
*/
protected LongArray m_arrayRefs;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy