/*
* Copyright 2014-2016 CyberVision, Inc.
*
* Licensed 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.kaaproject.kaa.server.sync.platform;
import java.nio.ByteBuffer;
import java.text.MessageFormat;
import java.util.Arrays;
/**
* This class wraps {@link ByteBuffer} and provides ability to automatically resize the buffer when
* needed.
*
* @author Andrew Shvayka
*/
public class GrowingByteBuffer {
private static final int SIZE_OF_BYTE = 1;
private static final int SIZE_OF_SHORT = 2;
private static final int SIZE_OF_INT = 4;
private static final int SIZE_OF_LONG = 8;
private ByteBuffer data;
public GrowingByteBuffer(int size) {
super();
data = ByteBuffer.wrap(new byte[size]);
}
/**
* Put byte to byte buffer.
*
* @param bt is byte for putting
* @return current instance of <code>GrowingByteBuffer</code>
*/
public GrowingByteBuffer put(byte bt) {
resizeIfNeeded(SIZE_OF_BYTE);
data.put(bt);
return this;
}
/**
* Put array of bytes in buffer.
*
* @param bytes is array of bytes
* @return current instance of <code>GrowingByteBuffer</code>
*/
public GrowingByteBuffer put(byte[] bytes) {
resizeIfNeeded(bytes.length);
data.put(bytes);
return this;
}
/**
* Put short number to byte buffer.
*
* @param shrt is short for putting
* @return current instance of <code>GrowingByteBuffer</code>
*/
public GrowingByteBuffer putShort(short shrt) {
resizeIfNeeded(SIZE_OF_SHORT);
data.putShort(shrt);
return this;
}
/**
* Put short number to byte buffer in given position.
*
* @param shrt is short for putting
* @param position is position where put number
* @return current instance of <code>GrowingByteBuffer</code>
*/
public GrowingByteBuffer putShort(int position, short shrt) {
checkPosition(position + SIZE_OF_SHORT);
int tmp = data.position();
data.position(position);
data.putShort(shrt);
data.position(tmp);
return this;
}
/**
* Put integer number to byte buffer.
*
* @param integer is integer number for putting
* @return current instance of <code>GrowingByteBuffer</code>
*/
public GrowingByteBuffer putInt(int integer) {
resizeIfNeeded(SIZE_OF_INT);
data.putInt(integer);
return this;
}
/**
* Put integer number to byte buffer.
*
* @param integer is integer for putting
* @param position is position where put number
* @return current instance of <code>GrowingByteBuffer</code>
*/
public GrowingByteBuffer putInt(int position, int integer) {
checkPosition(position + SIZE_OF_INT);
int tmp = data.position();
data.position(position);
data.putInt(integer);
data.position(tmp);
return this;
}
/**
* Put long number to byte buffer.
*
* @param value is long number for putting
* @return current instance of <code>GrowingByteBuffer</code>
*/
public GrowingByteBuffer putLong(long value) {
resizeIfNeeded(SIZE_OF_LONG);
data.putLong(value);
return this;
}
public int position() {
return data.position();
}
private void checkPosition(int position) {
if (data.capacity() < position) {
throw new IllegalArgumentException(
MessageFormat.format("Position {0} is greater then capacity {1}",
position, data.capacity()));
}
}
private void resizeIfNeeded(int size) {
if (size > data.remaining()) {
int position = data.position();
data = ByteBuffer.wrap(Arrays.copyOf(
data.array(), Math.max(data.position() + size, data.array().length * 2)));
data.position(position);
}
}
public byte[] toByteArray() {
return Arrays.copyOf(data.array(), data.position());
}
}