source: branches/0.16.x/abcl/src/org/armedbear/lisp/SimpleString.java

Last change on this file was 11754, checked in by vvoutilainen, 16 years ago

Convert using ClassCastException? to checking instanceof.
Performance tests show this approach to be faster.
Patch by Douglas R. Miles. I modified the patch to
remove tabs, so indentation may be slightly off in places.
That's something that we need to handle separately, abcl
doesn't have a clear indentation policy.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 13.5 KB
Line 
1/*
2 * SimpleString.java
3 *
4 * Copyright (C) 2004-2005 Peter Graves
5 * $Id: SimpleString.java 11754 2009-04-12 10:53:39Z vvoutilainen $
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 * As a special exception, the copyright holders of this library give you
22 * permission to link this library with independent modules to produce an
23 * executable, regardless of the license terms of these independent
24 * modules, and to copy and distribute the resulting executable under
25 * terms of your choice, provided that you also meet, for each linked
26 * independent module, the terms and conditions of the license of that
27 * module.  An independent module is a module which is not derived from
28 * or based on this library.  If you modify this library, you may extend
29 * this exception to your version of the library, but you are not
30 * obligated to do so.  If you do not wish to do so, delete this
31 * exception statement from your version.
32 */
33
34package org.armedbear.lisp;
35
36public final class SimpleString extends AbstractString
37{
38    private int capacity;
39    private char[] chars;
40
41    public SimpleString(LispCharacter c)
42    {
43        chars = new char[1];
44        chars[0] = c.value;
45        capacity = 1;
46    }
47
48    public SimpleString(char c)
49    {
50        chars = new char[1];
51        chars[0] = c;
52        capacity = 1;
53    }
54
55    public SimpleString(int capacity)
56    {
57        this.capacity = capacity;
58        chars = new char[capacity];
59    }
60
61    public SimpleString(String s)
62    {
63        capacity = s.length();
64        chars = s.toCharArray();
65    }
66
67    public SimpleString(StringBuffer sb)
68    {
69        chars = new char[capacity = sb.length()];
70        sb.getChars(0, capacity, chars, 0);
71    }
72
73    public SimpleString(FastStringBuffer sb)
74    {
75        chars = sb.toCharArray();
76        capacity = chars.length;
77    }
78
79    private SimpleString(char[] chars)
80    {
81        this.chars = chars;
82        capacity = chars.length;
83    }
84
85    @Override
86    public char[] chars()
87    {
88        return chars;
89    }
90
91    @Override
92    public char[] getStringChars()
93    {
94        return chars;
95    }
96
97    @Override
98    public LispObject typeOf()
99    {
100        return list(Symbol.SIMPLE_BASE_STRING, Fixnum.getInstance(capacity));
101    }
102
103    @Override
104    public LispObject classOf()
105    {
106        return BuiltInClass.SIMPLE_BASE_STRING;
107    }
108
109    @Override
110    public LispObject getDescription()
111    {
112        FastStringBuffer sb = new FastStringBuffer("A simple-string (");
113        sb.append(capacity);
114        sb.append(") \"");
115        sb.append(chars);
116        sb.append('"');
117        return new SimpleString(sb);
118    }
119
120    @Override
121    public LispObject typep(LispObject type) throws ConditionThrowable
122    {
123        if (type == Symbol.SIMPLE_STRING)
124            return T;
125        if (type == Symbol.SIMPLE_ARRAY)
126            return T;
127        if (type == Symbol.SIMPLE_BASE_STRING)
128            return T;
129        if (type == BuiltInClass.SIMPLE_STRING)
130            return T;
131        if (type == BuiltInClass.SIMPLE_ARRAY)
132            return T;
133        if (type == BuiltInClass.SIMPLE_BASE_STRING)
134            return T;
135        return super.typep(type);
136    }
137
138    @Override
139    public LispObject SIMPLE_STRING_P()
140    {
141        return T;
142    }
143
144    @Override
145    public boolean hasFillPointer()
146    {
147        return false;
148    }
149
150    @Override
151    public boolean isAdjustable()
152    {
153        return false;
154    }
155
156    @Override
157    public boolean equal(LispObject obj) throws ConditionThrowable
158    {
159        if (this == obj)
160            return true;
161        if (obj instanceof SimpleString) {
162            SimpleString string = (SimpleString) obj;
163            if (string.capacity != capacity)
164                return false;
165            for (int i = capacity; i-- > 0;)
166                if (string.chars[i] != chars[i])
167                    return false;
168            return true;
169        }
170        if (obj instanceof AbstractString) {
171            AbstractString string = (AbstractString) obj;
172            if (string.length() != capacity)
173                return false;
174            for (int i = length(); i-- > 0;)
175                if (string.charAt(i) != chars[i])
176                    return false;
177            return true;
178        }
179        if (obj instanceof NilVector)
180            return obj.equal(this);
181        return false;
182    }
183
184    @Override
185    public boolean equalp(LispObject obj) throws ConditionThrowable
186    {
187        if (this == obj)
188            return true;
189        if (obj instanceof SimpleString) {
190            SimpleString string = (SimpleString) obj;
191            if (string.capacity != capacity)
192                return false;
193            for (int i = capacity; i-- > 0;) {
194                if (string.chars[i] != chars[i]) {
195                    if (LispCharacter.toLowerCase(string.chars[i]) != LispCharacter.toLowerCase(chars[i]))
196                        return false;
197                }
198            }
199            return true;
200        }
201        if (obj instanceof AbstractString) {
202            AbstractString string = (AbstractString) obj;
203            if (string.length() != capacity)
204                return false;
205            for (int i = length(); i-- > 0;) {
206                if (string.charAt(i) != chars[i]) {
207                    if (LispCharacter.toLowerCase(string.charAt(i)) != LispCharacter.toLowerCase(chars[i]))
208                        return false;
209                }
210            }
211            return true;
212        }
213        if (obj instanceof AbstractBitVector)
214            return false;
215        if (obj instanceof AbstractArray)
216            return obj.equalp(this);
217        return false;
218    }
219
220    public final SimpleString substring(int start) throws ConditionThrowable
221    {
222        return substring(start, capacity);
223    }
224
225    public final SimpleString substring(int start, int end)
226        throws ConditionThrowable
227    {
228        SimpleString s = new SimpleString(end - start);
229        int i = start, j = 0;
230        try {
231            while (i < end)
232                s.chars[j++] = chars[i++];
233            return s;
234        }
235        catch (ArrayIndexOutOfBoundsException e) {
236            error(new TypeError("Array index out of bounds: " + i));
237            // Not reached.
238            return null;
239        }
240    }
241
242    @Override
243    public final LispObject subseq(int start, int end) throws ConditionThrowable
244    {
245        return substring(start, end);
246    }
247
248    @Override
249    public void fill(LispObject obj) throws ConditionThrowable
250    {
251        fill(LispCharacter.getValue(obj));
252    }
253
254    @Override
255    public void fill(char c)
256    {
257        for (int i = capacity; i-- > 0;)
258            chars[i] = c;
259    }
260
261    @Override
262    public void shrink(int n) throws ConditionThrowable
263    {
264        if (n < capacity) {
265            char[] newArray = new char[n];
266            System.arraycopy(chars, 0, newArray, 0, n);
267            chars = newArray;
268            capacity = n;
269            return;
270        }
271        if (n == capacity)
272            return;
273        error(new LispError());
274    }
275
276    @Override
277    public LispObject reverse() throws ConditionThrowable
278    {
279        SimpleString result = new SimpleString(capacity);
280        int i, j;
281        for (i = 0, j = capacity - 1; i < capacity; i++, j--)
282            result.chars[i] = chars[j];
283        return result;
284    }
285
286    @Override
287    public LispObject nreverse() throws ConditionThrowable
288    {
289        int i = 0;
290        int j = capacity - 1;
291        while (i < j) {
292            char temp = chars[i];
293            chars[i] = chars[j];
294            chars[j] = temp;
295            ++i;
296            --j;
297        }
298        return this;
299    }
300
301    @Override
302    public String getStringValue()
303    {
304        return String.valueOf(chars);
305    }
306
307    @Override
308    public Object javaInstance()
309    {
310        return String.valueOf(chars);
311    }
312
313    @Override
314    public Object javaInstance(Class c)
315    {
316        return javaInstance();
317    }
318
319    @Override
320    public final int capacity()
321    {
322        return capacity;
323    }
324
325    @Override
326    public final int length()
327    {
328        return capacity;
329    }
330
331    @Override
332    public char charAt(int index) throws ConditionThrowable
333    {
334        try {
335            return chars[index];
336        }
337        catch (ArrayIndexOutOfBoundsException e) {
338            badIndex(index, capacity);
339            return 0; // Not reached.
340        }
341    }
342
343    @Override
344    public void setCharAt(int index, char c) throws ConditionThrowable
345    {
346        try {
347            chars[index] = c;
348        }
349        catch (ArrayIndexOutOfBoundsException e) {
350            badIndex(index, capacity);
351        }
352    }
353
354    @Override
355    public LispObject elt(int index) throws ConditionThrowable
356    {
357        try {
358            return LispCharacter.getInstance(chars[index]);
359        }
360        catch (ArrayIndexOutOfBoundsException e) {
361            badIndex(index, capacity);
362            return NIL; // Not reached.
363        }
364    }
365
366    @Override
367    public LispObject CHAR(int index) throws ConditionThrowable
368    {
369        try {
370            return LispCharacter.getInstance(chars[index]);
371        }
372        catch (ArrayIndexOutOfBoundsException e) {
373            badIndex(index, capacity);
374            return NIL; // Not reached.
375        }
376    }
377
378    @Override
379    public LispObject SCHAR(int index) throws ConditionThrowable
380    {
381        try {
382            return LispCharacter.getInstance(chars[index]);
383        }
384        catch (ArrayIndexOutOfBoundsException e) {
385            badIndex(index, capacity);
386            return NIL; // Not reached.
387        }
388    }
389
390    @Override
391    public LispObject AREF(int index) throws ConditionThrowable
392    {
393        try {
394            return LispCharacter.getInstance(chars[index]);
395        }
396        catch (ArrayIndexOutOfBoundsException e) {
397            badIndex(index, capacity);
398            return NIL; // Not reached.
399        }
400    }
401
402    @Override
403    public LispObject AREF(LispObject index) throws ConditionThrowable
404    {
405        try {
406            return LispCharacter.getInstance(chars[Fixnum.getValue(index)]);
407        }
408        catch (ArrayIndexOutOfBoundsException e) {
409            badIndex(((Fixnum)index).value, capacity);
410            return NIL; // Not reached.
411        }
412    }
413
414    @Override
415    public void aset(int index, LispObject obj) throws ConditionThrowable
416    {
417        try {
418            chars[index] = LispCharacter.getValue(obj);
419        }
420        catch (ArrayIndexOutOfBoundsException e) {
421            badIndex(index, capacity);
422        }
423    }
424
425    @Override
426    public int sxhash()
427    {
428        int hashCode = 0;
429        for (int i = 0; i < capacity; i++) {
430            hashCode += chars[i];
431            hashCode += (hashCode << 10);
432            hashCode ^= (hashCode >> 6);
433        }
434        hashCode += (hashCode << 3);
435        hashCode ^= (hashCode >> 11);
436        hashCode += (hashCode << 15);
437        return (hashCode & 0x7fffffff);
438    }
439
440    // For EQUALP hash tables.
441    @Override
442    public int psxhash()
443    {
444        int hashCode = 0;
445        for (int i = 0; i < capacity; i++) {
446            hashCode += Character.toUpperCase(chars[i]);
447            hashCode += (hashCode << 10);
448            hashCode ^= (hashCode >> 6);
449        }
450        hashCode += (hashCode << 3);
451        hashCode ^= (hashCode >> 11);
452        hashCode += (hashCode << 15);
453        return (hashCode & 0x7fffffff);
454    }
455
456    @Override
457    public AbstractVector adjustArray(int newCapacity,
458                                       LispObject initialElement,
459                                       LispObject initialContents)
460        throws ConditionThrowable
461    {
462        if (initialContents != null) {
463            char[] newChars = new char[newCapacity];
464            if (initialContents.listp()) {
465                LispObject list = initialContents;
466                for (int i = 0; i < newCapacity; i++) {
467                    newChars[i] = LispCharacter.getValue(list.car());
468                    list = list.cdr();
469                }
470            } else if (initialContents.vectorp()) {
471                for (int i = 0; i < newCapacity; i++)
472                    newChars[i] = LispCharacter.getValue(initialContents.elt(i));
473            } else
474                type_error(initialContents, Symbol.SEQUENCE);
475            return new SimpleString(newChars);
476        }
477        if (capacity != newCapacity) {
478            char[] newChars = new char[newCapacity];
479            System.arraycopy(chars, 0, newChars, 0, Math.min(newCapacity, capacity));
480            if (initialElement != null && capacity < newCapacity) {
481                final char c = LispCharacter.getValue(initialElement);
482                for (int i = capacity; i < newCapacity; i++)
483                    newChars[i] = c;
484            }
485            return new SimpleString(newChars);
486        }
487        // No change.
488        return this;
489    }
490
491    @Override
492    public AbstractVector adjustArray(int newCapacity,
493                                       AbstractArray displacedTo,
494                                       int displacement)
495        throws ConditionThrowable
496    {
497        return new ComplexString(newCapacity, displacedTo, displacement);
498    }
499}
Note: See TracBrowser for help on using the repository browser.