Mercurial > projects > dwt2
diff 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 |
line wrap: on
line diff
--- a/base/src/java/lang/String.d Sun Apr 17 17:58:36 2011 +0200 +++ b/base/src/java/lang/String.d Sat Jul 09 15:50:20 2011 +0300 @@ -11,379 +11,21 @@ static import tango.text.Unicode; static import tango.text.convert.Utf; } else { // Phobos - static import core.exception; - static import std.uni; - static import std.utf; static import std.array; static import std.string; static import std.conv; static import std.exception; } -version(Tango){ - public alias char[] String; - public alias char[] CString; - public alias wchar[] String16; - public alias wchar[] CString16; - public alias char* ICharPtr; - public alias char* CCharPtr; - public alias wchar* CWCharPtr; - public alias wchar* IWCharPtr; -} else { // Phobos - public alias string String; - public alias wstring String16; - mixin( - "public alias const(char)[] CString; - public alias const(wchar)[] CString16; - public alias immutable(char)* ICharPtr; - public alias const(char)* CCharPtr; - public alias const(wchar)* CWCharPtr; - public alias immutable(wchar)* IWCharPtr;" - ); -} - -int codepointIndexToIndex( CString str, int cpIndex ){ - int cps = cpIndex; - int res = 0; - while( cps > 0 ){ - cps--; - if( str[res] < 0x80 ){ - res+=1; - } - else if( str[res] < 0xE0 ){ - res+=2; - } - else if( str[res] & 0xF0 ){ - res+=3; - } - else{ - res+=4; - } - } - return res; -} - -/++ -+ -+/ -int indexToCodepointIndex( CString str, int index ){ - if( index < 0 ) return index; - int i = 0; - int res = 0; - while( i < index ){ - if( i >= str.length ){ - break; - } - if( str[i] < 0x80 ){ - i+=1; - } - else if( str[i] < 0xE0 ){ - i+=2; - } - else if( str[i] & 0xF0 ){ - i+=3; - } - else{ - i+=4; - } - res++; - } - return res; -} +alias TryImmutable!(char)[] String; +alias TryImmutable!(wchar)[] String16; -/++ -+ Get that String, that contains the next codepoint of a String. -+/ -String firstCodePointStr( CString str, out int consumed ){ - version(Tango){ - dchar[1] buf; - uint ate; - dchar[] res = tango.text.convert.Utf.toString32( str, buf, &ate ); - consumed = ate; - return str[ 0 .. ate ]; - } else { // Phobos - implMissing( __FILE__, __LINE__ ); - return null; - } -} - -/++ -+ Get first codepoint of a String. If an offset is needed, simply use a slice: -+ --- -+ dchar res = str[ offset .. $ ].firstCodePoint(); -+ --- -+/ -dchar firstCodePoint( CString str ){ - int dummy; - return firstCodePoint( str, dummy ); -} -dchar firstCodePoint( CString str, out int consumed ){ - version(Tango){ - dchar[1] buf; - uint ate; - dchar[] res = tango.text.convert.Utf.toString32( str, buf, &ate ); - consumed = ate; - if( ate is 0 || res.length is 0 ){ - getDwtLogger().trace( __FILE__, __LINE__, "str.length={} str={:X2}", str.length, cast(ubyte[])str ); - } - assert( ate > 0 ); - assert( res.length is 1 ); - return res[0]; - } else { // Phobos - size_t ate = 0; - auto res = std.utf.decode(str, ate); - - if (ate == 0) - getDwtLogger().trace( __FILE__, __LINE__, "str.length={} str={:X2}", str.length, cast(ubyte[])str ); - - assert(ate > 0); - consumed = ate; - - return res; - } -} -dchar firstCodePoint( CString16 str, out int consumed ){ - version(Tango){ - dchar[1] buf; - uint ate; - dchar[] res = tango.text.convert.Utf.toString32( str, buf, &ate ); - consumed = ate; - if( ate is 0 || res.length is 0 ){ - getDwtLogger().trace( __FILE__, __LINE__, "str.length={} str={:X2}", str.length, cast(ubyte[])str ); - } - assert( ate > 0 ); - assert( res.length is 1 ); - return res[0]; - } else { // Phobos - size_t ate = 0; - auto res = std.utf.decode(str, ate); - - if (ate == 0) - getDwtLogger().trace( __FILE__, __LINE__, "str.length={} str={:X2}", str.length, cast(ubyte[])str ); - - assert(ate > 0); - consumed = ate; - - return res; - } -} - -String dcharToString( dchar key ){ - version(Tango){ - dchar[1] buf; - buf[0] = key; - return tango.text.convert.Utf.toString( buf ); - } else { // Phobos - return std.conv.to!(string)(key); - } -} - -int codepointCount( CString str ){ - version(Tango){ - scope dchar[] buf = new dchar[]( str.length ); - uint ate; - dchar[] res = tango.text.convert.Utf.toString32( str, buf, &ate ); - assert( ate is str.length ); - return res.length; - } else { // Phobos - return std.utf.count(str); - } +String new_String( String cont, int offset, int len ){ + return _idup(cont[ offset .. offset+len ]); } -//alias tango.text.convert.Utf.toString16 toString16; -//alias tango.text.convert.Utf.toString toString; - -int toAbsoluteCodePointStartOffset( CString str, int index ){ - //getDwtLogger().trace( __FILE__, __LINE__, "str={}, str.length={}, index={}", str, str.length, index ); - //getDwtLogger().trace( __FILE__, __LINE__, Trace.memory( str ); - if( str.length is index ){ - return index; - } - if( ( str[index] & 0x80 ) is 0x00 ) { - return index; - } - else{ - int steps = 0; - while(( str[index] & 0xC0 ) is 0x80 ){ - index--; - steps++; - if( steps > 3 || index < 0 ){ - break; - } - } - if((( str[index] & 0xE0 ) is 0xC0) && ( steps <= 1 )){ - // ok - } - else if((( str[index] & 0xF0 ) is 0xE0) && ( steps <= 2 )){ - // ok - } - else if((( str[index] & 0xF8 ) is 0xF0) && ( steps <= 3 )){ - // ok - } - else{ - throw new UnicodeException( "invalid utf8 input to toAbsoluteCodePointStartOffset", index ); - } - return index; - } -} -int getRelativeCodePointOffset( CString str, int startIndex, int searchRelCp ){ - return getAbsoluteCodePointOffset( str, startIndex, searchRelCp ) - startIndex; -} -int getAbsoluteCodePointOffset( CString str, int startIndex, int searchRelCp ){ - - //getDwtLogger().trace( __FILE__, __LINE__, "str={}, str.length={}, startIndex={}, searchRelCp={}", str, str.length, startIndex, searchRelCp ); - //getDwtLogger().trace( __FILE__, __LINE__, Trace.memory( str ); - - int ignore; - int i = startIndex; - if( searchRelCp > 0 ){ - while( searchRelCp !is 0 ){ - - if( ( i < str.length ) - && (( str[i] & 0x80 ) is 0x00 )) - { - i+=1; - } - else if( ( i+1 < str.length ) - && (( str[i+1] & 0xC0 ) is 0x80 ) - && (( str[i ] & 0xE0 ) is 0xC0 )) - { - i+=2; - } - else if( ( i+2 < str.length ) - && (( str[i+2] & 0xC0 ) is 0x80 ) - && (( str[i+1] & 0xC0 ) is 0x80 ) - && (( str[i ] & 0xF0 ) is 0xE0 )) - { - i+=3; - } - else if(( i+3 < str.length ) - && (( str[i+3] & 0xC0 ) is 0x80 ) - && (( str[i+2] & 0xC0 ) is 0x80 ) - && (( str[i+1] & 0xC0 ) is 0x80 ) - && (( str[i ] & 0xF8 ) is 0xF0 )) - { - i+=4; - } - else{ - getDwtLogger().trace( __FILE__, __LINE__, "getAbsoluteCodePointOffset invalid utf8 characters: {:X2}", cast(ubyte[]) str ); - throw new UnicodeException( "invalid utf8 input", i ); - } - searchRelCp--; - } - } - else if( searchRelCp < 0 ){ - while( searchRelCp !is 0 ){ - do{ - i--; - if( i < 0 ){ - return startIndex-1; - } - } while(( str[i] & 0xC0 ) is 0x80 ); - searchRelCp++; - } - } - return i; -} -int getAbsoluteCodePointOffset( CString16 str, int startIndex, int searchRelCp ){ - int ignore; - int i = startIndex; - if( searchRelCp > 0 ){ - while( searchRelCp !is 0 ){ - - if( ( i < str.length ) - && ( str[i] & 0xD800 ) !is 0xD800 ) - { - i+=1; - } - else if( ( i+1 < str.length ) - && (( str[i+1] & 0xDC00 ) is 0xDC00 ) - && (( str[i ] & 0xDC00 ) is 0xD800 )) - { - i+=2; - } - else{ - getDwtLogger().trace( __FILE__, __LINE__, "invalid utf16 characters: {:X2}", cast(ubyte[]) str ); - throw new UnicodeException( "invalid utf16 input", i ); - } - searchRelCp--; - } - } - else if( searchRelCp < 0 ){ - while( searchRelCp !is 0 ){ - do{ - i--; - if( i < 0 ){ - return startIndex-1; - //getDwtLogger().trace( __FILE__, __LINE__, "dwthelper.utils getRelativeCodePointOffset {}: str={}, startIndex={}, searchRelCp={}", __LINE__, str, startIndex, searchRelCp ); - //tango.text.convert.Utf.onUnicodeError( "invalid utf16 input", i ); - } - } while(( str[i] & 0xDC00 ) is 0xDC00 ); - searchRelCp++; - } - } - return i; -} -dchar getRelativeCodePoint( CString str, int startIndex, int searchRelCp ){ - int dummy; - return getRelativeCodePoint( str, startIndex, dummy ); -} -dchar getRelativeCodePoint( CString str, int startIndex, int searchRelCp, out int relIndex ){ - relIndex = getRelativeCodePointOffset( str, startIndex, searchRelCp ); - int ignore; - return firstCodePoint( str[ startIndex+relIndex .. $ ], ignore ); -} - -int utf8AdjustOffset( CString str, int offset ){ - if( str.length <= offset || offset <= 0 ){ - return offset; - } - while(( str[offset] & 0xC0 ) is 0x80 ){ - offset--; - } - return offset; -} -int utf8OffsetIncr( CString str, int offset ){ - int res = offset +1; - if( str.length <= res || res <= 0 ){ - return res; - } - int tries = 4; - while(( str[res] & 0xC0 ) is 0x80 ){ - res++; - assert( tries-- > 0 ); - } - return res; -} -int utf8OffsetDecr( CString str, int offset ){ - int res = offset-1; - if( str.length <= res || res <= 0 ){ - return res; - } - int tries = 4; - while(( str[res] & 0xC0 ) is 0x80 ){ - res--; - assert( tries-- > 0 ); - } - getDwtLogger().trace( __FILE__, __LINE__, "utf8OffsetDecr {}->{}", offset, res ); - getDwtLogger().trace( __FILE__, __LINE__, "{}", str ); - return res; -} - -String new_String( CString cont, int offset, int len ){ - version(D_Version2){ - return cont[ offset .. offset+len ].idup; - } else { - return cont[ offset .. offset+len ].dup; - } -} - -String new_String( CString cont ){ - version(D_Version2){ - return cont.idup; - } else { - return cont.dup; - } +String new_String( String cont ){ + return _idup(cont); } String String_valueOf( bool v ){ @@ -391,38 +33,19 @@ } String String_valueOf( byte v ){ - version(Tango){ - return tango.text.convert.Integer.toString(v); - } else { // Phobos - implMissing( __FILE__, __LINE__ ); - return null; - } + return String_valueOf( cast(long) v ); } String String_valueOf( ubyte v ){ - version(Tango){ - return tango.text.convert.Integer.toString(v); - } else { // Phobos - implMissing( __FILE__, __LINE__ ); - return null; - } + return String_valueOf( cast(uint) v ); } String String_valueOf( short v ){ - version(Tango){ - return tango.text.convert.Integer.toString(v); - } else { // Phobos - implMissing( __FILE__, __LINE__ ); - return null; - } + return String_valueOf( cast(long) v ); } String String_valueOf( int v ){ - version(Tango){ - return tango.text.convert.Integer.toString(v); - } else { // Phobos - return std.conv.to!(String)(v); - } + return String_valueOf( cast(long) v ); } String String_valueOf( uint v ){ @@ -458,30 +81,31 @@ } String String_valueOf( dchar v ){ - return dcharToString(v); + version(Tango){ + dchar[1] buf = v; + return tango.text.convert.Utf.toString( buf ); + } else { // Phobos + return std.conv.to!(String)(v); + } +} + +String dcharToString( dchar v ){ + return String_valueOf(v); } String String_valueOf( char[] v ){ - version(D_Version2){ - return v.idup; - } else { - return v.dup; - } + return _idup(v); } String String_valueOf( char[] v, int offset, int len ){ - version(D_Version2){ - return v[ offset .. offset+len ].idup; - } else { - return v[ offset .. offset+len ].dup; - } + return _idup(v[ offset .. offset+len ]); } String String_valueOf( Object v ){ return v is null ? "null" : v.toString(); } -String String_valueOf( CString16 wstr ){ +String String_valueOf( in wchar[] wstr ){ version(Tango){ return tango.text.convert.Utf.toString(wstr); } else { // Phobos @@ -489,152 +113,270 @@ } } -int length( CString str ){ +int length( String str ){ return str.length; } /// Extension to String -public String toUpperCase( CString str ){ +public String toUpperCase( String str ){ version(Tango){ return tango.text.Unicode.toUpper( str ); } else { // Phobos - implMissing( __FILE__, __LINE__ ); - return null; + return cast(String) std.string.toupper( str ); } } /// Extension to String -public String replaceFirst( CString str, CString regex, CString replacement ){ +public String replaceFirst( String str, String regex, String replacement ){ implMissing(__FILE__,__LINE__); return null; } +version(Tango) int tangoToJavaIdx(T)(int idx, T[] arr) { + return idx is arr.length ? -1 : idx; +} + /// Extension to String -public int indexOf( CString str, char searched ){ +public int indexOf( in char[] str, char searched ){ version(Tango){ - int res = tango.text.Util.locate( str, searched ); - if( res is str.length ) res = -1; - return res; + return tangoToJavaIdx(tango.text.Util.locate( str, searched ), str); } else { // Phobos return std.string.indexOf(str, searched); } } /// Extension to String -public int indexOf( CString str, char searched, int startpos ){ +public int indexOf( in char[] str, char searched, int fromIndex ){ + if(fromIndex >= str.length) + return -1; version(Tango){ - int res = tango.text.Util.locate( str, searched, startpos ); - if( res is str.length ) res = -1; + return tangoToJavaIdx(tango.text.Util.locate( str, searched, fromIndex ), str); + } else { // Phobos + int res = std.string.indexOf(str[fromIndex .. $], searched); + if (res !is -1) res += fromIndex; return res; + } +} + +/// Extension to String +public int indexOf(in char[] str, in char[] sub){ + return indexOf( str, sub, 0 ); +} + +/// Extension to String +public int indexOf(in char[] str, in char[] sub, int fromIndex){ + if(fromIndex + sub.length > str.length) + return -1; + if(!sub.length) + return fromIndex; + version(Tango){ + return tangoToJavaIdx(tango.text.Util.locatePattern( str, sub, fromIndex ), str); } else { // Phobos - int res = std.string.indexOf(str[startpos .. $], searched); - if (res !is -1) res += startpos; + int res = std.string.indexOf(str[fromIndex .. $], sub); + if (res !is -1) res += fromIndex; return res; } } /// Extension to String -public int indexOf(CString str, String ch){ - return indexOf( str, ch, 0 ); +public int lastIndexOf(in char[] str, char ch){ + return lastIndexOf( str, ch, str.length - 1 ); } /// Extension to String -public int indexOf(CString str, String ch, int start){ +public int lastIndexOf(in char[] str, char ch, int fromIndex){ + if(fromIndex >= str.length) + fromIndex = str.length - 1; version(Tango){ - int res = tango.text.Util.locatePattern( str, ch, start ); - if( res is str.length ) res = -1; - return res; + return tangoToJavaIdx(tango.text.Util.locatePrior( str, ch, fromIndex + 1 ), str); } else { // Phobos - return std.string.indexOf(str[start .. $], ch); + return std.string.lastIndexOf(str[0 .. fromIndex + 1], ch); } } /// Extension to String -public int lastIndexOf(CString str, char ch){ - return lastIndexOf( str, ch, str.length ); -} - -/// Extension to String -public int lastIndexOf(CString str, char ch, int formIndex){ - version(Tango){ - int res = tango.text.Util.locatePrior( str, ch, formIndex ); - if( res is str.length ) res = -1; - return res; - } else { // Phobos - return std.string.lastIndexOf(str[0 .. formIndex], ch); - } +public int lastIndexOf(in char[] str, in char[] sub ){ + return lastIndexOf( str, sub, str.length - sub.length ); } /// Extension to String -public int lastIndexOf(CString str, String ch ){ - return lastIndexOf( str, ch, str.length ); +public int lastIndexOf(in char[] str, in char[] sub, int fromIndex){ + int max = cast(int)str.length - cast(int)sub.length; + if(fromIndex > max) + fromIndex = max; + if(!sub.length) + return fromIndex; + version(Tango){ + return tangoToJavaIdx(tango.text.Util.locatePatternPrior( str, sub, fromIndex + 1 ), str); + } else { // Phobos + size_t to = fromIndex + sub.length; + return std.string.lastIndexOf(str[0 .. to < $ ? to : $], sub); + } +} + +unittest { + sizediff_t i; + + i = lastIndexOf("", 'a'); + assert(i == -1); + i = lastIndexOf("def", 'a'); + assert(i == -1); + i = lastIndexOf("abba", 'a'); + assert(i == 3); + i = lastIndexOf("abba", 'a', 0); + assert(i == 0); + i = lastIndexOf("abba", 'a', 1); + assert(i == 0); + i = lastIndexOf("abba", 'a', 2); + assert(i == 0); + i = lastIndexOf("abba", 'a', 3); + assert(i == 3); + i = lastIndexOf("abba", 'a', 4); + assert(i == 3); + i = lastIndexOf("abba", 'a', 10); + assert(i == 3); + i = lastIndexOf("def", 'f'); + assert(i == 2); + + i = lastIndexOf("", "a"); + assert(i == -1); + i = lastIndexOf("", ""); + assert(i == 0); + i = lastIndexOf("abcdefcdef", "c"); + assert(i == 6); + i = lastIndexOf("abcdefcdef", "cd"); + assert(i == 6); + i = lastIndexOf("abcdefcdef", "cd", 5); + assert(i == 2); + i = lastIndexOf("abcdefcdef", "cd", 6); + assert(i == 6); + i = lastIndexOf("abcdefcdef", "cd", 7); + assert(i == 6); + i = lastIndexOf("abcdefcdef", "cd", 10); + assert(i == 6); + i = lastIndexOf("abcdefcdef", "x"); + assert(i == -1); + i = lastIndexOf("abcdefcdef", "xy"); + assert(i == -1); + i = lastIndexOf("abcdefcdef", ""); + assert(i == 10); + i = lastIndexOf("abcdefcdef", "", 9); + assert(i == 9); + i = lastIndexOf("abcabc", "abc"); + assert(i == 3); + i = lastIndexOf("abcabc", "abc", 2); + assert(i == 0); + i = lastIndexOf("abcabc", "abc", 3); + assert(i == 3); + i = lastIndexOf("abcabc", "abc", 4); + assert(i == 3); + + + + i = indexOf("", 'a'); + assert(i == -1); + i = indexOf("def", 'a'); + assert(i == -1); + i = indexOf("abba", 'a'); + assert(i == 0); + i = indexOf("abba", 'a', 0); + assert(i == 0); + i = indexOf("abba", 'a', 1); + assert(i == 3); + i = indexOf("abba", 'a', 2); + assert(i == 3); + i = indexOf("abba", 'a', 3); + assert(i == 3); + i = indexOf("abba", 'a', 4); + assert(i == -1); + i = indexOf("abba", 'a', 10); + assert(i == -1); + i = indexOf("def", 'f'); + assert(i == 2); + + i = indexOf("", "a"); + assert(i == -1); + i = indexOf("", ""); + assert(i == 0); + i = indexOf("abcdefcdef", "c"); + assert(i == 2); + i = indexOf("abcdefcdef", "cd"); + assert(i == 2); + i = indexOf("abcdefcdef", "cd", 4); + assert(i == 6); + i = indexOf("abcdefcdef", "cd", 5); + assert(i == 6); + i = indexOf("abcdefcdef", "cd", 6); + assert(i == 6); + i = indexOf("abcdefcdef", "cd", 7); + assert(i == -1); + i = indexOf("abcdefcdef", "cd", 10); + assert(i == -1); + i = indexOf("abcdefcdef", "x"); + assert(i == -1); + i = indexOf("abcdefcdef", "xy"); + assert(i == -1); + i = indexOf("abcdefcdef", ""); + assert(i == 0); + i = indexOf("abcabc", "abc"); + assert(i == 0); + i = indexOf("abcabc", "abc", 2); + assert(i == 3); + i = indexOf("abcabc", "abc", 3); + assert(i == 3); + i = indexOf("abcabc", "abc", 4); + assert(i == -1); } /// Extension to String -public int lastIndexOf(CString str, String ch, int start ){ - version(Tango){ - int res = tango.text.Util.locatePatternPrior( str, ch, start ); - if( res is str.length ) res = -1; - return res; - } else { // Phobos - implMissing( __FILE__, __LINE__ ); - return 0; - } -} - -/// Extension to String -public String replaceAll( CString str, String regex, String replacement ){ +public String replaceAll( String str, String regex, String replacement ){ implMissing(__FILE__,__LINE__); return null; } /// Extension to String -public String replace( CString str, char from, char to ){ +public String replace( String str, char from, char to ){ version(Tango){ return tango.text.Util.replace( str.dup, from, to ); } else { // Phobos - auto res = std.array.replace(str, [from], [to]); + char[1] f = from, t = to; + auto res = std.array.replace(str, f[], t[]); return std.exception.assumeUnique(res); } } /// Extension to String -public String substring( CString str, int start ){ - return cast(String)str[ start .. $ ].dup; +public String substring( String str, int start ){ + return _idup(str[ start .. $ ]); } /// Extension to String -public String substring( CString str, int start, int end ){ - return cast(String)str[ start .. end ].dup; +public String substring( String str, int start, int end ){ + return _idup(str[ start .. end ]); } /// Extension to String -public wchar[] substring( CString16 str, int start ){ - return cast(wchar[])(str[ start .. $ ].dup); +public wchar[] substring( String16 str, int start ){ + return str[ start .. $ ].dup; } /// Extension to String -public wchar[] substring( CString16 str, int start, int end ){ +public wchar[] substring( String16 str, int start, int end ){ return str[ start .. end ].dup; } /// Extension to String -public char charAt( CString str, int pos ){ +public char charAt( String str, int pos ){ return str[ pos ]; } /// Extension to String -public dchar dcharAt( CString str, int pos ){ - return str[ pos .. $ ].firstCodePoint(); -} - -/// Extension to String public void getChars( String src, int srcBegin, int srcEnd, char[] dst, int dstBegin){ dst[ dstBegin .. dstBegin + srcEnd - srcBegin ] = src[ srcBegin .. srcEnd ]; } /// Extension to String -public String16 toWCharArray( CString str ){ +public String16 toWCharArray( in char[] str ){ version(Tango){ return tango.text.convert.Utf.toString16(str); } else { // Phobos @@ -643,12 +385,12 @@ } /// Extension to String -public char[] toCharArray( CString str ){ +public char[] toCharArray( String str ){ return cast(char[])str; } /// Extension to String -public bool endsWith( CString src, CString pattern ){ +public bool endsWith( String src, String pattern ){ if( src.length < pattern.length ){ return false; } @@ -656,37 +398,55 @@ } /// Extension to String -public bool equals( CString src, CString other ){ +public bool equals( in char[] src, in char[] other ){ return src == other; } /// Extension to String -public bool equalsIgnoreCase( CString src, CString other ){ - version(Tango){ - return tango.text.Unicode.toFold(src) == tango.text.Unicode.toFold(other); +public bool equalsIgnoreCase( in char[] src, in char[] other ){ + version(Tango) { + if(src.length != other.length) + return false; + String s1b = new char[ src.length * 2 ]; //*2, or Tango may reallocate buffers + String s2b = new char[ other.length * 2 ]; + scope(exit) { + delete s1b; + delete s2b; + } + return tango.text.Unicode.toFold( src, s1b ) == + tango.text.Unicode.toFold( other, s2b ); } else { // Phobos - implMissing( __FILE__, __LINE__ ); - return false; + return std.string.icmp(src, other) == 0; } } /// Extension to String -public int compareToIgnoreCase( CString src, CString other ){ +public int compareToIgnoreCase( in char[] src, in char[] other ){ version(Tango){ - return compareTo( tango.text.Unicode.toFold(src), tango.text.Unicode.toFold(other)); + String s1b = new char[ src.length * 2 ]; //*2, or Tango may reallocate buffers + String s2b = new char[ other.length * 2 ]; + scope(exit) { + delete s1b; + delete s2b; + } + return compareTo( tango.text.Unicode.toFold(src, s1b), + tango.text.Unicode.toFold(other, s2b)); } else { // Phobos - implMissing( __FILE__, __LINE__ ); - return 0; + return std.string.icmp(src, other); } } /// Extension to String -public int compareTo( CString src, CString other ){ - return typeid(String).compare( cast(void*)&src, cast(void*)&other ); +public int compareTo( in char[] src, in char[] other ){ + version(Tango){ + return typeid(String).compare( cast(void*)&src, cast(void*)&other ); + } else { // Phobos + return std.string.cmp(src, other); + } } /// Extension to String -public bool startsWith( CString src, CString pattern ){ +public bool startsWith( String src, String pattern ){ if( src.length < pattern.length ){ return false; } @@ -694,23 +454,22 @@ } /// Extension to String -public String toLowerCase( CString src ){ +public String toLowerCase( String src ){ version(Tango){ return tango.text.Unicode.toLower( src ); } else { // Phobos - implMissing( __FILE__, __LINE__ ); - return null; + return cast(String) std.string.tolower(src); } } /// Extension to String -public hash_t toHash( CString src ){ +public hash_t toHash( String src ){ return typeid(String).getHash(&src); } public alias toHash String_toHash; /// Extension to String -public String trim( CString str ){ +public String trim( String str ){ version(Tango){ return tango.text.Util.trim( str ).dup; } else { // Phobos @@ -719,22 +478,8 @@ } /// Extension to String -public String intern( CString str ){ - return str._idup(); -} - -/++ - + This is like tango.stdc.stringz.toStringz, but in case of an empty input string, - + this function returns a pointer to a null value instead of a null ptr. - +/ -public char* toStringzValidPtr( CString src ){ - if( src ){ - return src.toStringz(); - } - else{ - static const char[] nullPtr = "\0"; - return cast(char*)nullPtr.ptr; - } +public String intern( String str ){ + return _idup(str); } version(Tango){ @@ -742,60 +487,67 @@ public alias tango.stdc.stringz.toString16z toString16z; public alias tango.stdc.stringz.fromStringz fromStringz; public alias tango.stdc.stringz.fromString16z fromString16z; -} else { // Phobos - public char* toStringz( CString s ){ - if (s.ptr) { - if (s.length == 0) - return "\0".dup.ptr; - - else - return (s ~ "\0").dup.ptr; + + /++ + + This is like tango.stdc.stringz.toStringz, but in case of an empty input string, + + this function returns a pointer to a null value instead of a null ptr. + +/ + public char* toStringzValidPtr( String src ){ + if( src ){ + return src.toStringz(); } - - return null; - } - public wchar* toString16z( CString16 s ){ - if (s.ptr) { - if (s.length == 0) - return "\0"w.dup.ptr; - - else - return (s ~ "\0"w).dup.ptr; + else{ + return "".ptr; } - - return null; + } +} else { // Phobos + static import std.c.string; + + public char* toStringzValidPtr( in char[] s ) { + auto copy = new char[s.length + 1]; + copy[0..s.length] = s; + copy[s.length] = 0; + return copy.ptr; + } + + public char* toStringz( in char[] s ) { + return s is null ? null : toStringzValidPtr(s); + } + + public char[] fromStringz( in char* s ){ + return s ? s[0 .. std.c.string.strlen(s)].dup : cast(char[])null; } - public char[] fromStringz( CCharPtr s ){ - size_t len; - - if (s) - while (*s++) - len++; - - return s[0 .. len].dup; + /*public string fromStringz( in char* s ){ + return std.conv.to!(string)(s); + }*/ + + private size_t w_strlen(in wchar* s) { + size_t res = 0; + while(*(s+res)) + ++res; + return res; } - public wchar[] fromString16z( CWCharPtr s ){ - size_t len; - - if (s) - while (*s++) - len++; - - return s[0 .. len].dup; + + public wchar* toString16z( in wchar[] s ){ + if(s is null) + return null; + auto copy = new wchar[s.length + 1]; + copy[0..s.length] = s; + copy[s.length] = 0; + return copy.ptr; + } + + //Copy of std.conv.toImpl(T, S)(S s) for C-style strings + public wstring fromString16z( in wchar* s ){ + return s ? s[0 .. w_strlen(s)].idup : cast(wstring)null; } } -static String toHex(uint value, bool prefix = true, int radix = 8){ +static String toHex(uint i){ version(Tango){ - return tango.text.convert.Integer.toString( - value, - radix is 10 ? "d" : - radix is 8 ? "o" : - radix is 16 ? "x" : - "d" ); + return tango.text.convert.Integer.toString(i, "x"); } else { // Phobos - implMissing( __FILE__, __LINE__ ); - return null; + return std.conv.to!(String)(i, 16); } } @@ -807,16 +559,16 @@ this( String str ){ this.str = str; } - char charAt(int index){ + char charAt(int index){ return str[index]; } - int length(){ + int length(){ return str.length; } - CharSequence subSequence(int start, int end){ + CharSequence subSequence(int start, int end){ return new StringCharSequence( str[ start .. end ]); } - String toString(){ + String toString(){ return str; } } @@ -831,5 +583,3 @@ } } - -