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

Last change on this file since 12450 was 12431, checked in by Mark Evenson, 15 years ago

Replace FastStringBuffer? with java.lang.StringBuilder?.

Phil Hudson suggested in Feburary 2009 that "[FastStringBuffer?] should
be removed with all references to it replaced with
java.lang.StringBuilder? once enough confidence in this change has been
gained." After almost a year of using FastStringBuffer? as a delagate
for StringBuilder?, that confidence has indeed been gained.

One subtlety for use of StringBuilder?: there is no

StringBuilder?(char)

constructor, so use

StringBuilder?(String.valueOf(c))

to construct a new StringBuilder? containing a single char. Otherwise
that char will get promoted to an int, and you will invoke

StringBuilder?(int capacity)

which will "swallow" the first character that you thought you were adding.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 13.0 KB
RevLine 
[5895]1/*
2 * SimpleString.java
3 *
[8802]4 * Copyright (C) 2004-2005 Peter Graves
[11297]5 * $Id: SimpleString.java 12431 2010-02-08 08:05:15Z mevenson $
[5895]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.
[11391]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.
[5895]32 */
33
34package org.armedbear.lisp;
35
[12288]36import static org.armedbear.lisp.Lisp.*;
37
[5895]38public final class SimpleString extends AbstractString
39{
[5908]40    private int capacity;
[5895]41    private char[] chars;
42
43    public SimpleString(LispCharacter c)
44    {
45        chars = new char[1];
[8021]46        chars[0] = c.value;
[5908]47        capacity = 1;
[5895]48    }
49
50    public SimpleString(char c)
51    {
52        chars = new char[1];
53        chars[0] = c;
[5908]54        capacity = 1;
[5895]55    }
56
[5908]57    public SimpleString(int capacity)
[5895]58    {
[5908]59        this.capacity = capacity;
60        chars = new char[capacity];
[5895]61    }
62
63    public SimpleString(String s)
64    {
[5945]65        capacity = s.length();
[5895]66        chars = s.toCharArray();
67    }
68
[5945]69    public SimpleString(StringBuffer sb)
70    {
71        chars = new char[capacity = sb.length()];
72        sb.getChars(0, capacity, chars, 0);
73    }
74
[12431]75    public SimpleString(StringBuilder sb)
[9563]76    {
[12431]77        chars = sb.toString().toCharArray();
[10273]78        capacity = chars.length;
[9563]79    }
80
[5961]81    private SimpleString(char[] chars)
82    {
83        this.chars = chars;
84        capacity = chars.length;
85    }
86
[11488]87    @Override
[5895]88    public char[] chars()
89    {
90        return chars;
91    }
92
[11488]93    @Override
[7774]94    public char[] getStringChars()
95    {
96        return chars;
97    }
98
[11488]99    @Override
[5895]100    public LispObject typeOf()
101    {
[11714]102        return list(Symbol.SIMPLE_BASE_STRING, Fixnum.getInstance(capacity));
[5895]103    }
104
[11488]105    @Override
[7968]106    public LispObject classOf()
[5895]107    {
[11587]108        return BuiltInClass.SIMPLE_BASE_STRING;
[5895]109    }
110
[11488]111    @Override
[6864]112    public LispObject getDescription()
113    {
[12431]114        StringBuilder sb = new StringBuilder("A simple-string (");
[6864]115        sb.append(capacity);
116        sb.append(") \"");
117        sb.append(chars);
[6869]118        sb.append('"');
[6864]119        return new SimpleString(sb);
120    }
121
[11488]122    @Override
[12254]123    public LispObject typep(LispObject type)
[5895]124    {
[6265]125        if (type == Symbol.SIMPLE_STRING)
126            return T;
127        if (type == Symbol.SIMPLE_ARRAY)
128            return T;
[11433]129        if (type == Symbol.SIMPLE_BASE_STRING)
130            return T;
[6265]131        if (type == BuiltInClass.SIMPLE_STRING)
132            return T;
133        if (type == BuiltInClass.SIMPLE_ARRAY)
134            return T;
[11433]135        if (type == BuiltInClass.SIMPLE_BASE_STRING)
136            return T;
[5895]137        return super.typep(type);
138    }
139
[11488]140    @Override
[5895]141    public LispObject SIMPLE_STRING_P()
142    {
143        return T;
144    }
145
[11488]146    @Override
[5910]147    public boolean hasFillPointer()
148    {
149        return false;
150    }
151
[11488]152    @Override
[5908]153    public boolean isAdjustable()
154    {
155        return false;
156    }
157
[11488]158    @Override
[12254]159    public boolean equal(LispObject obj)
[5895]160    {
161        if (this == obj)
162            return true;
163        if (obj instanceof SimpleString) {
164            SimpleString string = (SimpleString) obj;
[5908]165            if (string.capacity != capacity)
[5895]166                return false;
[5908]167            for (int i = capacity; i-- > 0;)
[5895]168                if (string.chars[i] != chars[i])
169                    return false;
170            return true;
171        }
[5903]172        if (obj instanceof AbstractString) {
173            AbstractString string = (AbstractString) obj;
[5908]174            if (string.length() != capacity)
[5895]175                return false;
176            for (int i = length(); i-- > 0;)
[8198]177                if (string.charAt(i) != chars[i])
[5895]178                    return false;
179            return true;
180        }
181        if (obj instanceof NilVector)
182            return obj.equal(this);
183        return false;
184    }
185
[11488]186    @Override
[12254]187    public boolean equalp(LispObject obj)
[5895]188    {
189        if (this == obj)
190            return true;
191        if (obj instanceof SimpleString) {
192            SimpleString string = (SimpleString) obj;
[5908]193            if (string.capacity != capacity)
[5895]194                return false;
[5908]195            for (int i = capacity; i-- > 0;) {
[5895]196                if (string.chars[i] != chars[i]) {
[10120]197                    if (LispCharacter.toLowerCase(string.chars[i]) != LispCharacter.toLowerCase(chars[i]))
[5895]198                        return false;
199                }
200            }
201            return true;
202        }
[5903]203        if (obj instanceof AbstractString) {
204            AbstractString string = (AbstractString) obj;
[5908]205            if (string.length() != capacity)
[5895]206                return false;
207            for (int i = length(); i-- > 0;) {
[8198]208                if (string.charAt(i) != chars[i]) {
[10120]209                    if (LispCharacter.toLowerCase(string.charAt(i)) != LispCharacter.toLowerCase(chars[i]))
[5895]210                        return false;
211                }
212            }
213            return true;
214        }
[8802]215        if (obj instanceof AbstractBitVector)
216            return false;
[5895]217        if (obj instanceof AbstractArray)
218            return obj.equalp(this);
219        return false;
220    }
221
[12254]222    public final SimpleString substring(int start)
[5895]223    {
[8198]224        return substring(start, capacity);
225    }
[8271]226
[8198]227    public final SimpleString substring(int start, int end)
[12254]228
[8198]229    {
[5895]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) {
[11158]238            error(new TypeError("Array index out of bounds: " + i));
[8198]239            // Not reached.
240            return null;
[5895]241        }
242    }
243
[11488]244    @Override
[12254]245    public final LispObject subseq(int start, int end)
[8198]246    {
247        return substring(start, end);
248    }
[8271]249
[11488]250    @Override
[12254]251    public void fill(LispObject obj)
[5895]252    {
253        fill(LispCharacter.getValue(obj));
254    }
255
[11488]256    @Override
[5895]257    public void fill(char c)
258    {
[5908]259        for (int i = capacity; i-- > 0;)
[5895]260            chars[i] = c;
261    }
262
[11488]263    @Override
[12254]264    public void shrink(int n)
[5895]265    {
[5908]266        if (n < capacity) {
[5895]267            char[] newArray = new char[n];
268            System.arraycopy(chars, 0, newArray, 0, n);
269            chars = newArray;
[5908]270            capacity = n;
[5895]271            return;
272        }
[5908]273        if (n == capacity)
[5895]274            return;
[11158]275        error(new LispError());
[5895]276    }
277
[11488]278    @Override
[12254]279    public LispObject reverse()
[5895]280    {
[5908]281        SimpleString result = new SimpleString(capacity);
[5895]282        int i, j;
[5908]283        for (i = 0, j = capacity - 1; i < capacity; i++, j--)
[5895]284            result.chars[i] = chars[j];
285        return result;
286    }
287
[11488]288    @Override
[12254]289    public LispObject nreverse()
[5895]290    {
291        int i = 0;
[5908]292        int j = capacity - 1;
[5895]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
[11488]303    @Override
[9786]304    public String getStringValue()
[5895]305    {
[11366]306        return String.valueOf(chars);
[5895]307    }
308
[11488]309    @Override
[9786]310    public Object javaInstance()
[5895]311    {
[11366]312        return String.valueOf(chars);
[5895]313    }
314
[11488]315    @Override
[9786]316    public Object javaInstance(Class c)
317    {
318        return javaInstance();
319    }
320
[11488]321    @Override
[9786]322    public final int capacity()
323    {
324        return capacity;
325    }
326
[11488]327    @Override
[9786]328    public final int length()
329    {
330        return capacity;
331    }
332
[11488]333    @Override
[12254]334    public char charAt(int index)
[5895]335    {
336        try {
337            return chars[index];
338        }
339        catch (ArrayIndexOutOfBoundsException e) {
[5908]340            badIndex(index, capacity);
[5895]341            return 0; // Not reached.
342        }
343    }
344
[11488]345    @Override
[12254]346    public void setCharAt(int index, char c)
[5895]347    {
348        try {
349            chars[index] = c;
350        }
351        catch (ArrayIndexOutOfBoundsException e) {
[5908]352            badIndex(index, capacity);
[5895]353        }
354    }
355
[11488]356    @Override
[12254]357    public LispObject elt(int index)
[5895]358    {
[9786]359        try {
360            return LispCharacter.getInstance(chars[index]);
361        }
362        catch (ArrayIndexOutOfBoundsException e) {
363            badIndex(index, capacity);
364            return NIL; // Not reached.
365        }
[5895]366    }
367
[11488]368    @Override
[12254]369    public LispObject CHAR(int index)
[9791]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
[11488]380    @Override
[12254]381    public LispObject SCHAR(int index)
[8271]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
[11488]392    @Override
[12254]393    public LispObject AREF(int index)
[5895]394    {
395        try {
396            return LispCharacter.getInstance(chars[index]);
397        }
398        catch (ArrayIndexOutOfBoundsException e) {
[5908]399            badIndex(index, capacity);
[5895]400            return NIL; // Not reached.
401        }
402    }
403
[11488]404    @Override
[12254]405    public LispObject AREF(LispObject index)
[5895]406    {
407        try {
[11754]408            return LispCharacter.getInstance(chars[Fixnum.getValue(index)]);
[5895]409        }
410        catch (ArrayIndexOutOfBoundsException e) {
[5908]411            badIndex(((Fixnum)index).value, capacity);
[5895]412            return NIL; // Not reached.
413        }
414    }
415
[11488]416    @Override
[12254]417    public void aset(int index, LispObject obj)
[9786]418    {
419        try {
[11754]420            chars[index] = LispCharacter.getValue(obj);
[9786]421        }
422        catch (ArrayIndexOutOfBoundsException e) {
423            badIndex(index, capacity);
424        }
425    }
426
[11488]427    @Override
[6992]428    public int sxhash()
[5895]429    {
430        int hashCode = 0;
[8191]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);
[6992]439        return (hashCode & 0x7fffffff);
[5895]440    }
[5928]441
[6992]442    // For EQUALP hash tables.
[11488]443    @Override
[6992]444    public int psxhash()
445    {
446        int hashCode = 0;
[8191]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);
[6992]455        return (hashCode & 0x7fffffff);
456    }
457
[11488]458    @Override
[11557]459    public AbstractVector adjustArray(int newCapacity,
[5961]460                                       LispObject initialElement,
461                                       LispObject initialContents)
[12254]462
[5961]463    {
[11562]464        if (initialContents != null) {
[5961]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
[11158]476                type_error(initialContents, Symbol.SEQUENCE);
[5961]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));
[11562]482            if (initialElement != null && capacity < newCapacity) {
[5961]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
[11488]493    @Override
[11557]494    public AbstractVector adjustArray(int newCapacity,
[5961]495                                       AbstractArray displacedTo,
496                                       int displacement)
[12254]497
[5961]498    {
499        return new ComplexString(newCapacity, displacedTo, displacement);
500    }
[5895]501}
Note: See TracBrowser for help on using the repository browser.