001: // Copyright (c) 2001 Per M.A. Bothner and Brainfood Inc.
002: // This is free software; for terms and warranty disclaimer see ./COPYING.
003:
004: package gnu.lists;
005:
006: import java.io.*;
007:
008: /** Simple adjustable-length vector whose elements are 32-bit floats.
009: * Used for the Scheme string type.
010: * @author Per Bothner
011: */
012:
013: public class FString extends SimpleVector implements CharSeq,
014: Externalizable, Consumable {
015: public char[] data;
016: protected static char[] empty = new char[0];
017:
018: public FString() {
019: data = empty;
020: }
021:
022: public FString(int num) {
023: size = num;
024: data = new char[num];
025: }
026:
027: public FString(int num, char value) {
028: char[] array = new char[num];
029: data = array;
030: size = num;
031: while (--num >= 0)
032: array[num] = value;
033: }
034:
035: /** Create an FString from a char[].
036: * Note that this contructor does *not* copy the argument. */
037: public FString(char[] values) {
038: size = values.length;
039: data = values;
040: }
041:
042: public FString(String str) {
043: data = str.toCharArray();
044: size = data.length;
045: }
046:
047: public FString(StringBuffer buffer) {
048: this (buffer, 0, buffer.length());
049: }
050:
051: public FString(StringBuffer buffer, int offset, int length) {
052: this .size = length;
053: data = new char[length];
054: if (length > 0)
055: buffer.getChars(offset, offset + length, data, 0);
056: }
057:
058: public FString(char[] buffer, int offset, int length) {
059: this .size = length;
060: data = new char[length];
061: System.arraycopy(buffer, offset, data, 0, length);
062: }
063:
064: public FString(Sequence seq) {
065: this .data = new char[seq.size()];
066: addAll(seq);
067: }
068:
069: public FString(CharSeq seq) {
070: int size = seq.size();
071: char[] data = new char[size];
072: seq.getChars(0, size, data, 0);
073: this .data = data;
074: this .size = size;
075: }
076:
077: public FString(CharSeq seq, int offset, int length) {
078: char[] data = new char[length];
079: seq.getChars(offset, offset + length, data, 0);
080: this .data = data;
081: this .size = length;
082: }
083:
084: public int length() {
085: return size;
086: }
087:
088: /** Get the allocated length of the data buffer. */
089: public int getBufferLength() {
090: return data.length;
091: }
092:
093: public void setBufferLength(int length) {
094: int oldLength = data.length;
095: if (oldLength != length) {
096: char[] tmp = new char[length];
097: System.arraycopy(data, 0, tmp, 0,
098: oldLength < length ? oldLength : length);
099: data = tmp;
100: }
101: }
102:
103: protected Object getBuffer() {
104: return data;
105: }
106:
107: public final Object getBuffer(int index) {
108: return Convert.toObject(data[index]);
109: }
110:
111: public final Object setBuffer(int index, Object value) {
112: Object old = Convert.toObject(data[index]);
113: data[index] = Convert.toChar(value);
114: return old;
115: }
116:
117: public final Object get(int index) {
118: if (index >= size)
119: throw new ArrayIndexOutOfBoundsException();
120: return Convert.toObject(data[index]);
121: }
122:
123: public final char charAt(int index) {
124: if (index >= size)
125: throw new StringIndexOutOfBoundsException(index);
126: return data[index];
127: }
128:
129: public final char charAtBuffer(int index) {
130: return data[index];
131: }
132:
133: public void getChars(int srcBegin, int srcEnd, char dst[],
134: int dstBegin) {
135: if (srcBegin < 0 || srcBegin > srcEnd)
136: throw new StringIndexOutOfBoundsException(srcBegin);
137: if (srcEnd > size)
138: throw new StringIndexOutOfBoundsException(srcEnd);
139: if (dstBegin + srcEnd - srcBegin > dst.length)
140: throw new StringIndexOutOfBoundsException(dstBegin);
141: if (srcBegin < srcEnd)
142: System.arraycopy(data, srcBegin, dst, dstBegin, srcEnd
143: - srcBegin);
144: }
145:
146: public void getChars(int srcBegin, int srcEnd, StringBuffer dst) {
147: if (srcBegin < 0 || srcBegin > srcEnd)
148: throw new StringIndexOutOfBoundsException(srcBegin);
149: if (srcEnd > size)
150: throw new StringIndexOutOfBoundsException(srcEnd);
151: if (srcBegin < srcEnd)
152: dst.append(data, srcBegin, srcEnd - srcBegin);
153: }
154:
155: /** Return a char[] contain the characters of this string.
156: * It is unspecified if the result is a copy or shares with this FString.
157: */
158: public char[] toCharArray() {
159: int val_length = data.length;
160: int seq_length = size;
161: if (seq_length == val_length)
162: return data;
163: else {
164: char[] tmp = new char[seq_length];
165: System.arraycopy(data, 0, tmp, 0, seq_length);
166: return tmp;
167: }
168: }
169:
170: public void shift(int srcStart, int dstStart, int count) {
171: System.arraycopy(data, srcStart, data, dstStart, count);
172: }
173:
174: public FString copy(int start, int end) {
175: char[] copy = new char[end - start];
176: for (int i = start; i < end; i++)
177: copy[i - start] = data[i];
178: return new FString(copy);
179: }
180:
181: public String toString() {
182: return new String(data, 0, size);
183: }
184:
185: public String substring(int start, int end) {
186: return new String(data, start, end - start);
187: }
188:
189: // If JDK1.4 compatible:
190: // public java.lang.CharSequence subSequence(int start, int end)
191: // { return substring(start, end); }
192:
193: public void setCharAt(int index, char ch) {
194: if (index < 0 || index >= size)
195: throw new StringIndexOutOfBoundsException(index);
196: data[index] = ch;
197: }
198:
199: public void setCharAtBuffer(int index, char ch) {
200: data[index] = ch;
201: }
202:
203: /** Set all the elements to a given character. */
204: public final void fill(char ch) {
205: for (int i = size; --i >= 0;)
206: data[i] = ch;
207: }
208:
209: public void fill(int fromIndex, int toIndex, char value) {
210: if (fromIndex < 0 || toIndex > size)
211: throw new IndexOutOfBoundsException();
212: for (int i = fromIndex; i < toIndex; i++)
213: data[i] = value;
214: }
215:
216: protected void clearBuffer(int start, int count) {
217: while (--count >= 0)
218: data[start++] = 0;
219: }
220:
221: public void replace(int where, char[] chars, int start, int count) {
222: System.arraycopy(chars, start, data, where, count);
223: }
224:
225: public void replace(int where, String string) {
226: string.getChars(0, string.length(), data, where);
227: }
228:
229: public int hashCode() {
230: /* Matches String.hashCode specification, as updated specification in
231: http://www.javasoft.com/docs/books/jls/clarify.html. */
232: char[] val = data;
233: int len = size;
234: int hash = 0;
235: for (int i = 0; i < len; i++)
236: hash = 31 * hash + val[i];
237: return hash;
238: }
239:
240: public boolean equals(Object obj) {
241: if (obj == null || !(obj instanceof FString))
242: return false;
243: char[] str = ((FString) obj).data;
244: int n = size;
245: if (str == null || str.length != n)
246: return false;
247: for (int i = n; --i >= 0;) {
248: if (data[i] != str[i])
249: return false;
250: }
251: return true;
252: }
253:
254: public int getElementKind() {
255: return CHAR_VALUE;
256: }
257:
258: public void consume(Consumer out) {
259: out.write(data, 0, data.length);
260: }
261:
262: public boolean consumeNext(int ipos, Object xpos, Consumer out) {
263: int index = ipos >>> 1;
264: if (index >= size)
265: return false;
266: out.writeChar(data[index]);
267: return true;
268: }
269:
270: protected void consume(int iposStart, Object xposStart,
271: int iposEnd, Object xposEnd, Consumer out) {
272: if (out.ignoring())
273: return;
274: int i = iposStart >>> 1;
275: int end = iposEnd >>> 1;
276: out.write(data, i, end - i);
277: }
278:
279: public void writeTo(int start, int count, java.io.Writer dest)
280: throws java.io.IOException {
281: dest.write(data, start, count);
282: }
283:
284: public void writeTo(java.io.Writer dest) throws java.io.IOException {
285: dest.write(data, 0, size);
286: }
287:
288: /**
289: * @serialData Write 'size' (using writeInt),
290: * followed by 'size' elements in order (using writeChar).
291: */
292: public void writeExternal(ObjectOutput out) throws IOException {
293: int size = this .size;
294: out.writeInt(size);
295: for (int i = 0; i < size; i++)
296: out.writeChar(data[i]);
297: }
298:
299: public void readExternal(ObjectInput in) throws IOException,
300: ClassNotFoundException {
301: int size = in.readInt();
302: char[] data = new char[size];
303: for (int i = 0; i < size; i++)
304: data[i] = in.readChar();
305: this.data = data;
306: this.size = size;
307: }
308: }
|