org.nustaq.serialization.coders.FSTBytezEncoder 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 org.nustaq.offheap.bytez.BasicBytez;
import org.nustaq.offheap.bytez.onheap.HeapBytez;
import org.nustaq.serialization.*;
import org.nustaq.serialization.simpleapi.FSTBufferTooSmallException;
import org.nustaq.serialization.util.FSTUtil;
import java.io.IOException;
import java.io.OutputStream;
/**
* Created by ruedi on 08.11.2014.
*
* Enables serialization to arbitrary byte oriented memory
*
* no compression is applied, so writeFxx == writePlainXX
*/
public class FSTBytezEncoder implements FSTEncoder {
private FSTConfiguration conf;
private FSTClazzNameRegistry clnames;
private BasicBytez buffout;
private long pos;
private byte[] ascStringCache;
OutputStream outStream;
boolean autoResize = true;
public FSTBytezEncoder(FSTConfiguration conf, BasicBytez base) {
if ( FSTConfiguration.isAndroid )
throw new RuntimeException("not supported on android");
this.conf = conf;
buffout = base;
clnames = (FSTClazzNameRegistry) conf.getCachedObject(FSTClazzNameRegistry.class);
if ( clnames == null ) {
clnames = new FSTClazzNameRegistry(conf.getClassRegistry());
} else {
clnames.clear();
}
}
@Override
public void setConf(FSTConfiguration conf) {
this.conf = conf;
}
void writeFBooleanArr(boolean[] arr, int off, int len) throws IOException {
ensureFree(len);
buffout.setBoolean(pos,arr,off,len);
pos += len;
}
public void writeFFloatArr(float[] arr, int off, int len) throws IOException {
ensureFree(4*len);
buffout.setFloat(pos, arr, off, len);
pos += 4*len;
}
public void writeFDoubleArr(double[] arr, int off, int len) throws IOException {
ensureFree(8*len);
buffout.setDouble(pos,arr,off,len);
pos += 8 * len;
}
public void writeFShortArr(short[] arr, int off, int len) throws IOException {
ensureFree(2*len);
buffout.setShort(pos, arr, off, len);
pos += 2 * len;
}
public void writeFCharArr(char[] arr, int off, int len) throws IOException {
ensureFree(2*len);
buffout.setChar(pos,arr,off,len);
pos += 2 * len;
}
void writeFIntArr(int[] arr, int off, int len) throws IOException {
ensureFree(4*len);
buffout.setInt(pos, arr, off, len);
pos += 4 * len;
}
void writeFLongArr(long[] arr, int off, int len) throws IOException {
ensureFree(8*len);
buffout.setLong(pos, arr, off, len);
pos += 8 * len;
}
/**
* write prim array no len no tag
*
*
* @param array
* @throws IOException
*/
public void writePrimitiveArray(Object array, int off, int len) throws IOException {
Class> componentType = array.getClass().getComponentType();
if ( componentType == byte.class ) {
writeRawBytes((byte[]) array, off, len);
} else
if ( componentType == char.class ) {
writeFCharArr((char[]) array, off, len);
} else
if ( componentType == short.class ) {
writeFShortArr((short[]) array, off, len);
} else
if ( componentType == int.class ) {
writeFIntArr((int[]) array, off, len);
} else
if ( componentType == double.class ) {
writeFDoubleArr((double[]) array, off, len);
} else
if ( componentType == float.class ) {
writeFFloatArr((float[]) array, off, len);
} else
if ( componentType == long.class ) {
writeFLongArr((long[]) array, off, len);
} else
if ( componentType == boolean.class ) {
writeFBooleanArr((boolean[]) array, off, len);
} else {
throw new RuntimeException("expected primitive array");
}
}
/**
* does not write length, just plain bytes
*
* @param array
* @param length
* @throws java.io.IOException
*/
public void writeRawBytes(byte[] array, int start, int length) throws IOException {
ensureFree((int) (pos+length));
buffout.set(pos,array,start,length);
pos += length;
}
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;
}
@Override
public void writeStringUTF(String str) throws IOException {
final int strlen = str.length();
writeFInt(strlen);
ensureFree(strlen*2);
char c[] = getCharBuf(strlen);
str.getChars(0,strlen,c,0);
buffout.setChar(pos,c,0,strlen);
pos += strlen*2;
}
@Override
public void writeFShort(short c) throws IOException {
writePlainShort(c);
}
public void writeAttributeName(FSTClazzInfo.FSTFieldInfo subInfo) {
}
public boolean writeTag(byte tag, Object info, long somValue, Object toWrite, FSTObjectOutput oout) throws IOException {
writeFByte(tag);
return false;
}
@Override
public void writeFChar(char c) throws IOException {
writePlainChar(c);
}
@Override
public final void writeFByte(int v) throws IOException {
ensureFree(1);
buffout.put(pos++, (byte) v);
}
@Override
public void writeFInt(int anInt) throws IOException {
writePlainInt(anInt);
}
@Override
public void writeFLong(long anInt) throws IOException {
writePlainLong(anInt);
}
/**
* Writes a 4 byte float.
*/
@Override
public void writeFFloat(float value) throws IOException {
writePlainInt(Float.floatToIntBits(value));
}
@Override
public void writeFDouble(double value) throws IOException {
writePlainLong(Double.doubleToLongBits(value));
}
@Override
public int getWritten() {
return (int) pos;
}
/**
* close and flush to underlying stream if present. The stream is also closed
* @throws IOException
*/
@Override
public void close() throws IOException {
conf.returnObject(clnames);
}
@Override
public void reset(byte[] out) {
pos = 0;
clnames.clear();
if (out!=null)
throw new RuntimeException("not implemented");
}
@Override
public void skip(int i) {
pos+=i;
}
/**
* used to write uncompressed int (guaranteed length = 4) at a (eventually recent) position
* @param position
* @param v
*/
@Override
public void writeInt32At(int position, int v) {
try {
ensureFree( position+4);
} catch (IOException e) {
FSTUtil.rethrow(e);
}
buffout.putInt(position,v);
}
/**
* if output stream is null, just encode into a byte array
* @param outstream
*/
@Override
public void setOutstream(OutputStream outstream) {
this.outStream = outstream;
}
/**
* writes current buffer to underlying output and resets buffer.
* @throws IOException
*/
@Override
public void flush() throws IOException {
if ( outStream != null )
outStream.write(getBuffer(), 0, (int) pos);
pos = 0;
}
@Override
public void ensureFree(int bytes) throws IOException {
if ( buffout.length() <= pos+bytes) {
if ( autoResize ) {
BasicBytez newbytez = buffout.newInstance(Math.max(pos + bytes, Math.min(Integer.MAX_VALUE-10, buffout.length() * 2)));
buffout.copyTo(newbytez, 0, 0, pos);
// debug
// for ( int i = 0; i < pos; i++) {
// if ( buffout.get(i) != newbytez.get(i) ) {
// throw new RuntimeException("error");
// }
// }
buffout = newbytez;
} else {
throw FSTBufferTooSmallException.Instance;
}
}
}
// default is true
public boolean isAutoResize() {
return autoResize;
}
public void setAutoResize(boolean autoResize) {
this.autoResize = autoResize;
}
@Override
public byte[] getBuffer() {
if (isPlainBAAccessible()) {
return ((HeapBytez) buffout).asByteArray();
}
byte res[] = new byte[(int) pos];
buffout.getArr(0,res,0, (int) pos);
return res;
}
protected boolean isPlainBAAccessible() {
return buffout.getClass() == HeapBytez.class && ((HeapBytez) buffout).getOffsetIndex() == 0;
}
public void registerClass(Class possible) {
clnames.registerClass(possible,conf);
}
@Override
public final void writeClass(Class cl) {
try {
clnames.encodeClass(this,cl);
} catch ( IOException e) {
FSTUtil.rethrow(e);
}
}
@Override
public final void writeClass(FSTClazzInfo clInf) {
try {
clnames.encodeClass(this, clInf);
} catch ( IOException e) {
FSTUtil.rethrow(e);
}
}
private void writePlainLong(long v) throws IOException {
ensureFree(8);
buffout.putLong(pos,v);
pos += 8;
}
private void writePlainShort(int v) throws IOException {
ensureFree(2);
buffout.putShort(pos, (short) v);
pos += 2;
}
private void writePlainChar(int v) throws IOException {
ensureFree(2);
buffout.putChar(pos, (char) v);
pos += 2;
}
private void writePlainInt(int v) throws IOException {
ensureFree(4);
buffout.putInt(pos, v);
pos += 4;
}
public void externalEnd(FSTClazzInfo clz) {
}
@Override
public boolean isWritingAttributes() {
return false;
}
public boolean isPrimitiveArray(Object array, Class> componentType) {
return componentType.isPrimitive();
}
public boolean isTagMultiDimSubArrays() {
return false;
}
@Override
public void writeVersionTag(int version) throws IOException {
writeFByte(version);
}
@Override
public boolean isByteArrayBased() {
return false || isPlainBAAccessible();
}
@Override
public void writeArrayEnd() {
}
@Override
public void writeFieldsEnd(FSTClazzInfo serializationInfo) {
}
@Override
public FSTConfiguration getConf() {
return conf;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy