@@ -45,7 +45,18 @@ public final class String
45
45
implements java .io .Serializable , Comparable <String >, CharSequence {
46
46
47
47
/** The value is used for character storage. */
48
- private final char value [];
48
+ private final byte value [];
49
+
50
+ /**
51
+ * The identifier of the encoding used to encode the bytes in
52
+ * The supported values in this implementation are:
53
+ * LATIN1
54
+ * UTF16
55
+ */
56
+ private final byte coder ;
57
+
58
+ static final byte LATIN1 = 0 ;
59
+ static final byte UTF16 = 1 ;
49
60
50
61
/** Cache the hash code for the string */
51
62
private int hash ; // Default to 0
@@ -57,25 +68,28 @@ public final class String
57
68
new ObjectStreamField [0 ];
58
69
59
70
public String () {
60
- this .value = new char [0 ];
71
+ this .value = "" .value ;
72
+ this .coder = "" .coder ;
61
73
}
62
74
63
75
public String (String original ) {
64
76
this .value = original .value ;
77
+ this .coder = original .coder ;
65
78
this .hash = original .hash ;
66
79
}
67
80
68
81
public String (char value []) {
69
- this . value = Arrays . copyOf ( value , value .length );
82
+ this (( char []) value , 0 , value .length , ( Void ) null );
70
83
}
71
84
72
85
public String (char value [], boolean share ) {
73
- this . value = Arrays . copyOf ( value , value .length );
86
+ this (( char []) value , 0 , value .length , ( Void ) null );
74
87
}
75
88
76
89
public String (char value [], int offset , int count ) {
77
90
String proxy =init (value ,offset ,count );
78
91
this .value =proxy .value ;
92
+ this .coder =proxy .coder ;
79
93
this .hash =proxy .hash ;
80
94
}
81
95
@@ -84,6 +98,7 @@ public String(char value[], int offset, int count) {
84
98
public String (int [] codePoints , int offset , int count ) {
85
99
String proxy =init (codePoints ,offset ,count );
86
100
this .value =proxy .value ;
101
+ this .coder =proxy .coder ;
87
102
this .hash =proxy .hash ;
88
103
}
89
104
@@ -93,6 +108,7 @@ public String(int[] codePoints, int offset, int count) {
93
108
public String (byte ascii [], int hibyte , int offset , int count ) {
94
109
String proxy =init (ascii ,hibyte ,offset ,count );
95
110
this .value =proxy .value ;
111
+ this .coder =proxy .coder ;
96
112
this .hash =proxy .hash ;
97
113
}
98
114
@@ -108,6 +124,7 @@ public String(byte ascii[], int hibyte) {
108
124
public String (byte bytes [], int offset , int length , String charsetName ){
109
125
String proxy =init (bytes ,offset ,length ,charsetName );
110
126
this .value =proxy .value ;
127
+ this .coder =proxy .coder ;
111
128
this .hash =proxy .hash ;
112
129
}
113
130
@@ -129,7 +146,9 @@ public String(byte x[], int offset, int length, Charset cset) {
129
146
throw new StringIndexOutOfBoundsException (offset + length );
130
147
}
131
148
132
- this .value = StringCoding .decode (cset , x , offset , length );
149
+ StringCoding .Result result = StringCoding .decode (cset , x , offset , length );
150
+ this .value = result .value ;
151
+ this .coder = result .coder ;
133
152
}
134
153
135
154
public String (byte bytes [], String charsetName )
@@ -144,6 +163,7 @@ public String(byte bytes[], Charset charset) {
144
163
public String (byte bytes [], int offset , int length ) {
145
164
String proxy =init (bytes ,offset ,length );
146
165
this .value =proxy .value ;
166
+ this .coder =proxy .coder ;
147
167
this .hash =proxy .hash ;
148
168
}
149
169
@@ -156,14 +176,30 @@ public String(byte bytes[]) {
156
176
157
177
158
178
public String (StringBuffer x ) {
159
- synchronized (x ) {
160
- this .value = Arrays .copyOf (x .getValue (), x .length ());
161
- }
179
+ this (x .toString ());
162
180
}
163
181
164
182
165
183
public String (StringBuilder x ) {
166
184
this .value = Arrays .copyOf (x .getValue (), x .length ());
185
+ this .coder = x .coder ;
186
+ }
187
+
188
+ String (char [] value , int off , int len , Void sig ) {
189
+ if (len == 0 ) {
190
+ this .value = "" .value ;
191
+ this .coder = "" .coder ;
192
+ } else {
193
+ byte [] val = StringUTF16 .compress (value , off , len );
194
+ if (val != null ) {
195
+ this .value = val ;
196
+ this .coder = LATIN1 ;
197
+ return ;
198
+ }
199
+
200
+ this .coder = UTF16 ;
201
+ this .value = StringUTF16 .toBytes (value , off , len );
202
+ }
167
203
}
168
204
169
205
@ Deprecated
@@ -182,7 +218,7 @@ public char charAt(int index) {
182
218
if ((index < 0 ) || (index >= value .length )) {
183
219
throw new StringIndexOutOfBoundsException (index );
184
220
}
185
- return value [ index ] ;
221
+ return this . isLatin1 () ? StringLatin1 . charAt ( this . value , index ) : StringUTF16 . charAt ( this . value , index ) ;
186
222
}
187
223
188
224
native public int codePointAt (int index );
@@ -202,7 +238,7 @@ public byte[] getBytes(Charset x){
202
238
if (x == null ){
203
239
throw new NullPointerException ();
204
240
}
205
- return StringCoding .encode (x , value , 0 , value . length );
241
+ return StringCoding .encode (x , this . coder , this . value );
206
242
}
207
243
208
244
native public byte [] getBytes ();
@@ -224,25 +260,34 @@ public boolean contentEquals(StringBuffer stringBuffer){
224
260
public boolean contentEquals (CharSequence charSequence ){
225
261
if (value .length != charSequence .length ()){
226
262
return false ;
227
- }
263
+ }
228
264
229
- // that should be the common case (String)
265
+ // that should be the common case (String)
230
266
if (charSequence .equals (this )){
231
267
return true ;
232
268
}
233
-
234
- // we can do that natively, too
269
+
270
+ // we can do that natively, too
235
271
if (charSequence instanceof AbstractStringBuilder ) {
236
- return equals0 ( value , ((AbstractStringBuilder ) charSequence ).getValue (), value .length );
272
+ byte [] val = ((AbstractStringBuilder ) charSequence ).getValue ();
273
+ byte coder = ((AbstractStringBuilder ) charSequence ).getCoder ();
274
+ assert coder == UTF16 : "Currently only UTF16 is supported for String comparision with an instance of type AbstractStringBuilder" ;
275
+ return StringUTF16 .contentEquals (this .value , val , this .length ());
237
276
}
238
277
239
278
// generic CharSequence - expensive
240
- char v [] = value ;
241
- for (int n =value .length , i =0 ; n >= 0 ; n --,i ++){
242
- if (v [i ] != charSequence .charAt (i )){
243
- return false ;
244
- }
245
- }
279
+ int n = charSequence .length ();
280
+ byte [] val = this .value ;
281
+ if (isLatin1 ()) {
282
+ for (int i = 0 ; i < n ; i ++) {
283
+ if ((val [i ] & 0xff ) != charSequence .charAt (i )) {
284
+ return false ;
285
+ }
286
+ }
287
+ } else {
288
+ return StringUTF16 .contentEquals (val , charSequence , n );
289
+ }
290
+
246
291
return true ;
247
292
}
248
293
@@ -356,7 +401,10 @@ public static String valueOf(char character) {
356
401
native public static String valueOf (double d );
357
402
public native String intern ();
358
403
359
-
404
+ private boolean isLatin1 () {
405
+ return this .coder == LATIN1 ;
406
+ }
407
+
360
408
/*
361
409
* methods to be compatible with Harmony/Android, which now has modified
362
410
* versions of the old (offset based) String
0 commit comments