Changeset 685

Show
Ignore:
Timestamp:
05/03/08 12:06:52 (8 months ago)
Author:
andrei
Message:

* Made atoi work with all string types, but also scheduled it for deprecation in favor of to!(int) and parse!(int).

* Made atof work with all string types, but also scheduled it for deprecation in favor of to!(double) and parse!(double) (or real).

* Made cmp and icmp work with strings of all widths

* Changed signature of toStringz to return const(char)*

* Fixed signature of join so it works with immutable arrays

* Added tolowerInPlace, toupperInPlace (these may be changed or removed).

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/phobos/std/string.d

    r675 r685  
    3232//debug=string;     // uncomment to turn on debugging printf's 
    3333 
     34private import std.algorithm; 
    3435private import std.stdio; 
    3536private import std.c.stdio; 
     
    3738private import std.c.string; 
    3839private import std.utf; 
     40private import std.encoding; 
    3941private import std.uni; 
    4042private import std.array; 
     
    9193 
    9294/********************************* 
    93  * Convert string to integer. 
    94  */ 
    95  
    96 long atoi(in string s) 
    97 
    98     return std.c.stdlib.atoi(toStringz(s)); 
     95Convert string $(D s) to integer. $(RED Scheduled for deprecation. Use 
     96the $(D to!(int)(s)) or $(D parse!(int)(s)) routines in $(WEB 
     97std_conv, std.conv)). 
     98 */ 
     99 
     100long atoi(C)(in C[] s) 
     101
     102    return to!(long)(s);//std.c.stdlib.atoi(toStringz(s)); 
    99103} 
    100104 
    101105/************************************* 
    102  * Convert string to real. 
    103  */ 
    104  
    105 real atof(in string s) 
    106 {   char* endptr; 
    107  
    108     auto result = strtold(toStringz(s), &endptr); 
    109     return result; 
     106Convert string to real. $(RED Scheduled for deprecation. Use the $(D 
     107to!(int)(s)) or $(D parse!(int)(s)) routines in $(WEB std_conv, 
     108std.conv)). 
     109 */ 
     110 
     111real atof(C)(in C[] s) 
     112
     113    return parse!(real)(s); 
     114
     115 
     116unittest 
     117
     118    alias TypeTuple!(char, wchar, dchar, 
     119            const char, const wchar, const dchar, 
     120            invariant char, invariant wchar, invariant dchar) 
     121        AllChars; 
     122    foreach (Char; AllChars) 
     123    { 
     124        auto s = to!(Char[])("123"); 
     125        assert(atoi(s) == 123); 
     126    } 
    110127} 
    111128 
     
    120137 */ 
    121138 
    122 int cmp(in char[] s1, in char[] s2) 
    123 
    124     auto len = s1.length; 
    125     int result; 
    126  
    127     //printf("cmp('%.*s', '%.*s')\n", s1, s2); 
    128     if (s2.length < len) 
    129     len = s2.length; 
    130     result = memcmp(s1.ptr, s2.ptr, len); 
    131     if (result == 0) 
    132     result = cast(int)s1.length - cast(int)s2.length; 
    133     return result; 
     139int cmp(C1, C2)(in C1[] s1, in C2[] s2) 
     140
     141    static if (C1.sizeof == C2.sizeof) 
     142    { 
     143        invariant len = min(s1.length, s2.length); 
     144        invariant result = std.c.string.memcmp(s1.ptr, s2.ptr, len); 
     145        return result ? result : cast(int)s1.length - cast(int)s2.length; 
     146    } 
     147    else 
     148    { 
     149        size_t i1, i2; 
     150        for (;;) 
     151        { 
     152            if (i1 == s1.length) return s2.length - i2; 
     153            if (i2 == s2.length) return s1.length - i1; 
     154            invariant c1 = std.utf.decode(s1, i1),  
     155                c2 = std.utf.decode(s2, i2); 
     156            if (c1 != c2) return cast(int) c1 - cast(int) c2; 
     157        }         
     158    } 
    134159} 
    135160 
     
    140165int icmp(in char[] s1, in char[] s2) 
    141166{ 
    142     auto len = s1.length; 
    143     int result; 
    144  
    145     if (s2.length < len) 
    146     len = s2.length; 
    147     version (Win32) 
    148     { 
    149     result = memicmp(s1.ptr, s2.ptr, len); 
    150     } 
    151     version (linux) 
    152     { 
    153     for (size_t i = 0; i < len; i++) 
    154     { 
    155         if (s1[i] != s2[i]) 
    156         { 
    157         char c1 = s1[i]; 
    158         char c2 = s2[i]; 
    159  
    160         if (c1 >= 'A' && c1 <= 'Z') 
    161             c1 += cast(int)'a' - cast(int)'A'; 
    162         if (c2 >= 'A' && c2 <= 'Z') 
    163             c2 += cast(int)'a' - cast(int)'A'; 
    164         result = cast(int)c1 - cast(int)c2; 
    165         if (result) 
    166             break; 
    167         } 
    168     } 
    169     } 
    170     if (result == 0) 
    171     result = cast(int)s1.length - cast(int)s2.length; 
    172     return result; 
     167    size_t i1, i2; 
     168    for (;;) 
     169    { 
     170        if (i1 == s1.length) return i2 - s2.length; 
     171        if (i2 == s2.length) return s1.length - i1; 
     172        auto c1 = std.utf.decode(s1, i1),  
     173            c2 = std.utf.decode(s2, i2); 
     174        if (c1 >= 'A' && c1 <= 'Z') 
     175            c1 += cast(int)'a' - cast(int)'A'; 
     176        if (c2 >= 'A' && c2 <= 'Z') 
     177            c2 += cast(int)'a' - cast(int)'A'; 
     178        if (c1 != c2) return cast(int) c1 - cast(int) c2; 
     179    } 
    173180} 
    174181 
     
    199206 */ 
    200207 
    201 deprecated char* toCharz(in string s) 
     208deprecated const(char)* toCharz(string s) 
    202209{ 
    203210    return toStringz(s); 
     
    209216 */ 
    210217 
    211 char* toStringz(const(char)[] s) 
     218const(char)* toStringz(const(char)[] s) 
    212219    in 
    213220    { 
     
    250257    } 
    251258 
     259// /// Ditto 
     260// const(char)* toStringz(invariant(char)[] s) 
     261// { 
     262//     /* Peek past end of s[], if it's 0, no conversion necessary. 
     263//      * Note that the compiler will put a 0 past the end of static 
     264//      * strings, and the storage allocator will put a 0 past the end 
     265//      * of newly allocated char[]'s. 
     266//      */ 
     267//     invariant p = &s[0] + s.length; 
     268//     if (*p == 0) 
     269//         return s.ptr; 
     270//     return toStringz(cast(const char[]) s); 
     271// } 
     272 
    252273unittest 
    253274{ 
    254275    debug(string) printf("string.toStringz.unittest\n"); 
    255276 
    256     char* p = toStringz("foo"); 
     277    auto p = toStringz("foo"); 
    257278    assert(strlen(p) == 3); 
    258279    const(char) foo[] = "abbzxyzzy"; 
     
    325346int ifind(in char[] s, dchar c) 
    326347{ 
    327     char* p; 
    328  
    329348    if (c <= 0x7F) 
    330349    {   // Plain old ASCII 
     
    865884} 
    866885 
     886/** 
     887   Converts $(D s) to lowercase in place. 
     888 */ 
     889 
     890void tolowerInPlace(C)(ref C[] s) 
     891{ 
     892    for (size_t i = 0; i < s.length; ) 
     893    { 
     894    invariant c = s[i]; 
     895    if ('A' <= c && c <= 'Z') 
     896    { 
     897            s[i++] = cast(C) (c + (cast(C)'a' - 'A')); 
     898    } 
     899    else if (c > 0x7F) 
     900    { 
     901            // wide character 
     902            size_t j = i; 
     903            dchar dc = decode(s, j); 
     904            assert(j > i); 
     905            if (!std.uni.isUniUpper(dc)) 
     906            { 
     907                i = j; 
     908                continue; 
     909            } 
     910            auto toAdd = to!(C[])(std.uni.toUniLower(dc)); 
     911            s = s[0 .. i] ~ toAdd  ~ s[j .. $]; 
     912            i += toAdd.length; 
     913    } 
     914        else 
     915        { 
     916            ++i; 
     917        } 
     918    } 
     919} 
     920 
    867921unittest 
    868922{ 
     
    876930    assert(s2 != s1); 
    877931 
     932    char[] s3 = s1.dup; 
     933    tolowerInPlace(s3); 
     934    assert(s3 == s2, s3); 
     935 
    878936    s1 = "A\u0100B\u0101d"; 
    879937    s2 = tolower(s1); 
     938    s3 = s1.dup; 
    880939    assert(cmp(s2, "a\u0101b\u0101d") == 0); 
    881940    assert(s2 !is s1); 
     941    tolowerInPlace(s3); 
     942    assert(s3 == s2, s3); 
    882943 
    883944    s1 = "A\u0460B\u0461d"; 
    884945    s2 = tolower(s1); 
     946    s3 = s1.dup; 
    885947    assert(cmp(s2, "a\u0461b\u0461d") == 0); 
    886948    assert(s2 !is s1); 
     949    tolowerInPlace(s3); 
     950    assert(s3 == s2, s3); 
    887951 
    888952    s1 = "\u0130"; 
    889953    s2 = tolower(s1); 
     954    s3 = s1.dup; 
    890955    assert(s2 == "i"); 
    891956    assert(s2 !is s1); 
     957    tolowerInPlace(s3); 
     958    assert(s3 == s2, s3); 
    892959} 
    893960 
     
    9411008} 
    9421009 
     1010/** 
     1011   Converts $(D s) to uppercase in place. 
     1012 */ 
     1013 
     1014void toupperInPlace(C)(ref C[] s) 
     1015{ 
     1016    for (size_t i = 0; i < s.length; ) 
     1017    { 
     1018    invariant c = s[i]; 
     1019    if ('a' <= c && c <= 'z') 
     1020    { 
     1021            s[i++] = cast(C) (c - (cast(C)'a' - 'A')); 
     1022    } 
     1023    else if (c > 0x7F) 
     1024    { 
     1025            // wide character 
     1026            size_t j = i; 
     1027            dchar dc = decode(s, j); 
     1028            assert(j > i); 
     1029            if (!std.uni.isUniLower(dc)) 
     1030            { 
     1031                i = j; 
     1032                continue; 
     1033            } 
     1034            auto toAdd = to!(C[])(std.uni.toUniUpper(dc)); 
     1035            s = s[0 .. i] ~ toAdd  ~ s[j .. $]; 
     1036            i += toAdd.length; 
     1037    } 
     1038        else 
     1039        { 
     1040            ++i; 
     1041        } 
     1042    } 
     1043} 
     1044 
    9431045unittest 
    9441046{ 
     
    9471049    string s1 = "FoL"; 
    9481050    string s2; 
     1051    char[] s3; 
    9491052 
    9501053    s2 = toupper(s1); 
     1054    s3 = s1.dup; toupperInPlace(s3); 
     1055    assert(s3 == s2, s3); 
    9511056    assert(cmp(s2, "FOL") == 0); 
    9521057    assert(s2 !is s1); 
     
    9541059    s1 = "a\u0100B\u0101d"; 
    9551060    s2 = toupper(s1); 
     1061    s3 = s1.dup; toupperInPlace(s3); 
     1062    assert(s3 == s2); 
    9561063    assert(cmp(s2, "A\u0100B\u0100D") == 0); 
    9571064    assert(s2 !is s1); 
     
    9591066    s1 = "a\u0460B\u0461d"; 
    9601067    s2 = toupper(s1); 
     1068    s3 = s1.dup; toupperInPlace(s3); 
     1069    assert(s3 == s2); 
    9611070    assert(cmp(s2, "A\u0460B\u0460D") == 0); 
    9621071    assert(s2 !is s1); 
     
    11401249 */ 
    11411250 
    1142 string join(string[] words, string sep) 
     1251string join(in string[] words, string sep) 
    11431252{ 
    11441253    char[] result; 
     
    43354444        continue; 
    43364445    if (c == '-' || c == '_' || c == '?' || 
    4337        c == '=' || c == '%' || c == '&' || 
    4338        c == '/' || c == '+' || c == '#' || 
    4339        c == '~') 
     4446                c == '=' || c == '%' || c == '&' || 
     4447                c == '/' || c == '+' || c == '#' || 
     4448                c == '~') 
    43404449        continue; 
    43414450    if (c == '.') 
     
    43564465} 
    43574466 
    4358 // Undocummented yet 
    4359  
    4360 string stringize(T...)(T args) 
    4361 { 
    4362     string result; 
     4467// Undocumented yet 
     4468 
     4469private S textImpl(S, T...)(T args) 
     4470{ 
     4471    S result; 
    43634472    foreach (arg; args) 
    43644473    { 
    4365         result ~= to!(string)(arg); 
     4474        result ~= to!(S)(arg); 
    43664475    } 
    43674476    return result; 
    43684477} 
     4478 
     4479string text(T...)(T args) { return textImpl!(string, T)(args); } 
     4480wstring wtext(T...)(T args) { return textImpl!(wstring, T)(args); } 
     4481dstring dtext(T...)(T args) { return textImpl!(dstring, T)(args); } 
     4482 
     4483unittest 
     4484{ 
     4485    assert(text(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"); 
     4486    assert(wtext(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"w); 
     4487    assert(dtext(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"d); 
     4488}