1 package org.apache.lucene.util;
3 import java.util.Comparator;
6 * Licensed to the Apache Software Foundation (ASF) under one or more
7 * contributor license agreements. See the NOTICE file distributed with
8 * this work for additional information regarding copyright ownership.
9 * The ASF licenses this file to You under the Apache License, Version 2.0
10 * (the "License"); you may not use this file except in compliance with
11 * the License. You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
23 * Represents char[], as a slice (offset + length) into an existing char[].
24 * The {@link #chars} member should never be null; use
25 * {@link #EMPTY_ARRAY} if necessary.
28 public final class CharsRef implements Comparable<CharsRef>, CharSequence {
29 private static final char[] EMPTY_ARRAY = new char[0];
35 * Creates a new {@link CharsRef} initialized an empty array zero-length
38 this(EMPTY_ARRAY, 0, 0);
42 * Creates a new {@link CharsRef} initialized with an array of the given
45 public CharsRef(int capacity) {
46 chars = new char[capacity];
50 * Creates a new {@link CharsRef} initialized with the given array, offset and
53 public CharsRef(char[] chars, int offset, int length) {
55 assert chars.length >= offset + length;
62 * Creates a new {@link CharsRef} initialized with the given Strings character
65 public CharsRef(String string) {
66 this.chars = string.toCharArray();
68 this.length = chars.length;
72 * Creates a new {@link CharsRef} and copies the contents of the source into
74 * @see #copy(CharsRef)
76 public CharsRef(CharsRef other) {
81 public Object clone() {
82 return new CharsRef(this);
86 public int hashCode() {
89 final int end = offset + length;
90 for (int i = offset; i < end; i++) {
91 result = prime * result + chars[i];
97 public boolean equals(Object other) {
102 if (other instanceof CharsRef) {
103 return charsEquals((CharsRef) other);
106 if (other instanceof CharSequence) {
107 final CharSequence seq = (CharSequence) other;
108 if (length == seq.length()) {
113 if (chars[i++] != seq.charAt(j++))
122 public boolean charsEquals(CharsRef other) {
123 if (length == other.length) {
124 int otherUpto = other.offset;
125 final char[] otherChars = other.chars;
126 final int end = offset + length;
127 for (int upto = offset; upto < end; upto++, otherUpto++) {
128 if (chars[upto] != otherChars[otherUpto]) {
138 /** Signed int order comparison */
139 public int compareTo(CharsRef other) {
143 final char[] aChars = this.chars;
144 int aUpto = this.offset;
145 final char[] bChars = other.chars;
146 int bUpto = other.offset;
148 final int aStop = aUpto + Math.min(this.length, other.length);
150 while (aUpto < aStop) {
151 int aInt = aChars[aUpto++];
152 int bInt = bChars[bUpto++];
155 } else if (aInt < bInt) {
160 // One is a prefix of the other, or, they are equal:
161 return this.length - other.length;
165 * Copies the given {@link CharsRef} referenced content into this instance
166 * starting at offset 0.
169 * the {@link CharsRef} to copy
171 public void copy(CharsRef other) {
173 chars = new char[other.length];
175 chars = ArrayUtil.grow(chars, other.length);
177 System.arraycopy(other.chars, other.offset, chars, 0, other.length);
178 length = other.length;
182 public void grow(int newLength) {
183 if (chars.length < newLength) {
184 chars = ArrayUtil.grow(chars, newLength);
189 * Copies the given array into this CharsRef starting at offset 0
191 public void copy(char[] otherChars, int otherOffset, int otherLength) {
193 System.arraycopy(otherChars, otherOffset, this.chars, 0,
196 this.length = otherLength;
200 * Appends the given array to this CharsRef
202 public void append(char[] otherChars, int otherOffset, int otherLength) {
203 final int newLength = length + otherLength;
204 grow(this.offset + newLength);
205 System.arraycopy(otherChars, otherOffset, this.chars, this.offset+length,
207 this.length += otherLength;
211 public String toString() {
212 return new String(chars, offset, length);
215 public int length() {
219 public char charAt(int index) {
220 return chars[offset + index];
223 public CharSequence subSequence(int start, int end) {
224 return new CharsRef(chars, offset + start, offset + end - 1);
227 private final static Comparator<CharsRef> utf16SortedAsUTF8SortOrder = new UTF16SortedAsUTF8Comparator();
229 public static Comparator<CharsRef> getUTF16SortedAsUTF8Comparator() {
230 return utf16SortedAsUTF8SortOrder;
233 private static class UTF16SortedAsUTF8Comparator implements Comparator<CharsRef> {
235 private UTF16SortedAsUTF8Comparator() {};
237 public int compare(CharsRef a, CharsRef b) {
241 final char[] aChars = a.chars;
242 int aUpto = a.offset;
243 final char[] bChars = b.chars;
244 int bUpto = b.offset;
246 final int aStop = aUpto + Math.min(a.length, b.length);
248 while (aUpto < aStop) {
249 char aChar = aChars[aUpto++];
250 char bChar = bChars[bUpto++];
251 if (aChar != bChar) {
252 // http://icu-project.org/docs/papers/utf16_code_point_order.html
254 /* aChar != bChar, fix up each one if they're both in or above the surrogate range, then compare them */
255 if (aChar >= 0xd800 && bChar >= 0xd800) {
256 if (aChar >= 0xe000) {
262 if (bChar >= 0xe000) {
269 /* now aChar and bChar are in code point order */
270 return (int)aChar - (int)bChar; /* int must be 32 bits wide */
274 // One is a prefix of the other, or, they are equal:
275 return a.length - b.length;