View Javadoc
1   /*
2   * Copyright 2014 The Netty Project
3   *
4   * The Netty Project licenses this file to you under the Apache License,
5   * version 2.0 (the "License"); you may not use this file except in compliance
6   * with the License. You may obtain a copy of the License at:
7   *
8   *   http://www.apache.org/licenses/LICENSE-2.0
9   *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations
14  * under the License.
15  */
16  
17  package io.netty.buffer;
18  
19  import io.netty.util.internal.PlatformDependent;
20  
21  import java.nio.ByteOrder;
22  
23  /**
24   * Special {@link SwappedByteBuf} for {@link ByteBuf}s that are backed by a {@code memoryAddress}.
25   */
26  final class UnsafeDirectSwappedByteBuf extends SwappedByteBuf {
27      private static final boolean NATIVE_ORDER = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
28      private final boolean nativeByteOrder;
29      private final AbstractByteBuf wrapped;
30  
31      UnsafeDirectSwappedByteBuf(AbstractByteBuf buf) {
32          super(buf);
33          wrapped = buf;
34          nativeByteOrder = NATIVE_ORDER == (order() == ByteOrder.BIG_ENDIAN);
35      }
36  
37      private long addr(int index) {
38          // We need to call wrapped.memoryAddress() everytime and NOT cache it as it may change if the buffer expand.
39          // See:
40          // - https://github.com/netty/netty/issues/2587
41          // - https://github.com/netty/netty/issues/2580
42          return wrapped.memoryAddress() + index;
43      }
44  
45      @Override
46      public long getLong(int index) {
47          wrapped.checkIndex(index, 8);
48          long v = PlatformDependent.getLong(addr(index));
49          return nativeByteOrder? v : Long.reverseBytes(v);
50      }
51  
52      @Override
53      public float getFloat(int index) {
54          return Float.intBitsToFloat(getInt(index));
55      }
56  
57      @Override
58      public double getDouble(int index) {
59          return Double.longBitsToDouble(getLong(index));
60      }
61  
62      @Override
63      public char getChar(int index) {
64          return (char) getShort(index);
65      }
66  
67      @Override
68      public long getUnsignedInt(int index) {
69          return getInt(index) & 0xFFFFFFFFL;
70      }
71  
72      @Override
73      public int getInt(int index) {
74          wrapped.checkIndex(index, 4);
75          int v = PlatformDependent.getInt(addr(index));
76          return nativeByteOrder? v : Integer.reverseBytes(v);
77      }
78  
79      @Override
80      public int getUnsignedShort(int index) {
81          return getShort(index) & 0xFFFF;
82      }
83  
84      @Override
85      public short getShort(int index) {
86          wrapped.checkIndex(index, 2);
87          short v = PlatformDependent.getShort(addr(index));
88          return nativeByteOrder? v : Short.reverseBytes(v);
89      }
90  
91      @Override
92      public ByteBuf setShort(int index, int value) {
93          wrapped.checkIndex(index, 2);
94          _setShort(index, value);
95          return this;
96      }
97  
98      @Override
99      public ByteBuf setInt(int index, int value) {
100         wrapped.checkIndex(index, 4);
101         _setInt(index, value);
102         return this;
103     }
104 
105     @Override
106     public ByteBuf setLong(int index, long value) {
107         wrapped.checkIndex(index, 8);
108         _setLong(index, value);
109         return this;
110     }
111 
112     @Override
113     public ByteBuf setChar(int index, int value) {
114         setShort(index, value);
115         return this;
116     }
117 
118     @Override
119     public ByteBuf setFloat(int index, float value) {
120         setInt(index, Float.floatToRawIntBits(value));
121         return this;
122     }
123 
124     @Override
125     public ByteBuf setDouble(int index, double value) {
126         setLong(index, Double.doubleToRawLongBits(value));
127         return this;
128     }
129 
130     @Override
131     public ByteBuf writeShort(int value) {
132         wrapped.ensureAccessible();
133         wrapped.ensureWritable(2);
134         _setShort(wrapped.writerIndex, value);
135         wrapped.writerIndex += 2;
136         return this;
137     }
138 
139     @Override
140     public ByteBuf writeInt(int value) {
141         wrapped.ensureAccessible();
142         wrapped.ensureWritable(4);
143         _setInt(wrapped.writerIndex, value);
144         wrapped.writerIndex += 4;
145         return this;
146     }
147 
148     @Override
149     public ByteBuf writeLong(long value) {
150         wrapped.ensureAccessible();
151         wrapped.ensureWritable(8);
152         _setLong(wrapped.writerIndex, value);
153         wrapped.writerIndex += 8;
154         return this;
155     }
156 
157     @Override
158     public ByteBuf writeChar(int value) {
159         writeShort(value);
160         return this;
161     }
162 
163     @Override
164     public ByteBuf writeFloat(float value) {
165         writeInt(Float.floatToRawIntBits(value));
166         return this;
167     }
168 
169     @Override
170     public ByteBuf writeDouble(double value) {
171         writeLong(Double.doubleToRawLongBits(value));
172         return this;
173     }
174 
175     private void _setShort(int index, int value) {
176         PlatformDependent.putShort(addr(index), nativeByteOrder ? (short) value : Short.reverseBytes((short) value));
177     }
178 
179     private void _setInt(int index, int value) {
180         PlatformDependent.putInt(addr(index), nativeByteOrder ? value : Integer.reverseBytes(value));
181     }
182 
183     private void _setLong(int index, long value) {
184         PlatformDependent.putLong(addr(index), nativeByteOrder ? value : Long.reverseBytes(value));
185     }
186 }