comparison src/main/java/org/msgpack/io/LinkedBufferInput.java @ 0:cb825acd883a

first commit
author sugi
date Sat, 18 Oct 2014 15:06:15 +0900
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:cb825acd883a
1 //
2 // MessagePack for Java
3 //
4 // Copyright (C) 2009 - 2013 FURUHASHI Sadayuki
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 // You may obtain a copy of the License at
9 //
10 // http://www.apache.org/licenses/LICENSE-2.0
11 //
12 // Unless required by applicable law or agreed to in writing, software
13 // distributed under the License is distributed on an "AS IS" BASIS,
14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 // See the License for the specific language governing permissions and
16 // limitations under the License.
17 //
18 package org.msgpack.io;
19
20 import java.io.IOException;
21 import java.io.EOFException;
22 import java.util.LinkedList;
23 import java.util.Iterator;
24 import java.util.NoSuchElementException;
25 import java.nio.ByteBuffer;
26
27 public class LinkedBufferInput extends AbstractInput {
28 LinkedList<ByteBuffer> link;
29
30 int writable;
31
32 private int nextAdvance;
33
34 private byte[] tmpBuffer;
35
36 private ByteBuffer tmpByteBuffer;
37
38 private final int bufferSize;
39
40 public LinkedBufferInput(int bufferSize) {
41 this.link = new LinkedList<ByteBuffer>();
42 this.writable = -1;
43 this.tmpBuffer = new byte[8];
44 this.tmpByteBuffer = ByteBuffer.wrap(tmpBuffer);
45 this.bufferSize = bufferSize;
46 }
47
48 public int read(byte[] b, int off, int len) throws EOFException {
49 if (link.isEmpty()) {
50 return 0;
51 }
52 int olen = len;
53 while (true) {
54 ByteBuffer bb = link.getFirst();
55 if (len < bb.remaining()) {
56 bb.get(b, off, len);
57 incrReadByteCount(len);
58 return olen;
59 }
60 int rem = bb.remaining();
61 bb.get(b, off, rem);
62 incrReadByteCount(rem);
63 len -= rem;
64 off += rem;
65 if (!removeFirstLink(bb)) {
66 break;
67 }
68 }
69 return olen - len;
70 }
71
72 public boolean tryRefer(BufferReferer ref, int len) throws IOException {
73 ByteBuffer bb = null;
74 try {
75 bb = link.getFirst();
76 } catch(NoSuchElementException e) {}
77 if (bb == null) {
78 throw new EndOfBufferException();
79 } else if (bb.remaining() < len) {
80 return false;
81 }
82 boolean success = false;
83 int pos = bb.position();
84 int lim = bb.limit();
85 try {
86 bb.limit(pos + len);
87 ref.refer(bb, true);
88 incrReadByteCount(len);
89 success = true;
90 } finally {
91 bb.limit(lim);
92 if (success) {
93 bb.position(pos + len);
94 } else {
95 bb.position(pos);
96 }
97 if (bb.remaining() == 0) {
98 removeFirstLink(bb);
99 }
100 }
101 return true;
102 }
103
104 public byte readByte() throws EOFException {
105 ByteBuffer bb = null;
106 try {
107 bb = link.getFirst();
108 } catch(NoSuchElementException e) {}
109 if (bb == null || bb.remaining() == 0) {
110 throw new EndOfBufferException();
111 }
112 byte result = bb.get();
113 incrReadOneByteCount();
114 if (bb.remaining() == 0) {
115 removeFirstLink(bb);
116 }
117 return result;
118 }
119
120 public void advance() {
121 if (link.isEmpty()) {
122 return;
123 }
124 int len = nextAdvance;
125 ByteBuffer bb;
126 while (true) {
127 bb = link.getFirst();
128 if (len < bb.remaining()) {
129 bb.position(bb.position() + len);
130 break;
131 }
132 len -= bb.remaining();
133 bb.position(bb.position() + bb.remaining());
134 if (!removeFirstLink(bb)) {
135 break;
136 }
137 }
138 incrReadByteCount(nextAdvance);
139 nextAdvance = 0;
140 }
141
142 private boolean removeFirstLink(ByteBuffer first) {
143 if (link.size() == 1) {
144 if (writable >= 0) {
145 first.position(0);
146 first.limit(0);
147 writable = first.capacity();
148 return false;
149 } else {
150 link.removeFirst();
151 return false;
152 }
153 } else {
154 link.removeFirst();
155 return true;
156 }
157 }
158
159 private void requireMore(int n) throws EOFException {
160 int off = 0;
161 for (ByteBuffer bb : link) {
162 if (n <= bb.remaining()) {
163 int pos = bb.position();
164 bb.get(tmpBuffer, off, n);
165 bb.position(pos);
166 return;
167 }
168 int rem = bb.remaining();
169 int pos = bb.position();
170 bb.get(tmpBuffer, off, rem);
171 bb.position(pos);
172 n -= rem;
173 off += rem;
174 }
175 throw new EndOfBufferException();
176 }
177
178 private ByteBuffer require(int n) throws EOFException {
179 ByteBuffer bb = null;
180 try {
181 bb = link.getFirst();
182 } catch(NoSuchElementException e) {}
183 if (bb == null) {
184 throw new EndOfBufferException();
185 }
186 if (n <= bb.remaining()) {
187 nextAdvance = n;
188 return bb;
189 } else {
190 requireMore(n);
191 nextAdvance = n;
192 return tmpByteBuffer;
193 }
194 }
195
196 public byte getByte() throws EOFException {
197 ByteBuffer bb = require(1);
198 return bb.get(bb.position());
199 }
200
201 public short getShort() throws EOFException {
202 ByteBuffer bb = require(2);
203 return bb.getShort(bb.position());
204 }
205
206 public int getInt() throws EOFException {
207 ByteBuffer bb = require(4);
208 return bb.getInt(bb.position());
209 }
210
211 public long getLong() throws EOFException {
212 ByteBuffer bb = require(8);
213 return bb.getLong(bb.position());
214 }
215
216 public float getFloat() throws EOFException {
217 ByteBuffer bb = require(4);
218 return bb.getFloat(bb.position());
219 }
220
221 public double getDouble() throws EOFException {
222 ByteBuffer bb = require(8);
223 return bb.getDouble(bb.position());
224 }
225
226 public void feed(byte[] b) {
227 feed(b, 0, b.length, false);
228 }
229
230 public void feed(byte[] b, boolean reference) {
231 feed(b, 0, b.length, reference);
232 }
233
234 public void feed(byte[] b, int off, int len) {
235 feed(b, off, len, false);
236 }
237
238 public void feed(byte[] b, int off, int len, boolean reference) {
239 if (reference) {
240 if (writable > 0 && link.getLast().remaining() == 0) {
241 link.add(link.size()-1, ByteBuffer.wrap(b, off, len));
242 return;
243 }
244 link.addLast(ByteBuffer.wrap(b, off, len));
245 writable = -1;
246 return;
247 }
248
249 ByteBuffer bb = null;
250 try {
251 bb = link.getLast();
252 } catch(NoSuchElementException e) {}
253 if (len <= writable) {
254 int pos = bb.position();
255 bb.position(bb.limit());
256 bb.limit(bb.limit() + len);
257 bb.put(b, off, len);
258 bb.position(pos);
259 writable = bb.capacity() - bb.limit();
260 return;
261 }
262
263 if (writable > 0) {
264 int pos = bb.position();
265 bb.position(bb.limit());
266 bb.limit(bb.limit() + writable);
267 bb.put(b, off, writable);
268 bb.position(pos);
269 off += writable;
270 len -= writable;
271 writable = 0;
272 }
273
274 int sz = Math.max(len, bufferSize);
275 ByteBuffer nb = ByteBuffer.allocate(sz);
276 nb.put(b, off, len);
277 nb.limit(len);
278 nb.position(0);
279 link.addLast(nb);
280 writable = sz - len;
281 }
282
283 public void feed(ByteBuffer b) {
284 feed(b, false);
285 }
286
287 public void feed(ByteBuffer buf, boolean reference) {
288 if (reference) {
289 if (writable > 0 && link.getLast().remaining() == 0) {
290 link.add(link.size()-1, buf);
291 return;
292 }
293 link.addLast(buf);
294 writable = -1;
295 return;
296 }
297
298 int rem = buf.remaining();
299
300 ByteBuffer bb = null;
301 try {
302 bb = link.getLast();
303 } catch(NoSuchElementException e) {}
304 if (rem <= writable) {
305 int pos = bb.position();
306 bb.position(bb.limit());
307 bb.limit(bb.limit() + rem);
308 bb.put(buf);
309 bb.position(pos);
310 writable = bb.capacity() - bb.limit();
311 return;
312 }
313
314 if (writable > 0) {
315 int pos = bb.position();
316 bb.position(bb.limit());
317 bb.limit(bb.limit() + writable);
318 buf.limit(writable);
319 bb.put(buf);
320 bb.position(pos);
321 rem -= writable;
322 buf.limit(buf.limit() + rem);
323 writable = 0;
324 }
325
326 int sz = Math.max(rem, bufferSize);
327 ByteBuffer nb = ByteBuffer.allocate(sz);
328 nb.put(buf);
329 nb.limit(rem);
330 nb.position(0);
331 link.addLast(nb);
332 writable = sz - rem;
333 }
334
335 public void clear() {
336 if (writable >= 0) {
337 ByteBuffer bb = link.getLast();
338 link.clear();
339 bb.position(0);
340 bb.limit(0);
341 link.addLast(bb);
342 writable = bb.capacity();
343 } else {
344 link.clear();
345 writable = -1;
346 }
347 }
348
349 public void copyReferencedBuffer() {
350 if (link.isEmpty()) {
351 return;
352 }
353
354 int size = 0;
355 for(ByteBuffer bb : link) {
356 size += bb.remaining();
357 }
358 if (size == 0) {
359 return;
360 }
361
362 if (writable >= 0) {
363 ByteBuffer last = link.removeLast();
364 byte[] copy = new byte[size - last.remaining()];
365 int off = 0;
366 for(ByteBuffer bb : link) {
367 int len = bb.remaining();
368 bb.get(copy, off, len);
369 off += len;
370 }
371 link.clear();
372 link.add(ByteBuffer.wrap(copy));
373 link.add(last);
374
375 } else {
376 byte[] copy = new byte[size];
377 int off = 0;
378 for(ByteBuffer bb : link) {
379 int len = bb.remaining();
380 bb.get(copy, off, len);
381 off += len;
382 }
383 link.clear();
384 link.add(ByteBuffer.wrap(copy));
385 writable = 0;
386 }
387 }
388
389 public int getSize() {
390 int size = 0;
391 for(ByteBuffer bb : link) {
392 size += bb.remaining();
393 }
394 return size;
395 }
396
397 public void close() {
398 }
399 }