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