package org.exist.storage.io; import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import org.apache.log4j.Logger; import org.exist.util.ByteArray; import org.exist.util.FastByteBuffer; /** * A byte array output stream using variable byte encoding. * * @author wolf */ public class VariableByteOutputStream extends OutputStream { private final int MAX_BUFFER_SIZE = 65536; protected FastByteBuffer buf; private final byte[] temp = new byte[5]; private static final Logger LOG = Logger.getLogger(VariableByteArrayInput.class); public VariableByteOutputStream() { super(); buf = new FastByteBuffer(9); } public VariableByteOutputStream(int size) { super(); buf = new FastByteBuffer(size); } public void clear() { if (buf.size() > MAX_BUFFER_SIZE) buf = new FastByteBuffer(9); else buf.setLength(0); } public void close() throws IOException { buf = null; } public int size() { return buf.length(); } public void flush() throws IOException { } public int position() { return buf.size(); } public byte[] toByteArray() { byte[] b = new byte[buf.size()]; buf.copyTo(b, 0); return b; } public ByteArray data() { return buf; } public void write(int b) throws IOException { buf.append((byte) b); } public void write(byte[] b) { buf.append(b); } public void write(byte[] b, int off, int len) throws IOException { buf.append(b, off, len); } public void write(ByteArray b) { b.copyTo(buf); } public void writeByte(byte b) { buf.append(b); } public void writeShort(int s) { while ((s & ~0177) != 0) { buf.append((byte) ((s & 0177) | 0200)); s >>>= 7; } buf.append((byte) s); } public void writeInt(int i) { int count = 0; while ((i & ~0177) != 0) { temp[count++] = (byte) ((i & 0177) | 0200); i >>>= 7; } temp[count++] = (byte) i; buf.append(temp, 0, count); } public void writeFixedInt(int i) { temp[0] = (byte) ( ( i >>> 0 ) & 0xff ); temp[1] = (byte) ( ( i >>> 8 ) & 0xff ); temp[2] = (byte) ( ( i >>> 16 ) & 0xff ); temp[3] = (byte) ( ( i >>> 24 ) & 0xff ); buf.append(temp, 0, 4); } public void writeFixedInt(int position, int i) { buf.set(position, (byte) ( ( i >>> 0 ) & 0xff )); buf.set(position + 1, (byte) ( ( i >>> 8 ) & 0xff )); buf.set(position + 2, (byte) ( ( i >>> 16 ) & 0xff )); buf.set(position + 3, (byte) ( ( i >>> 24 ) & 0xff )); } public void writeInt(int position, int i) { while ((i & ~0177) != 0) { buf.set(position++, (byte) ((i & 0177) | 0200)); i >>>= 7; } buf.set(position, (byte) i); } public void writeLong(long l) { while ((l & ~0177) != 0) { buf.append((byte) ((l & 0177) | 0200)); l >>>= 7; } buf.append((byte) l); } public void writeFixedLong(long l) { buf.append((byte) ((l >>> 56) & 0xff)); buf.append((byte) ((l >>> 48) & 0xff)); buf.append((byte) ((l >>> 40) & 0xff)); buf.append((byte) ((l >>> 32) & 0xff)); buf.append((byte) ((l >>> 24) & 0xff)); buf.append((byte) ((l >>> 16) & 0xff)); buf.append((byte) ((l >>> 8) & 0xff)); buf.append((byte) ((l >>> 0) & 0xff)); } public void writeUTF(String s) throws IOException { byte[] data = null; try { data = s.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { LOG.warn(e); data = s.getBytes(); } writeInt(data.length); write(data, 0, data.length); } }