comparison base/src/java/lang/String.d @ 27:1bf55a6eb092

Renamed java tree to base
author Frank Benoit <benoit@tionex.de>
date Sat, 21 Mar 2009 11:33:57 +0100
parents java/src/java/lang/String.d@f713da8bc051
children 0ecb2b338560
comparison
equal deleted inserted replaced
26:f589fc20a5f9 27:1bf55a6eb092
1 module java.lang.String;
2
3 import java.lang.util;
4 import java.lang.interfaces;
5 import java.lang.exceptions;
6
7 version(Tango){
8 static import tango.stdc.stringz;
9 static import tango.text.Util;
10 static import tango.text.Unicode;
11 static import tango.text.convert.Utf;
12 } else { // Phobos
13 static import core.exception;
14 static import std.uni;
15 static import std.utf;
16 static import std.string;
17 }
18
19 version(Tango){
20 alias char[] String;
21 alias char[] CString;
22 alias wchar[] CString16;
23 } else { // Phobos
24 alias string String;
25 alias wstring String16;
26 mixin("alias const(char)[] CString;");
27 mixin("alias const(wchar)[] CString16;");
28 }
29
30 int codepointIndexToIndex( String str, int cpIndex ){
31 int cps = cpIndex;
32 int res = 0;
33 while( cps > 0 ){
34 cps--;
35 if( str[res] < 0x80 ){
36 res+=1;
37 }
38 else if( str[res] < 0xE0 ){
39 res+=2;
40 }
41 else if( str[res] & 0xF0 ){
42 res+=3;
43 }
44 else{
45 res+=4;
46 }
47 }
48 return res;
49 }
50
51 /++
52 +
53 +/
54 int indexToCodepointIndex( String str, int index ){
55 if( index < 0 ) return index;
56 int i = 0;
57 int res = 0;
58 while( i < index ){
59 if( i >= str.length ){
60 break;
61 }
62 if( str[i] < 0x80 ){
63 i+=1;
64 }
65 else if( str[i] < 0xE0 ){
66 i+=2;
67 }
68 else if( str[i] & 0xF0 ){
69 i+=3;
70 }
71 else{
72 i+=4;
73 }
74 res++;
75 }
76 return res;
77 }
78
79 /++
80 + Get that String, that contains the next codepoint of a String.
81 +/
82 String firstCodePointStr( String str, out int consumed ){
83 version(Tango){
84 dchar[1] buf;
85 uint ate;
86 dchar[] res = tango.text.convert.Utf.toString32( str, buf, &ate );
87 consumed = ate;
88 return str[ 0 .. ate ];
89 } else { // Phobos
90 implMissing( __FILE__, __LINE__ );
91 return null;
92 }
93 }
94
95 /++
96 + Get first codepoint of a String. If an offset is needed, simply use a slice:
97 + ---
98 + dchar res = str[ offset .. $ ].firstCodePoint();
99 + ---
100 +/
101 dchar firstCodePoint( String str ){
102 int dummy;
103 return firstCodePoint( str, dummy );
104 }
105 dchar firstCodePoint( String str, out int consumed ){
106 version(Tango){
107 dchar[1] buf;
108 uint ate;
109 dchar[] res = tango.text.convert.Utf.toString32( str, buf, &ate );
110 consumed = ate;
111 if( ate is 0 || res.length is 0 ){
112 getDwtLogger().trace( __FILE__, __LINE__, "str.length={} str={:X2}", str.length, cast(ubyte[])str );
113 }
114 assert( ate > 0 );
115 assert( res.length is 1 );
116 return res[0];
117 } else { // Phobos
118 implMissing( __FILE__, __LINE__ );
119 return '\0';
120 }
121 }
122 dchar firstCodePoint( wchar[] str, out int consumed ){
123 version(Tango){
124 dchar[1] buf;
125 uint ate;
126 dchar[] res = tango.text.convert.Utf.toString32( str, buf, &ate );
127 consumed = ate;
128 if( ate is 0 || res.length is 0 ){
129 getDwtLogger().trace( __FILE__, __LINE__, "str.length={} str={:X2}", str.length, cast(ubyte[])str );
130 }
131 assert( ate > 0 );
132 assert( res.length is 1 );
133 return res[0];
134 } else { // Phobos
135 implMissing( __FILE__, __LINE__ );
136 return '\0';
137 }
138 }
139
140 String dcharToString( dchar key ){
141 version(Tango){
142 dchar[1] buf;
143 buf[0] = key;
144 return tango.text.convert.Utf.toString( buf );
145 } else { // Phobos
146 implMissing( __FILE__, __LINE__ );
147 return null;
148 }
149 }
150
151 int codepointCount( String str ){
152 version(Tango){
153 scope dchar[] buf = new dchar[]( str.length );
154 uint ate;
155 dchar[] res = tango.text.convert.Utf.toString32( str, buf, &ate );
156 assert( ate is str.length );
157 return res.length;
158 } else { // Phobos
159 implMissing( __FILE__, __LINE__ );
160 return 0;
161 }
162 }
163
164 //alias tango.text.convert.Utf.toString16 toString16;
165 //alias tango.text.convert.Utf.toString toString;
166
167 int toAbsoluteCodePointStartOffset( String str, int index ){
168 //getDwtLogger().trace( __FILE__, __LINE__, "str={}, str.length={}, index={}", str, str.length, index );
169 //getDwtLogger().trace( __FILE__, __LINE__, Trace.memory( str );
170 if( str.length is index ){
171 return index;
172 }
173 if( ( str[index] & 0x80 ) is 0x00 ) {
174 return index;
175 }
176 else{
177 int steps = 0;
178 while(( str[index] & 0xC0 ) is 0x80 ){
179 index--;
180 steps++;
181 if( steps > 3 || index < 0 ){
182 break;
183 }
184 }
185 if((( str[index] & 0xE0 ) is 0xC0) && ( steps <= 1 )){
186 // ok
187 }
188 else if((( str[index] & 0xF0 ) is 0xE0) && ( steps <= 2 )){
189 // ok
190 }
191 else if((( str[index] & 0xF8 ) is 0xF0) && ( steps <= 3 )){
192 // ok
193 }
194 else{
195 throw new UnicodeException( "invalid utf8 input to toAbsoluteCodePointStartOffset", index );
196 }
197 return index;
198 }
199 }
200 int getRelativeCodePointOffset( String str, int startIndex, int searchRelCp ){
201 return getAbsoluteCodePointOffset( str, startIndex, searchRelCp ) - startIndex;
202 }
203 int getAbsoluteCodePointOffset( String str, int startIndex, int searchRelCp ){
204
205 //getDwtLogger().trace( __FILE__, __LINE__, "str={}, str.length={}, startIndex={}, searchRelCp={}", str, str.length, startIndex, searchRelCp );
206 //getDwtLogger().trace( __FILE__, __LINE__, Trace.memory( str );
207
208 int ignore;
209 int i = startIndex;
210 if( searchRelCp > 0 ){
211 while( searchRelCp !is 0 ){
212
213 if( ( i < str.length )
214 && (( str[i] & 0x80 ) is 0x00 ))
215 {
216 i+=1;
217 }
218 else if( ( i+1 < str.length )
219 && (( str[i+1] & 0xC0 ) is 0x80 )
220 && (( str[i ] & 0xE0 ) is 0xC0 ))
221 {
222 i+=2;
223 }
224 else if( ( i+2 < str.length )
225 && (( str[i+2] & 0xC0 ) is 0x80 )
226 && (( str[i+1] & 0xC0 ) is 0x80 )
227 && (( str[i ] & 0xF0 ) is 0xE0 ))
228 {
229 i+=3;
230 }
231 else if(( i+3 < str.length )
232 && (( str[i+3] & 0xC0 ) is 0x80 )
233 && (( str[i+2] & 0xC0 ) is 0x80 )
234 && (( str[i+1] & 0xC0 ) is 0x80 )
235 && (( str[i ] & 0xF8 ) is 0xF0 ))
236 {
237 i+=4;
238 }
239 else{
240 getDwtLogger().trace( __FILE__, __LINE__, "getAbsoluteCodePointOffset invalid utf8 characters: {:X2}", cast(ubyte[]) str );
241 throw new UnicodeException( "invalid utf8 input", i );
242 }
243 searchRelCp--;
244 }
245 }
246 else if( searchRelCp < 0 ){
247 while( searchRelCp !is 0 ){
248 do{
249 i--;
250 if( i < 0 ){
251 return startIndex-1;
252 }
253 } while(( str[i] & 0xC0 ) is 0x80 );
254 searchRelCp++;
255 }
256 }
257 return i;
258 }
259 int getAbsoluteCodePointOffset( wchar[] str, int startIndex, int searchRelCp ){
260 int ignore;
261 int i = startIndex;
262 if( searchRelCp > 0 ){
263 while( searchRelCp !is 0 ){
264
265 if( ( i < str.length )
266 && ( str[i] & 0xD800 ) !is 0xD800 )
267 {
268 i+=1;
269 }
270 else if( ( i+1 < str.length )
271 && (( str[i+1] & 0xDC00 ) is 0xDC00 )
272 && (( str[i ] & 0xDC00 ) is 0xD800 ))
273 {
274 i+=2;
275 }
276 else{
277 getDwtLogger().trace( __FILE__, __LINE__, "invalid utf16 characters: {:X2}", cast(ubyte[]) str );
278 throw new UnicodeException( "invalid utf16 input", i );
279 }
280 searchRelCp--;
281 }
282 }
283 else if( searchRelCp < 0 ){
284 while( searchRelCp !is 0 ){
285 do{
286 i--;
287 if( i < 0 ){
288 return startIndex-1;
289 //getDwtLogger().trace( __FILE__, __LINE__, "dwthelper.utils getRelativeCodePointOffset {}: str={}, startIndex={}, searchRelCp={}", __LINE__, str, startIndex, searchRelCp );
290 //tango.text.convert.Utf.onUnicodeError( "invalid utf16 input", i );
291 }
292 } while(( str[i] & 0xDC00 ) is 0xDC00 );
293 searchRelCp++;
294 }
295 }
296 return i;
297 }
298 dchar getRelativeCodePoint( String str, int startIndex, int searchRelCp ){
299 int dummy;
300 return getRelativeCodePoint( str, startIndex, dummy );
301 }
302 dchar getRelativeCodePoint( String str, int startIndex, int searchRelCp, out int relIndex ){
303 relIndex = getRelativeCodePointOffset( str, startIndex, searchRelCp );
304 int ignore;
305 return firstCodePoint( str[ startIndex+relIndex .. $ ], ignore );
306 }
307
308 int utf8AdjustOffset( String str, int offset ){
309 if( str.length <= offset || offset <= 0 ){
310 return offset;
311 }
312 while(( str[offset] & 0xC0 ) is 0x80 ){
313 offset--;
314 }
315 return offset;
316 }
317 int utf8OffsetIncr( String str, int offset ){
318 int res = offset +1;
319 if( str.length <= res || res <= 0 ){
320 return res;
321 }
322 int tries = 4;
323 while(( str[res] & 0xC0 ) is 0x80 ){
324 res++;
325 assert( tries-- > 0 );
326 }
327 return res;
328 }
329 int utf8OffsetDecr( String str, int offset ){
330 int res = offset-1;
331 if( str.length <= res || res <= 0 ){
332 return res;
333 }
334 int tries = 4;
335 while(( str[res] & 0xC0 ) is 0x80 ){
336 res--;
337 assert( tries-- > 0 );
338 }
339 getDwtLogger().trace( __FILE__, __LINE__, "utf8OffsetDecr {}->{}", offset, res );
340 getDwtLogger().trace( __FILE__, __LINE__, "{}", str );
341 return res;
342 }
343
344 String new_String( String cont, int offset, int len ){
345 version(D_Version2){
346 return cont[ offset .. offset+len ].idup;
347 } else {
348 return cont[ offset .. offset+len ].dup;
349 }
350 }
351
352 String new_String( String cont ){
353 version(D_Version2){
354 return cont.idup;
355 } else {
356 return cont.dup;
357 }
358 }
359
360 String String_valueOf( bool v ){
361 return v ? "true" : "false";
362 }
363
364 String String_valueOf( byte v ){
365 version(Tango){
366 return tango.text.convert.Integer.toString(v);
367 } else { // Phobos
368 implMissing( __FILE__, __LINE__ );
369 return null;
370 }
371 }
372
373 String String_valueOf( ubyte v ){
374 version(Tango){
375 return tango.text.convert.Integer.toString(v);
376 } else { // Phobos
377 implMissing( __FILE__, __LINE__ );
378 return null;
379 }
380 }
381
382 String String_valueOf( short v ){
383 version(Tango){
384 return tango.text.convert.Integer.toString(v);
385 } else { // Phobos
386 implMissing( __FILE__, __LINE__ );
387 return null;
388 }
389 }
390
391 String String_valueOf( int v ){
392 version(Tango){
393 return tango.text.convert.Integer.toString(v);
394 } else { // Phobos
395 implMissing( __FILE__, __LINE__ );
396 return null;
397 }
398 }
399
400 String String_valueOf( uint v ){
401 version(Tango){
402 return tango.text.convert.Integer.toString(v);
403 } else { // Phobos
404 implMissing( __FILE__, __LINE__ );
405 return null;
406 }
407 }
408
409 String String_valueOf( long v ){
410 version(Tango){
411 return tango.text.convert.Integer.toString(v);
412 } else { // Phobos
413 implMissing( __FILE__, __LINE__ );
414 return null;
415 }
416 }
417
418 String String_valueOf( float v ){
419 version(Tango){
420 return tango.text.convert.Float.toString(v);
421 } else { // Phobos
422 implMissing( __FILE__, __LINE__ );
423 return null;
424 }
425 }
426
427 String String_valueOf( double v ){
428 version(Tango){
429 return tango.text.convert.Float.toString(v);
430 } else { // Phobos
431 implMissing( __FILE__, __LINE__ );
432 return null;
433 }
434 }
435
436 String String_valueOf( dchar v ){
437 return dcharToString(v);
438 }
439
440 String String_valueOf( char[] v ){
441 version(D_Version2){
442 return v.idup;
443 } else {
444 return v.dup;
445 }
446 }
447
448 String String_valueOf( char[] v, int offset, int len ){
449 version(D_Version2){
450 return v[ offset .. offset+len ].idup;
451 } else {
452 return v[ offset .. offset+len ].dup;
453 }
454 }
455
456 String String_valueOf( Object v ){
457 return v is null ? "null" : v.toString();
458 }
459
460 String String_valueOf( wchar[] wstr ){
461 version(Tango){
462 return tango.text.convert.Utf.toString(wstr);
463 } else { // Phobos
464 implMissing( __FILE__, __LINE__ );
465 return null;
466 }
467 }
468
469 int length( String str ){
470 return str.length;
471 }
472
473 /// Extension to String
474 public String toUpperCase( String str ){
475 version(Tango){
476 return tango.text.Unicode.toUpper( str );
477 } else { // Phobos
478 implMissing( __FILE__, __LINE__ );
479 return null;
480 }
481 }
482
483 /// Extension to String
484 public String replaceFirst( String str, String regex, String replacement ){
485 implMissing(__FILE__,__LINE__);
486 return str;
487 }
488
489 /// Extension to String
490 public int indexOf( String str, char searched ){
491 version(Tango){
492 int res = tango.text.Util.locate( str, searched );
493 if( res is str.length ) res = -1;
494 return res;
495 } else { // Phobos
496 implMissing( __FILE__, __LINE__ );
497 return 0;
498 }
499 }
500
501 /// Extension to String
502 public int indexOf( String str, char searched, int startpos ){
503 version(Tango){
504 int res = tango.text.Util.locate( str, searched, startpos );
505 if( res is str.length ) res = -1;
506 return res;
507 } else { // Phobos
508 implMissing( __FILE__, __LINE__ );
509 return 0;
510 }
511 }
512
513 /// Extension to String
514 public int indexOf(String str, String ch){
515 return indexOf( str, ch, 0 );
516 }
517
518 /// Extension to String
519 public int indexOf(String str, String ch, int start){
520 version(Tango){
521 int res = tango.text.Util.locatePattern( str, ch, start );
522 if( res is str.length ) res = -1;
523 return res;
524 } else { // Phobos
525 implMissing( __FILE__, __LINE__ );
526 return 0;
527 }
528 }
529
530 /// Extension to String
531 public int lastIndexOf(String str, char ch){
532 return lastIndexOf( str, ch, str.length );
533 }
534
535 /// Extension to String
536 public int lastIndexOf(String str, char ch, int formIndex){
537 version(Tango){
538 int res = tango.text.Util.locatePrior( str, ch, formIndex );
539 if( res is str.length ) res = -1;
540 return res;
541 } else { // Phobos
542 implMissing( __FILE__, __LINE__ );
543 return 0;
544 }
545 }
546
547 /// Extension to String
548 public int lastIndexOf(String str, String ch ){
549 return lastIndexOf( str, ch, str.length );
550 }
551
552 /// Extension to String
553 public int lastIndexOf(String str, String ch, int start ){
554 version(Tango){
555 int res = tango.text.Util.locatePatternPrior( str, ch, start );
556 if( res is str.length ) res = -1;
557 return res;
558 } else { // Phobos
559 implMissing( __FILE__, __LINE__ );
560 return 0;
561 }
562 }
563
564 /// Extension to String
565 public String replaceAll( String str, String regex, String replacement ){
566 implMissing(__FILE__,__LINE__);
567 return null;
568 }
569
570 /// Extension to String
571 public String replace( String str, char from, char to ){
572 version(Tango){
573 return tango.text.Util.replace( str.dup, from, to );
574 } else { // Phobos
575 implMissing( __FILE__, __LINE__ );
576 return null;
577 }
578 }
579
580 /// Extension to String
581 public String substring( String str, int start ){
582 return cast(String)str[ start .. $ ].dup;
583 }
584
585 /// Extension to String
586 public String substring( String str, int start, int end ){
587 return cast(String)str[ start .. end ].dup;
588 }
589
590 /// Extension to String
591 public wchar[] substring( wchar[] str, int start ){
592 return cast(wchar[])(str[ start .. $ ].dup);
593 }
594
595 /// Extension to String
596 public wchar[] substring( wchar[] str, int start, int end ){
597 return str[ start .. end ].dup;
598 }
599
600 /// Extension to String
601 public char charAt( String str, int pos ){
602 return str[ pos ];
603 }
604
605 /// Extension to String
606 public dchar dcharAt( String str, int pos ){
607 return str[ pos .. $ ].firstCodePoint();
608 }
609
610 /// Extension to String
611 public void getChars( String src, int srcBegin, int srcEnd, char[] dst, int dstBegin){
612 dst[ dstBegin .. dstBegin + srcEnd - srcBegin ] = src[ srcBegin .. srcEnd ];
613 }
614
615 /// Extension to String
616 public wchar[] toWCharArray( String str ){
617 version(Tango){
618 return tango.text.convert.Utf.toString16(str);
619 } else { // Phobos
620 implMissing( __FILE__, __LINE__ );
621 return null;
622 }
623 }
624
625 /// Extension to String
626 public char[] toCharArray( String str ){
627 return cast(char[])str;
628 }
629
630 /// Extension to String
631 public bool endsWith( String src, String pattern ){
632 if( src.length < pattern.length ){
633 return false;
634 }
635 return src[ $-pattern.length .. $ ] == pattern;
636 }
637
638 /// Extension to String
639 public bool equals( String src, String other ){
640 return src == other;
641 }
642
643 /// Extension to String
644 public bool equalsIgnoreCase( String src, String other ){
645 version(Tango){
646 return tango.text.Unicode.toFold(src) == tango.text.Unicode.toFold(other);
647 } else { // Phobos
648 implMissing( __FILE__, __LINE__ );
649 return false;
650 }
651 }
652
653 /// Extension to String
654 public int compareToIgnoreCase( String src, String other ){
655 version(Tango){
656 return compareTo( tango.text.Unicode.toFold(src), tango.text.Unicode.toFold(other));
657 } else { // Phobos
658 implMissing( __FILE__, __LINE__ );
659 return 0;
660 }
661 }
662
663 /// Extension to String
664 public int compareTo( String src, String other ){
665 return typeid(String).compare( cast(void*)&src, cast(void*)&other );
666 }
667
668 /// Extension to String
669 public bool startsWith( String src, String pattern ){
670 if( src.length < pattern.length ){
671 return false;
672 }
673 return src[ 0 .. pattern.length ] == pattern;
674 }
675
676 /// Extension to String
677 public String toLowerCase( String src ){
678 version(Tango){
679 return tango.text.Unicode.toLower( src );
680 } else { // Phobos
681 implMissing( __FILE__, __LINE__ );
682 return null;
683 }
684 }
685
686 /// Extension to String
687 public hash_t toHash( String src ){
688 return typeid(String).getHash(&src);
689 }
690
691 /// Extension to String
692 public String trim( String str ){
693 version(Tango){
694 return tango.text.Util.trim( str ).dup;
695 } else { // Phobos
696 implMissing( __FILE__, __LINE__ );
697 return null;
698 }
699 }
700
701 /// Extension to String
702 public String intern( String str ){
703 return str;
704 }
705
706 /++
707 + This is like tango.stdc.stringz.toStringz, but in case of an empty input string,
708 + this function returns a pointer to a null value instead of a null ptr.
709 +/
710 public char* toStringzValidPtr( String src ){
711 if( src ){
712 return src.toStringz();
713 }
714 else{
715 static const char[] nullPtr = "\0";
716 return cast(char*)nullPtr.ptr;
717 }
718 }
719
720 version(Tango){
721 public alias tango.stdc.stringz.toStringz toStringz;
722 public alias tango.stdc.stringz.toString16z toString16z;
723 public alias tango.stdc.stringz.fromStringz fromStringz;
724 public alias tango.stdc.stringz.fromString16z fromString16z;
725 } else { // Phobos
726 public char* toStringz( String s ){
727 implMissing(__FILE__,__LINE__);
728 return null;
729 }
730 public wchar* toString16z( String16 s ){
731 implMissing(__FILE__,__LINE__);
732 return null;
733 }
734 public char[] fromStringz( String s ){
735 implMissing(__FILE__,__LINE__);
736 return null;
737 }
738 public char[] fromString16z( String16 s ){
739 implMissing(__FILE__,__LINE__);
740 return null;
741 }
742 }
743
744 static String toHex(uint value, bool prefix = true, int radix = 8){
745 version(Tango){
746 return tango.text.convert.Integer.toString(
747 value,
748 radix is 10 ? "d" :
749 radix is 8 ? "o" :
750 radix is 16 ? "x" :
751 "d" );
752 } else { // Phobos
753 implMissing( __FILE__, __LINE__ );
754 return null;
755 }
756 }
757
758 /++
759 + String in java is implementing the interface CharSequence
760 +/
761 class StringCharSequence : CharSequence {
762 private String str;
763 this( String str ){
764 this.str = str;
765 }
766 char charAt(int index){
767 return str[index];
768 }
769 int length(){
770 return str.length;
771 }
772 CharSequence subSequence(int start, int end){
773 return new StringCharSequence( str[ start .. end ]);
774 }
775 String toString(){
776 return str;
777 }
778 }
779
780
781