blob: f290a937112df8afc8a8073af07a8625146a9471 [file] [log] [blame]
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.qpid.server.protocol.v0_10.transport;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.UUID;
/**
* Byte Buffer Encoder.
* Encoder concrete implementor using a backing byte buffer for encoding data.
*
* @author Rafael H. Schloming
*/
public final class BBEncoder extends AbstractEncoder
{
private ByteBuffer out;
private int segment;
public BBEncoder(int capacity) {
out = ByteBuffer.allocate(capacity);
out.order(ByteOrder.BIG_ENDIAN);
segment = 0;
}
@Override
public void init()
{
out.clear();
segment = 0;
}
public ByteBuffer segment()
{
int pos = out.position();
out.position(segment);
ByteBuffer slice = out.slice();
slice.limit(pos - segment);
out.position(pos);
segment = pos;
return slice;
}
public ByteBuffer buffer()
{
int pos = out.position();
out.position(segment);
ByteBuffer slice = out.slice();
slice.limit(pos - segment);
out.position(pos);
return slice;
}
@Override
public int position()
{
return out.position();
}
public ByteBuffer underlyingBuffer()
{
return out;
}
private void grow(int size)
{
ByteBuffer old = out;
int capacity = old.capacity();
out = ByteBuffer.allocate(Math.max(capacity + size, 2*capacity));
out.order(ByteOrder.BIG_ENDIAN);
old.flip();
out.put(old);
}
@Override
protected void doPut(byte b)
{
try
{
out.put(b);
}
catch (BufferOverflowException e)
{
grow(1);
out.put(b);
}
}
@Override
protected void doPut(ByteBuffer src)
{
try
{
out.put(src);
}
catch (BufferOverflowException e)
{
grow(src.remaining());
out.put(src);
}
}
@Override
protected void put(byte[] bytes)
{
try
{
out.put(bytes);
}
catch (BufferOverflowException e)
{
grow(bytes.length);
out.put(bytes);
}
}
@Override
public void writeUint8(short b)
{
assert b < 0x100;
try
{
out.put((byte) b);
}
catch (BufferOverflowException e)
{
grow(1);
out.put((byte) b);
}
}
@Override
public void writeUint16(int s)
{
assert s < 0x10000;
try
{
out.putShort((short) s);
}
catch (BufferOverflowException e)
{
grow(2);
out.putShort((short) s);
}
}
@Override
public void writeUint32(long i)
{
assert i < 0x100000000L;
try
{
out.putInt((int) i);
}
catch (BufferOverflowException e)
{
grow(4);
out.putInt((int) i);
}
}
@Override
public void writeUint64(long l)
{
try
{
out.putLong(l);
}
catch (BufferOverflowException e)
{
grow(8);
out.putLong(l);
}
}
@Override
public int beginSize8()
{
int pos = out.position();
try
{
out.put((byte) 0);
}
catch (BufferOverflowException e)
{
grow(1);
out.put((byte) 0);
}
return pos;
}
@Override
public void endSize8(int pos)
{
int cur = out.position();
out.put(pos, (byte) (cur - pos - 1));
}
@Override
public int beginSize16()
{
int pos = out.position();
try
{
out.putShort((short) 0);
}
catch (BufferOverflowException e)
{
grow(2);
out.putShort((short) 0);
}
return pos;
}
@Override
public void endSize16(int pos)
{
int cur = out.position();
out.putShort(pos, (short) (cur - pos - 2));
}
@Override
public int beginSize32()
{
int pos = out.position();
try
{
out.putInt(0);
}
catch (BufferOverflowException e)
{
grow(4);
out.putInt(0);
}
return pos;
}
@Override
public void endSize32(int pos)
{
int cur = out.position();
out.putInt(pos, (cur - pos - 4));
}
@Override
public void writeDouble(double aDouble)
{
try
{
out.putDouble(aDouble);
} catch(BufferOverflowException exception)
{
grow(8);
out.putDouble(aDouble);
}
}
@Override
public void writeInt16(short aShort)
{
try
{
out.putShort(aShort);
} catch(BufferOverflowException exception)
{
grow(2);
out.putShort(aShort);
}
}
@Override
public void writeInt32(int anInt)
{
try
{
out.putInt(anInt);
} catch(BufferOverflowException exception)
{
grow(4);
out.putInt(anInt);
}
}
@Override
public void writeInt64(long aLong)
{
try
{
out.putLong(aLong);
} catch(BufferOverflowException exception)
{
grow(8);
out.putLong(aLong);
}
}
@Override
public void writeInt8(byte aByte)
{
try
{
out.put(aByte);
} catch(BufferOverflowException exception)
{
grow(1);
out.put(aByte);
}
}
@Override
public void writeBin128(byte[] byteArray)
{
byteArray = (byteArray != null) ? byteArray : new byte [16];
assert byteArray.length == 16;
try
{
out.put(byteArray);
} catch(BufferOverflowException exception)
{
grow(16);
out.put(byteArray);
}
}
public void writeBin128(UUID id)
{
byte[] data = new byte[16];
long msb = id.getMostSignificantBits();
long lsb = id.getLeastSignificantBits();
assert data.length == 16;
for (int i=7; i>=0; i--)
{
data[i] = (byte)(msb & 0xff);
msb = msb >> 8;
}
for (int i=15; i>=8; i--)
{
data[i] = (byte)(lsb & 0xff);
lsb = (lsb >> 8);
}
writeBin128(data);
}
@Override
public void writeFloat(float aFloat)
{
try
{
out.putFloat(aFloat);
} catch(BufferOverflowException exception)
{
grow(4);
out.putFloat(aFloat);
}
}
}