KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jruby > util > ByteList


1 /***** BEGIN LICENSE BLOCK *****
2  * Version: CPL 1.0/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Common Public
5  * License Version 1.0 (the "License"); you may not use this file
6  * except in compliance with the License. You may obtain a copy of
7  * the License at http://www.eclipse.org/legal/cpl-v10.html
8  *
9  * Software distributed under the License is distributed on an "AS
10  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11  * implied. See the License for the specific language governing
12  * rights and limitations under the License.
13  *
14  * Copyright (C) 2007 Charles O Nutter <headius@headius.com>
15  * Copyright (C) 2007 Nick Sieger <nicksieger@gmail.com>
16  * Copyright (C) 2007 Ola Bini <ola@ologix.com>
17  *
18  * Alternatively, the contents of this file may be used under the terms of
19  * either of the GNU General Public License Version 2 or later (the "GPL"),
20  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
21  * in which case the provisions of the GPL or the LGPL are applicable instead
22  * of those above. If you wish to allow use of your version of this file only
23  * under the terms of either the GPL or the LGPL, and not to allow others to
24  * use your version of this file under the terms of the CPL, indicate your
25  * decision by deleting the provisions above and replace them with the notice
26  * and other provisions required by the GPL or the LGPL. If you do not delete
27  * the provisions above, a recipient may use your version of this file under
28  * the terms of any one of the CPL, the GPL or the LGPL.
29  ***** END LICENSE BLOCK *****/

30 package org.jruby.util;
31
32 import java.io.Serializable JavaDoc;
33
34
35 /**
36  *
37  * @author headius
38  */

