source: trunk/abcl/src/org/armedbear/lisp/SimpleString.java @ 12559

Last change on this file since 12559 was 12494, checked in by vvoutilainen, 15 years ago

Don't use StringBuilder? for StringFunctions? that can use arraycopy
instead. This requires making the relevant SimpleString? constructor
public.

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