1 package java.lang; 2 3 import sun.misc.ConstantLengthCharSequence; 4 5 /** 6 * ArrayCharSequence is a simple {@link CharSequence} implementation based on the 7 * primitive character array. It represents a view of the underlying sub-array 8 * bounded by {@code offset} and {@code length}. 9 * The underlying array can not be mutated through the ArrayCharSequence, 10 * but direct changes to the underlying array are visible through the ArrayCharSequence. 11 * ArrayCharSequence is not {@link java.io.Serializable}. 12 * 13 * @since 1.9 14 */ 15 public final class ArrayCharSequence implements CharSequence, ConstantLengthCharSequence { 16 private final char[] chars; 17 private final int offset, length; 18 19 /** 20 * Constructs an {@code ArrayCharSequence} representing the view of the 21 * characters of the given {@code chars} array. Any changes to the 22 * array are visible through the sequence, but the array can not be modified 23 * through the sequence. 24 * 25 * @param chars the character array to construct the sequence with 26 * @throws NullPointerException if given {@code chars} array is {@code null} 27 */ 28 public ArrayCharSequence(char[] chars) { 29 this(chars, 0, chars.length, true); 30 } 31 32 /** 33 * Constructs an {@code ArrayCharSequence} representing the sub-array view of 34 * the given {@code chars} array. The sequence starts with the {@code char} 35 * value at the specified index and ends with the {@code char} value at index 36 * {@code end - 1}. The length (in {@code char}s) of the constructed sequence 37 * is {@code end - start}, so if {@code start == end} then constructed sequence 38 * is empty. Any changes to the given {@code chars} array that pertain to the 39 * represented range are visible through the sequence, but the array can not 40 * be modified through the sequence. 41 * 42 * @param chars the character array to construct the sequence with 43 * @param start the start index, inclusive 44 * @param end the end index, exclusive 45 * @throws NullPointerException if given {@code chars} array is {@code null} 46 * @throws IndexOutOfBoundsException if {@code start} or {@code end} are negative, 47 * if {@code end} is greater than 48 * {@code chars.length}, or if {@code start} 49 * is greater than {@code end} 50 */ 51 public ArrayCharSequence(char[] chars, int start, int end) { 52 this(chars, 53 checkSubSequenceIndexReturnStart(start, end, chars.length), 54 end - start, true); 55 } 56 57 /** 58 * Constructs an {@code ArrayCharSequence} representing the 59 * characters of the given {@code string}. The constructed sequence may 60 * share the character storage with the given {@code string}. 61 * 62 * @param string the {@code String} to construct the sequence from 63 * @throws NullPointerException if given {@code string} is {@code null} 64 */ 65 public ArrayCharSequence(String string) { 66 this(string.getCharsShared(), 0, string.length(), true); 67 } 68 69 /** 70 * Constructs an {@code ArrayCharSequence} representing the sub-sequence of 71 * the given {@code string}. The sequence starts with the {@code char} 72 * value at the specified index and ends with the {@code char} value at index 73 * {@code end - 1}. The length (in {@code char}s) of the constructed sequence 74 * is {@code end - start}, so if {@code start == end} then constructed sequence 75 * is empty. The constructed sequence may share the character storage with 76 * the given {@code string}. 77 * 78 * @param string the {@code String} to construct the sequence from 79 * @param start the start index, inclusive 80 * @param end the end index, exclusive 81 * @throws NullPointerException if given {@code chars} array is {@code null} 82 * @throws IndexOutOfBoundsException if {@code start} or {@code end} are negative, 83 * if {@code end} is greater than 84 * {@code string.length()}, or if {@code start} 85 * is greater than {@code end} 86 */ 87 public ArrayCharSequence(String string, int start, int end) { 88 this(string.getCharsShared(), 89 checkSubSequenceIndexReturnStart(start, end, string.length()), 90 end - start, true); 91 } 92 93 // designated unchecked constructor 94 private ArrayCharSequence(char[] chars, int offset, int length, boolean unchecked) { 95 this.chars = chars; 96 this.offset = offset; 97 this.length = length; 98 } 99 100 /** 101 * @inheritDoc 102 */ 103 @Override 104 public int length() { 105 return length; 106 } 107 108 /** 109 * @inheritDoc 110 */ 111 @Override 112 public char charAt(int index) { 113 if (index < 0 || index >= length) { 114 throw new IndexOutOfBoundsException("index: " + index); 115 } 116 return chars[offset + index]; 117 } 118 119 /** 120 * Returns an {@code ArrayCharSequence} that is a subsequence of this sequence. 121 * The subsequence starts with the {@code char} value at the specified index and 122 * ends with the {@code char} value at index {@code end - 1}. The length 123 * (in {@code char}s) of the 124 * returned sequence is {@code end - start}, so if {@code start == end} 125 * then an empty sequence is returned. 126 * <p> 127 * The returned {@code ArrayCharSequence} 128 * represents a subsequence view of this sequence, so any changes to the 129 * underlying array of this sequence that pertain to the range of the returned 130 * sub-sequence are also visible in the returned sub-sequence. 131 * 132 * @param start the start index, inclusive 133 * @param end the end index, exclusive 134 * @return the specified subsequence 135 * @throws IndexOutOfBoundsException if {@code start} or {@code end} are negative, 136 * if {@code end} is greater than {@code length()}, 137 * or if {@code start} is greater than {@code end} 138 * @implSpec The returned {@code ArrayCharSequence} shares the underlying character storage 139 * with this sequence and is obtainable in constant time. It is therefore advisable 140 * to use it only as intermediate result of some computation that is not 141 * retained for extended period of time, to allow the underlying shared character 142 * storage to be reclaimed. 143 */ 144 @Override 145 public ArrayCharSequence subSequence(int start, int end) { 146 checkSubSequenceIndexReturnStart(start, end, length); 147 if (start == 0 && end == length) { 148 return this; 149 } else { 150 return new ArrayCharSequence(chars, offset + start, end - start); 151 } 152 } 153 154 /** 155 * Copies characters from this {@code ArrayCharSequence} into the 156 * destination character array. 157 * <p> 158 * The first character to be copied is at index {@code srcBegin}; 159 * the last character to be copied is at index {@code srcEnd-1} 160 * (thus the total number of characters to be copied is 161 * {@code srcEnd-srcBegin}). The characters are copied into the 162 * subarray of {@code dst} starting at index {@code dstBegin} 163 * and ending at index: 164 * <blockquote><pre> 165 * dstBegin + (srcEnd-srcBegin) - 1 166 * </pre></blockquote> 167 * 168 * @param srcBegin index of the first character in the sequence 169 * to copy. 170 * @param srcEnd index after the last character in the sequence 171 * to copy. 172 * @param dst the destination array. 173 * @param dstBegin the start offset in the destination array. 174 * @throws IndexOutOfBoundsException If any of the following 175 * is true: 176 * <ul><li>{@code srcBegin} is negative. 177 * <li>{@code srcBegin} is greater than {@code srcEnd} 178 * <li>{@code srcEnd} is greater than the length of this 179 * sequence 180 * <li>{@code dstBegin} is negative 181 * <li>{@code dstBegin+(srcEnd-srcBegin)} is larger than 182 * {@code dst.length}</ul> 183 */ 184 public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) { 185 if (srcBegin < 0) { 186 throw new IndexOutOfBoundsException("srcBegin: " + srcBegin); 187 } 188 if (srcEnd > length) { 189 throw new IndexOutOfBoundsException("srcEnd: " + srcEnd); 190 } 191 if (srcBegin > srcEnd) { 192 throw new IndexOutOfBoundsException("srcBegin: " + srcBegin + 193 " > srcEnd: " + srcEnd); 194 } 195 System.arraycopy(chars, offset + srcBegin, dst, dstBegin, srcEnd - srcBegin); 196 } 197 198 /** 199 * Returns a string containing the characters in this sequence in the same 200 * order as this sequence. The length of the string will be the length of 201 * this sequence. 202 * 203 * @return a string consisting of exactly this sequence of characters 204 */ 205 @Override 206 public String toString() { 207 return new String(chars, offset, length); 208 } 209 210 // common subSequence arguments checking method 211 private static int checkSubSequenceIndexReturnStart(int start, int end, int length) { 212 if (start < 0 || end < 0 || start > end || end > length) { 213 throw new IndexOutOfBoundsException("start: " + start + ", end: " + end); 214 } 215 return start; 216 } 217 }