Mercurial > projects > dwt2
comparison base/src/java/lang/String.d @ 120:536e43f63c81
Comprehensive update for Win32/Linux32 dmd-2.053/dmd-1.068+Tango-r5661
===D2===
* added [Try]Immutable/Const/Shared templates to work with differenses in D1/D2 instead of version statements
used these templates to work with strict type storage rules of dmd-2.053
* com.ibm.icu now also compilable with D2, but not tested yet
* small fixes
Snippet288 - shared data is in TLS
===Phobos===
* fixed critical bugs in Phobos implemention
completely incorrect segfault prone fromStringz (Linux's port ruthless killer)
terrible, incorrect StringBuffer realization (StyledText killer)
* fixed small bugs as well
Snippet72 - misprint in the snippet
* implemented missed functionality for Phobos
ByteArrayOutputStream implemented (image loading available)
formatting correctly works for all DWT's cases
As a result, folowing snippets now works with Phobos (Snippet### - what is fixed):
Snippet24, 42, 111, 115, 130, 235, 276 - bad string formatting
Snippet48, 282 - crash on image loading
Snippet163, 189, 211, 213, 217, 218, 222 - crash on copy/cut in StyledText
Snippet244 - hang-up
===Tango===
* few changes for the latest Tango trunc-r5661
* few small performance improvments
===General===
* implMissing-s for only one version changed to implMissingInTango/InPhobos
* incorrect calls to Format in toString-s fixed
* fixed loading \uXXXX characters in ResourceBundle
* added good UTF-8 support for StyledText, TextLayout (Win32) and friends
UTF functions revised and tested. It is now in java.nonstandard.*Utf modules
StyledText and TextLayout (Win32) modules revised for UTF-8 support
* removed small diferences in most identical files in *.swt.* folders
*.swt.internal.image, *.swt.events and *.swt.custom are identical in Win32/Linux32
now 179 of 576 (~31%) files in *.swt.* folders are fully identical
* Win32: snippets now have right subsystem, pretty icons and native system style controls
* small fixes in snippets
Snippet44 - it's not Snippet44
Snippet212 - functions work with different images and offsets arrays
Win32: Snippet282 - crash on close if the button has an image
Snippet293 - setGrayed is commented
and others
Win32: As a result, folowing snippets now works
Snippet68 - color doesn't change
Snippet163, 189, 211, 213, 217, 218, 222 - UTF-8 issues (see above)
Snippet193 - no tabel headers
author | Denis Shelomovskij <verylonglogin.reg@gmail.com> |
---|---|
date | Sat, 09 Jul 2011 15:50:20 +0300 |
parents | d00e8db0a568 |
children | dc6fc593e8d7 |
comparison
equal
deleted
inserted
replaced
119:d00e8db0a568 | 120:536e43f63c81 |
---|---|
9 static import tango.stdc.stringz; | 9 static import tango.stdc.stringz; |
10 static import tango.text.Util; | 10 static import tango.text.Util; |
11 static import tango.text.Unicode; | 11 static import tango.text.Unicode; |
12 static import tango.text.convert.Utf; | 12 static import tango.text.convert.Utf; |
13 } else { // Phobos | 13 } else { // Phobos |
14 static import core.exception; | |
15 static import std.uni; | |
16 static import std.utf; | |
17 static import std.array; | 14 static import std.array; |
18 static import std.string; | 15 static import std.string; |
19 static import std.conv; | 16 static import std.conv; |
20 static import std.exception; | 17 static import std.exception; |
21 } | 18 } |
22 | 19 |
23 version(Tango){ | 20 alias TryImmutable!(char)[] String; |
24 public alias char[] String; | 21 alias TryImmutable!(wchar)[] String16; |
25 public alias char[] CString; | 22 |
26 public alias wchar[] String16; | 23 String new_String( String cont, int offset, int len ){ |
27 public alias wchar[] CString16; | 24 return _idup(cont[ offset .. offset+len ]); |
28 public alias char* ICharPtr; | 25 } |
29 public alias char* CCharPtr; | 26 |
30 public alias wchar* CWCharPtr; | 27 String new_String( String cont ){ |
31 public alias wchar* IWCharPtr; | 28 return _idup(cont); |
32 } else { // Phobos | |
33 public alias string String; | |
34 public alias wstring String16; | |
35 mixin( | |
36 "public alias const(char)[] CString; | |
37 public alias const(wchar)[] CString16; | |
38 public alias immutable(char)* ICharPtr; | |
39 public alias const(char)* CCharPtr; | |
40 public alias const(wchar)* CWCharPtr; | |
41 public alias immutable(wchar)* IWCharPtr;" | |
42 ); | |
43 } | |
44 | |
45 int codepointIndexToIndex( CString str, int cpIndex ){ | |
46 int cps = cpIndex; | |
47 int res = 0; | |
48 while( cps > 0 ){ | |
49 cps--; | |
50 if( str[res] < 0x80 ){ | |
51 res+=1; | |
52 } | |
53 else if( str[res] < 0xE0 ){ | |
54 res+=2; | |
55 } | |
56 else if( str[res] & 0xF0 ){ | |
57 res+=3; | |
58 } | |
59 else{ | |
60 res+=4; | |
61 } | |
62 } | |
63 return res; | |
64 } | |
65 | |
66 /++ | |
67 + | |
68 +/ | |
69 int indexToCodepointIndex( CString str, int index ){ | |
70 if( index < 0 ) return index; | |
71 int i = 0; | |
72 int res = 0; | |
73 while( i < index ){ | |
74 if( i >= str.length ){ | |
75 break; | |
76 } | |
77 if( str[i] < 0x80 ){ | |
78 i+=1; | |
79 } | |
80 else if( str[i] < 0xE0 ){ | |
81 i+=2; | |
82 } | |
83 else if( str[i] & 0xF0 ){ | |
84 i+=3; | |
85 } | |
86 else{ | |
87 i+=4; | |
88 } | |
89 res++; | |
90 } | |
91 return res; | |
92 } | |
93 | |
94 /++ | |
95 + Get that String, that contains the next codepoint of a String. | |
96 +/ | |
97 String firstCodePointStr( CString str, out int consumed ){ | |
98 version(Tango){ | |
99 dchar[1] buf; | |
100 uint ate; | |
101 dchar[] res = tango.text.convert.Utf.toString32( str, buf, &ate ); | |
102 consumed = ate; | |
103 return str[ 0 .. ate ]; | |
104 } else { // Phobos | |
105 implMissing( __FILE__, __LINE__ ); | |
106 return null; | |
107 } | |
108 } | |
109 | |
110 /++ | |
111 + Get first codepoint of a String. If an offset is needed, simply use a slice: | |
112 + --- | |
113 + dchar res = str[ offset .. $ ].firstCodePoint(); | |
114 + --- | |
115 +/ | |
116 dchar firstCodePoint( CString str ){ | |
117 int dummy; | |
118 return firstCodePoint( str, dummy ); | |
119 } | |
120 dchar firstCodePoint( CString str, out int consumed ){ | |
121 version(Tango){ | |
122 dchar[1] buf; | |
123 uint ate; | |
124 dchar[] res = tango.text.convert.Utf.toString32( str, buf, &ate ); | |
125 consumed = ate; | |
126 if( ate is 0 || res.length is 0 ){ | |
127 getDwtLogger().trace( __FILE__, __LINE__, "str.length={} str={:X2}", str.length, cast(ubyte[])str ); | |
128 } | |
129 assert( ate > 0 ); | |
130 assert( res.length is 1 ); | |
131 return res[0]; | |
132 } else { // Phobos | |
133 size_t ate = 0; | |
134 auto res = std.utf.decode(str, ate); | |
135 | |
136 if (ate == 0) | |
137 getDwtLogger().trace( __FILE__, __LINE__, "str.length={} str={:X2}", str.length, cast(ubyte[])str ); | |
138 | |
139 assert(ate > 0); | |
140 consumed = ate; | |
141 | |
142 return res; | |
143 } | |
144 } | |
145 dchar firstCodePoint( CString16 str, out int consumed ){ | |
146 version(Tango){ | |
147 dchar[1] buf; | |
148 uint ate; | |
149 dchar[] res = tango.text.convert.Utf.toString32( str, buf, &ate ); | |
150 consumed = ate; | |
151 if( ate is 0 || res.length is 0 ){ | |
152 getDwtLogger().trace( __FILE__, __LINE__, "str.length={} str={:X2}", str.length, cast(ubyte[])str ); | |
153 } | |
154 assert( ate > 0 ); | |
155 assert( res.length is 1 ); | |
156 return res[0]; | |
157 } else { // Phobos | |
158 size_t ate = 0; | |
159 auto res = std.utf.decode(str, ate); | |
160 | |
161 if (ate == 0) | |
162 getDwtLogger().trace( __FILE__, __LINE__, "str.length={} str={:X2}", str.length, cast(ubyte[])str ); | |
163 | |
164 assert(ate > 0); | |
165 consumed = ate; | |
166 | |
167 return res; | |
168 } | |
169 } | |
170 | |
171 String dcharToString( dchar key ){ | |
172 version(Tango){ | |
173 dchar[1] buf; | |
174 buf[0] = key; | |
175 return tango.text.convert.Utf.toString( buf ); | |
176 } else { // Phobos | |
177 return std.conv.to!(string)(key); | |
178 } | |
179 } | |
180 | |
181 int codepointCount( CString str ){ | |
182 version(Tango){ | |
183 scope dchar[] buf = new dchar[]( str.length ); | |
184 uint ate; | |
185 dchar[] res = tango.text.convert.Utf.toString32( str, buf, &ate ); | |
186 assert( ate is str.length ); | |
187 return res.length; | |
188 } else { // Phobos | |
189 return std.utf.count(str); | |
190 } | |
191 } | |
192 | |
193 //alias tango.text.convert.Utf.toString16 toString16; | |
194 //alias tango.text.convert.Utf.toString toString; | |
195 | |
196 int toAbsoluteCodePointStartOffset( CString str, int index ){ | |
197 //getDwtLogger().trace( __FILE__, __LINE__, "str={}, str.length={}, index={}", str, str.length, index ); | |
198 //getDwtLogger().trace( __FILE__, __LINE__, Trace.memory( str ); | |
199 if( str.length is index ){ | |
200 return index; | |
201 } | |
202 if( ( str[index] & 0x80 ) is 0x00 ) { | |
203 return index; | |
204 } | |
205 else{ | |
206 int steps = 0; | |
207 while(( str[index] & 0xC0 ) is 0x80 ){ | |
208 index--; | |
209 steps++; | |
210 if( steps > 3 || index < 0 ){ | |
211 break; | |
212 } | |
213 } | |
214 if((( str[index] & 0xE0 ) is 0xC0) && ( steps <= 1 )){ | |
215 // ok | |
216 } | |
217 else if((( str[index] & 0xF0 ) is 0xE0) && ( steps <= 2 )){ | |
218 // ok | |
219 } | |
220 else if((( str[index] & 0xF8 ) is 0xF0) && ( steps <= 3 )){ | |
221 // ok | |
222 } | |
223 else{ | |
224 throw new UnicodeException( "invalid utf8 input to toAbsoluteCodePointStartOffset", index ); | |
225 } | |
226 return index; | |
227 } | |
228 } | |
229 int getRelativeCodePointOffset( CString str, int startIndex, int searchRelCp ){ | |
230 return getAbsoluteCodePointOffset( str, startIndex, searchRelCp ) - startIndex; | |
231 } | |
232 int getAbsoluteCodePointOffset( CString str, int startIndex, int searchRelCp ){ | |
233 | |
234 //getDwtLogger().trace( __FILE__, __LINE__, "str={}, str.length={}, startIndex={}, searchRelCp={}", str, str.length, startIndex, searchRelCp ); | |
235 //getDwtLogger().trace( __FILE__, __LINE__, Trace.memory( str ); | |
236 | |
237 int ignore; | |
238 int i = startIndex; | |
239 if( searchRelCp > 0 ){ | |
240 while( searchRelCp !is 0 ){ | |
241 | |
242 if( ( i < str.length ) | |
243 && (( str[i] & 0x80 ) is 0x00 )) | |
244 { | |
245 i+=1; | |
246 } | |
247 else if( ( i+1 < str.length ) | |
248 && (( str[i+1] & 0xC0 ) is 0x80 ) | |
249 && (( str[i ] & 0xE0 ) is 0xC0 )) | |
250 { | |
251 i+=2; | |
252 } | |
253 else if( ( i+2 < str.length ) | |
254 && (( str[i+2] & 0xC0 ) is 0x80 ) | |
255 && (( str[i+1] & 0xC0 ) is 0x80 ) | |
256 && (( str[i ] & 0xF0 ) is 0xE0 )) | |
257 { | |
258 i+=3; | |
259 } | |
260 else if(( i+3 < str.length ) | |
261 && (( str[i+3] & 0xC0 ) is 0x80 ) | |
262 && (( str[i+2] & 0xC0 ) is 0x80 ) | |
263 && (( str[i+1] & 0xC0 ) is 0x80 ) | |
264 && (( str[i ] & 0xF8 ) is 0xF0 )) | |
265 { | |
266 i+=4; | |
267 } | |
268 else{ | |
269 getDwtLogger().trace( __FILE__, __LINE__, "getAbsoluteCodePointOffset invalid utf8 characters: {:X2}", cast(ubyte[]) str ); | |
270 throw new UnicodeException( "invalid utf8 input", i ); | |
271 } | |
272 searchRelCp--; | |
273 } | |
274 } | |
275 else if( searchRelCp < 0 ){ | |
276 while( searchRelCp !is 0 ){ | |
277 do{ | |
278 i--; | |
279 if( i < 0 ){ | |
280 return startIndex-1; | |
281 } | |
282 } while(( str[i] & 0xC0 ) is 0x80 ); | |
283 searchRelCp++; | |
284 } | |
285 } | |
286 return i; | |
287 } | |
288 int getAbsoluteCodePointOffset( CString16 str, int startIndex, int searchRelCp ){ | |
289 int ignore; | |
290 int i = startIndex; | |
291 if( searchRelCp > 0 ){ | |
292 while( searchRelCp !is 0 ){ | |
293 | |
294 if( ( i < str.length ) | |
295 && ( str[i] & 0xD800 ) !is 0xD800 ) | |
296 { | |
297 i+=1; | |
298 } | |
299 else if( ( i+1 < str.length ) | |
300 && (( str[i+1] & 0xDC00 ) is 0xDC00 ) | |
301 && (( str[i ] & 0xDC00 ) is 0xD800 )) | |
302 { | |
303 i+=2; | |
304 } | |
305 else{ | |
306 getDwtLogger().trace( __FILE__, __LINE__, "invalid utf16 characters: {:X2}", cast(ubyte[]) str ); | |
307 throw new UnicodeException( "invalid utf16 input", i ); | |
308 } | |
309 searchRelCp--; | |
310 } | |
311 } | |
312 else if( searchRelCp < 0 ){ | |
313 while( searchRelCp !is 0 ){ | |
314 do{ | |
315 i--; | |
316 if( i < 0 ){ | |
317 return startIndex-1; | |
318 //getDwtLogger().trace( __FILE__, __LINE__, "dwthelper.utils getRelativeCodePointOffset {}: str={}, startIndex={}, searchRelCp={}", __LINE__, str, startIndex, searchRelCp ); | |
319 //tango.text.convert.Utf.onUnicodeError( "invalid utf16 input", i ); | |
320 } | |
321 } while(( str[i] & 0xDC00 ) is 0xDC00 ); | |
322 searchRelCp++; | |
323 } | |
324 } | |
325 return i; | |
326 } | |
327 dchar getRelativeCodePoint( CString str, int startIndex, int searchRelCp ){ | |
328 int dummy; | |
329 return getRelativeCodePoint( str, startIndex, dummy ); | |
330 } | |
331 dchar getRelativeCodePoint( CString str, int startIndex, int searchRelCp, out int relIndex ){ | |
332 relIndex = getRelativeCodePointOffset( str, startIndex, searchRelCp ); | |
333 int ignore; | |
334 return firstCodePoint( str[ startIndex+relIndex .. $ ], ignore ); | |
335 } | |
336 | |
337 int utf8AdjustOffset( CString str, int offset ){ | |
338 if( str.length <= offset || offset <= 0 ){ | |
339 return offset; | |
340 } | |
341 while(( str[offset] & 0xC0 ) is 0x80 ){ | |
342 offset--; | |
343 } | |
344 return offset; | |
345 } | |
346 int utf8OffsetIncr( CString str, int offset ){ | |
347 int res = offset +1; | |
348 if( str.length <= res || res <= 0 ){ | |
349 return res; | |
350 } | |
351 int tries = 4; | |
352 while(( str[res] & 0xC0 ) is 0x80 ){ | |
353 res++; | |
354 assert( tries-- > 0 ); | |
355 } | |
356 return res; | |
357 } | |
358 int utf8OffsetDecr( CString str, int offset ){ | |
359 int res = offset-1; | |
360 if( str.length <= res || res <= 0 ){ | |
361 return res; | |
362 } | |
363 int tries = 4; | |
364 while(( str[res] & 0xC0 ) is 0x80 ){ | |
365 res--; | |
366 assert( tries-- > 0 ); | |
367 } | |
368 getDwtLogger().trace( __FILE__, __LINE__, "utf8OffsetDecr {}->{}", offset, res ); | |
369 getDwtLogger().trace( __FILE__, __LINE__, "{}", str ); | |
370 return res; | |
371 } | |
372 | |
373 String new_String( CString cont, int offset, int len ){ | |
374 version(D_Version2){ | |
375 return cont[ offset .. offset+len ].idup; | |
376 } else { | |
377 return cont[ offset .. offset+len ].dup; | |
378 } | |
379 } | |
380 | |
381 String new_String( CString cont ){ | |
382 version(D_Version2){ | |
383 return cont.idup; | |
384 } else { | |
385 return cont.dup; | |
386 } | |
387 } | 29 } |
388 | 30 |
389 String String_valueOf( bool v ){ | 31 String String_valueOf( bool v ){ |
390 return v ? "true" : "false"; | 32 return v ? "true" : "false"; |
391 } | 33 } |
392 | 34 |
393 String String_valueOf( byte v ){ | 35 String String_valueOf( byte v ){ |
36 return String_valueOf( cast(long) v ); | |
37 } | |
38 | |
39 String String_valueOf( ubyte v ){ | |
40 return String_valueOf( cast(uint) v ); | |
41 } | |
42 | |
43 String String_valueOf( short v ){ | |
44 return String_valueOf( cast(long) v ); | |
45 } | |
46 | |
47 String String_valueOf( int v ){ | |
48 return String_valueOf( cast(long) v ); | |
49 } | |
50 | |
51 String String_valueOf( uint v ){ | |
394 version(Tango){ | 52 version(Tango){ |
395 return tango.text.convert.Integer.toString(v); | 53 return tango.text.convert.Integer.toString(v); |
396 } else { // Phobos | 54 } else { // Phobos |
397 implMissing( __FILE__, __LINE__ ); | 55 return std.conv.to!(String)(v); |
398 return null; | 56 } |
399 } | 57 } |
400 } | 58 |
401 | 59 String String_valueOf( long v ){ |
402 String String_valueOf( ubyte v ){ | |
403 version(Tango){ | 60 version(Tango){ |
404 return tango.text.convert.Integer.toString(v); | 61 return tango.text.convert.Integer.toString(v); |
405 } else { // Phobos | 62 } else { // Phobos |
406 implMissing( __FILE__, __LINE__ ); | |
407 return null; | |
408 } | |
409 } | |
410 | |
411 String String_valueOf( short v ){ | |
412 version(Tango){ | |
413 return tango.text.convert.Integer.toString(v); | |
414 } else { // Phobos | |
415 implMissing( __FILE__, __LINE__ ); | |
416 return null; | |
417 } | |
418 } | |
419 | |
420 String String_valueOf( int v ){ | |
421 version(Tango){ | |
422 return tango.text.convert.Integer.toString(v); | |
423 } else { // Phobos | |
424 return std.conv.to!(String)(v); | 63 return std.conv.to!(String)(v); |
425 } | 64 } |
426 } | 65 } |
427 | 66 |
428 String String_valueOf( uint v ){ | 67 String String_valueOf( float v ){ |
429 version(Tango){ | 68 version(Tango){ |
430 return tango.text.convert.Integer.toString(v); | 69 return tango.text.convert.Float.toString(v); |
431 } else { // Phobos | 70 } else { // Phobos |
432 return std.conv.to!(String)(v); | 71 return std.conv.to!(String)(v); |
433 } | 72 } |
434 } | 73 } |
435 | 74 |
436 String String_valueOf( long v ){ | 75 String String_valueOf( double v ){ |
437 version(Tango){ | 76 version(Tango){ |
438 return tango.text.convert.Integer.toString(v); | 77 return tango.text.convert.Float.toString(v); |
439 } else { // Phobos | 78 } else { // Phobos |
440 return std.conv.to!(String)(v); | 79 return std.conv.to!(String)(v); |
441 } | 80 } |
442 } | 81 } |
443 | 82 |
444 String String_valueOf( float v ){ | 83 String String_valueOf( dchar v ){ |
445 version(Tango){ | 84 version(Tango){ |
446 return tango.text.convert.Float.toString(v); | 85 dchar[1] buf = v; |
86 return tango.text.convert.Utf.toString( buf ); | |
447 } else { // Phobos | 87 } else { // Phobos |
448 return std.conv.to!(String)(v); | 88 return std.conv.to!(String)(v); |
449 } | 89 } |
450 } | 90 } |
451 | 91 |
452 String String_valueOf( double v ){ | 92 String dcharToString( dchar v ){ |
453 version(Tango){ | 93 return String_valueOf(v); |
454 return tango.text.convert.Float.toString(v); | |
455 } else { // Phobos | |
456 return std.conv.to!(String)(v); | |
457 } | |
458 } | |
459 | |
460 String String_valueOf( dchar v ){ | |
461 return dcharToString(v); | |
462 } | 94 } |
463 | 95 |
464 String String_valueOf( char[] v ){ | 96 String String_valueOf( char[] v ){ |
465 version(D_Version2){ | 97 return _idup(v); |
466 return v.idup; | |
467 } else { | |
468 return v.dup; | |
469 } | |
470 } | 98 } |
471 | 99 |
472 String String_valueOf( char[] v, int offset, int len ){ | 100 String String_valueOf( char[] v, int offset, int len ){ |
473 version(D_Version2){ | 101 return _idup(v[ offset .. offset+len ]); |
474 return v[ offset .. offset+len ].idup; | |
475 } else { | |
476 return v[ offset .. offset+len ].dup; | |
477 } | |
478 } | 102 } |
479 | 103 |
480 String String_valueOf( Object v ){ | 104 String String_valueOf( Object v ){ |
481 return v is null ? "null" : v.toString(); | 105 return v is null ? "null" : v.toString(); |
482 } | 106 } |
483 | 107 |
484 String String_valueOf( CString16 wstr ){ | 108 String String_valueOf( in wchar[] wstr ){ |
485 version(Tango){ | 109 version(Tango){ |
486 return tango.text.convert.Utf.toString(wstr); | 110 return tango.text.convert.Utf.toString(wstr); |
487 } else { // Phobos | 111 } else { // Phobos |
488 return std.conv.to!(String)(wstr); | 112 return std.conv.to!(String)(wstr); |
489 } | 113 } |
490 } | 114 } |
491 | 115 |
492 int length( CString str ){ | 116 int length( String str ){ |
493 return str.length; | 117 return str.length; |
494 } | 118 } |
495 | 119 |
496 /// Extension to String | 120 /// Extension to String |
497 public String toUpperCase( CString str ){ | 121 public String toUpperCase( String str ){ |
498 version(Tango){ | 122 version(Tango){ |
499 return tango.text.Unicode.toUpper( str ); | 123 return tango.text.Unicode.toUpper( str ); |
500 } else { // Phobos | 124 } else { // Phobos |
501 implMissing( __FILE__, __LINE__ ); | 125 return cast(String) std.string.toupper( str ); |
502 return null; | 126 } |
503 } | 127 } |
504 } | 128 |
505 | 129 /// Extension to String |
506 /// Extension to String | 130 public String replaceFirst( String str, String regex, String replacement ){ |
507 public String replaceFirst( CString str, CString regex, CString replacement ){ | |
508 implMissing(__FILE__,__LINE__); | 131 implMissing(__FILE__,__LINE__); |
509 return null; | 132 return null; |
510 } | 133 } |
511 | 134 |
512 /// Extension to String | 135 version(Tango) int tangoToJavaIdx(T)(int idx, T[] arr) { |
513 public int indexOf( CString str, char searched ){ | 136 return idx is arr.length ? -1 : idx; |
514 version(Tango){ | 137 } |
515 int res = tango.text.Util.locate( str, searched ); | 138 |
516 if( res is str.length ) res = -1; | 139 /// Extension to String |
140 public int indexOf( in char[] str, char searched ){ | |
141 version(Tango){ | |
142 return tangoToJavaIdx(tango.text.Util.locate( str, searched ), str); | |
143 } else { // Phobos | |
144 return std.string.indexOf(str, searched); | |
145 } | |
146 } | |
147 | |
148 /// Extension to String | |
149 public int indexOf( in char[] str, char searched, int fromIndex ){ | |
150 if(fromIndex >= str.length) | |
151 return -1; | |
152 version(Tango){ | |
153 return tangoToJavaIdx(tango.text.Util.locate( str, searched, fromIndex ), str); | |
154 } else { // Phobos | |
155 int res = std.string.indexOf(str[fromIndex .. $], searched); | |
156 if (res !is -1) res += fromIndex; | |
517 return res; | 157 return res; |
518 } else { // Phobos | 158 } |
519 return std.string.indexOf(str, searched); | 159 } |
520 } | 160 |
521 } | 161 /// Extension to String |
522 | 162 public int indexOf(in char[] str, in char[] sub){ |
523 /// Extension to String | 163 return indexOf( str, sub, 0 ); |
524 public int indexOf( CString str, char searched, int startpos ){ | 164 } |
525 version(Tango){ | 165 |
526 int res = tango.text.Util.locate( str, searched, startpos ); | 166 /// Extension to String |
527 if( res is str.length ) res = -1; | 167 public int indexOf(in char[] str, in char[] sub, int fromIndex){ |
168 if(fromIndex + sub.length > str.length) | |
169 return -1; | |
170 if(!sub.length) | |
171 return fromIndex; | |
172 version(Tango){ | |
173 return tangoToJavaIdx(tango.text.Util.locatePattern( str, sub, fromIndex ), str); | |
174 } else { // Phobos | |
175 int res = std.string.indexOf(str[fromIndex .. $], sub); | |
176 if (res !is -1) res += fromIndex; | |
528 return res; | 177 return res; |
529 } else { // Phobos | 178 } |
530 int res = std.string.indexOf(str[startpos .. $], searched); | 179 } |
531 if (res !is -1) res += startpos; | 180 |
532 return res; | 181 /// Extension to String |
533 } | 182 public int lastIndexOf(in char[] str, char ch){ |
534 } | 183 return lastIndexOf( str, ch, str.length - 1 ); |
535 | 184 } |
536 /// Extension to String | 185 |
537 public int indexOf(CString str, String ch){ | 186 /// Extension to String |
538 return indexOf( str, ch, 0 ); | 187 public int lastIndexOf(in char[] str, char ch, int fromIndex){ |
539 } | 188 if(fromIndex >= str.length) |
540 | 189 fromIndex = str.length - 1; |
541 /// Extension to String | 190 version(Tango){ |
542 public int indexOf(CString str, String ch, int start){ | 191 return tangoToJavaIdx(tango.text.Util.locatePrior( str, ch, fromIndex + 1 ), str); |
543 version(Tango){ | 192 } else { // Phobos |
544 int res = tango.text.Util.locatePattern( str, ch, start ); | 193 return std.string.lastIndexOf(str[0 .. fromIndex + 1], ch); |
545 if( res is str.length ) res = -1; | 194 } |
546 return res; | 195 } |
547 } else { // Phobos | 196 |
548 return std.string.indexOf(str[start .. $], ch); | 197 /// Extension to String |
549 } | 198 public int lastIndexOf(in char[] str, in char[] sub ){ |
550 } | 199 return lastIndexOf( str, sub, str.length - sub.length ); |
551 | 200 } |
552 /// Extension to String | 201 |
553 public int lastIndexOf(CString str, char ch){ | 202 /// Extension to String |
554 return lastIndexOf( str, ch, str.length ); | 203 public int lastIndexOf(in char[] str, in char[] sub, int fromIndex){ |
555 } | 204 int max = cast(int)str.length - cast(int)sub.length; |
556 | 205 if(fromIndex > max) |
557 /// Extension to String | 206 fromIndex = max; |
558 public int lastIndexOf(CString str, char ch, int formIndex){ | 207 if(!sub.length) |
559 version(Tango){ | 208 return fromIndex; |
560 int res = tango.text.Util.locatePrior( str, ch, formIndex ); | 209 version(Tango){ |
561 if( res is str.length ) res = -1; | 210 return tangoToJavaIdx(tango.text.Util.locatePatternPrior( str, sub, fromIndex + 1 ), str); |
562 return res; | 211 } else { // Phobos |
563 } else { // Phobos | 212 size_t to = fromIndex + sub.length; |
564 return std.string.lastIndexOf(str[0 .. formIndex], ch); | 213 return std.string.lastIndexOf(str[0 .. to < $ ? to : $], sub); |
565 } | 214 } |
566 } | 215 } |
567 | 216 |
568 /// Extension to String | 217 unittest { |
569 public int lastIndexOf(CString str, String ch ){ | 218 sizediff_t i; |
570 return lastIndexOf( str, ch, str.length ); | 219 |
571 } | 220 i = lastIndexOf("", 'a'); |
572 | 221 assert(i == -1); |
573 /// Extension to String | 222 i = lastIndexOf("def", 'a'); |
574 public int lastIndexOf(CString str, String ch, int start ){ | 223 assert(i == -1); |
575 version(Tango){ | 224 i = lastIndexOf("abba", 'a'); |
576 int res = tango.text.Util.locatePatternPrior( str, ch, start ); | 225 assert(i == 3); |
577 if( res is str.length ) res = -1; | 226 i = lastIndexOf("abba", 'a', 0); |
578 return res; | 227 assert(i == 0); |
579 } else { // Phobos | 228 i = lastIndexOf("abba", 'a', 1); |
580 implMissing( __FILE__, __LINE__ ); | 229 assert(i == 0); |
581 return 0; | 230 i = lastIndexOf("abba", 'a', 2); |
582 } | 231 assert(i == 0); |
583 } | 232 i = lastIndexOf("abba", 'a', 3); |
584 | 233 assert(i == 3); |
585 /// Extension to String | 234 i = lastIndexOf("abba", 'a', 4); |
586 public String replaceAll( CString str, String regex, String replacement ){ | 235 assert(i == 3); |
236 i = lastIndexOf("abba", 'a', 10); | |
237 assert(i == 3); | |
238 i = lastIndexOf("def", 'f'); | |
239 assert(i == 2); | |
240 | |
241 i = lastIndexOf("", "a"); | |
242 assert(i == -1); | |
243 i = lastIndexOf("", ""); | |
244 assert(i == 0); | |
245 i = lastIndexOf("abcdefcdef", "c"); | |
246 assert(i == 6); | |
247 i = lastIndexOf("abcdefcdef", "cd"); | |
248 assert(i == 6); | |
249 i = lastIndexOf("abcdefcdef", "cd", 5); | |
250 assert(i == 2); | |
251 i = lastIndexOf("abcdefcdef", "cd", 6); | |
252 assert(i == 6); | |
253 i = lastIndexOf("abcdefcdef", "cd", 7); | |
254 assert(i == 6); | |
255 i = lastIndexOf("abcdefcdef", "cd", 10); | |
256 assert(i == 6); | |
257 i = lastIndexOf("abcdefcdef", "x"); | |
258 assert(i == -1); | |
259 i = lastIndexOf("abcdefcdef", "xy"); | |
260 assert(i == -1); | |
261 i = lastIndexOf("abcdefcdef", ""); | |
262 assert(i == 10); | |
263 i = lastIndexOf("abcdefcdef", "", 9); | |
264 assert(i == 9); | |
265 i = lastIndexOf("abcabc", "abc"); | |
266 assert(i == 3); | |
267 i = lastIndexOf("abcabc", "abc", 2); | |
268 assert(i == 0); | |
269 i = lastIndexOf("abcabc", "abc", 3); | |
270 assert(i == 3); | |
271 i = lastIndexOf("abcabc", "abc", 4); | |
272 assert(i == 3); | |
273 | |
274 | |
275 | |
276 i = indexOf("", 'a'); | |
277 assert(i == -1); | |
278 i = indexOf("def", 'a'); | |
279 assert(i == -1); | |
280 i = indexOf("abba", 'a'); | |
281 assert(i == 0); | |
282 i = indexOf("abba", 'a', 0); | |
283 assert(i == 0); | |
284 i = indexOf("abba", 'a', 1); | |
285 assert(i == 3); | |
286 i = indexOf("abba", 'a', 2); | |
287 assert(i == 3); | |
288 i = indexOf("abba", 'a', 3); | |
289 assert(i == 3); | |
290 i = indexOf("abba", 'a', 4); | |
291 assert(i == -1); | |
292 i = indexOf("abba", 'a', 10); | |
293 assert(i == -1); | |
294 i = indexOf("def", 'f'); | |
295 assert(i == 2); | |
296 | |
297 i = indexOf("", "a"); | |
298 assert(i == -1); | |
299 i = indexOf("", ""); | |
300 assert(i == 0); | |
301 i = indexOf("abcdefcdef", "c"); | |
302 assert(i == 2); | |
303 i = indexOf("abcdefcdef", "cd"); | |
304 assert(i == 2); | |
305 i = indexOf("abcdefcdef", "cd", 4); | |
306 assert(i == 6); | |
307 i = indexOf("abcdefcdef", "cd", 5); | |
308 assert(i == 6); | |
309 i = indexOf("abcdefcdef", "cd", 6); | |
310 assert(i == 6); | |
311 i = indexOf("abcdefcdef", "cd", 7); | |
312 assert(i == -1); | |
313 i = indexOf("abcdefcdef", "cd", 10); | |
314 assert(i == -1); | |
315 i = indexOf("abcdefcdef", "x"); | |
316 assert(i == -1); | |
317 i = indexOf("abcdefcdef", "xy"); | |
318 assert(i == -1); | |
319 i = indexOf("abcdefcdef", ""); | |
320 assert(i == 0); | |
321 i = indexOf("abcabc", "abc"); | |
322 assert(i == 0); | |
323 i = indexOf("abcabc", "abc", 2); | |
324 assert(i == 3); | |
325 i = indexOf("abcabc", "abc", 3); | |
326 assert(i == 3); | |
327 i = indexOf("abcabc", "abc", 4); | |
328 assert(i == -1); | |
329 } | |
330 | |
331 /// Extension to String | |
332 public String replaceAll( String str, String regex, String replacement ){ | |
587 implMissing(__FILE__,__LINE__); | 333 implMissing(__FILE__,__LINE__); |
588 return null; | 334 return null; |
589 } | 335 } |
590 | 336 |
591 /// Extension to String | 337 /// Extension to String |
592 public String replace( CString str, char from, char to ){ | 338 public String replace( String str, char from, char to ){ |
593 version(Tango){ | 339 version(Tango){ |
594 return tango.text.Util.replace( str.dup, from, to ); | 340 return tango.text.Util.replace( str.dup, from, to ); |
595 } else { // Phobos | 341 } else { // Phobos |
596 auto res = std.array.replace(str, [from], [to]); | 342 char[1] f = from, t = to; |
343 auto res = std.array.replace(str, f[], t[]); | |
597 return std.exception.assumeUnique(res); | 344 return std.exception.assumeUnique(res); |
598 } | 345 } |
599 } | 346 } |
600 | 347 |
601 /// Extension to String | 348 /// Extension to String |
602 public String substring( CString str, int start ){ | 349 public String substring( String str, int start ){ |
603 return cast(String)str[ start .. $ ].dup; | 350 return _idup(str[ start .. $ ]); |
604 } | 351 } |
605 | 352 |
606 /// Extension to String | 353 /// Extension to String |
607 public String substring( CString str, int start, int end ){ | 354 public String substring( String str, int start, int end ){ |
608 return cast(String)str[ start .. end ].dup; | 355 return _idup(str[ start .. end ]); |
609 } | 356 } |
610 | 357 |
611 /// Extension to String | 358 /// Extension to String |
612 public wchar[] substring( CString16 str, int start ){ | 359 public wchar[] substring( String16 str, int start ){ |
613 return cast(wchar[])(str[ start .. $ ].dup); | 360 return str[ start .. $ ].dup; |
614 } | 361 } |
615 | 362 |
616 /// Extension to String | 363 /// Extension to String |
617 public wchar[] substring( CString16 str, int start, int end ){ | 364 public wchar[] substring( String16 str, int start, int end ){ |
618 return str[ start .. end ].dup; | 365 return str[ start .. end ].dup; |
619 } | 366 } |
620 | 367 |
621 /// Extension to String | 368 /// Extension to String |
622 public char charAt( CString str, int pos ){ | 369 public char charAt( String str, int pos ){ |
623 return str[ pos ]; | 370 return str[ pos ]; |
624 } | |
625 | |
626 /// Extension to String | |
627 public dchar dcharAt( CString str, int pos ){ | |
628 return str[ pos .. $ ].firstCodePoint(); | |
629 } | 371 } |
630 | 372 |
631 /// Extension to String | 373 /// Extension to String |
632 public void getChars( String src, int srcBegin, int srcEnd, char[] dst, int dstBegin){ | 374 public void getChars( String src, int srcBegin, int srcEnd, char[] dst, int dstBegin){ |
633 dst[ dstBegin .. dstBegin + srcEnd - srcBegin ] = src[ srcBegin .. srcEnd ]; | 375 dst[ dstBegin .. dstBegin + srcEnd - srcBegin ] = src[ srcBegin .. srcEnd ]; |
634 } | 376 } |
635 | 377 |
636 /// Extension to String | 378 /// Extension to String |
637 public String16 toWCharArray( CString str ){ | 379 public String16 toWCharArray( in char[] str ){ |
638 version(Tango){ | 380 version(Tango){ |
639 return tango.text.convert.Utf.toString16(str); | 381 return tango.text.convert.Utf.toString16(str); |
640 } else { // Phobos | 382 } else { // Phobos |
641 return std.conv.to!(String16)(str); | 383 return std.conv.to!(String16)(str); |
642 } | 384 } |
643 } | 385 } |
644 | 386 |
645 /// Extension to String | 387 /// Extension to String |
646 public char[] toCharArray( CString str ){ | 388 public char[] toCharArray( String str ){ |
647 return cast(char[])str; | 389 return cast(char[])str; |
648 } | 390 } |
649 | 391 |
650 /// Extension to String | 392 /// Extension to String |
651 public bool endsWith( CString src, CString pattern ){ | 393 public bool endsWith( String src, String pattern ){ |
652 if( src.length < pattern.length ){ | 394 if( src.length < pattern.length ){ |
653 return false; | 395 return false; |
654 } | 396 } |
655 return src[ $-pattern.length .. $ ] == pattern; | 397 return src[ $-pattern.length .. $ ] == pattern; |
656 } | 398 } |
657 | 399 |
658 /// Extension to String | 400 /// Extension to String |
659 public bool equals( CString src, CString other ){ | 401 public bool equals( in char[] src, in char[] other ){ |
660 return src == other; | 402 return src == other; |
661 } | 403 } |
662 | 404 |
663 /// Extension to String | 405 /// Extension to String |
664 public bool equalsIgnoreCase( CString src, CString other ){ | 406 public bool equalsIgnoreCase( in char[] src, in char[] other ){ |
665 version(Tango){ | 407 version(Tango) { |
666 return tango.text.Unicode.toFold(src) == tango.text.Unicode.toFold(other); | 408 if(src.length != other.length) |
667 } else { // Phobos | 409 return false; |
668 implMissing( __FILE__, __LINE__ ); | 410 String s1b = new char[ src.length * 2 ]; //*2, or Tango may reallocate buffers |
669 return false; | 411 String s2b = new char[ other.length * 2 ]; |
670 } | 412 scope(exit) { |
671 } | 413 delete s1b; |
672 | 414 delete s2b; |
673 /// Extension to String | 415 } |
674 public int compareToIgnoreCase( CString src, CString other ){ | 416 return tango.text.Unicode.toFold( src, s1b ) == |
675 version(Tango){ | 417 tango.text.Unicode.toFold( other, s2b ); |
676 return compareTo( tango.text.Unicode.toFold(src), tango.text.Unicode.toFold(other)); | 418 } else { // Phobos |
677 } else { // Phobos | 419 return std.string.icmp(src, other) == 0; |
678 implMissing( __FILE__, __LINE__ ); | 420 } |
679 return 0; | 421 } |
680 } | 422 |
681 } | 423 /// Extension to String |
682 | 424 public int compareToIgnoreCase( in char[] src, in char[] other ){ |
683 /// Extension to String | 425 version(Tango){ |
684 public int compareTo( CString src, CString other ){ | 426 String s1b = new char[ src.length * 2 ]; //*2, or Tango may reallocate buffers |
685 return typeid(String).compare( cast(void*)&src, cast(void*)&other ); | 427 String s2b = new char[ other.length * 2 ]; |
686 } | 428 scope(exit) { |
687 | 429 delete s1b; |
688 /// Extension to String | 430 delete s2b; |
689 public bool startsWith( CString src, CString pattern ){ | 431 } |
432 return compareTo( tango.text.Unicode.toFold(src, s1b), | |
433 tango.text.Unicode.toFold(other, s2b)); | |
434 } else { // Phobos | |
435 return std.string.icmp(src, other); | |
436 } | |
437 } | |
438 | |
439 /// Extension to String | |
440 public int compareTo( in char[] src, in char[] other ){ | |
441 version(Tango){ | |
442 return typeid(String).compare( cast(void*)&src, cast(void*)&other ); | |
443 } else { // Phobos | |
444 return std.string.cmp(src, other); | |
445 } | |
446 } | |
447 | |
448 /// Extension to String | |
449 public bool startsWith( String src, String pattern ){ | |
690 if( src.length < pattern.length ){ | 450 if( src.length < pattern.length ){ |
691 return false; | 451 return false; |
692 } | 452 } |
693 return src[ 0 .. pattern.length ] == pattern; | 453 return src[ 0 .. pattern.length ] == pattern; |
694 } | 454 } |
695 | 455 |
696 /// Extension to String | 456 /// Extension to String |
697 public String toLowerCase( CString src ){ | 457 public String toLowerCase( String src ){ |
698 version(Tango){ | 458 version(Tango){ |
699 return tango.text.Unicode.toLower( src ); | 459 return tango.text.Unicode.toLower( src ); |
700 } else { // Phobos | 460 } else { // Phobos |
701 implMissing( __FILE__, __LINE__ ); | 461 return cast(String) std.string.tolower(src); |
702 return null; | 462 } |
703 } | 463 } |
704 } | 464 |
705 | 465 /// Extension to String |
706 /// Extension to String | 466 public hash_t toHash( String src ){ |
707 public hash_t toHash( CString src ){ | |
708 return typeid(String).getHash(&src); | 467 return typeid(String).getHash(&src); |
709 } | 468 } |
710 public alias toHash String_toHash; | 469 public alias toHash String_toHash; |
711 | 470 |
712 /// Extension to String | 471 /// Extension to String |
713 public String trim( CString str ){ | 472 public String trim( String str ){ |
714 version(Tango){ | 473 version(Tango){ |
715 return tango.text.Util.trim( str ).dup; | 474 return tango.text.Util.trim( str ).dup; |
716 } else { // Phobos | 475 } else { // Phobos |
717 return std.string.strip( str.idup ); | 476 return std.string.strip( str.idup ); |
718 } | 477 } |
719 } | 478 } |
720 | 479 |
721 /// Extension to String | 480 /// Extension to String |
722 public String intern( CString str ){ | 481 public String intern( String str ){ |
723 return str._idup(); | 482 return _idup(str); |
724 } | |
725 | |
726 /++ | |
727 + This is like tango.stdc.stringz.toStringz, but in case of an empty input string, | |
728 + this function returns a pointer to a null value instead of a null ptr. | |
729 +/ | |
730 public char* toStringzValidPtr( CString src ){ | |
731 if( src ){ | |
732 return src.toStringz(); | |
733 } | |
734 else{ | |
735 static const char[] nullPtr = "\0"; | |
736 return cast(char*)nullPtr.ptr; | |
737 } | |
738 } | 483 } |
739 | 484 |
740 version(Tango){ | 485 version(Tango){ |
741 public alias tango.stdc.stringz.toStringz toStringz; | 486 public alias tango.stdc.stringz.toStringz toStringz; |
742 public alias tango.stdc.stringz.toString16z toString16z; | 487 public alias tango.stdc.stringz.toString16z toString16z; |
743 public alias tango.stdc.stringz.fromStringz fromStringz; | 488 public alias tango.stdc.stringz.fromStringz fromStringz; |
744 public alias tango.stdc.stringz.fromString16z fromString16z; | 489 public alias tango.stdc.stringz.fromString16z fromString16z; |
490 | |
491 /++ | |
492 + This is like tango.stdc.stringz.toStringz, but in case of an empty input string, | |
493 + this function returns a pointer to a null value instead of a null ptr. | |
494 +/ | |
495 public char* toStringzValidPtr( String src ){ | |
496 if( src ){ | |
497 return src.toStringz(); | |
498 } | |
499 else{ | |
500 return "".ptr; | |
501 } | |
502 } | |
745 } else { // Phobos | 503 } else { // Phobos |
746 public char* toStringz( CString s ){ | 504 static import std.c.string; |
747 if (s.ptr) { | 505 |
748 if (s.length == 0) | 506 public char* toStringzValidPtr( in char[] s ) { |
749 return "\0".dup.ptr; | 507 auto copy = new char[s.length + 1]; |
750 | 508 copy[0..s.length] = s; |
751 else | 509 copy[s.length] = 0; |
752 return (s ~ "\0").dup.ptr; | 510 return copy.ptr; |
753 } | 511 } |
754 | 512 |
755 return null; | 513 public char* toStringz( in char[] s ) { |
756 } | 514 return s is null ? null : toStringzValidPtr(s); |
757 public wchar* toString16z( CString16 s ){ | 515 } |
758 if (s.ptr) { | 516 |
759 if (s.length == 0) | 517 public char[] fromStringz( in char* s ){ |
760 return "\0"w.dup.ptr; | 518 return s ? s[0 .. std.c.string.strlen(s)].dup : cast(char[])null; |
761 | 519 } |
762 else | 520 /*public string fromStringz( in char* s ){ |
763 return (s ~ "\0"w).dup.ptr; | 521 return std.conv.to!(string)(s); |
764 } | 522 }*/ |
765 | 523 |
766 return null; | 524 private size_t w_strlen(in wchar* s) { |
767 } | 525 size_t res = 0; |
768 public char[] fromStringz( CCharPtr s ){ | 526 while(*(s+res)) |
769 size_t len; | 527 ++res; |
770 | 528 return res; |
771 if (s) | 529 } |
772 while (*s++) | 530 |
773 len++; | 531 public wchar* toString16z( in wchar[] s ){ |
774 | 532 if(s is null) |
775 return s[0 .. len].dup; | 533 return null; |
776 } | 534 auto copy = new wchar[s.length + 1]; |
777 public wchar[] fromString16z( CWCharPtr s ){ | 535 copy[0..s.length] = s; |
778 size_t len; | 536 copy[s.length] = 0; |
779 | 537 return copy.ptr; |
780 if (s) | 538 } |
781 while (*s++) | 539 |
782 len++; | 540 //Copy of std.conv.toImpl(T, S)(S s) for C-style strings |
783 | 541 public wstring fromString16z( in wchar* s ){ |
784 return s[0 .. len].dup; | 542 return s ? s[0 .. w_strlen(s)].idup : cast(wstring)null; |
785 } | 543 } |
786 } | 544 } |
787 | 545 |
788 static String toHex(uint value, bool prefix = true, int radix = 8){ | 546 static String toHex(uint i){ |
789 version(Tango){ | 547 version(Tango){ |
790 return tango.text.convert.Integer.toString( | 548 return tango.text.convert.Integer.toString(i, "x"); |
791 value, | 549 } else { // Phobos |
792 radix is 10 ? "d" : | 550 return std.conv.to!(String)(i, 16); |
793 radix is 8 ? "o" : | |
794 radix is 16 ? "x" : | |
795 "d" ); | |
796 } else { // Phobos | |
797 implMissing( __FILE__, __LINE__ ); | |
798 return null; | |
799 } | 551 } |
800 } | 552 } |
801 | 553 |
802 /++ | 554 /++ |
803 + String in java is implementing the interface CharSequence | 555 + String in java is implementing the interface CharSequence |
805 class StringCharSequence : CharSequence { | 557 class StringCharSequence : CharSequence { |
806 private String str; | 558 private String str; |
807 this( String str ){ | 559 this( String str ){ |
808 this.str = str; | 560 this.str = str; |
809 } | 561 } |
810 char charAt(int index){ | 562 char charAt(int index){ |
811 return str[index]; | 563 return str[index]; |
812 } | 564 } |
813 int length(){ | 565 int length(){ |
814 return str.length; | 566 return str.length; |
815 } | 567 } |
816 CharSequence subSequence(int start, int end){ | 568 CharSequence subSequence(int start, int end){ |
817 return new StringCharSequence( str[ start .. end ]); | 569 return new StringCharSequence( str[ start .. end ]); |
818 } | 570 } |
819 String toString(){ | 571 String toString(){ |
820 return str; | 572 return str; |
821 } | 573 } |
822 } | 574 } |
823 | 575 |
824 class StringCls { | 576 class StringCls { |
829 } | 581 } |
830 return TYPE_; | 582 return TYPE_; |
831 } | 583 } |
832 | 584 |
833 } | 585 } |
834 | |
835 |