39 public class ByteList implements Comparable JavaDoc, CharSequence JavaDoc, Serializable JavaDoc {
40     private static final long serialVersionUID = -1286166947275543731L;
41
42     public static final byte[] NULL_ARRAY = new byte[0];
43
44     public byte[] bytes;
45     public int realSize;
46
47     private static final int DEFAULT_SIZE = 4;
48     private static final double FACTOR = 1.5;
49
50     /** Creates a new instance of ByteList */
51     public ByteList() {
52         this(DEFAULT_SIZE);
53     }
54
55     public ByteList(int size) {
56         bytes = new byte[size];
57         realSize = 0;
58     }
59
60     public ByteList(byte[] wrap) {
61         this(wrap,true);
62     }
63
64     public ByteList(byte[] wrap, boolean copy) {
65         if (wrap == null) throw new NullPointerException JavaDoc("Invalid argument: constructing with null array");
66         if(copy) {
67             bytes = (byte[])wrap.clone();
68         } else {
69             bytes = wrap;
70         }
71         realSize = wrap.length;
72     }
73
74     public ByteList(ByteList wrap) {
75         this(wrap.bytes, 0, wrap.realSize);
76     }
77
78     public ByteList(byte[] wrap, int index, int len) {
79         this(wrap,index,len,true);
80     }
81
82     public ByteList(byte[] wrap, int index, int len, boolean copy) {
83         if (wrap == null) throw new NullPointerException JavaDoc("Invalid argument: constructing with null array");
84         if(copy || index != 0) {
85             bytes = new byte[len];
86             System.arraycopy(wrap, index, bytes, 0, len);
87         } else {
88             bytes = wrap;
89         }
90         realSize = len;
91     }
92
93     public ByteList(ByteList wrap, int index, int len) {
94         this(wrap.bytes, index, len);
95     }
96
97     public void delete(int start, int len) {
98         realSize-=len;
99         System.arraycopy(bytes,start+len,bytes,start,realSize);
100     }
101
102     public void append(byte b) {
103         grow(1);
104         bytes[realSize++] = b;
105     }
106
107     public void append(int b) {
108         append((byte)b);
109     }
110
111     public void prepend(byte b) {
112         grow(1);
113         System.arraycopy(bytes, 0, bytes, 1, realSize);
114         bytes[0] = b;
115         realSize++;
116     }
117
118     public void append(byte[] moreBytes) {
119         grow(moreBytes.length);
120         System.arraycopy(moreBytes, 0, bytes, realSize, moreBytes.length);
121         realSize += moreBytes.length;
122     }
123
124     public void append(ByteList moreBytes) {
125         append(moreBytes.bytes, 0, moreBytes.realSize);
126     }
127
128     public void append(ByteList moreBytes, int index, int len) {
129         append(moreBytes.bytes, index, len);
130     }
131
132     public void append(byte[] moreBytes, int start, int len) {
133         grow(len);
134         System.arraycopy(moreBytes, start, bytes, realSize, len);
135         realSize += len;
136     }
137
138     public int length() {
139         return realSize;
140     }
141
142     public void length(int newLength) {
143         grow(newLength - realSize);
144         realSize = newLength;
145     }
146
147     public int get(int index) {
148         if (index >= realSize) throw new IndexOutOfBoundsException JavaDoc();
149         return bytes[index];
150     }
151
152     public void set(int index, int b) {
153         if (index >= realSize) throw new IndexOutOfBoundsException JavaDoc();
154         bytes[index] = (byte)b;
155     }
156
157     public void replace(byte[] newBytes) {
158         if (newBytes == null) throw new NullPointerException JavaDoc("Invalid argument: replacing with null array");
159         this.bytes = newBytes;
160         realSize = newBytes.length;
161     }
162
163     /**
164      * Unsafe version of replace(int,int,ByteList). The contract is that these
165      * unsafe versions will not make sure thet beg and len indices are correct.
166      */

167     public void unsafeReplace(int beg, int len, ByteList nbytes) {
168         unsafeReplace(beg, len, nbytes.bytes, 0, nbytes.realSize);
169     }
170
171     /**
172      * Unsafe version of replace(int,int,byte[]). The contract is that these
173      * unsafe versions will not make sure thet beg and len indices are correct.
174      */

175     public void unsafeReplace(int beg, int len, byte[] buf) {
176         unsafeReplace(beg, len, buf, 0, buf.length);
177     }
178
179     /**
180      * Unsafe version of replace(int,int,byte[],int,int). The contract is that these
181      * unsafe versions will not make sure thet beg and len indices are correct.
182      */

183     public void unsafeReplace(int beg, int len, byte[] nbytes, int index, int count) {
184         grow(count - len);
185         int newSize = realSize + count - len;
186         System.arraycopy(bytes,beg+len,bytes,beg+count,realSize - (len+beg));
187         System.arraycopy(nbytes,index,bytes,beg,count);
188         realSize = newSize;
189     }
190
191     public void replace(int beg, int len, ByteList nbytes) {
192         replace(beg, len, nbytes.bytes, 0, nbytes.realSize);
193     }
194
195     public void replace(int beg, int len, byte[] buf) {
196         replace(beg, len, buf, 0, buf.length);
197     }
198
199     public void replace(int beg, int len, byte[] nbytes, int index, int count) {
200         if (len - beg > realSize) throw new IndexOutOfBoundsException JavaDoc();
201         unsafeReplace(beg,len,nbytes,index,count);
202     }
203
204     public void insert(int index, int b) {
205         if (index >= realSize) throw new IndexOutOfBoundsException JavaDoc();
206         grow(1);
207         System.arraycopy(bytes,index,bytes,index+1,realSize-index);
208         bytes[index] = (byte)b;
209         realSize++;
210     }
211
212     public boolean equals(Object JavaDoc other) {
213         if (other == this) return true;
214         if (other instanceof ByteList) {
215             ByteList b = (ByteList) other;
216             if (b.realSize != realSize) {
217                 return false;
218             }
219             for (int i = 0; i < realSize; i++) {
220                 if (bytes[i] != b.bytes[i]) {
221                     return false;
222                 }
223             }
224             return true;
225         }
226         return false;
227     }
228
229     /**
230      * This comparison matches MRI comparison of Strings (rb_str_cmp).
231      * I wish we had memcmp right now...
232      */

233     public int compareTo(Object JavaDoc other) {
234         return cmp((ByteList)other);
235     }
236
237     public int cmp(ByteList other) {
238         if (other == this || other.bytes == bytes) return 0;
239         int len = Math.min(realSize,other.realSize);
240         int retval = 0;
241         for(int i=0;i<len && retval == 0;i++) {
242             retval = (bytes[i]&0xFF) - (other.bytes[i]&0xFF);
243         }
244         if(retval == 0) {
245             if(realSize == other.realSize) {
246                 return 0;
247             } else if(realSize > len) {
248                 return 1;
249             }
250             return -1;
251         }
252         if(retval > 0) {
253             return 1;
254         }
255         return -1;
256     }
257
258     /**
259      * Returns the internal byte array. This is unsafe unless you know what you're
260      * doing. But it can improve performance for byte-array operations that
261      * won't change the array.
262      *
263      * @return the internal byte array
264      */

265     public byte[] unsafeBytes() {
266         return bytes;
267     }
268
269     public byte[] bytes() {
270         byte[] newBytes = new byte[realSize];
271         System.arraycopy(bytes, 0, newBytes, 0, realSize);
272         return newBytes;
273     }
274
275     public Object JavaDoc clone() {
276         return new ByteList(bytes, 0, realSize);
277     }
278
279     private void grow(int increaseRequested) {
280         if (increaseRequested < 0) {
281             return;
282         }
283         int newSize = realSize + increaseRequested;
284         if (bytes.length < newSize) {
285             byte[] newBytes = new byte[(int) (newSize * FACTOR)];
286             System.arraycopy(bytes,0,newBytes,0,realSize);
287             bytes = newBytes;
288         }
289     }
290
291     /**
292      * Implements the same hashcode as MRI ELFHASH in rb_str_hash.
293      * No caching here. It's the clients responsibility to cache this value.
294      */

295     public int hashCode() {
296         int key = 0;
297         int g;
298         for(int i = 0; i < realSize; i++) {
299             key = (key << 4) + (((int)bytes[i]) & 0xFF);
300             if((g = key & 0xF0000000) != 0) {
301                 key ^= g >> 24;
302             }
303             key &= ~g;
304         }
305         return key;
306     }
307
308     public String JavaDoc toString() {
309         return new String JavaDoc(this.bytes,0,realSize);
310     }
311
312     public static ByteList create(CharSequence JavaDoc s) {
313         return new ByteList(plain(s),false);
314     }
315
316     public static byte[] plain(CharSequence JavaDoc s) {
317         byte[] bytes = new byte[s.length()];
318         for (int i = 0; i < bytes.length; i++) {
319             bytes[i] = (byte) s.charAt(i);
320         }
321         return bytes;
322     }
323
324     public static byte[] plain(char[] s) {
325         byte[] bytes = new byte[s.length];
326         for (int i = 0; i < s.length; i++) {
327             bytes[i] = (byte) s[i];
328         }
329         return bytes;
330     }
331     
332     public static char[] plain(byte[] b) {
333         char[] chars = new char[b.length];
334         for (int i = 0; i < b.length; i++) {
335             chars[i] = (char) (b[i] & 0xFF);
336         }
337         return chars;
338     }
339
340     public char charAt(int ix) {
341         return (char)(this.bytes[ix] & 0xFF);
342     }
343
344     public CharSequence JavaDoc subSequence(int start, int end) {
345         return new ByteList(this, start, end-start);
346     }
347 }
348
Popular Tags