org.nustaq.serialization.coders.FSTBytezDecoder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fst Show documentation
Show all versions of fst Show documentation
A fast java serialization drop in-replacement and some serialization based utils such as Structs and OffHeap Memory.
/*
* Copyright 2014 Ruediger Moeller.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.nustaq.serialization.coders;
import java.io.*;
import org.nustaq.offheap.bytez.*;
import org.nustaq.offheap.bytez.onheap.*;
import org.nustaq.serialization.*;
import org.nustaq.serialization.util.*;
/**
* Created by ruedi on 09.11.2014.
*
* uses unsafe to read values directly from memory instead an inputstream. no value compression is applied.
*
*/
public class FSTBytezDecoder implements FSTDecoder {
BasicBytez input;
HeapBytez ascStringCache;
FSTConfiguration conf;
public FSTClazzNameRegistry clnames;
long pos;
InputStream inputStream;
long readUntil = 0;
public FSTBytezDecoder(FSTConfiguration conf, BasicBytez input) {
this(conf);
if ( FSTConfiguration.isAndroid )
throw new RuntimeException("not supported on android");
this.input = input;
}
@Override
public void setConf(FSTConfiguration conf) {
this.conf = conf;
}
public FSTBytezDecoder(FSTConfiguration conf) {
this.conf = conf;
clnames = (FSTClazzNameRegistry) conf.getCachedObject(FSTClazzNameRegistry.class);
if (clnames == null) {
clnames = new FSTClazzNameRegistry(conf.getClassRegistry());
} else {
clnames.clear();
}
}
byte tmp[];
public int ensureReadAhead(int bytes) {
if ( inputStream != null ) {
if ( pos+bytes > readUntil ) {
return readNextInputChunk(bytes);
}
} else if ( pos+bytes > input.length() ) {
return -1;
}
return 0;
}
protected int readNextInputChunk(int bytes) {
try {
int toRead = Math.min(Integer.MAX_VALUE - 5, bytes);
if ( inputStream instanceof ByteArrayInputStream ) {
toRead = Math.min(((ByteArrayInputStream) inputStream).available(),toRead);
}
if ( tmp == null || tmp.length < toRead ) {
tmp = new byte[toRead];
}
int read = inputStream.read(tmp, 0, toRead);
if ( read > 0 ) {
if ( input.length() < pos+read ) {
BasicBytez bytez = input.newInstance(2*(pos + read));
input.copyTo(bytez,0,0,pos);
input = (HeapBytez) bytez;
}
input.set(pos,tmp,0,read);
readUntil = pos+read;
return read;
} else if ( read == -1 )
return -1;
// fixme: should loop in case read == 0
} catch (IOException e) {
FSTUtil.rethrow(e);
}
return 0;
}
char chBufS[];
char[] getCharBuf(int siz) {
char chars[] = chBufS;
if (chars == null || chars.length < siz) {
chars = new char[Math.max(siz, 15)];
chBufS = chars;
}
return chars;
}
public String readStringUTF() throws IOException {
int len = readFInt();
char[] charBuf = getCharBuf(len * 2);
ensureReadAhead(len*2);
input.getCharArr(pos,charBuf,0,len);
pos += len*2;
return new String(charBuf, 0, len);
}
public byte readObjectHeaderTag() throws IOException {
return readFByte();
}
/**
* len < 127 !!!!!
*
* @return
* @throws java.io.IOException
*/
@Override
public String readStringAsc() throws IOException {
int len = readFInt();
if (ascStringCache == null || ascStringCache.length() < len)
ascStringCache = new HeapBytez(new byte[len]);
ensureReadAhead(len);
// System.arraycopy(input.buf, input.pos, ascStringCache, 0, len);
input.copyTo(ascStringCache, 0, pos, len);
pos += len;
return new String(ascStringCache.getBase(), 0, 0, len);
}
public BasicBytez getInput() {
return input;
}
public void setInput(BasicBytez input) {
this.input = input;
}
/**
* assumes class header+len already read
*
* @param componentType
* @param len
* @return
*/
@Override
public Object readFPrimitiveArray(Object array, Class componentType, int len) {
// FIXME: if else chaining could be avoided
if (componentType == byte.class) {
ensureReadAhead(len);
byte arr[] = (byte[]) array;
input.getArr(pos, arr, 0, len);
pos += len;
return arr;
} else if (componentType == char.class) {
ensureReadAhead(len*2);
char[] arr = (char[]) array;
input.getCharArr(pos, arr, 0, len);
pos += len * 2;
return arr;
} else if (componentType == short.class) {
ensureReadAhead(len*2);
short[] arr = (short[]) array;
input.getShortArr(pos, arr, 0, len);
pos += len * 2;
return arr;
} else if (componentType == int.class) {
ensureReadAhead(len*4);
int[] arr = (int[]) array;
input.getIntArr(pos, arr, 0, len);
pos += len * 4;
return arr;
} else if (componentType == float.class) {
ensureReadAhead(len*4);
float[] arr = (float[]) array;
input.getFloatArr(pos, arr, 0, len);
pos += len * 4;
return arr;
} else if (componentType == double.class) {
ensureReadAhead(len*8);
double[] arr = (double[]) array;
input.getDoubleArr(pos, arr, 0, len);
pos += len * 8;
return arr;
} else if (componentType == long.class) {
ensureReadAhead(len*8);
long[] arr = (long[]) array;
input.getLongArr(pos, arr, 0, len);
pos += len * 8;
return arr;
} else if (componentType == boolean.class) {
ensureReadAhead(len);
boolean[] arr = (boolean[]) array;
input.getBooleanArr(pos, arr, 0, len);
pos += len;
return arr;
} else {
throw new RuntimeException("unexpected primitive type " + componentType.getName());
}
}
@Override
public void readFIntArr(int len, int[] arr) throws IOException {
input.getIntArr(pos, arr, 0, len);
pos += len * 4;
}
@Override
public int readFInt() throws IOException {
return readPlainInt();
}
@Override
public double readFDouble() throws IOException {
return Double.longBitsToDouble(readPlainLong());
}
/**
* Reads a 4 byte float.
*/
@Override
public float readFFloat() throws IOException {
return Float.intBitsToFloat(readPlainInt());
}
@Override
public final byte readFByte() throws IOException {
ensureReadAhead(1);
return input.get(pos++);
}
@Override
public int readIntByte() throws IOException {
final int res = ensureReadAhead(1);
if ( res == -1 )
return -1;
return input.get(pos++) & 0xff;
}
@Override
public long readFLong() throws IOException {
return readPlainLong();
}
@Override
public char readFChar() throws IOException {
return readPlainChar();
}
@Override
public short readFShort() throws IOException {
return readPlainShort();
}
private char readPlainChar() throws IOException {
ensureReadAhead(2);
char res = input.getChar(pos);
pos += 2;
return res;
}
private short readPlainShort() throws IOException {
ensureReadAhead(2);
short res = input.getShort(pos);
pos += 2;
return res;
}
@Override
public int readPlainInt() throws IOException {
ensureReadAhead(4);
int res = input.getInt(pos);
pos += 4;
return res;
}
private long readPlainLong() throws IOException {
ensureReadAhead(8);
long res = input.getLong(pos);
pos += 8;
return res;
}
@Override
public byte[] getBuffer() {
if ( input instanceof HeapBytez && ((HeapBytez) input).getOffsetIndex() == 0 ) {
return ((HeapBytez) input).asByteArray();
}
byte res[] = new byte[(int) pos];
input.getArr(0,res,0, (int) pos);
return res;
}
@Override
public int getInputPos() {
return (int) pos;
}
@Override
public void moveTo(int position) {
pos = position;
}
@Override
public void reset() {
pos = 0;
clnames.clear();
inputStream = null;
}
@Override
public void setInputStream(InputStream in) {
if ( in == FSTObjectInput.emptyStream ) {
inputStream = null;
readUntil = 0;
return;
}
this.inputStream = in;
clnames.clear();
pos = 0;
if ( input == null )
input = new HeapBytez(new byte[4096]);
readUntil = 0;
}
@Override
public void resetToCopyOf(byte[] bytes, int off, int len) {
inputStream = null;
if ( input == null ) {
byte[] base = new byte[len];
input = new HeapBytez(base,0,len);
}
if ( input.length() < len )
{
input = (HeapBytez) input.newInstance(len);
}
input.set(0, bytes, off, len);
pos = 0;
clnames.clear();
}
@Override
public void resetWith(byte[] bytes, int len) {
inputStream = null;
if ( input == null ) {
input = new HeapBytez(bytes,0,len);
return;
}
// suboptimal method for non heap backing
if ( input.getClass() == HeapBytez.class ) {
((HeapBytez)input).setBase(bytes,0,len);
} else {
BasicBytez newBytez = input.newInstance(len);
newBytez.set(0,bytes,0,len);
}
pos = 0;
clnames.clear();
}
@Override
public FSTClazzInfo readClass() throws IOException, ClassNotFoundException {
return clnames.decodeClass(this,conf);
}
@Override
public Class classForName(String name) throws ClassNotFoundException {
return clnames.classForName(name,conf);
}
@Override
public void registerClass(Class possible) {
clnames.registerClass(possible,conf);
}
@Override
public void close() {
conf.returnObject(clnames);
}
@Override
public void skip(int n) {
pos += n;
}
@Override
public void readPlainBytes(byte[] b, int off, int len) {
ensureReadAhead(len);
// System.arraycopy(input.buf,input.pos,b,off,len);
input.getArr(pos, b, off, len);
pos += len;
}
@Override
public boolean isMapBased() {
return false;
}
@Override
public Object getDirectObject() // in case class already resolves to read object (e.g. mix input)
{
return null;
}
@Override
public int getObjectHeaderLen() {
return -1;
}
@Override
public void consumeEndMarker() {
}
@Override
public Class readArrayHeader() throws Exception {
return readClass().getClazz();
}
@Override
public void readExternalEnd() {
// do nothing for direct encoding
}
@Override
public boolean isEndMarker(String s) {
return false;
}
@Override
public int readVersionTag() throws IOException {
return readFByte();
}
@Override
public void pushBack(int bytes) {
pos -= bytes;
}
@Override
public void readArrayEnd(FSTClazzInfo clzSerInfo) {}
@Override
public void readObjectEnd() {}
@Override
public Object coerceElement(Class arrType, Object value) {
return value;
}
@Override
public int available() {
return (int) (input.length()-pos);
}
@Override
public boolean inArray() {
return false;
}
@Override
public void startFieldReading(Object newObj) {
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy