View Javadoc

1   // ========================================================================
2   // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at 
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses. 
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      protected byte[] _bytes;
30  
31      protected ByteArrayBuffer(int access, boolean isVolatile)
32      {
33          super(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, size, 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,String encoding) throws UnsupportedEncodingException
81      {
82          super(READWRITE,NON_VOLATILE);
83          _bytes = value.getBytes(encoding);
84          setGetIndex(0);
85          setPutIndex(_bytes.length);
86          _access=IMMUTABLE;
87          _string = value;
88      }
89  
90      public byte[] array()
91      {
92          return _bytes;
93      }
94  
95      public int capacity()
96      {
97          return _bytes.length;
98      }
99      
100     public void compact()
101     {
102         if (isReadOnly()) 
103             throw new IllegalStateException(__READONLY);
104         int s = markIndex() >= 0 ? markIndex() : getIndex();
105         if (s > 0)
106         {
107             int length = putIndex() - s;
108             if (length > 0)
109             {
110                 System.arraycopy(_bytes, s,_bytes, 0, length);
111             }
112             if (markIndex() > 0) setMarkIndex(markIndex() - s);
113             setGetIndex(getIndex() - s);
114             setPutIndex(putIndex() - s);
115         }
116     }
117 
118 
119     public boolean equals(Object obj)
120     {
121         if (obj==this)
122             return true;
123 
124         if (obj == null || !(obj instanceof Buffer)) 
125             return false;
126         
127         if (obj instanceof Buffer.CaseInsensitve)
128             return equalsIgnoreCase((Buffer)obj);
129         
130 
131         Buffer b = (Buffer) obj;
132         
133         // reject different lengths
134         if (b.length() != length()) 
135             return false;
136 
137         // reject AbstractBuffer with different hash value
138         if (_hash != 0 && obj instanceof AbstractBuffer)
139         {
140             AbstractBuffer ab = (AbstractBuffer) obj;
141             if (ab._hash != 0 && _hash != ab._hash) 
142                 return false;
143         }
144 
145         // Nothing for it but to do the hard grind.
146         int get=getIndex();
147         int bi=b.putIndex();
148         for (int i = putIndex(); i-->get;)
149         {
150             byte b1 = _bytes[i];
151             byte b2 = b.peek(--bi);
152             if (b1 != b2) return false;
153         }
154         return true;
155     }
156 
157 
158     public boolean equalsIgnoreCase(Buffer b)
159     {
160         if (b==this)
161             return true;
162         
163         // reject different lengths
164         if (b==null || b.length() != length()) 
165             return false;
166 
167         // reject AbstractBuffer with different hash value
168         if (_hash != 0 && b instanceof AbstractBuffer)
169         {
170             AbstractBuffer ab = (AbstractBuffer) b;
171             if (ab._hash != 0 && _hash != ab._hash) return false;
172         }
173 
174         // Nothing for it but to do the hard grind.
175         int get=getIndex();
176         int bi=b.putIndex();
177         byte[] barray=b.array();
178         if (barray==null)
179         {
180             for (int i = putIndex(); i-->get;)
181             {
182                 byte b1 = _bytes[i];
183                 byte b2 = b.peek(--bi);
184                 if (b1 != b2)
185                 {
186                     if ('a' <= b1 && b1 <= 'z') b1 = (byte) (b1 - 'a' + 'A');
187                     if ('a' <= b2 && b2 <= 'z') b2 = (byte) (b2 - 'a' + 'A');
188                     if (b1 != b2) return false;
189                 }
190             }
191         }
192         else
193         {
194             for (int i = putIndex(); i-->get;)
195             {
196                 byte b1 = _bytes[i];
197                 byte b2 = barray[--bi];
198                 if (b1 != b2)
199                 {
200                     if ('a' <= b1 && b1 <= 'z') b1 = (byte) (b1 - 'a' + 'A');
201                     if ('a' <= b2 && b2 <= 'z') b2 = (byte) (b2 - 'a' + 'A');
202                     if (b1 != b2) return false;
203                 }
204             }
205         }
206         return true;
207     }
208 
209     public byte get()
210     {
211         return _bytes[_get++];
212     }
213 
214     public int hashCode()
215     {
216         if (_hash == 0 || _hashGet!=_get || _hashPut!=_put) 
217         {
218             int get=getIndex();
219             for (int i = putIndex(); i-- >get;)
220             {
221                 byte b = _bytes[i];
222                 if ('a' <= b && b <= 'z') 
223                     b = (byte) (b - 'a' + 'A');
224                 _hash = 31 * _hash + b;
225             }
226             if (_hash == 0) 
227                 _hash = -1;
228             _hashGet=_get;
229             _hashPut=_put;
230         }
231         return _hash;
232     }
233     
234     
235     public byte peek(int index)
236     {
237         return _bytes[index];
238     }
239     
240     public int peek(int index, byte[] b, int offset, int length)
241     {
242         int l = length;
243         if (index + l > capacity())
244         {
245             l = capacity() - index;
246             if (l==0)
247                 return -1;
248         }
249         
250         if (l < 0) 
251             return -1;
252         
253         System.arraycopy(_bytes, index, b, offset, l);
254         return l;
255     }
256 
257     public void poke(int index, byte b)
258     {
259         /* 
260         if (isReadOnly()) 
261             throw new IllegalStateException(__READONLY);
262         
263         if (index < 0) 
264             throw new IllegalArgumentException("index<0: " + index + "<0");
265         if (index > capacity())
266                 throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity());
267         */
268         _bytes[index] = b;
269     }
270     
271     public int poke(int index, Buffer src)
272     {
273         _hash=0;
274         
275         /* 
276         if (isReadOnly()) 
277             throw new IllegalStateException(__READONLY);
278         if (index < 0) 
279             throw new IllegalArgumentException("index<0: " + index + "<0");
280         */
281         
282         int length=src.length();
283         if (index + length > capacity())
284         {
285             length=capacity()-index;
286             /*
287             if (length<0)
288                 throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity());
289             */
290         }
291         
292         byte[] src_array = src.array();
293         if (src_array != null)
294             System.arraycopy(src_array, src.getIndex(), _bytes, index, length);
295         else 
296         {
297             int s=src.getIndex();
298             for (int i=0;i<length;i++)
299                 _bytes[index++]=src.peek(s++);
300         }
301         
302         return length;
303     }
304     
305 
306     public int poke(int index, byte[] b, int offset, int length)
307     {
308         _hash=0;
309         /*
310         if (isReadOnly()) 
311             throw new IllegalStateException(__READONLY);
312         if (index < 0) 
313             throw new IllegalArgumentException("index<0: " + index + "<0");
314         */
315         
316         if (index + length > capacity())
317         {
318             length=capacity()-index;
319             /* if (length<0)
320                 throw new IllegalArgumentException("index>capacity(): " + index + ">" + capacity());
321             */
322         }
323         
324         System.arraycopy(b, offset, _bytes, index, length);
325         
326         return length;
327     }
328 
329     /* ------------------------------------------------------------ */
330     /** Wrap a byte array.
331      * @param b
332      * @param off
333      * @param len
334      */
335     public void wrap(byte[] b, int off, int len)
336     {
337         if (b==null)
338             throw new IllegalArgumentException();
339         if (isReadOnly()) throw new IllegalStateException(__READONLY);
340         if (isImmutable()) throw new IllegalStateException(__IMMUTABLE);
341         _bytes=b;
342         clear();
343         setGetIndex(off);
344         setPutIndex(off+len);
345     }
346 
347     /* ------------------------------------------------------------ */
348     /** Wrap a byte array
349      * @param b
350      */
351     public void wrap(byte[] b)
352     {
353         if (isReadOnly()) throw new IllegalStateException(__READONLY);
354         if (isImmutable()) throw new IllegalStateException(__IMMUTABLE);
355         _bytes=b;
356         setGetIndex(0);
357         setPutIndex(b.length);
358     }
359 
360     /* ------------------------------------------------------------ */
361     public void writeTo(OutputStream out)
362         throws IOException
363     {
364         out.write(_bytes,getIndex(),length());
365         clear();
366     }
367     
368     /* ------------------------------------------------------------ */
369     public int readFrom(InputStream in,int max) throws IOException
370     {
371         if (max<0||max>space())
372             max=space();
373         int p = putIndex();
374         
375         int len=0, total=0, available=max;
376         while (total<max) 
377         {
378             len=in.read(_bytes,p,available);
379             if (len<0)
380                 break;
381             else if (len>0)
382             {
383                 p += len;
384                 total += len;
385                 available -= len;
386                 setPutIndex(p);
387             }
388             if (in.available()<=0)
389                 break;
390         }
391         if (len<0 && total==0)
392             return -1;
393         return total;
394     }
395 
396     /* ------------------------------------------------------------ */
397     public int space()
398     {
399         return _bytes.length - _put;
400     }
401 
402     
403     /* ------------------------------------------------------------ */
404     /* ------------------------------------------------------------ */
405     /* ------------------------------------------------------------ */
406     public static class CaseInsensitive extends ByteArrayBuffer implements Buffer.CaseInsensitve
407     {
408         public CaseInsensitive(String s)
409         {
410             super(s);
411         }
412 
413         public CaseInsensitive(byte[] b, int o, int l, int rw)
414         {
415             super(b,o,l,rw);
416         }
417 
418         public boolean equals(Object obj)
419         {
420             return obj instanceof Buffer && equalsIgnoreCase((Buffer)obj);
421         }
422         
423     }
424 }