Mercurial > hg > Members > sugi > MessagePack-java
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 } |