/* $Id$ */
package ibis.ipl.util.messagecombining;
import ibis.io.DataOutputStream;
import ibis.ipl.WriteMessage;
import java.io.IOException;
import java.nio.ByteBuffer;
final class StoreArrayOutputStream extends DataOutputStream {
private static final int DEFAULT_SIZE = 16*1024;
private int[] indices = new int[8];
private boolean[] boolean_store;
private int boolean_count;
private byte[] byte_store;
private int byte_count;
private short[] short_store;
private int short_count;
private char[] char_store;
private int char_count;
private int[] int_store;
private int int_count;
private long[] long_store;
private int long_count;
private float[] float_store;
private int float_count;
private double[] double_store;
private int double_count;
private long count = 0;
private final int initialSize;
public StoreArrayOutputStream() {
this(DEFAULT_SIZE);
}
public StoreArrayOutputStream(int initialSize) {
this.initialSize = initialSize;
clear();
}
public int bufferSize() {
return -1;
}
private void clear() {
boolean_store = new boolean[initialSize];
byte_store = new byte[initialSize];
short_store = new short[initialSize];
char_store = new char[initialSize];
int_store = new int[initialSize];
long_store = new long[initialSize];
float_store = new float[initialSize];
double_store = new double[initialSize];
boolean_count = 0;
byte_count = 0;
short_count = 0;
char_count = 0;
int_count = 0;
long_count = 0;
float_count = 0;
double_count = 0;
count = 0;
}
private final void resize_boolean(int required) {
int new_size = boolean_store.length;
while (new_size < required) {
new_size *= 2;
}
boolean [] tmp = new boolean[new_size];
System.arraycopy(boolean_store, 0, tmp, 0, boolean_count);
boolean_store = tmp;
}
private final void resize_byte(int required) {
int new_size = byte_store.length;
while (new_size < required) {
new_size *= 2;
}
byte [] tmp = new byte[new_size];
System.arraycopy(byte_store, 0, tmp, 0, byte_count);
byte_store = tmp;
}
private final void resize_short(int required) {
int new_size = short_store.length;
while (new_size < required) {
new_size *= 2;
}
short [] tmp = new short[new_size];
System.arraycopy(short_store, 0, tmp, 0, short_count);
short_store = tmp;
}
private final void resize_char(int required) {
int new_size = char_store.length;
while (new_size < required) {
new_size *= 2;
}
char [] tmp = new char[new_size];
System.arraycopy(char_store, 0, tmp, 0, char_count);
char_store = tmp;
}
private final void resize_int(int required) {
int new_size = int_store.length;
while (new_size < required) {
new_size *= 2;
}
int [] tmp = new int[new_size];
System.arraycopy(int_store, 0, tmp, 0, int_count);
int_store = tmp;
}
private final void resize_long(int required) {
int new_size = long_store.length;
while (new_size < required) {
new_size *= 2;
}
long [] tmp = new long[new_size];
System.arraycopy(long_store, 0, tmp, 0, long_count);
long_store = tmp;
}
private final void resize_float(int required) {
int new_size = float_store.length;
while (new_size < required) {
new_size *= 2;
}
float [] tmp = new float[new_size];
System.arraycopy(float_store, 0, tmp, 0, float_count);
float_store = tmp;
}
private final void resize_double(int required) {
int new_size = double_store.length;
while (new_size < required) {
new_size *= 2;
}
double [] tmp = new double[new_size];
System.arraycopy(double_store, 0, tmp, 0, double_count);
double_store = tmp;
}
public void writeArray(boolean[] a, int off, int len) {
if (boolean_count + len > boolean_store.length) {
resize_boolean(boolean_count+len);
}
System.arraycopy(a, off, boolean_store, boolean_count, len);
boolean_count += len;
count += len;
}
public void writeArray(byte[] a, int off, int len) {
if (byte_count + len > byte_store.length) {
resize_byte(byte_count+len);
}
System.arraycopy(a, off, byte_store, byte_count, len);
byte_count += len;
count += len;
}
public void writeArray(short[] a, int off, int len) {
if (short_count + len > short_store.length) {
resize_short(short_count+len);
}
System.arraycopy(a, off, short_store, short_count, len);
short_count += len;
count += 2L*len;
}
public void writeArray(char[] a, int off, int len) {
if (char_count + len > char_store.length) {
resize_char(char_count+len);
}
System.arraycopy(a, off, char_store, char_count, len);
char_count += len;
count += 2L*len;
}
public void writeArray(int[] a, int off, int len) {
if (int_count + len > int_store.length) {
resize_int(int_count+len);
}
System.arraycopy(a, off, int_store, int_count, len);
int_count += len;
count += 4L*len;
}
public void writeArray(long[] a, int off, int len) {
if (long_count + len > long_store.length) {
resize_long(long_count+len);
}
System.arraycopy(a, off, long_store, long_count, len);
long_count += len;
count += 8L*len;
}
public void writeArray(float[] a, int off, int len) {
if (float_count + len > float_store.length) {
resize_float(float_count+len);
}
System.arraycopy(a, off, float_store, float_count, len);
float_count += len;
count += 4L*len;
}
public void writeArray(double[] a, int off, int len) {
if (double_count + len > double_store.length) {
resize_double(double_count+len);
}
System.arraycopy(a, off, double_store, double_count, len);
double_count += len;
count += 8L*len;
}
public void write(byte[] a, int off, int len) {
writeArray(a, off, len);
}
public void write(byte[] a) {
writeArray(a, 0, a.length);
}
public void write(int b) {
writeByte((byte) b);
}
public void writeByte(byte b) {
if (byte_count + 1 > byte_store.length) {
resize_byte(byte_count+1);
}
byte_store[byte_count++] = b;
count++;
}
public void writeBoolean(boolean b) {
if (boolean_count + 1 > boolean_store.length) {
resize_boolean(boolean_count+1);
}
boolean_store[boolean_count++] = b;
count++;
}
public void writeShort(short b) {
if (short_count + 1 > short_store.length) {
resize_short(short_count+1);
}
short_store[short_count++] = b;
count += 2;
}
public void writeChar(char b) {
if (char_count + 1 > char_store.length) {
resize_char(char_count+1);
}
char_store[char_count++] = b;
count += 2;
}
public void writeInt(int b) {
if (int_count + 1 > int_store.length) {
resize_int(int_count+1);
}
int_store[int_count++] = b;
count += 4;
}
public void writeLong(long b) {
if (long_count + 1 > long_store.length) {
resize_long(long_count+1);
}
long_store[long_count++] = b;
count += 8;
}
public void writeFloat(float b) {
if (float_count + 1 > float_store.length) {
resize_float(float_count+1);
}
float_store[float_count++] = b;
count += 4;
}
public void writeDouble(double b) {
if (double_count + 1 > double_store.length) {
resize_double(double_count+1);
}
double_store[double_count++] = b;
count += 8;
}
public long bytesWritten() {
return count;
}
public void resetBytesWritten() {
count = 0;
}
public void flush() throws IOException {
// nothing to flush
}
public boolean finished() {
return true;
}
public void finish() throws IOException {
flush();
}
public void close() throws IOException {
flush();
}
/**
* @param message
* @throws IOException
*/
public void writeToMessage(WriteMessage message) throws IOException {
indices[0] = boolean_count;
indices[1] = byte_count;
indices[2] = short_count;
indices[3] = char_count;
indices[4] = int_count;
indices[5] = long_count;
indices[6] = float_count;
indices[7] = double_count;
message.writeArray(indices);
if (boolean_count > 0) {
message.writeArray(boolean_store, 0, boolean_count);
}
if (byte_count > 0) {
message.writeArray(byte_store, 0, byte_count);
}
if (short_count > 0) {
message.writeArray(short_store, 0, short_count);
}
if (char_count > 0) {
message.writeArray(char_store, 0, char_count);
}
if (int_count > 0) {
message.writeArray(int_store, 0, int_count);
}
if (long_count > 0) {
message.writeArray(long_store, 0, long_count);
}
if (float_count > 0) {
message.writeArray(float_store, 0, float_count);
}
if (double_count > 0) {
message.writeArray(double_store, 0, double_count);
}
message.finish();
boolean_count = 0;
byte_count = 0;
short_count = 0;
char_count = 0;
int_count = 0;
long_count = 0;
float_count = 0;
double_count = 0;
count = 0;
}
public void writeByteBuffer(ByteBuffer value) throws IOException {
int len = value.limit() - value.position();
if (byte_count + len > byte_store.length) {
resize_byte(byte_count+len);
}
value.get(byte_store, byte_count, len);
byte_count += len;
count += len;
}
}