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