/* This file is part of the db4o object database http://www.db4o.com
Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com
db4o is free software; you can redistribute it and/or modify it under
the terms of version 3 of the GNU General Public License as published
by the Free Software Foundation.
db4o 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 this program. If not, see http://www.gnu.org/licenses/. */
package com.db4o.internal;
import com.db4o.*;
import com.db4o.ext.*;
import com.db4o.foundation.*;
import com.db4o.internal.encoding.*;
import com.db4o.internal.handlers.*;
/**
*
* @exclude
*/
public class ByteArrayBuffer implements ReadWriteBuffer {
private static final ThreadLocal<Boolean> _checkXBytes = Debug4.xbytes ? new ThreadLocal<Boolean>() : null;
// for coding convenience, we allow objects to grab into the buffer
public byte[] _buffer;
public int _offset;
ByteArrayBuffer(){
if(Debug4.xbytes){
checkXBytes(true);
}
}
public ByteArrayBuffer(int length){
this();
_buffer = new byte[length];
}
public ByteArrayBuffer(byte[] buffer){
this();
_buffer = buffer;
}
public void seek(int offset) {
_offset = offset;
}
public void writeBytes(byte[] bytes) {
System.arraycopy(bytes, 0, _buffer, _offset, bytes.length);
_offset += bytes.length;
}
// TODO: Change all callers to call writeBytes directly.
public void append(byte[] bytes) {
writeBytes(bytes);
}
public final boolean containsTheSame(ByteArrayBuffer other) {
if (other != null) {
return Arrays4.equals(_buffer, other._buffer);
}
return false;
}
public void copyTo(ByteArrayBuffer to, int fromOffset, int toOffset, int length) {
System.arraycopy(_buffer, fromOffset, to._buffer, toOffset, length);
}
public int length() {
return _buffer.length;
}
public void incrementOffset(int a_by) {
_offset += a_by;
}
/**
* non-encrypted read, used for indexes
*/
public void read(ObjectContainerBase stream, int address, int addressOffset){
stream.readBytes(_buffer, address, addressOffset, length());
}
public final void readBegin(byte identifier) {
if (Deploy.debug) {
Debug4.readBegin(this, identifier);
}
}
public BitMap4 readBitMap(int bitCount){
BitMap4 map = new BitMap4(_buffer, _offset, bitCount);
_offset += map.marshalledLength();
return map;
}
public byte readByte() {
return _buffer[_offset++];
}
public byte[] readBytes(int a_length){
byte[] bytes = new byte[a_length];
readBytes(bytes);
return bytes;
}
public void readBytes(byte[] bytes) {
int length = bytes.length;
System.arraycopy(_buffer, _offset, bytes, 0, length);
_offset += length;
}
public final ByteArrayBuffer readEmbeddedObject(Transaction trans) throws Db4oIOException {
int address = readInt();
int length = readInt();
if(address == 0){
return null;
}
return trans.container().decryptedBufferByAddress(address, length);
}
public void readEncrypt(ObjectContainerBase stream, int address) throws Db4oIOException {
stream.readBytes(_buffer, address, length());
stream._handlers.decrypt(this);
}
public void readEnd() {
if(Deploy.debug){
Debug4.readEnd(this);
}
}
public final int readInt() {
if (Deploy.debug) {
int ret = 0;
readBegin(Const4.YAPINTEGER);
if (Deploy.debugLong) {
ret =
Integer.valueOf(new LatinStringIO().read(this, Const4.INTEGER_BYTES).trim())
.intValue();
} else {
for (int i = 0; i < Const4.INTEGER_BYTES; i++) {
ret = (ret << 8) + (_buffer[_offset++] & 0xff);
}
}
readEnd();
return ret;
}
int o = (_offset += 4) - 1;
return (_buffer[o] & 255) | (_buffer[--o] & 255)
<< 8 | (_buffer[--o] & 255)
<< 16 | _buffer[--o]
<< 24;
}
public long readLong() {
return LongHandler.readLong(this);
}
public ByteArrayBuffer readPayloadReader(int offset, int length){
ByteArrayBuffer payLoad = new ByteArrayBuffer(length);
System.arraycopy(_buffer,offset, payLoad._buffer, 0, length);
return payLoad;
}
void replaceWith(byte[] a_bytes) {
System.arraycopy(a_bytes, 0, _buffer, 0, length());
}
public String toString() {
String str = "";
for (int i = 0; i < _buffer.length; i++) {
if (i > 0) {
str += " , ";
}
str += _buffer[i];
}
return str;
}
public void writeBegin(byte a_identifier) {
if (Deploy.debug) {
if (Deploy.brackets) {
writeByte(Const4.YAPBEGIN);
}
if (Deploy.identifiers) {
writeByte(a_identifier);
}
}
}
public final void writeBitMap(BitMap4 nullBitMap) {
nullBitMap.writeTo(_buffer, _offset);
_offset += nullBitMap.marshalledLength();
}
public final void writeByte(byte a_byte) {
_buffer[_offset++] = a_byte;
}
public void writeEnd() {
if (Deploy.debug && Deploy.brackets) {
writeByte(Const4.YAPEND);
}
}
public final void writeInt(int a_int) {
if (Deploy.debug) {
IntHandler.writeInt(a_int, this);
} else {
int o = _offset + 4;
_offset = o;
byte[] b = _buffer;
b[--o] = (byte)a_int;
b[--o] = (byte) (a_int >>= 8);
b[--o] = (byte) (a_int >>= 8);
b[--o] = (byte) (a_int >> 8);
}
}
public void writeIDOf(Transaction trans, Object obj) {
if(obj == null){
writeInt(0);
return;
}
if(obj instanceof PersistentBase){
writeIDOf(trans, (PersistentBase)obj);
return;
}
writeInt(((Integer)obj).intValue());
}
public void writeIDOf(Transaction trans, PersistentBase persistent) {
if(persistent == null){
writeInt(0);
return;
}
if(canWritePersistentBase()){
persistent.writeOwnID(trans, this);
}else{
writeInt(persistent.getID());
}
}
protected boolean canWritePersistentBase(){
return true;
}
public void writeShortString(Transaction trans, String a_string) {
trans.container()._handlers._stringHandler.writeShort(trans, a_string, this);
}
public void writeLong(long l) {
LongHandler.writeLong(this, l);
}
public void incrementIntSize() {
incrementOffset(Const4.INT_LENGTH);
}
public int offset() {
return _offset;
}
public void ensureSize(int size){
if(size == _buffer.length){
return;
}
_buffer = new byte[size];
}
public void skip(int length) {
seek(_offset + length);
}
public void checkXBytes(boolean flag){
if(Debug4.xbytes){
_checkXBytes.set(flag);
}
}
public boolean checkXBytes() {
if(Debug4.xbytes){
return _checkXBytes.get();
}
throw new IllegalStateException();
}
public boolean eof() {
if(Deploy.debug){
return _offset >= _buffer.length - Const4.ADDED_LENGTH;
}
return _offset == _buffer.length;
}
public int remainingByteCount() {
return _buffer.length - _offset;
}
}