1 module java.lang.String; 2 3 import java.lang.util; 4 import java.lang.interfaces; 5 import java.lang.exceptions; 6 import java.lang.Class; 7 8 version(Tango){ 9 static import tango.stdc.stringz; 10 static import tango.text.Util; 11 static import tango.text.Unicode; 12 static import tango.text.convert.Utf; 13 } else { // Phobos 14 static import std.array; 15 static import std..string; 16 static import std.conv; 17 static import std.exception; 18 } 19 20 alias TryImmutable!(char)[] String; 21 alias TryImmutable!(wchar)[] String16; 22 23 String new_String( String cont, int offset, int len ){ 24 return _idup(cont[ offset .. offset+len ]); 25 } 26 27 String new_String( String cont ){ 28 return _idup(cont); 29 } 30 31 String String_valueOf( bool v ){ 32 return v ? "true" : "false"; 33 } 34 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 ){ 52 version(Tango){ 53 return tango.text.convert.Integer.toString(v); 54 } else { // Phobos 55 return std.conv.to!(String)(v); 56 } 57 } 58 59 String String_valueOf( long v ){ 60 version(Tango){ 61 return tango.text.convert.Integer.toString(v); 62 } else { // Phobos 63 return std.conv.to!(String)(v); 64 } 65 } 66 67 String String_valueOf( float v ){ 68 version(Tango){ 69 return tango.text.convert.Float.toString(v); 70 } else { // Phobos 71 return std.conv.to!(String)(v); 72 } 73 } 74 75 String String_valueOf( double v ){ 76 version(Tango){ 77 return tango.text.convert.Float.toString(v); 78 } else { // Phobos 79 return std.conv.to!(String)(v); 80 } 81 } 82 83 String String_valueOf( dchar v ){ 84 version(Tango){ 85 dchar[1] buf = v; 86 return tango.text.convert.Utf.toString( buf ); 87 } else { // Phobos 88 return std.conv.to!(String)(v); 89 } 90 } 91 92 String dcharToString( dchar v ){ 93 return String_valueOf(v); 94 } 95 96 String String_valueOf( char[] v ){ 97 return _idup(v); 98 } 99 100 String String_valueOf( char[] v, int offset, int len ){ 101 return _idup(v[ offset .. offset+len ]); 102 } 103 104 String String_valueOf( Object v ){ 105 return v is null ? "null" : v.toString(); 106 } 107 108 String String_valueOf( in wchar[] wstr ){ 109 version(Tango){ 110 return tango.text.convert.Utf.toString(wstr); 111 } else { // Phobos 112 return std.conv.to!(String)(wstr); 113 } 114 } 115 116 int length( String str ){ 117 return cast(int)/*64bit*/str.length; 118 } 119 120 /// Extension to String 121 public String toUpperCase( String str ){ 122 version(Tango){ 123 return tango.text.Unicode.toUpper( str ); 124 } else { // Phobos 125 return cast(String) std..string.toUpper( str ); 126 } 127 } 128 129 /// Extension to String 130 public String replaceFirst( String str, String regex, String replacement ){ 131 implMissing(__FILE__,__LINE__); 132 return null; 133 } 134 135 version(Tango) int tangoToJavaIdx(T)(int idx, T[] arr) { 136 return idx is arr.length ? -1 : idx; 137 } 138 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 cast(int)/*64bit*/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 = cast(int)/*64bit*/std..string.indexOf(str[fromIndex .. $], searched); 156 if (res !is -1) res += fromIndex; 157 return res; 158 } 159 } 160 161 /// Extension to String 162 public int indexOf(in char[] str, in char[] sub){ 163 return indexOf( str, sub, 0 ); 164 } 165 166 /// Extension to String 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 = cast(int)/*64bit*/std..string.indexOf(str[fromIndex .. $], sub); 176 if (res !is -1) res += fromIndex; 177 return res; 178 } 179 } 180 181 /// Extension to String 182 public int lastIndexOf(in char[] str, char ch){ 183 return lastIndexOf( str, ch, cast(int)/*64bit*/str.length - 1 ); 184 } 185 186 /// Extension to String 187 public int lastIndexOf(in char[] str, char ch, int fromIndex){ 188 if(fromIndex >= str.length) 189 fromIndex = cast(int)/*64bit*/str.length - 1; 190 version(Tango){ 191 return tangoToJavaIdx(tango.text.Util.locatePrior( str, ch, fromIndex + 1 ), str); 192 } else { // Phobos 193 return cast(int)/*64bit*/std..string.lastIndexOf(str[0 .. fromIndex + 1], ch); 194 } 195 } 196 197 /// Extension to String 198 public int lastIndexOf(in char[] str, in char[] sub ){ 199 return lastIndexOf( str, sub, cast(int)/*64bit*/(str.length - sub.length) ); 200 } 201 202 /// Extension to String 203 public int lastIndexOf(in char[] str, in char[] sub, int fromIndex){ 204 int max = cast(int)str.length - cast(int)sub.length; 205 if(fromIndex > max) 206 fromIndex = max; 207 if(!sub.length) 208 return fromIndex; 209 version(Tango){ 210 return tangoToJavaIdx(tango.text.Util.locatePatternPrior( str, sub, fromIndex + 1 ), str); 211 } else { // Phobos 212 size_t to = fromIndex + sub.length; 213 return cast(int)/*64bit*/std..string.lastIndexOf(str[0 .. to < $ ? to : $], sub); 214 } 215 } 216 217 unittest { 218 sizediff_t i; 219 220 i = lastIndexOf("", 'a'); 221 assert(i == -1); 222 i = lastIndexOf("def", 'a'); 223 assert(i == -1); 224 i = lastIndexOf("abba", 'a'); 225 assert(i == 3); 226 i = lastIndexOf("abba", 'a', 0); 227 assert(i == 0); 228 i = lastIndexOf("abba", 'a', 1); 229 assert(i == 0); 230 i = lastIndexOf("abba", 'a', 2); 231 assert(i == 0); 232 i = lastIndexOf("abba", 'a', 3); 233 assert(i == 3); 234 i = lastIndexOf("abba", 'a', 4); 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 ){ 333 implMissing(__FILE__,__LINE__); 334 return null; 335 } 336 337 /// Extension to String 338 public String replace( String str, char from, char to ){ 339 version(Tango){ 340 return tango.text.Util.replace( str.dup, from, to ); 341 } else { // Phobos 342 char[1] f = from, t = to; 343 auto res = std.array.replace(str, f[], t[]); 344 return std.exception.assumeUnique(res); 345 } 346 } 347 348 /// Extension to String 349 public String substring( String str, int start ){ 350 return _idup(str[ start .. $ ]); 351 } 352 353 /// Extension to String 354 public String substring( String str, int start, int end ){ 355 return _idup(str[ start .. end ]); 356 } 357 358 /// Extension to String 359 public wchar[] substring( String16 str, int start ){ 360 return str[ start .. $ ].dup; 361 } 362 363 /// Extension to String 364 public wchar[] substring( String16 str, int start, int end ){ 365 return str[ start .. end ].dup; 366 } 367 368 /// Extension to String 369 public char charAt( String str, int pos ){ 370 return str[ pos ]; 371 } 372 373 /// Extension to String 374 public void getChars( String src, int srcBegin, int srcEnd, char[] dst, int dstBegin){ 375 dst[ dstBegin .. dstBegin + srcEnd - srcBegin ] = src[ srcBegin .. srcEnd ]; 376 } 377 378 /// Extension to String 379 public String16 toWCharArray( in char[] str ){ 380 version(Tango){ 381 return tango.text.convert.Utf.toString16(str); 382 } else { // Phobos 383 return std.conv.to!(String16)(str); 384 } 385 } 386 387 /// Extension to String 388 public char[] toCharArray( String str ){ 389 return cast(char[])str; 390 } 391 392 /// Extension to String 393 public bool endsWith( String src, String pattern ){ 394 if( src.length < pattern.length ){ 395 return false; 396 } 397 return src[ $-pattern.length .. $ ] == pattern; 398 } 399 400 /// Extension to String 401 public bool equals( in char[] src, in char[] other ){ 402 return src == other; 403 } 404 405 /// Extension to String 406 public bool equalsIgnoreCase( in char[] src, in char[] other ){ 407 version(Tango) { 408 static assert(false, "Not implemented"); 409 } else { // Phobos 410 return std..string.icmp(src, other) == 0; 411 } 412 } 413 414 /// Extension to String 415 public int compareToIgnoreCase( in char[] src, in char[] other ){ 416 version(Tango){ 417 static assert(false, "Not implemented"); 418 } else { // Phobos 419 return std..string.icmp(src, other); 420 } 421 } 422 423 /// Extension to String 424 public int compareTo( in char[] src, in char[] other ){ 425 version(Tango){ 426 return typeid(String).compare( cast(void*)&src, cast(void*)&other ); 427 } else { // Phobos 428 return std..string.cmp(src, other); 429 } 430 } 431 432 /// Extension to String 433 public bool startsWith( String src, String pattern ){ 434 if( src.length < pattern.length ){ 435 return false; 436 } 437 return src[ 0 .. pattern.length ] == pattern; 438 } 439 440 /// Extension to String 441 public String toLowerCase( String src ){ 442 version(Tango){ 443 return tango.text.Unicode.toLower( src ); 444 } else { // Phobos 445 return cast(String) std..string.toLower(src); 446 } 447 } 448 449 /// Extension to String 450 version(Tango){ 451 public hash_t toHash( String src ){ 452 return typeid(String).getHash(&src); 453 } 454 } else { // Phobos 455 mixin(`@safe nothrow public hash_t toHash( String src ){ 456 // http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#hashCode%28%29 457 hash_t hash = 0; 458 foreach( i, c; src ){ 459 hash += c * 31 ^ (src.length - 1 - i); 460 } 461 return hash; 462 }`); 463 } 464 public alias toHash String_toHash; 465 466 /// Extension to String 467 public String trim( String str ){ 468 version(Tango){ 469 return tango.text.Util.trim( str ).dup; 470 } else { // Phobos 471 return std..string.strip( str.idup ); 472 } 473 } 474 475 /// Extension to String 476 public String intern( String str ){ 477 return _idup(str); 478 } 479 480 version(Tango){ 481 public alias tango.stdc.stringz.toStringz toStringz; 482 public alias tango.stdc.stringz.toString16z toString16z; 483 public alias tango.stdc.stringz.fromStringz fromStringz; 484 public alias tango.stdc.stringz.fromString16z fromString16z; 485 486 /++ 487 + This is like tango.stdc.stringz.toStringz, but in case of an empty input string, 488 + this function returns a pointer to a null value instead of a null ptr. 489 +/ 490 public char* toStringzValidPtr( String src ){ 491 if( src ){ 492 return src.toStringz(); 493 } 494 else{ 495 return "".ptr; 496 } 497 } 498 } else { // Phobos 499 static import core.stdc..string; 500 501 public char* toStringzValidPtr( in char[] s ) { 502 auto copy = new char[s.length + 1]; 503 copy[0..s.length] = s; 504 copy[s.length] = 0; 505 return copy.ptr; 506 } 507 508 public char* toStringz( in char[] s ) { 509 return s is null ? null : toStringzValidPtr(s); 510 } 511 512 public char[] fromStringz( in char* s ){ 513 return s ? s[0 .. core.stdc..string.strlen(s)].dup : cast(char[])null; 514 } 515 /*public string fromStringz( in char* s ){ 516 return std.conv.to!(string)(s); 517 }*/ 518 519 private size_t w_strlen(in wchar* s) { 520 size_t res = 0; 521 while(*(s+res)) 522 ++res; 523 return res; 524 } 525 526 public wchar* toString16z( in wchar[] s ){ 527 if(s is null) 528 return null; 529 auto copy = new wchar[s.length + 1]; 530 copy[0..s.length] = s; 531 copy[s.length] = 0; 532 return copy.ptr; 533 } 534 535 //Copy of std.conv.toImpl(T, S)(S s) for C-style strings 536 public wstring fromString16z( in wchar* s ){ 537 return s ? s[0 .. w_strlen(s)].idup : cast(wstring)null; 538 } 539 } 540 541 static String toHex(uint i){ 542 version(Tango){ 543 return tango.text.convert.Integer.toString(i, "x"); 544 } else { // Phobos 545 return std.conv.to!(String)(i, 16); 546 } 547 } 548 549 /++ 550 + String in java is implementing the interface CharSequence 551 +/ 552 class StringCharSequence : CharSequence { 553 private String str; 554 this( String str ){ 555 this.str = str; 556 } 557 char charAt(int index){ 558 return str[index]; 559 } 560 int length(){ 561 return cast(int)/*64bit*/str.length; 562 } 563 CharSequence subSequence(int start, int end){ 564 return new StringCharSequence( str[ start .. end ]); 565 } 566 override 567 String toString(){ 568 return str; 569 } 570 } 571 572 class StringCls { 573 private static Class TYPE_; 574 public static Class TYPE(){ 575 if( TYPE_ is null ){ 576 TYPE_ = Class.fromType!(char[]); 577 } 578 return TYPE_; 579 } 580 581 }