Wolfgang Thallergcc16 merge934c3885 months agoHistory
7323 lines · 219.1 KB · D
RawDownload
// Written in the D programming language. /**String handling functions. $(SCRIPT inhibitQuickIndex = 1;) $(DIVC quickindex,$(BOOKTABLE ,$(TR $(TH Category) $(TH Functions) )$(TR $(TDNW Searching)    $(TD         $(MYREF column)         $(MYREF indexOf)         $(MYREF indexOfAny)         $(MYREF indexOfNeither)         $(MYREF lastIndexOf)         $(MYREF lastIndexOfAny)         $(MYREF lastIndexOfNeither)    ))$(TR $(TDNW Comparison)    $(TD         $(MYREF isNumeric)    ))$(TR $(TDNW Mutation)    $(TD         $(MYREF capitalize)    ))$(TR $(TDNW Pruning and Filling)    $(TD         $(MYREF center)         $(MYREF chomp)         $(MYREF chompPrefix)         $(MYREF chop)         $(MYREF detabber)         $(MYREF detab)         $(MYREF entab)         $(MYREF entabber)         $(MYREF leftJustify)         $(MYREF outdent)         $(MYREF rightJustify)         $(MYREF strip)         $(MYREF stripLeft)         $(MYREF stripRight)         $(MYREF wrap)    ))$(TR $(TDNW Substitution)    $(TD         $(MYREF abbrev)         $(MYREF soundex)         $(MYREF soundexer)         $(MYREF succ)         $(MYREF tr)         $(MYREF translate)    ))$(TR $(TDNW Miscellaneous)    $(TD         $(MYREF assumeUTF)         $(MYREF fromStringz)         $(MYREF lineSplitter)         $(MYREF representation)         $(MYREF splitLines)         $(MYREF toStringz)    )))) Objects of types `string`, `wstring`, and `dstring` are value typesand cannot be mutated element-by-element. For using mutation during buildingstrings, use `char[]`, `wchar[]`, or `dchar[]`. The `xxxstring`types are preferable because they don't exhibit undesired aliasing, thusmaking code more robust. The following functions are publicly imported: $(BOOKTABLE ,$(TR $(TH Module) $(TH Functions) )$(LEADINGROW Publicly imported functions)    $(TR $(TD std.algorithm)        $(TD         $(REF_SHORT cmp, std,algorithm,comparison)         $(REF_SHORT count, std,algorithm,searching)         $(REF_SHORT endsWith, std,algorithm,searching)         $(REF_SHORT startsWith, std,algorithm,searching)    ))    $(TR $(TD std.array)        $(TD         $(REF_SHORT join, std,array)         $(REF_SHORT replace, std,array)         $(REF_SHORT replaceInPlace, std,array)         $(REF_SHORT split, std,array)         $(REF_SHORT empty, std,array)    ))    $(TR $(TD std.format)        $(TD         $(REF_SHORT format, std,format)         $(REF_SHORT sformat, std,format)    ))    $(TR $(TD std.uni)        $(TD         $(REF_SHORT icmp, std,uni)         $(REF_SHORT toLower, std,uni)         $(REF_SHORT toLowerInPlace, std,uni)         $(REF_SHORT toUpper, std,uni)         $(REF_SHORT toUpperInPlace, std,uni)    ))) There is a rich set of functions for string handling defined in other modules.Functions related to Unicode and ASCII are found in $(MREF std, uni)and $(MREF std, ascii), respectively. Other functions that have awider generality than just strings can be found in $(MREF std, algorithm)and $(MREF std, range). See_Also:    $(LIST    $(MREF std, algorithm) and    $(MREF std, range)    for generic range algorithms    ,    $(MREF std, ascii)    for functions that work with ASCII strings    ,    $(MREF std, uni)    for functions that work with unicode strings    ) Copyright: Copyright The D Language Foundation 2007-. License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0). Authors: $(HTTP digitalmars.com, Walter Bright),         $(HTTP erdani.org, Andrei Alexandrescu),         $(HTTP jmdavisprog.com, Jonathan M Davis),         and David L. 'SpottedTiger' Davis Source:    $(PHOBOSSRC std/string.d) */module std.string; version (StdUnittest){private:    struct TestAliasedString    {        string get() @safe @nogc pure nothrow return scope { return _s; }        alias get this;        @disable this(this);        string _s;    }     bool testAliasedString(alias func, Args...)(string s, Args args)    {        import std.algorithm.comparison : equal;        auto a = func(TestAliasedString(s), args);        auto b = func(s, args);        static if (is(typeof(equal(a, b))))        {            // For ranges, compare contents instead of object identity.            return equal(a, b);        }        else        {            return a == b;        }    }} public import std.format : format, sformat;import std.typecons : Flag, Yes, No;public import std.uni : icmp, toLower, toLowerInPlace, toUpper, toUpperInPlace; import std.meta : AliasSeq, staticIndexOf;import std.range.primitives : back, ElementEncodingType, ElementType, front,    hasLength, hasSlicing, isBidirectionalRange, isForwardRange, isInfinite,    isInputRange, isOutputRange, isRandomAccessRange, popBack, popFront, put,    save;import std.traits : isConvertibleToString, isNarrowString, isSomeChar,    isSomeString, StringTypeOf, Unqual; //public imports for backward compatibilitypublic import std.algorithm.comparison : cmp;public import std.algorithm.searching : startsWith, endsWith, count;public import std.array : join, replace, replaceInPlace, split, empty; /* ************* Exceptions *************** */ /++    Exception thrown on errors in std.string functions.  +/class StringException : Exception{    import std.exception : basicExceptionCtors;     ///    mixin basicExceptionCtors;} ///@safe pure unittest{    import std.exception : assertThrown;    auto bad = "      a\n\tb\n   c";    assertThrown!StringException(bad.outdent);} /++    Params:        cString = A null-terminated c-style string.     Returns: A D-style array of `char`, `wchar` or `dchar` referencing the same    string. The returned array will retain the same type qualifiers as the input.     $(RED Important Note:) The returned array is a slice of the original buffer.    The original data is not changed and not copied.+/inout(Char)[] fromStringz(Char)(return scope inout(Char)* cString) @nogc @system pure nothrowif (isSomeChar!Char){    import core.stdc.stddef : wchar_t;     static if (is(immutable Char == immutable char))        import core.stdc.string : cstrlen = strlen;    else static if (is(immutable Char == immutable wchar_t))        import core.stdc.wchar_ : cstrlen = wcslen;    else        static size_t cstrlen(scope const Char* s)        {            const(Char)* p = s;            while (*p)                ++p;            return p - s;        }     return cString ? cString[0 .. cstrlen(cString)] : null;} /// dittoinout(Char)[] fromStringz(Char)(return scope inout(Char)[] cString) @nogc @safe pure nothrowif (isSomeChar!Char){    foreach (i; 0 .. cString.length)        if (cString[i] == '\0')            return cString[0 .. i];     return cString;} ///@system pure unittest{    assert(fromStringz("foo\0"c.ptr) == "foo"c);    assert(fromStringz("foo\0"w.ptr) == "foo"w);    assert(fromStringz("foo\0"d.ptr) == "foo"d);     assert(fromStringz("福\0"c.ptr) == "福"c);    assert(fromStringz("福\0"w.ptr) == "福"w);    assert(fromStringz("福\0"d.ptr) == "福"d);} ///@nogc @safe pure nothrow unittest{    struct C    {        char[32] name;    }    assert(C("foo\0"c).name.fromStringz() == "foo"c);     struct W    {        wchar[32] name;    }    assert(W("foo\0"w).name.fromStringz() == "foo"w);     struct D    {        dchar[32] name;    }    assert(D("foo\0"d).name.fromStringz() == "foo"d);} @nogc @safe pure nothrow unittest{    assert( string.init.fromStringz() == ""c);    assert(wstring.init.fromStringz() == ""w);    assert(dstring.init.fromStringz() == ""d);     immutable  char[3] a = "foo"c;    assert(a.fromStringz() == "foo"c);     immutable wchar[3] b = "foo"w;    assert(b.fromStringz() == "foo"w);     immutable dchar[3] c = "foo"d;    assert(c.fromStringz() == "foo"d);} @system pure unittest{    char* a = null;    assert(fromStringz(a) == null);    wchar* b = null;    assert(fromStringz(b) == null);    dchar* c = null;    assert(fromStringz(c) == null);     const char* d = "foo\0";    assert(fromStringz(d) == "foo");     immutable char* e = "foo\0";    assert(fromStringz(e) == "foo");     const wchar* f = "foo\0";    assert(fromStringz(f) == "foo");     immutable wchar* g = "foo\0";    assert(fromStringz(g) == "foo");     const dchar* h = "foo\0";    assert(fromStringz(h) == "foo");     immutable dchar* i = "foo\0";    assert(fromStringz(i) == "foo");     immutable wchar z = 0x0000;    // Test some surrogate pairs    // high surrogates are in the range 0xD800 .. 0xDC00    // low surrogates are in the range  0xDC00 .. 0xE000    // since UTF16 doesn't specify endianness we test both.    foreach (wchar[] t; [[0xD800, 0xDC00], [0xD800, 0xE000], [0xDC00, 0xDC00],            [0xDC00, 0xE000], [0xDA00, 0xDE00]])    {        immutable hi = t[0], lo = t[1];        assert(fromStringz([hi, lo, z].ptr) == [hi, lo]);        assert(fromStringz([lo, hi, z].ptr) == [lo, hi]);    }} /++    Params:        s = A D-style string.     Returns: A C-style null-terminated string equivalent to `s`. `s`    must not contain embedded `'\0'`'s as any C function will treat the    first `'\0'` that it sees as the end of the string. If `s.empty` is    `true`, then a string containing only `'\0'` is returned.     $(RED Important Note:) When passing a `char*` to a C function, and the C    function keeps it around for any reason, make sure that you keep a    reference to it in your D code. Otherwise, it may become invalid during a    garbage collection cycle and cause a nasty bug when the C code tries to use    it.  +/immutable(char)* toStringz(scope const(char)[] s) @trusted pure nothrowout (result){    import core.stdc.string : strlen, memcmp;    if (result)    {        auto slen = s.length;        while (slen > 0 && s[slen-1] == 0) --slen;        assert(strlen(result) == slen,                "The result c string is shorter than the in input string");        assert(result[0 .. slen] == s[0 .. slen],                "The input and result string are not equal");    }}do{    import std.exception : assumeUnique;     if (s.empty) return "".ptr;     /+ Unfortunately, this isn't reliable.     We could make this work if string literals are put     in read-only memory and we test if s[] is pointing into     that.      /* Peek past end of s[], if it's 0, no conversion necessary.     * Note that the compiler will put a 0 past the end of static     * strings, and the storage allocator will put a 0 past the end     * of newly allocated char[]'s.     */     char* p = &s[0] + s.length;     if (*p == 0)     return s;     +/     // Need to make a copy    auto copy = new char[s.length + 1];    copy[0 .. s.length] = s[];    copy[s.length] = 0;     return &assumeUnique(copy)[0];} ///pure nothrow @system unittest{    import core.stdc.string : strlen;    import std.conv : to;     auto p = toStringz("foo");    assert(strlen(p) == 3);    const(char)[] foo = "abbzxyzzy";    p = toStringz(foo[3 .. 5]);    assert(strlen(p) == 2);     string test = "";    p = toStringz(test);    assert(*p == 0);     test = "\0";    p = toStringz(test);    assert(*p == 0);     test = "foo\0";    p = toStringz(test);    assert(p[0] == 'f' && p[1] == 'o' && p[2] == 'o' && p[3] == 0);     const string test2 = "";    p = toStringz(test2);    assert(*p == 0);     assert(toStringz([]) is toStringz(""));} pure nothrow @system unittest // https://issues.dlang.org/show_bug.cgi?id=15136{    static struct S    {        immutable char[5] str;        ubyte foo;        this(char[5] str) pure nothrow        {            this.str = str;        }    }    auto s = S("01234");    const str = s.str.toStringz;    assert(str !is s.str.ptr);    assert(*(str + 5) == 0); // Null terminated.    s.foo = 42;    assert(*(str + 5) == 0); // Still null terminated.}  /**   Flag indicating whether a search is case-sensitive.*/alias CaseSensitive = Flag!"caseSensitive"; /++    Searches for a character in a string or range.     Params:        s = string or InputRange of characters to search for `c` in        c = character to search for in `s`        startIdx = index to a well-formed code point in `s` to start            searching from; defaults to 0        cs = specifies whether comparisons are case-sensitive            (`Yes.caseSensitive`) or not (`No.caseSensitive`).     Returns:        If `c` is found in `s`, then the index of its first occurrence is        returned. If `c` is not found or `startIdx` is greater than or equal to        `s.length`, then -1 is returned. If the parameters are not valid UTF,        the result will still be either -1 or in the range [`startIdx` ..        `s.length`], but will not be reliable otherwise.     Throws:        If the sequence starting at `startIdx` does not represent a well-formed        code point, then a $(REF UTFException, std,utf) may be thrown.     See_Also: $(REF countUntil, std,algorithm,searching)  +/ptrdiff_t indexOf(Range)(Range s, dchar c, CaseSensitive cs = Yes.caseSensitive)if (isInputRange!Range && isSomeChar!(ElementType!Range) && !isSomeString!Range){    return _indexOf(s, c, cs);} /// Dittoptrdiff_t indexOf(C)(scope const(C)[] s, dchar c, CaseSensitive cs = Yes.caseSensitive)if (isSomeChar!C){    return _indexOf(s, c, cs);} /// Dittoptrdiff_t indexOf(Range)(Range s, dchar c, size_t startIdx, CaseSensitive cs = Yes.caseSensitive)if (isInputRange!Range && isSomeChar!(ElementType!Range) && !isSomeString!Range){    return _indexOf(s, c, startIdx, cs);

Lines 1–500 of 7323.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t