1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.io;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.OutputStream;
24 import java.io.UnsupportedEncodingException;
25
26 import org.eclipse.jetty.util.StringUtil;
27
28
29
30
31
32 public class ByteArrayBuffer extends AbstractBuffer
33 {
34 final protected byte[] _bytes;
35
36 protected ByteArrayBuffer(int size, int access, boolean isVolatile)
37 {
38 this(new byte[size],0,0,access, isVolatile);
39 }
40
41 public ByteArrayBuffer(byte[] bytes)
42 {
43 this(bytes, 0, bytes.length, READWRITE);
44 }
45
46 public ByteArrayBuffer(byte[] bytes, int index, int length)
47 {
48 this(bytes, index, length, READWRITE);
49 }
50
51 public ByteArrayBuffer(byte[] bytes, int index, int length, int access)
52 {
53 super(READWRITE, NON_VOLATILE);
54 _bytes = bytes;
55 setPutIndex(index + length);
56 setGetIndex(index);
57 _access = access;
58 }
59
60 public ByteArrayBuffer(byte[] bytes, int index, int length, int access, boolean isVolatile)
61 {
62 super(READWRITE, isVolatile);
63 _bytes = bytes;
64 setPutIndex(index + length);
65 setGetIndex(index);
66 _access = access;
67 }
68
69 public ByteArrayBuffer(int size)
70 {
71 this(new byte[size], 0, 0, READWRITE);
72 setPutIndex(0);
73 }
74
75 public ByteArrayBuffer(String value)
76 {
77 super(READWRITE,NON_VOLATILE);
78 _bytes = StringUtil.getBytes(value);
79 setGetIndex(0);
80 setPutIndex(_bytes.length);
81 _access=IMMUTABLE;
82 _string = value;
83 }
84
85 public ByteArrayBuffer(String value,boolean immutable)
86 {
87 super(READWRITE,NON_VOLATILE);
88 _bytes = StringUtil.getBytes(value);
89 setGetIndex(0);
90 setPutIndex(_bytes.length);
91 if (immutable)
92 {
93 _access=IMMUTABLE;
94 _string = value;
95 }
96 }
97
98 public ByteArrayBuffer(String value,String encoding) throws UnsupportedEncodingException
99 {
100 super(READWRITE,NON_VOLATILE);
101 _bytes = value.getBytes(encoding);
102 setGetIndex(0);
103 setPutIndex(_bytes.length);
104 _access=IMMUTABLE;
105 _string = value;
106 }
107
108 public byte[] array()
109 {
110 return _bytes;
111 }
112
113 public int capacity()
114 {
115 return _bytes.length;
116 }
117
118 @Override
119 public void compact()
120 {
121 if (isReadOnly())
122 throw new IllegalStateException(__READONLY);
123 int s = markIndex() >= 0 ? markIndex() : getIndex();
124 if (s > 0)
125 {
126 int length = putIndex() - s;
127 if (length > 0)
128 {
129 System.arraycopy(_bytes, s,_bytes, 0, length);
130 }
131 if (markIndex() > 0) setMarkIndex(markIndex() - s);
132 setGetIndex(getIndex() - s);
133 setPutIndex(putIndex() - s);
134 }
135 }
136
137
138 @Override
139 public boolean equals(Object obj)
140 {
141 if (obj==this)
142 return true;
143
144 if (obj == null || !(obj instanceof Buffer))
145 return false;
146
147 if (obj instanceof Buffer.CaseInsensitve)
148 return equalsIgnoreCase((Buffer)obj);
149
150
151 Buffer b = (Buffer) obj;
152
153
154 if (b.length() != length())
155 return false;
156
157
158 if (_hash != 0 && obj instanceof AbstractBuffer)
159 {
160 AbstractBuffer ab = (AbstractBuffer) obj;
161 if (ab._hash != 0 && _hash != ab._hash)
162 return false;
163 }
164
165
166 int get=getIndex();
167 int bi=b.putIndex();
168 for (int i = putIndex(); i-->get;)
169 {
170 byte b1 = _bytes[i];
171 byte b2 = b.peek(--bi);
172 if (b1 != b2) return false;
173 }
174 return true;
175 }
176
177
178 @Override
179 public boolean equalsIgnoreCase(Buffer b)
180 {
181 if (b==this)
182 return true;
183
184
185 if (b==null || b.length() != length())
186 return false;
187
188
189 if (_hash != 0 && b instanceof AbstractBuffer)
190 {
191 AbstractBuffer ab = (AbstractBuffer) b;
192 if (ab._hash != 0 && _hash != ab._hash) return false;
193 }
194
195
196 int get=getIndex();
197 int bi=b.putIndex();
198 byte[] barray=b.array();
199 if (barray==null)
200 {
201 for (int i = putIndex(); i-->get;)
202 {
203 byte b1 = _bytes[i];
204 byte b2 = b.peek(--bi);
205 if (b1 != b2)
206 {
207 if ('a' <= b1 && b1 <= 'z') b1 = (byte) (b1 - 'a' + 'A');
208 if ('a' <= b2 && b2 <= 'z') b2 = (byte) (b2 - 'a' + 'A');
209 if (b1 != b2) return false;
210 }
211 }
212 }
213 else
214 {
215 for (int i = putIndex(); i-->get;)
216 {
217 byte b1 = _bytes[i];
218 byte b2 = barray[--bi];
219 if (b1 != b2)
220 {
221 if ('a' <= b1 && b1 <= 'z') b1 = (byte) (b1 - 'a' + 'A');
222 if ('a' <= b2 && b2 <= 'z') b2 = (byte) (b2 - 'a' + 'A');
223 if (b1 != b2) return false;
224 }
225 }
226 }
227 return true;
228 }
229
230 @Override
231 public byte get()
232 {
233 return _bytes[_get++];
234 }
235
236 @Override
237 public int hashCode()
238 {
239 if (_hash == 0 || _hashGet!=_get || _hashPut!=_put)
240 {
241 int get=getIndex();
242 for (int i = putIndex(); i-- >get;)
243 {
244 byte b = _bytes[i];
245 if ('a' <= b && b <= 'z')
246 b = (byte) (b - 'a' + 'A');
247 _hash = 31 * _hash + b;
248 }
249 if (_hash == 0)
250 _hash = -1;
251 _hashGet=_get;
252 _hashPut=_put;
253 }
254 return _hash;
255 }
256
257
258 public byte peek(int index)
259 {
260 return _bytes[index];
261 }
262
263 public int peek(int index, byte[] b, int offset, int length)
264 {
265 int l = length;
266 if (index + l > capacity())
267 {
268 l = capacity() - index;
269 if (l==0)
270 return -1;
271 }
272
273 if (l < 0)
274 return -1;
275
276 System.arraycopy(_bytes, index, b, offset, l);
277 return l;
278 }
279
280 public void poke(int index, byte b)
281 {
282
283
284
285
286
287
288
289
290
291 _bytes[index] = b;
292 }
293
294 @Override
295 public int poke(int index, Buffer src)
296 {
297 _hash=0;
298
299
300
301
302
303
304
305
306 int length=src.length();
307 if (index + length > capacity())
308 {
309 length=capacity()-index;
310
311
312
313
314 }
315
316 byte[] src_array = src.array();
317 if (src_array != null)
318 System.arraycopy(src_array, src.getIndex(), _bytes, index, length);
319 else
320 {
321 int s=src.getIndex();
322 for (int i=0;i<length;i++)
323 _bytes[index++]=src.peek(s++);
324 }
325
326 return length;
327 }
328
329
330 @Override
331 public int poke(int index, byte[] b, int offset, int length)
332 {
333 _hash=0;
334
335
336
337
338
339
340
341 if (index + length > capacity())
342 {
343 length=capacity()-index;
344
345
346
347 }
348
349 System.arraycopy(b, offset, _bytes, index, length);
350
351 return length;
352 }
353
354
355 @Override
356 public void writeTo(OutputStream out)
357 throws IOException
358 {
359 out.write(_bytes,getIndex(),length());
360 if (!isImmutable())
361 clear();
362 }
363
364
365 @Override
366 public int readFrom(InputStream in,int max) throws IOException
367 {
368 if (max<0||max>space())
369 max=space();
370 int p = putIndex();
371
372 int len=0, total=0, available=max;
373 while (total<max)
374 {
375 len=in.read(_bytes,p,available);
376 if (len<0)
377 break;
378 else if (len>0)
379 {
380 p += len;
381 total += len;
382 available -= len;
383 setPutIndex(p);
384 }
385 if (in.available()<=0)
386 break;
387 }
388 if (len<0 && total==0)
389 return -1;
390 return total;
391 }
392
393
394 @Override
395 public int space()
396 {
397 return _bytes.length - _put;
398 }
399
400
401
402
403
404 public static class CaseInsensitive extends ByteArrayBuffer implements Buffer.CaseInsensitve
405 {
406 public CaseInsensitive(String s)
407 {
408 super(s);
409 }
410
411 public CaseInsensitive(byte[] b, int o, int l, int rw)
412 {
413 super(b,o,l,rw);
414 }
415
416 @Override
417 public boolean equals(Object obj)
418 {
419 return obj instanceof Buffer && equalsIgnoreCase((Buffer)obj);
420 }
421
422 }
423 }