// Copyright 2017 JanusGraph Authors
//
// 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.janusgraph.diskstorage.util;
import com.google.common.base.Preconditions;
import org.janusgraph.diskstorage.StaticBuffer;
import static org.janusgraph.diskstorage.util.StaticArrayBuffer.*;
import org.janusgraph.diskstorage.WriteBuffer;
import java.nio.ByteBuffer;
/**
* @author Matthias Broecheler (me@matthiasb.com)
*/
public class WriteByteBuffer implements WriteBuffer {
public static final int DEFAULT_CAPACITY = 64;
public static final int MAX_BUFFER_CAPACITY = 128 * 1024 * 1024; //128 MB
private ByteBuffer buffer;
public WriteByteBuffer() {
this(DEFAULT_CAPACITY);
}
public WriteByteBuffer(int capacity) {
Preconditions.checkArgument(capacity<=MAX_BUFFER_CAPACITY,"Capacity exceeds max buffer capacity: %s",MAX_BUFFER_CAPACITY);
buffer = ByteBuffer.allocate(capacity);
}
private void require(int size) {
if (buffer.capacity()-buffer.position()<size) {
//Need to resize
int newcapacity = buffer.position() + size + buffer.capacity(); //extra capacity as buffer
Preconditions.checkArgument(newcapacity<=MAX_BUFFER_CAPACITY,"Capacity exceeds max buffer capacity: %s",MAX_BUFFER_CAPACITY);
ByteBuffer newBuffer = ByteBuffer.allocate(newcapacity);
buffer.flip();
newBuffer.put(buffer);
buffer=newBuffer;
}
}
@Override
public WriteBuffer putLong(long val) {
require(LONG_LEN);
buffer.putLong(val);
return this;
}
@Override
public WriteBuffer putInt(int val) {
require(INT_LEN);
buffer.putInt(val);
return this;
}
@Override
public WriteBuffer putShort(short val) {
require(SHORT_LEN);
buffer.putShort(val);
return this;
}
@Override
public WriteBuffer putBoolean(boolean val) {
return putByte((byte)(val?1:0));
}
@Override
public WriteBuffer putByte(byte val) {
require(BYTE_LEN);
buffer.put(val);
return this;
}
@Override
public WriteBuffer putBytes(byte[] val) {
require(BYTE_LEN*val.length);
buffer.put(val);
return this;
}
@Override
public WriteBuffer putBytes(final StaticBuffer val) {
require(BYTE_LEN*val.length());
val.as(new Factory<Boolean>() {
@Override
public Boolean get(byte[] array, int offset, int limit) {
buffer.put(array,offset,val.length());
return Boolean.TRUE;
}
});
return this;
}
@Override
public WriteBuffer putChar(char val) {
require(CHAR_LEN);
buffer.putChar(val);
return this;
}
@Override
public WriteBuffer putFloat(float val) {
require(FLOAT_LEN);
buffer.putFloat(val);
return this;
}
@Override
public WriteBuffer putDouble(double val) {
require(DOUBLE_LEN);
buffer.putDouble(val);
return this;
}
@Override
public int getPosition() {
return buffer.position();
}
@Override
public StaticBuffer getStaticBuffer() {
return getStaticBufferFlipBytes(0,0);
}
@Override
public StaticBuffer getStaticBufferFlipBytes(int from, int to) {
ByteBuffer b = buffer.duplicate();
b.flip();
Preconditions.checkArgument(from>=0 && from<=to);
Preconditions.checkArgument(to<=b.limit());
for (int i=from;i<to;i++) b.put(i,(byte)~b.get(i));
return StaticArrayBuffer.of(b);
}
}