001: package net.sf.saxon.tinytree;
002:
003: import java.io.Writer;
004: import java.io.Serializable;
005:
006: /**
007: * This is an implementation of the JDK 1.4 CharSequence interface: it implements
008: * a CharSequence as a view of an array. The implementation relies on the array
009: * being immutable: as a minimum, the caller is required to ensure that the array
010: * contents will not change so long as the CharSlice remains in existence.
011: *
012: * This class should be more efficient than String because it avoids copying the
013: * characters unnecessarily.
014: *
015: * The methods in the class don't check their arguments. Incorrect arguments will
016: * generally result in exceptions from lower-level classes.
017: *
018: */
019: public final class CharSlice implements CharSequence, Serializable {
020:
021: private char[] array;
022: private int offset;
023: private int count;
024:
025: public CharSlice(char[] array) {
026: this .array = array;
027: this .offset = 0;
028: this .count = array.length;
029: }
030:
031: public CharSlice(char[] array, int start, int length) {
032: this .array = array;
033: this .offset = start;
034: this .count = length;
035: }
036:
037: /**
038: * Returns the length of this character sequence. The length is the number
039: * of 16-bit Unicode characters in the sequence. </p>
040: *
041: * @return the number of characters in this sequence
042: */
043: public int length() {
044: return count;
045: }
046:
047: /**
048: * Set the length of this character sequence, without changing the array and start offset
049: * to which it is bound
050: */
051: public void setLength(int length) {
052: count = length;
053: }
054:
055: /**
056: * Returns the character at the specified index. An index ranges from zero
057: * to <tt>length() - 1</tt>. The first character of the sequence is at
058: * index zero, the next at index one, and so on, as for array
059: * indexing. </p>
060: *
061: * @param index the index of the character to be returned
062: *
063: * @return the specified character
064: *
065: * @throws java.lang.IndexOutOfBoundsException
066: * if the <tt>index</tt> argument is negative or not less than
067: * <tt>length()</tt>
068: */
069: public char charAt(int index) {
070: return array[offset + index];
071: }
072:
073: /**
074: * Returns a new character sequence that is a subsequence of this sequence.
075: * The subsequence starts with the character at the specified index and
076: * ends with the character at index <tt>end - 1</tt>. The length of the
077: * returned sequence is <tt>end - start</tt>, so if <tt>start == end</tt>
078: * then an empty sequence is returned. </p>
079: *
080: * @param start the start index, inclusive
081: * @param end the end index, exclusive
082: *
083: * @return the specified subsequence
084: *
085: * @throws java.lang.IndexOutOfBoundsException
086: * if <tt>start</tt> or <tt>end</tt> are negative,
087: * if <tt>end</tt> is greater than <tt>length()</tt>,
088: * or if <tt>start</tt> is greater than <tt>end</tt>
089: */
090: public CharSequence subSequence(int start, int end) {
091: return new CharSlice(array, offset + start, end - start);
092: }
093:
094: /**
095: * Convert to a string
096: */
097:
098: public String toString() {
099: return new String(array, offset, count);
100: }
101:
102: /**
103: * Compare equality
104: */
105:
106: public boolean equals(Object other) {
107: return toString().equals(other);
108: }
109:
110: /**
111: * Generate a hash code
112: */
113:
114: public int hashCode() {
115: // Same algorithm as String#hashCode(), but not cached
116: int end = offset + count;
117: int h = 0;
118: for (int i = offset; i < end; i++) {
119: h = 31 * h + array[i];
120: }
121: return h;
122: }
123:
124: /**
125: * Get the index of a specific character in the sequence. Returns -1 if not found.
126: * This method mimics {@link String#indexOf}
127: * @param c the character to be found
128: * @return the position of the first occurrence of that character, or -1 if not found.
129: */
130:
131: public int indexOf(char c) {
132: int end = offset + count;
133: for (int i = offset; i < end; i++) {
134: if (array[i] == c) {
135: return i - offset;
136: }
137: ;
138: }
139: return -1;
140: }
141:
142: /**
143: * Returns a new character sequence that is a subsequence of this sequence.
144: * Unlike subSequence, this is guaranteed to return a String.
145: */
146:
147: public String substring(int start, int end) {
148: return new String(array, offset + start, end - start);
149: }
150:
151: /**
152: * Append the contents to another array at a given offset. The caller is responsible
153: * for ensuring that sufficient space is available.
154: * @param destination the array to which the characters will be copied
155: * @param destOffset the offset in the target array where the copy will start
156: */
157:
158: public void copyTo(char[] destination, int destOffset) {
159: System.arraycopy(array, offset, destination, destOffset, count);
160: }
161:
162: /**
163: * Write the value to a writer
164: */
165:
166: public void write(Writer writer) throws java.io.IOException {
167: writer.write(array, offset, count);
168: }
169:
170: }
171:
172: //
173: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
174: // you may not use this file except in compliance with the License. You may obtain a copy of the
175: // License at http://www.mozilla.org/MPL/
176: //
177: // Software distributed under the License is distributed on an "AS IS" basis,
178: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
179: // See the License for the specific language governing rights and limitations under the License.
180: //
181: // The Original Code is: all this file.
182: //
183: // The Initial Developer of the Original Code is Michael H. Kay
184: //
185: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
186: //
187: // Contributor(s): none
188: //
|