All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zoodb.jdo.internal.GenericObjectWriter Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2009-2013 Tilmann Zaeschke. All rights reserved.
 * 
 * This file is part of ZooDB.
 * 
 * ZooDB is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * ZooDB is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with ZooDB.  If not, see .
 * 
 * See the README and COPYING files for further information. 
 */
package org.zoodb.jdo.internal;

import java.nio.ByteBuffer;
import java.nio.CharBuffer;

import org.zoodb.jdo.internal.server.DiskIO;
import org.zoodb.jdo.internal.server.ObjectWriter;


/**
 * 
 * @author Tilmann Zaschke
 *
 */
class GenericObjectWriter implements ObjectWriter, DiskIO {

	private ByteBuffer buf;
	private final long headerClassOid;
	
	private int MAX_POS;
	
	public GenericObjectWriter(int nBytes, long clsOid) {
		this.buf = ByteBuffer.allocate(nBytes);
        this.headerClassOid = clsOid;
        this.MAX_POS = nBytes;
	}

	@Override
	public void startObject(long oid, int prevSchemaVersion) {
		//nothing to do...
	}

	@Override
	public void finishObject() {
		//nothing to do...
	}
	
	/**
	 * This can be necessary when subsequent objects are of a different class.
	 */
	@Override
	public void newPage() {
		writeHeader();
	}

	private void writeHeader() {
		writeLong(headerClassOid);
	}
	
	@Override
	public void writeString(String string) {
        checkPosWrite(4);
        buf.putInt(string.length());

        //Align for 2-byte writing
        int p = buf.position();
        if ((p & 0x00000001) == 1) {
            buf.position(p+1);
        }
        
        CharBuffer cb;
        int l = string.length();
        int posA = 0; //position in array
        while (l > 0) {
            checkPosWrite(2);
            int putLen = MAX_POS - buf.position();
            putLen = putLen >> 1; //TODO loses odd values!
            if (putLen > l) {
                putLen = l;
            }
            //This is crazy!!! Unlike ByteBuffer, CharBuffer requires END as third param!!
            cb = buf.asCharBuffer();
            cb.put(string, posA, posA + putLen);
            buf.position(buf.position() + putLen * 2);

            posA += putLen;
            l -= putLen;
        }
	}

	@Override
	public void write(byte[] array) {
		int l = array.length;
		int posA = 0; //position in array
		while (l > 0) {
		    checkPosWrite(1);
		    int putLen = MAX_POS - buf.position();
		    if (putLen > l) {
		        putLen = l;
		    }
		    buf.put(array, posA, putLen);
		    posA += putLen;
		    l -= putLen;
		}
	}

	@Override
	public void writeBoolean(boolean boolean1) {
		writeByte((byte) (boolean1 ? 1 : 0));
	}

	@Override
	public void writeByte(byte byte1) {
		checkPosWrite(S_BYTE);
		buf.put(byte1);
	}

	@Override
	public void writeChar(char char1) {
		if (!checkPos(S_CHAR)) {
			write(ByteBuffer.allocate(S_CHAR).putChar(char1).array());
			return;
		}
		buf.putChar(char1);
	}

	@Override
	public void writeDouble(double double1) {
		if (!checkPos(S_DOUBLE)) {
			writeLong(Double.doubleToLongBits(double1));
			return;
		}
		buf.putDouble(double1);
	}

	@Override
	public void writeFloat(float float1) {
		if (!checkPos(S_FLOAT)) {
			writeInt(Float.floatToIntBits(float1));
			return;
		}
		buf.putFloat(float1);
	}

	@Override
	public void writeInt(int int1) {
		if (!checkPos(S_INT)) {
			write(ByteBuffer.allocate(S_INT).putInt(int1).array());
			return;
		}
		buf.putInt(int1);
	}

	@Override
	public void writeLong(long long1) {
		if (!checkPos(S_LONG)) {
			write(ByteBuffer.allocate(S_LONG).putLong(long1).array());
			return;
		}
		buf.putLong(long1);
	}

	@Override
	public void writeShort(short short1) {
		if (!checkPos(S_SHORT)) {
			write(ByteBuffer.allocate(S_SHORT).putShort(short1).array());
			return;
		}
		buf.putShort(short1);
	}
	
	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.
//		if (isAutoPaging) {
//			return (buf.position() + delta - MAX_POS) <= 0;
//		}
		return true;
	}

	private void checkPosWrite(int delta) {
		if (buf.position() + delta > MAX_POS) {
			MAX_POS = buf.capacity()*2 + delta;
		    System.err.println("FIXME: Resizing buffer (internally)! " + MAX_POS);
			ByteBuffer b2 = ByteBuffer.allocate(MAX_POS);
			buf.flip();
			b2.put(buf);
			buf = b2;
			//throw new ArrayIndexOutOfBoundsException((buf.position() + delta) + " > " + MAX_POS);
		}
	}

	@Override
	public void skipWrite(int nBytes) {
	    int l = nBytes;
	    while (l > 0) {
	        checkPosWrite(1);
	        int bPos = buf.position();
	        int putLen = MAX_POS - bPos;
	        if (putLen > l) {
	            putLen = l;
	        }
	        buf.position(bPos + putLen);
	        l -= putLen;
	    }
	}

	@Override
	public void flush() {
		//nothing to do...
	}

	public ByteBuffer toByteArray() {
		return buf;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy