package org.zoodb.internal; import java.nio.ByteBuffer; import java.nio.CharBuffer; import org.zoodb.internal.server.DiskIO; public class GenericObjectReader implements SerialInput, DiskIO { private final ByteBuffer buf; //The header is only written in auto-paging mode private long pageHeader = -1; private long txTimestamp = -1; //TODO remove this private static final int MAX_POS = Integer.MAX_VALUE; public GenericObjectReader(ByteBuffer ba) { buf = ba; pageHeader = buf.getLong(); txTimestamp = buf.getLong(); } @Override public String readString() { checkPosRead(4); int len = buf.getInt(); //Align for 2-byte writing int p = buf.position(); if ((p & 0x00000001) == 1) { buf.position(p+1); } char[] array = new char[len]; CharBuffer cb = buf.asCharBuffer(); int l = array.length; int posA = 0; //position in array while (l > 0) { checkPosRead(2); int getLen = MAX_POS - buf.position(); getLen = getLen >> 1; if (getLen > l) { getLen = l; } cb = buf.asCharBuffer(); //create a buffer at the correct position cb.get(array, posA, getLen); buf.position(buf.position()+getLen*2); posA += getLen; l -= getLen; } return String.valueOf(array); //return String.copyValueOf(array); //return new String(array); } @Override public boolean readBoolean() { return readByte() != 0; } @Override public byte readByte() { checkPosRead(S_BYTE); return buf.get(); } @Override public char readChar() { if (!checkPos(S_CHAR)) { return readByteBuffer(S_CHAR).getChar(); } return buf.getChar(); } @Override public double readDouble() { if (!checkPos(S_DOUBLE)) { return Double.longBitsToDouble(readLong()); } return buf.getDouble(); } @Override public float readFloat() { if (!checkPos(S_FLOAT)) { return Float.intBitsToFloat(readInt()); } return buf.getFloat(); } @Override public void readFully(byte[] array) { int l = array.length; int posA = 0; //position in array while (l > 0) { checkPosRead(1); int getLen = MAX_POS - buf.position(); if (getLen > l) { getLen = l; } buf.get(array, posA, getLen); posA += getLen; l -= getLen; } } @Override public int readInt() { if (!checkPos(S_INT)) { return readByteBuffer(S_INT).getInt(); } return buf.getInt(); } @Override public long readLong() { if (!checkPos(S_LONG)) { return readByteBuffer(S_LONG).getLong(); } // checkPosRead(S_LONG); return buf.getLong(); } @Override public short readShort() { if (!checkPos(S_SHORT)) { return readByteBuffer(S_SHORT).getShort(); } return buf.getShort(); } private ByteBuffer readByteBuffer(int len) { byte[] ba = new byte[len]; readFully(ba); return ByteBuffer.wrap(ba); } private boolean checkPos(int delta) { //TODO remove autopaging, the indices use anyway the noCheckMethods!! //TODO -> otherwise, make it final, as it should be known when a view is constructed. return true; } private void checkPosRead(int delta) { //TODO remove? } @Override public void skipRead(int nBytes) { int l = nBytes; while (l > 0) { checkPosRead(1); int bPos = buf.position(); int putLen = MAX_POS - bPos; if (putLen > l) { putLen = l; } buf.position(bPos + putLen); l -= putLen; } } @Override public long getHeaderClassOID() { return pageHeader; } @Override public long getHeaderTimestamp() { return txTimestamp; } }