| /** |
| * 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 io.netty.buffer; |
| |
| import io.netty.util.internal.PlatformDependent; |
| |
| import java.nio.ByteOrder; |
| import java.util.concurrent.atomic.AtomicLong; |
| |
| import org.apache.drill.exec.util.AssertionUtil; |
| |
| public final class UnsafeDirectLittleEndian extends WrappedByteBuf { |
| private static final boolean NATIVE_ORDER = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN; |
| private final AbstractByteBuf wrapped; |
| private final long memoryAddress; |
| private AtomicLong bufferCount; |
| private AtomicLong bufferSize; |
| private long initCap = -1; |
| |
| UnsafeDirectLittleEndian(LargeBuffer buf) { |
| this(buf, true); |
| } |
| |
| UnsafeDirectLittleEndian(PooledUnsafeDirectByteBuf buf, AtomicLong bufferCount, AtomicLong bufferSize) { |
| this(buf, true); |
| this.bufferCount = bufferCount; |
| this.bufferSize = bufferSize; |
| |
| // initCap is used if we're tracking memory release. If we're in non-debug mode, we'll skip this. |
| this.initCap = AssertionUtil.ASSERT_ENABLED ? capacity() : -1; |
| } |
| |
| private UnsafeDirectLittleEndian(AbstractByteBuf buf, boolean fake) { |
| super(buf); |
| if (!NATIVE_ORDER || buf.order() != ByteOrder.BIG_ENDIAN) { |
| throw new IllegalStateException("Drill only runs on LittleEndian systems."); |
| } |
| wrapped = buf; |
| this.memoryAddress = buf.memoryAddress(); |
| } |
| private long addr(int index) { |
| return memoryAddress + index; |
| } |
| |
| @Override |
| public long getLong(int index) { |
| // wrapped.checkIndex(index, 8); |
| long v = PlatformDependent.getLong(addr(index)); |
| return v; |
| } |
| |
| @Override |
| public float getFloat(int index) { |
| return Float.intBitsToFloat(getInt(index)); |
| } |
| |
| @Override |
| public ByteBuf slice() { |
| return slice(this.readerIndex(), readableBytes()); |
| } |
| |
| @Override |
| public ByteBuf slice(int index, int length) { |
| return new SlicedByteBuf(this, index, length); |
| } |
| |
| @Override |
| public ByteOrder order() { |
| return ByteOrder.LITTLE_ENDIAN; |
| } |
| |
| @Override |
| public ByteBuf order(ByteOrder endianness) { |
| return this; |
| } |
| |
| @Override |
| public double getDouble(int index) { |
| return Double.longBitsToDouble(getLong(index)); |
| } |
| |
| @Override |
| public char getChar(int index) { |
| return (char) getShort(index); |
| } |
| |
| @Override |
| public long getUnsignedInt(int index) { |
| return getInt(index) & 0xFFFFFFFFL; |
| } |
| |
| @Override |
| public int getInt(int index) { |
| // wrapped.checkIndex(index, 4); |
| int v = PlatformDependent.getInt(addr(index)); |
| return v; |
| } |
| |
| @Override |
| public int getUnsignedShort(int index) { |
| return getShort(index) & 0xFFFF; |
| } |
| |
| @Override |
| public short getShort(int index) { |
| // wrapped.checkIndex(index, 2); |
| short v = PlatformDependent.getShort(addr(index)); |
| return v; |
| } |
| |
| @Override |
| public ByteBuf setShort(int index, int value) { |
| wrapped.checkIndex(index, 2); |
| _setShort(index, value); |
| return this; |
| } |
| |
| @Override |
| public ByteBuf setInt(int index, int value) { |
| wrapped.checkIndex(index, 4); |
| _setInt(index, value); |
| return this; |
| } |
| |
| @Override |
| public ByteBuf setLong(int index, long value) { |
| wrapped.checkIndex(index, 8); |
| _setLong(index, value); |
| return this; |
| } |
| |
| @Override |
| public ByteBuf setChar(int index, int value) { |
| setShort(index, value); |
| return this; |
| } |
| |
| @Override |
| public ByteBuf setFloat(int index, float value) { |
| setInt(index, Float.floatToRawIntBits(value)); |
| return this; |
| } |
| |
| @Override |
| public ByteBuf setDouble(int index, double value) { |
| setLong(index, Double.doubleToRawLongBits(value)); |
| return this; |
| } |
| |
| @Override |
| public ByteBuf writeShort(int value) { |
| wrapped.ensureWritable(2); |
| _setShort(wrapped.writerIndex, value); |
| wrapped.writerIndex += 2; |
| return this; |
| } |
| |
| @Override |
| public ByteBuf writeInt(int value) { |
| wrapped.ensureWritable(4); |
| _setInt(wrapped.writerIndex, value); |
| wrapped.writerIndex += 4; |
| return this; |
| } |
| |
| @Override |
| public ByteBuf writeLong(long value) { |
| wrapped.ensureWritable(8); |
| _setLong(wrapped.writerIndex, value); |
| wrapped.writerIndex += 8; |
| return this; |
| } |
| |
| @Override |
| public ByteBuf writeChar(int value) { |
| writeShort(value); |
| return this; |
| } |
| |
| @Override |
| public ByteBuf writeFloat(float value) { |
| writeInt(Float.floatToRawIntBits(value)); |
| return this; |
| } |
| |
| @Override |
| public ByteBuf writeDouble(double value) { |
| writeLong(Double.doubleToRawLongBits(value)); |
| return this; |
| } |
| |
| private void _setShort(int index, int value) { |
| PlatformDependent.putShort(addr(index), (short) value); |
| } |
| |
| private void _setInt(int index, int value) { |
| PlatformDependent.putInt(addr(index), value); |
| } |
| |
| private void _setLong(int index, long value) { |
| PlatformDependent.putLong(addr(index), value); |
| } |
| |
| @Override |
| public byte getByte(int index) { |
| return PlatformDependent.getByte(addr(index)); |
| } |
| |
| @Override |
| public ByteBuf setByte(int index, int value) { |
| PlatformDependent.putByte(addr(index), (byte) value); |
| return this; |
| } |
| |
| @Override |
| public boolean release() { |
| return release(1); |
| } |
| |
| @Override |
| public boolean release(int decrement) { |
| boolean released = super.release(decrement); |
| if (released && initCap != -1) { |
| bufferCount.decrementAndGet(); |
| bufferSize.addAndGet(-initCap); |
| } |
| return released; |
| } |
| |
| |
| } |