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