KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > lisp > ComplexString


1 /*
2  * ComplexString.java
3  *
4  * Copyright (C) 2002-2004 Peter Graves
5  * $Id: ComplexString.java,v 1.18 2004/09/21 00:39:04 piso Exp $
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */

21
22 package org.armedbear.lisp;
23
24 public final class ComplexString extends AbstractString
25 {
26     private int capacity;
27     private int fillPointer = -1; // -1 indicates no fill pointer.
28
private boolean isDisplaced;
29
30     // For non-displaced arrays.
31
private char[] chars;
32
33     // For displaced arrays.
34
private AbstractArray array;
35     private int displacement;
36
37     public ComplexString(int capacity)
38     {
39         this.capacity = capacity;
40         chars = new char[capacity];
41         isDisplaced = false;
42     }
43
44     public ComplexString(int capacity, AbstractArray array, int displacement)
45     {
46         this.capacity = capacity;
47         this.array = array;
48         this.displacement = displacement;
49         isDisplaced = true;
50     }
51
52     public LispObject typeOf()
53     {
54         return list2(Symbol.STRING, number(capacity()));
55     }
56
57     public LispClass classOf()
58     {
59         return BuiltInClass.STRING;
60     }
61
62     public boolean hasFillPointer()
63     {
64         return fillPointer >= 0;
65     }
66
67     public int getFillPointer()
68     {
69         return fillPointer;
70     }
71
72     public void setFillPointer(int n)
73     {
74         fillPointer = n;
75     }
76
77     public void setFillPointer(LispObject obj) throws ConditionThrowable
78     {
79         if (obj == T)
80             fillPointer = capacity();
81         else {
82             int n = Fixnum.getValue(obj);
83             if (n > capacity()) {
84                 StringBuffer JavaDoc sb = new StringBuffer JavaDoc("The new fill pointer (");
85                 sb.append(n);
86                 sb.append(") exceeds the capacity of the vector (");
87                 sb.append(capacity());
88                 sb.append(").");
89                 signal(new LispError(sb.toString()));
90             } else if (n < 0) {
91                 StringBuffer JavaDoc sb = new StringBuffer JavaDoc("The new fill pointer (");
92                 sb.append(n);
93                 sb.append(") is negative.");
94                 signal(new LispError(sb.toString()));
95             } else
96                 fillPointer = n;
97         }
98     }
99
100     public boolean isDisplaced()
101     {
102         return isDisplaced;
103     }
104
105     public LispObject arrayDisplacement() throws ConditionThrowable
106     {
107         LispObject value1, value2;
108         if (array != null) {
109             value1 = array;
110             value2 = new Fixnum(displacement);
111         } else {
112             value1 = NIL;
113             value2 = Fixnum.ZERO;
114         }
115         return LispThread.currentThread().setValues(value1, value2);
116     }
117
118     public char[] chars() throws ConditionThrowable
119     {
120         if (chars != null)
121             return chars;
122         Debug.assertTrue(array != null);
123         char[] chars = new char[capacity];
124         System.arraycopy(array.chars(), displacement, chars, 0, capacity);
125         return chars;
126     }
127
128     public char[] getStringChars() throws ConditionThrowable
129     {
130         if (fillPointer < 0)
131             return chars();
132         char[] ret = new char[fillPointer];
133         System.arraycopy(chars(), 0, ret, 0, fillPointer);
134         return ret;
135     }
136
137     public boolean equal(LispObject obj) throws ConditionThrowable
138     {
139         if (this == obj)
140             return true;
141         if (obj instanceof AbstractString) {
142             AbstractString string = (AbstractString) obj;
143             if (string.length() != length())
144                 return false;
145             for (int i = length(); i-- > 0;)
146                 if (string.getChar(i) != getChar(i))
147                     return false;
148             return true;
149         }
150         if (obj instanceof NilVector)
151             return obj.equal(this);
152         return false;
153     }
154
155     public boolean equalp(LispObject obj) throws ConditionThrowable
156     {
157         if (this == obj)
158             return true;
159         if (obj instanceof AbstractString) {
160             AbstractString string = (AbstractString) obj;
161             if (string.length() != length())
162                 return false;
163             for (int i = length(); i-- > 0;) {
164                 if (string.getChar(i) != getChar(i)) {
165                     if (Utilities.toLowerCase(string.getChar(i)) != Utilities.toLowerCase(getChar(i)))
166                         return false;
167                 }
168             }
169             return true;
170         }
171         if (obj instanceof AbstractArray)
172             return obj.equalp(this);
173         return false;
174     }
175
176     public LispObject subseq(int start, int end) throws ConditionThrowable
177     {
178         SimpleString s = new SimpleString(end - start);
179         int i = start, j = 0;
180         while (i < end)
181             s.setChar(j++, getChar(i++));
182         return s;
183     }
184
185     public void fill(LispObject obj) throws ConditionThrowable
186     {
187         fill(LispCharacter.getValue(obj));
188     }
189
190     public void fill(char c) throws ConditionThrowable
191     {
192         for (int i = length(); i-- > 0;)
193             setChar(i, c);
194     }
195
196     public void shrink(int n) throws ConditionThrowable
197     {
198         if (chars != null) {
199             if (n < capacity) {
200                 char[] newArray = new char[n];
201                 System.arraycopy(chars, 0, newArray, 0, n);
202                 chars = newArray;
203                 capacity = n;
204                 return;
205             }
206             if (n == capacity)
207                 return;
208         }
209         signal(new LispError());
210     }
211
212     public LispObject reverse() throws ConditionThrowable
213     {
214         int length = length();
215         SimpleString result = new SimpleString(length);
216         int i, j;
217         for (i = 0, j = length - 1; i < length; i++, j--)
218             result.setChar(i, getChar(j));
219         return result;
220     }
221
222     public LispObject nreverse() throws ConditionThrowable
223     {
224         int i = 0;
225         int j = length() - 1;
226         while (i < j) {
227             char temp = getChar(i);
228             setChar(i, getChar(j));
229             setChar(j, temp);
230             ++i;
231             --j;
232         }
233         return this;
234     }
235
236     public LispObject getRowMajor(int index) throws ConditionThrowable
237     {
238         return LispCharacter.getInstance(getChar(index));
239     }
240
241     public void setRowMajor(int index, LispObject newValue) throws ConditionThrowable
242     {
243         setChar(index, LispCharacter.getValue(newValue));
244     }
245
246     public char getChar(int index) throws ConditionThrowable
247     {
248         if (chars != null) {
249             try {
250                 return chars[index];
251             }
252             catch (ArrayIndexOutOfBoundsException JavaDoc e) {
253                 badIndex(index, capacity);
254                 return 0; // Not reached.
255
}
256         } else
257             return LispCharacter.getValue(array.getRowMajor(index + displacement));
258     }
259
260     public void setChar(int index, char c) throws ConditionThrowable
261     {
262         if (chars != null) {
263             try {
264                 chars[index] = c;
265             }
266             catch (ArrayIndexOutOfBoundsException JavaDoc e) {
267                 badIndex(index, capacity);
268             }
269         } else
270             array.setRowMajor(index + displacement, LispCharacter.getInstance(c));
271     }
272
273     public String JavaDoc getStringValue() throws ConditionThrowable
274     {
275         if (fillPointer >= 0)
276             return new String JavaDoc(chars(), 0, fillPointer);
277         else
278             return new String JavaDoc(chars());
279     }
280
281     public Object JavaDoc javaInstance() throws ConditionThrowable
282     {
283         return new String JavaDoc(chars());
284     }
285
286     public Object JavaDoc javaInstance(Class JavaDoc c) throws ConditionThrowable
287     {
288         return javaInstance();
289     }
290
291     public final int capacity()
292     {
293         return capacity;
294     }
295
296     public AbstractVector adjustVector(int newCapacity,
297                                        LispObject initialElement,
298                                        LispObject initialContents)
299         throws ConditionThrowable
300     {
301         if (initialContents != NIL) {
302             // "If INITIAL-CONTENTS is supplied, it is treated as for MAKE-
303
// ARRAY. In this case none of the original contents of array
304
// appears in the resulting array."
305
char[] newChars = new char[newCapacity];
306             if (initialContents.listp()) {
307                 LispObject list = initialContents;
308                 for (int i = 0; i < newCapacity; i++) {
309                     newChars[i] = LispCharacter.getValue(list.car());
310                     list = list.cdr();
311                 }
312             } else if (initialContents.vectorp()) {
313                 for (int i = 0; i < newCapacity; i++)
314                     newChars[i] = LispCharacter.getValue(initialContents.elt(i));
315             } else
316                 signal(new TypeError(initialContents, Symbol.SEQUENCE));
317             chars = newChars;
318         } else {
319             if (chars == null) {
320                 // Displaced array. Copy existing characters.
321
chars = new char[newCapacity];
322                 final int limit = Math.min(capacity, newCapacity);
323                 if (array instanceof AbstractString) {
324                     AbstractString string = (AbstractString) array;
325                     for (int i = 0; i < limit; i++) {
326                         chars[i] = string.getChar(displacement + i);
327                     }
328                 } else {
329                     for (int i = 0; i < limit; i++) {
330                         LispCharacter character =
331                             (LispCharacter) array.getRowMajor(displacement + i);
332                         chars[i] = character.value;
333                     }
334                 }
335             } else if (capacity != newCapacity) {
336                 char[] newElements = new char[newCapacity];
337                 System.arraycopy(chars, 0, newElements, 0,
338                                  Math.min(capacity, newCapacity));
339                 chars = newElements;
340             }
341             if (initialElement != NIL && capacity < newCapacity) {
342                 // Initialize new elements.
343
final char c = LispCharacter.getValue(initialElement);
344                 for (int i = capacity; i < newCapacity; i++)
345                     chars[i] = c;
346             }
347         }
348         capacity = newCapacity;
349         array = null;
350         displacement = 0;
351         isDisplaced = false;
352         return this;
353     }
354
355     public AbstractVector adjustVector(int newCapacity,
356                                        AbstractArray displacedTo,
357                                        int displacement)
358         throws ConditionThrowable
359     {
360         capacity = newCapacity;
361         array = displacedTo;
362         this.displacement = displacement;
363         chars = null;
364         isDisplaced = true;
365         return this;
366     }
367
368     public final int length()
369     {
370         return fillPointer >= 0 ? fillPointer : capacity;
371     }
372
373     public LispObject elt(int index) throws ConditionThrowable
374     {
375         final int limit = length();
376         if (index < 0 || index >= limit)
377             badIndex(index, limit);
378         return LispCharacter.getInstance(getChar(index));
379     }
380
381     // Ignores fill pointer.
382
public LispObject AREF(LispObject index) throws ConditionThrowable
383     {
384         return LispCharacter.getInstance(getChar(Fixnum.getValue(index)));
385     }
386
387     public LispObject vectorPushExtend(LispObject element)
388         throws ConditionThrowable
389     {
390         if (fillPointer < 0)
391             noFillPointer();
392         if (fillPointer >= capacity) {
393             // Need to extend vector.
394
ensureCapacity(capacity * 2 + 1);
395         }
396         if (chars != null) {
397             try {
398                 chars[fillPointer] = ((LispCharacter)element).value;
399             }
400             catch (ClassCastException JavaDoc e) {
401                 signal(new TypeError(element, Symbol.CHARACTER));
402             }
403         } else
404             array.setRowMajor(fillPointer + displacement, element);
405         return new Fixnum(fillPointer++);
406     }
407
408     public LispObject vectorPushExtend(LispObject element, LispObject extension)
409         throws ConditionThrowable
410     {
411         int ext = Fixnum.getValue(extension);
412         if (fillPointer < 0)
413             noFillPointer();
414         if (fillPointer >= capacity) {
415             // Need to extend vector.
416
ext = Math.max(ext, capacity + 1);
417             ensureCapacity(capacity + ext);
418         }
419         if (chars != null) {
420             try {
421                 chars[fillPointer] = ((LispCharacter)element).value;
422             }
423             catch (ClassCastException JavaDoc e) {
424                 signal(new TypeError(element, Symbol.CHARACTER));
425             }
426         } else
427             array.setRowMajor(fillPointer + displacement, element);
428         return new Fixnum(fillPointer++);
429     }
430
431     public final void ensureCapacity(int minCapacity) throws ConditionThrowable
432     {
433         if (chars != null) {
434             if (capacity < minCapacity) {
435                 char[] newArray = new char[minCapacity];
436                 System.arraycopy(chars, 0, newArray, 0, capacity);
437                 chars = newArray;
438                 capacity = minCapacity;
439             }
440         } else {
441             Debug.assertTrue(array != null);
442             if (array.getTotalSize() - displacement < minCapacity) {
443                 // Copy array.
444
chars = new char[minCapacity];
445                 final int limit = array.getTotalSize() - displacement;
446                 if (array instanceof AbstractString) {
447                     AbstractString string = (AbstractString) array;
448                     for (int i = 0; i < limit; i++) {
449                         chars[i] = string.getChar(displacement + i);
450                     }
451                 } else {
452                     for (int i = 0; i < limit; i++) {
453                         LispCharacter character =
454                             (LispCharacter) array.getRowMajor(displacement + i);
455                         chars[i] = character.value;
456                     }
457                 }
458                 capacity = minCapacity;
459                 array = null;
460                 displacement = 0;
461                 isDisplaced = false;
462             }
463         }
464     }
465
466     public int hashCode()
467     {
468         int hashCode = 0;
469         try {
470             final int limit = length();
471             for (int i = 0; i < limit; i++)
472                 hashCode = hashCode * 31 + getChar(i);
473         }
474         catch (ConditionThrowable t) {
475             // Shouldn't happen.
476
Debug.trace(t);
477         }
478         return hashCode;
479     }
480 }
481
Popular Tags