1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.buffer;
17
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.io.OutputStream;
21 import java.nio.ByteBuffer;
22 import java.nio.ByteOrder;
23 import java.nio.channels.ClosedChannelException;
24 import java.nio.channels.GatheringByteChannel;
25 import java.nio.channels.ScatteringByteChannel;
26
27
28
29
30
31
32
33
34
35
36
37
38 public class ByteBufferBackedChannelBuffer extends AbstractChannelBuffer {
39
40 private final ByteBuffer buffer;
41 private final ByteOrder order;
42 private final int capacity;
43
44
45
46
47 public ByteBufferBackedChannelBuffer(ByteBuffer buffer) {
48 if (buffer == null) {
49 throw new NullPointerException("buffer");
50 }
51
52 order = buffer.order();
53 this.buffer = buffer.slice().order(order);
54 capacity = buffer.remaining();
55 writerIndex(capacity);
56 }
57
58 private ByteBufferBackedChannelBuffer(ByteBufferBackedChannelBuffer buffer) {
59 this.buffer = buffer.buffer;
60 order = buffer.order;
61 capacity = buffer.capacity;
62 setIndex(buffer.readerIndex(), buffer.writerIndex());
63 }
64
65 public ChannelBufferFactory factory() {
66 if (buffer.isDirect()) {
67 return DirectChannelBufferFactory.getInstance(order());
68 } else {
69 return HeapChannelBufferFactory.getInstance(order());
70 }
71 }
72
73 public boolean isDirect() {
74 return buffer.isDirect();
75 }
76
77 public ByteOrder order() {
78 return order;
79 }
80
81 public int capacity() {
82 return capacity;
83 }
84
85 public boolean hasArray() {
86 return buffer.hasArray();
87 }
88
89 public byte[] array() {
90 return buffer.array();
91 }
92
93 public int arrayOffset() {
94 return buffer.arrayOffset();
95 }
96
97 public byte getByte(int index) {
98 return buffer.get(index);
99 }
100
101 public short getShort(int index) {
102 return buffer.getShort(index);
103 }
104
105 public int getUnsignedMedium(int index) {
106 return (getByte(index) & 0xff) << 16 |
107 (getByte(index+1) & 0xff) << 8 |
108 (getByte(index+2) & 0xff) << 0;
109 }
110
111 public int getInt(int index) {
112 return buffer.getInt(index);
113 }
114
115 public long getLong(int index) {
116 return buffer.getLong(index);
117 }
118
119 public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
120 if (dst instanceof ByteBufferBackedChannelBuffer) {
121 ByteBufferBackedChannelBuffer bbdst = (ByteBufferBackedChannelBuffer) dst;
122 ByteBuffer data = bbdst.buffer.duplicate();
123
124 data.limit(dstIndex + length).position(dstIndex);
125 getBytes(index, data);
126 } else if (buffer.hasArray()) {
127 dst.setBytes(dstIndex, buffer.array(), index + buffer.arrayOffset(), length);
128 } else {
129 dst.setBytes(dstIndex, this, index, length);
130 }
131 }
132
133 public void getBytes(int index, byte[] dst, int dstIndex, int length) {
134 ByteBuffer data = buffer.duplicate();
135 try {
136 data.limit(index + length).position(index);
137 } catch (IllegalArgumentException e) {
138 throw new IndexOutOfBoundsException();
139 }
140 data.get(dst, dstIndex, length);
141 }
142
143 public void getBytes(int index, ByteBuffer dst) {
144 ByteBuffer data = buffer.duplicate();
145 int bytesToCopy = Math.min(capacity() - index, dst.remaining());
146 try {
147 data.limit(index + bytesToCopy).position(index);
148 } catch (IllegalArgumentException e) {
149 throw new IndexOutOfBoundsException();
150 }
151 dst.put(data);
152 }
153
154 public void setByte(int index, int value) {
155 buffer.put(index, (byte) value);
156 }
157
158 public void setShort(int index, int value) {
159 buffer.putShort(index, (short) value);
160 }
161
162 public void setMedium(int index, int value) {
163 setByte(index, (byte) (value >>> 16));
164 setByte(index+1, (byte) (value >>> 8));
165 setByte(index+2, (byte) (value >>> 0));
166 }
167
168 public void setInt(int index, int value) {
169 buffer.putInt(index, value);
170 }
171
172 public void setLong(int index, long value) {
173 buffer.putLong(index, value);
174 }
175
176 public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
177 if (src instanceof ByteBufferBackedChannelBuffer) {
178 ByteBufferBackedChannelBuffer bbsrc = (ByteBufferBackedChannelBuffer) src;
179 ByteBuffer data = bbsrc.buffer.duplicate();
180
181 data.limit(srcIndex + length).position(srcIndex);
182 setBytes(index, data);
183 } else if (buffer.hasArray()) {
184 src.getBytes(srcIndex, buffer.array(), index + buffer.arrayOffset(), length);
185 } else {
186 src.getBytes(srcIndex, this, index, length);
187 }
188 }
189
190 public void setBytes(int index, byte[] src, int srcIndex, int length) {
191 ByteBuffer data = buffer.duplicate();
192 data.limit(index + length).position(index);
193 data.put(src, srcIndex, length);
194 }
195
196 public void setBytes(int index, ByteBuffer src) {
197 ByteBuffer data = buffer.duplicate();
198 data.limit(index + src.remaining()).position(index);
199 data.put(src);
200 }
201
202 public void getBytes(int index, OutputStream out, int length) throws IOException {
203 if (length == 0) {
204 return;
205 }
206
207 if (buffer.hasArray()) {
208 out.write(
209 buffer.array(),
210 index + buffer.arrayOffset(),
211 length);
212 } else {
213 byte[] tmp = new byte[length];
214 ((ByteBuffer) buffer.duplicate().position(index)).get(tmp);
215 out.write(tmp);
216 }
217 }
218
219 public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
220 if (length == 0) {
221 return 0;
222 }
223
224 return out.write((ByteBuffer) buffer.duplicate().position(index).limit(index + length));
225 }
226
227 public int setBytes(int index, InputStream in, int length)
228 throws IOException {
229
230 int readBytes = 0;
231
232 if (buffer.hasArray()) {
233 index += buffer.arrayOffset();
234 do {
235 int localReadBytes = in.read(buffer.array(), index, length);
236 if (localReadBytes < 0) {
237 if (readBytes == 0) {
238 return -1;
239 } else {
240 break;
241 }
242 }
243 readBytes += localReadBytes;
244 index += localReadBytes;
245 length -= localReadBytes;
246 } while (length > 0);
247 } else {
248 byte[] tmp = new byte[length];
249 int i = 0;
250 do {
251 int localReadBytes = in.read(tmp, i, tmp.length - i);
252 if (localReadBytes < 0) {
253 if (readBytes == 0) {
254 return -1;
255 } else {
256 break;
257 }
258 }
259 readBytes += localReadBytes;
260 i += readBytes;
261 } while (i < tmp.length);
262 ((ByteBuffer) buffer.duplicate().position(index)).put(tmp);
263 }
264
265 return readBytes;
266 }
267
268 public int setBytes(int index, ScatteringByteChannel in, int length)
269 throws IOException {
270
271 ByteBuffer slice = (ByteBuffer) buffer.duplicate().limit(index + length).position(index);
272 int readBytes = 0;
273
274 while (readBytes < length) {
275 int localReadBytes;
276 try {
277 localReadBytes = in.read(slice);
278 } catch (ClosedChannelException e) {
279 localReadBytes = -1;
280 }
281 if (localReadBytes < 0) {
282 if (readBytes == 0) {
283 return -1;
284 } else {
285 return readBytes;
286 }
287 } else if (localReadBytes == 0) {
288 break;
289 }
290 readBytes += localReadBytes;
291 }
292
293 return readBytes;
294 }
295
296 public ByteBuffer toByteBuffer(int index, int length) {
297 if (index == 0 && length == capacity()) {
298 return buffer.duplicate().order(order());
299 } else {
300 return ((ByteBuffer) buffer.duplicate().position(
301 index).limit(index + length)).slice().order(order());
302 }
303 }
304
305 public ChannelBuffer slice(int index, int length) {
306 if (index == 0 && length == capacity()) {
307 ChannelBuffer slice = duplicate();
308 slice.setIndex(0, length);
309 return slice;
310 } else {
311 if (index >= 0 && length == 0) {
312 return ChannelBuffers.EMPTY_BUFFER;
313 }
314 return new ByteBufferBackedChannelBuffer(
315 ((ByteBuffer) buffer.duplicate().position(
316 index).limit(index + length)).order(order()));
317 }
318 }
319
320 public ChannelBuffer duplicate() {
321 return new ByteBufferBackedChannelBuffer(this);
322 }
323
324 public ChannelBuffer copy(int index, int length) {
325 ByteBuffer src;
326 try {
327 src = (ByteBuffer) buffer.duplicate().position(index).limit(index + length);
328 } catch (IllegalArgumentException e) {
329 throw new IndexOutOfBoundsException();
330 }
331
332 ByteBuffer dst = buffer.isDirect() ? ByteBuffer.allocateDirect(length) : ByteBuffer.allocate(length);
333 dst.put(src);
334 dst.order(order());
335 dst.clear();
336 return new ByteBufferBackedChannelBuffer(dst);
337 }
338 }