package org.bbssh.io; import java.io.EOFException; import org.bbssh.util.Logger; import net.rim.device.api.util.DataBuffer; public class SyncBuffer { DataBuffer data; byte fieldId = 0; int expectedCount = 0; public static final byte ARR_VALUE = 0; public static final byte ARR_EMPTY = 1; public static final byte ARR_NULL = 2; public SyncBuffer(DataBuffer data, int expectedCount) { this(data, (byte) 0, expectedCount); } public SyncBuffer(DataBuffer data) { this(data, (byte) 0, 0); } public SyncBuffer(DataBuffer data, byte fieldId, int expectedCount) { this.data = data; this.fieldId = fieldId; this.expectedCount = expectedCount; } public void writeField(short value) { data.writeShort(2); // int length data.writeByte(fieldId++); data.writeShort(value); } public void writeField(int value) { data.writeShort(4); // int length data.writeByte(fieldId++); data.writeInt(value); } public void writeField(boolean value) { data.writeShort(1); // byte length data.writeByte(fieldId++); data.writeBoolean(value); } public void writeField(byte value) { data.writeShort(1); // byte length data.writeByte(fieldId++); data.writeByte(value); } public void writeField(long value) { data.writeShort(8); data.writeByte(fieldId++); data.writeLong(value); } public void writeField(byte[] value) { short len = 1; byte lengthInd; if (value == null) { lengthInd = ARR_NULL; } else if (value.length == 0) { lengthInd = ARR_EMPTY; } else { len += value.length; lengthInd = ARR_VALUE; } data.writeShort(len); data.writeByte(fieldId++); data.writeByte(lengthInd); if (lengthInd == ARR_VALUE) { data.write(value); } } public void writeField(String value) { if (value == null) { writeField((byte[]) null); } else { writeField(value.getBytes()); } } /** * Returns field length and positions buffer at start of field id. . * * @return field length * @throws EOFException */ private short getFieldLength() throws EOFException { return data.readShort(); // length } /** * Reads and returns field ID from the stream. If field id does not match expected (based on sequential * incrementing) then an error is logged. * * Positions buffer at start of field data. * * @return field id * @throws EOFException */ private byte getFieldId() throws EOFException { byte id = data.readByte(); // id if (id != fieldId) { // @todo - we'll need to throw a meaingful exception here... Logger.info("Field id mismatch: expected ID " + fieldId + " + but received " + id); } fieldId++; return id; } public short readNextShortField() throws EOFException { getFieldLength(); // don't care getFieldId(); // don't care return data.readShort(); } public int readNextIntField() throws EOFException { getFieldLength(); // don't care getFieldId(); // don't care return data.readInt(); } public long readNextLongField() throws EOFException { getFieldLength(); // don't care getFieldId(); // don't care return data.readLong(); } /** * Reads next string field from the buffer. * * @return Will return null if original string was null; otherwise a valid string of length 0 or more. * @throws EOFException */ public String readNextStringField() throws EOFException { byte[] value = readNextByteArrayField(); if (value == null) { return null; } return new String(value); } /** * Reads next byte array field from the buffer. * * @return Will return null if original array was null; otherwise a valid byte array containing 0 or more bytes. * @throws EOFException */ public byte[] readNextByteArrayField() throws EOFException { short length = getFieldLength(); getFieldId(); // don't care byte valueInd = data.readByte(); byte[] value; switch (valueInd) { case ARR_EMPTY: value = new byte[] {}; break; case ARR_VALUE: if (length > 0) { value = new byte[length - 1]; data.readFully(value); } else { value = new byte[] {}; } break; case ARR_NULL: default: value = null; break; } return value; } public boolean readNextBooleanField() throws EOFException { getFieldLength(); // don't care getFieldId(); // don't care return data.readBoolean(); } public byte readNextByteField() throws EOFException { getFieldLength(); // don't care getFieldId(); // don't care return data.readByte(); } public int getFieldCount() { if (fieldId > 0) return fieldId; return expectedCount; } }