/*
* 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.activemq.artemis.core.buffers.impl;
import java.io.IOException;
import java.nio.ByteBuffer;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.utils.ByteUtil;
import org.apache.activemq.artemis.utils.DataConstants;
import org.apache.activemq.artemis.utils.UTF8Util;
public class ChannelBufferWrapper implements ActiveMQBuffer {
protected final ByteBuf buffer;
private final boolean releasable;
private final boolean isPooled;
public static ByteBuf unwrap(ByteBuf buffer) {
ByteBuf parent;
while ((parent = buffer.unwrap()) != null && parent != buffer) { // this last part is just in case the semantic
// ever changes where unwrap is returning itself
buffer = parent;
}
return buffer;
}
public ChannelBufferWrapper(final ByteBuf buffer) {
this(buffer, false);
}
public ChannelBufferWrapper(final ByteBuf buffer, boolean releasable) {
this(buffer, releasable, false);
}
public ChannelBufferWrapper(final ByteBuf buffer, boolean releasable, boolean pooled) {
if (!releasable) {
this.buffer = Unpooled.unreleasableBuffer(buffer);
} else {
this.buffer = buffer;
}
this.releasable = releasable;
this.isPooled = pooled;
}
@Override
public boolean readBoolean() {
return readByte() != 0;
}
@Override
public SimpleString readNullableSimpleString() {
return SimpleString.readNullableSimpleString(buffer);
}
@Override
public String readNullableString() {
int b = buffer.readByte();
if (b == DataConstants.NULL) {
return null;
}
return readStringInternal();
}
@Override
public SimpleString readSimpleString() {
return SimpleString.readSimpleString(buffer);
}
@Override
public String readString() {
return readStringInternal();
}
private String readStringInternal() {
int len = buffer.readInt();
if (len < 9) {
char[] chars = new char[len];
for (int i = 0; i < len; i++) {
chars[i] = (char) buffer.readShort();
}
return new String(chars);
} else if (len < 0xfff) {
return readUTF();
} else {
return SimpleString.readSimpleString(buffer).toString();
}
}
@Override
public void writeNullableString(String val) {
UTF8Util.writeNullableString(buffer, val);
}
@Override
public void writeUTF(String utf) {
UTF8Util.saveUTF(buffer, utf);
}
@Override
public String readUTF() {
return UTF8Util.readUTF(this);
}
@Override
public void writeBoolean(final boolean val) {
buffer.writeByte((byte) (val ? -1 : 0));
}
@Override
public void writeNullableSimpleString(final SimpleString val) {
SimpleString.writeNullableSimpleString(buffer, val);
}
@Override
public void writeSimpleString(final SimpleString val) {
SimpleString.writeSimpleString(buffer, val);
}
@Override
public void writeString(final String val) {
UTF8Util.writeString(buffer, val);
}
@Override
public int capacity() {
return buffer.capacity();
}
@Override
public ByteBuf byteBuf() {
return buffer;
}
@Override
public void clear() {
buffer.clear();
}
@Override
public ActiveMQBuffer copy() {
return new ChannelBufferWrapper(buffer.copy(), releasable);
}
@Override
public ActiveMQBuffer copy(final int index, final int length) {
return new ChannelBufferWrapper(buffer.copy(index, length), releasable);
}
@Override
public void discardReadBytes() {
buffer.discardReadBytes();
}
@Override
public ActiveMQBuffer duplicate() {
return new ChannelBufferWrapper(buffer.duplicate(), releasable);
}
@Override
public byte getByte(final int index) {
return buffer.getByte(index);
}
@Override
public void getBytes(final int index, final byte[] dst, final int dstIndex, final int length) {
buffer.getBytes(index, dst, dstIndex, length);
}
@Override
public void getBytes(final int index, final byte[] dst) {
buffer.getBytes(index, dst);
}
@Override
public void getBytes(final int index, final ByteBuffer dst) {
buffer.getBytes(index, dst);
}
@Override
public void getBytes(final int index, final ActiveMQBuffer dst, final int dstIndex, final int length) {
buffer.getBytes(index, dst.byteBuf(), dstIndex, length);
}
@Override
public void getBytes(final int index, final ActiveMQBuffer dst, final int length) {
buffer.getBytes(index, dst.byteBuf(), length);
}
@Override
public void getBytes(final int index, final ActiveMQBuffer dst) {
buffer.getBytes(index, dst.byteBuf());
}
@Override
public char getChar(final int index) {
return (char) buffer.getShort(index);
}
@Override
public double getDouble(final int index) {
return Double.longBitsToDouble(buffer.getLong(index));
}
@Override
public float getFloat(final int index) {
return Float.intBitsToFloat(buffer.getInt(index));
}
@Override
public int getInt(final int index) {
return buffer.getInt(index);
}
@Override
public long getLong(final int index) {
return buffer.getLong(index);
}
@Override
public short getShort(final int index) {
return buffer.getShort(index);
}
@Override
public short getUnsignedByte(final int index) {
return buffer.getUnsignedByte(index);
}
@Override
public long getUnsignedInt(final int index) {
return buffer.getUnsignedInt(index);
}
@Override
public int getUnsignedShort(final int index) {
return buffer.getUnsignedShort(index);
}
@Override
public void markReaderIndex() {
buffer.markReaderIndex();
}
@Override
public void markWriterIndex() {
buffer.markWriterIndex();
}
@Override
public boolean readable() {
return buffer.isReadable();
}
@Override
public int readableBytes() {
return buffer.readableBytes();
}
@Override
public byte readByte() {
return buffer.readByte();
}
@Override
public void readBytes(final byte[] dst, final int dstIndex, final int length) {
buffer.readBytes(dst, dstIndex, length);
}
@Override
public void readBytes(final byte[] dst) {
buffer.readBytes(dst);
}
@Override
public void readBytes(final ByteBuffer dst) {
buffer.readBytes(dst);
}
@Override
public void readBytes(final ActiveMQBuffer dst, final int dstIndex, final int length) {
buffer.readBytes(dst.byteBuf(), dstIndex, length);
}
@Override
public void readBytes(final ActiveMQBuffer dst, final int length) {
buffer.readBytes(dst.byteBuf(), length);
}
@Override
public void readBytes(final ActiveMQBuffer dst) {
buffer.readBytes(dst.byteBuf());
}
@Override
public ActiveMQBuffer readBytes(final int length) {
return new ChannelBufferWrapper(buffer.readBytes(length), releasable);
}
@Override
public char readChar() {
return (char) buffer.readShort();
}
@Override
public double readDouble() {
return Double.longBitsToDouble(buffer.readLong());
}
@Override
public int readerIndex() {
return buffer.readerIndex();
}
@Override
public void readerIndex(final int readerIndex) {
buffer.readerIndex(readerIndex);
}
@Override
public float readFloat() {
return Float.intBitsToFloat(buffer.readInt());
}
@Override
public int readInt() {
return buffer.readInt();
}
@Override
public long readLong() {
return buffer.readLong();
}
@Override
public short readShort() {
return buffer.readShort();
}
@Override
public ActiveMQBuffer readSlice(final int length) {
if ( isPooled ) {
ByteBuf fromBuffer = buffer.readSlice(length);
ByteBuf newNettyBuffer = Unpooled.buffer(fromBuffer.capacity());
int read = fromBuffer.readerIndex();
int writ = fromBuffer.writerIndex();
fromBuffer.readerIndex(0);
fromBuffer.readBytes(newNettyBuffer,0,writ);
newNettyBuffer.setIndex(read,writ);
ActiveMQBuffer returnBuffer = new ChannelBufferWrapper(newNettyBuffer,releasable,false);
returnBuffer.setIndex(read,writ);
return returnBuffer;
}
return new ChannelBufferWrapper(buffer.readSlice(length), releasable, isPooled);
}
@Override
public int readUnsignedByte() {
return buffer.readUnsignedByte();
}
@Override
public long readUnsignedInt() {
return buffer.readUnsignedInt();
}
@Override
public int readUnsignedShort() {
return buffer.readUnsignedShort();
}
@Override
public void resetReaderIndex() {
buffer.resetReaderIndex();
}
@Override
public void resetWriterIndex() {
buffer.resetWriterIndex();
}
@Override
public void setByte(final int index, final byte value) {
buffer.setByte(index, value);
}
@Override
public void setBytes(final int index, final byte[] src, final int srcIndex, final int length) {
buffer.setBytes(index, src, srcIndex, length);
}
@Override
public void setBytes(final int index, final byte[] src) {
buffer.setBytes(index, src);
}
@Override
public void setBytes(final int index, final ByteBuffer src) {
buffer.setBytes(index, src);
}
@Override
public void setBytes(final int index, final ActiveMQBuffer src, final int srcIndex, final int length) {
buffer.setBytes(index, src.byteBuf(), srcIndex, length);
}
@Override
public void setBytes(final int index, final ActiveMQBuffer src, final int length) {
buffer.setBytes(index, src.byteBuf(), length);
}
@Override
public void setBytes(final int index, final ActiveMQBuffer src) {
buffer.setBytes(index, src.byteBuf());
}
@Override
public void setChar(final int index, final char value) {
buffer.setShort(index, (short) value);
}
@Override
public void setDouble(final int index, final double value) {
buffer.setLong(index, Double.doubleToLongBits(value));
}
@Override
public void setFloat(final int index, final float value) {
buffer.setInt(index, Float.floatToIntBits(value));
}
@Override
public void setIndex(final int readerIndex, final int writerIndex) {
buffer.setIndex(readerIndex, writerIndex);
}
@Override
public void setInt(final int index, final int value) {
buffer.setInt(index, value);
}
@Override
public void setLong(final int index, final long value) {
buffer.setLong(index, value);
}
@Override
public void setShort(final int index, final short value) {
buffer.setShort(index, value);
}
@Override
public int skipBytes(final int length) {
buffer.skipBytes(length);
return length;
}
@Override
public ActiveMQBuffer slice() {
return new ChannelBufferWrapper(buffer.slice(), releasable);
}
@Override
public ActiveMQBuffer slice(final int index, final int length) {
return new ChannelBufferWrapper(buffer.slice(index, length), releasable);
}
@Override
public ByteBuffer toByteBuffer() {
return buffer.nioBuffer();
}
@Override
public ByteBuffer toByteBuffer(final int index, final int length) {
return buffer.nioBuffer(index, length);
}
@Override
public void release() {
if ( this.isPooled ) {
buffer.release();
}
}
@Override
public boolean writable() {
return buffer.isWritable();
}
@Override
public int writableBytes() {
return buffer.writableBytes();
}
@Override
public void writeByte(final byte value) {
buffer.writeByte(value);
}
@Override
public void writeBytes(final byte[] src, final int srcIndex, final int length) {
buffer.writeBytes(src, srcIndex, length);
}
@Override
public void writeBytes(final byte[] src) {
buffer.writeBytes(src);
}
@Override
public void writeBytes(final ByteBuffer src) {
buffer.writeBytes(src);
}
@Override
public void writeBytes(ByteBuf src, int srcIndex, int length) {
buffer.writeBytes(src, srcIndex, length);
}
@Override
public void writeBytes(final ActiveMQBuffer src, final int srcIndex, final int length) {
buffer.writeBytes(src.byteBuf(), srcIndex, length);
}
@Override
public void writeBytes(final ActiveMQBuffer src, final int length) {
buffer.writeBytes(src.byteBuf(), length);
}
@Override
public void writeChar(final char chr) {
buffer.writeShort((short) chr);
}
@Override
public void writeDouble(final double value) {
buffer.writeLong(Double.doubleToLongBits(value));
}
@Override
public void writeFloat(final float value) {
buffer.writeInt(Float.floatToIntBits(value));
}
@Override
public void writeInt(final int value) {
buffer.writeInt(value);
}
@Override
public void writeLong(final long value) {
buffer.writeLong(value);
}
@Override
public int writerIndex() {
return buffer.writerIndex();
}
@Override
public void writerIndex(final int writerIndex) {
buffer.writerIndex(writerIndex);
}
@Override
public void writeShort(final short value) {
buffer.writeShort(value);
}
/**
* from {@link java.io.DataInput} interface
*/
@Override
public void readFully(byte[] b) throws IOException {
readBytes(b);
}
/**
* from {@link java.io.DataInput} interface
*/
@Override
public void readFully(byte[] b, int off, int len) throws IOException {
readBytes(b, off, len);
}
/**
* from {@link java.io.DataInput} interface
*/
@Override
public String readLine() throws IOException {
return ByteUtil.readLine(this);
}
}