1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.util;
18 
19 import android.compat.annotation.UnsupportedAppUsage;
20 
21 /**
22  * {@link CharSequence} utility methods.
23  */
24 public class CharSequences {
25 
26     /**
27      * Adapts {@link CharSequence} to an array of ASCII (7-bits per character)
28      * bytes.
29      *
30      * @param bytes ASCII bytes
31      */
forAsciiBytes(final byte[] bytes)32     public static CharSequence forAsciiBytes(final byte[] bytes) {
33         return new CharSequence() {
34             public char charAt(int index) {
35                 return (char) bytes[index];
36             }
37 
38             public int length() {
39                 return bytes.length;
40             }
41 
42             public CharSequence subSequence(int start, int end) {
43                 return forAsciiBytes(bytes, start, end);
44             }
45 
46             public String toString() {
47                 return new String(bytes);
48             }
49         };
50     }
51 
52     /**
53      * Adapts {@link CharSequence} to an array of ASCII (7-bits per character)
54      * bytes.
55      *
56      * @param bytes ASCII bytes
57      * @param start index, inclusive
58      * @param end index, exclusive
59      *
60      * @throws IndexOutOfBoundsException if start or end are negative, if end
61      *  is greater than length(), or if start is greater than end
62      */
63     public static CharSequence forAsciiBytes(final byte[] bytes,
64             final int start, final int end) {
65         validate(start, end, bytes.length);
66         return new CharSequence() {
67             public char charAt(int index) {
68                 return (char) bytes[index + start];
69             }
70 
71             public int length() {
72                 return end - start;
73             }
74 
75             public CharSequence subSequence(int newStart, int newEnd) {
76                 newStart -= start;
77                 newEnd -= start;
78                 validate(newStart, newEnd, length());
79                 return forAsciiBytes(bytes, newStart, newEnd);
80             }
81 
82             public String toString() {
83                 return new String(bytes, start, length());
84             }
85         };
86     }
87 
88     static void validate(int start, int end, int length) {
89         if (start < 0) throw new IndexOutOfBoundsException();
90         if (end < 0) throw new IndexOutOfBoundsException();
91         if (end > length) throw new IndexOutOfBoundsException();
92         if (start > end) throw new IndexOutOfBoundsException();
93     }
94 
95     /**
96      * Compares two character sequences for equality.
97      */
98     @UnsupportedAppUsage
99     public static boolean equals(CharSequence a, CharSequence b) {
100         if (a.length() != b.length()) {
101             return false;
102         }
103 
104         int length = a.length();
105         for (int i = 0; i < length; i++) {
106             if (a.charAt(i) != b.charAt(i)) {
107                 return false;
108             }
109         }
110         return true;
111     }
112 
113     /**
114      * Compares two character sequences with API like {@link Comparable#compareTo}.
115      *
116      * @param me The CharSequence that receives the compareTo call.
117      * @param another The other CharSequence.
118      * @return See {@link Comparable#compareTo}.
119      */
120     @UnsupportedAppUsage
121     public static int compareToIgnoreCase(CharSequence me, CharSequence another) {
122         // Code adapted from String#compareTo
123         int myLen = me.length(), anotherLen = another.length();
124         int myPos = 0, anotherPos = 0, result;
125         int end = (myLen < anotherLen) ? myLen : anotherLen;
126 
127         while (myPos < end) {
128             if ((result = Character.toLowerCase(me.charAt(myPos++))
129                     - Character.toLowerCase(another.charAt(anotherPos++))) != 0) {
130                 return result;
131             }
132         }
133         return myLen - anotherLen;
134     }
135 }
136