toUpper

@trusted
toUpper
()
(
const SSOString x
)

Return Value

Type: SSOString

x uppercased.

Examples

construct from non-immutable source is allowed in non-@nogc-scope

alias S = SSOString;

scope const char[] x0;
const s0 = SSOString(x0);           // no .idup

scope const char[] x16 = new char[16];
const s16 = SSOString(x16);         // will call .idup

construct from non-immutable source is not allowed in @nogc-scope

scope const char[] s;
// TODO why does this fail? static assert(!__traits(compiles, { const _ = SSOString(s); }));

verify isNull when @nogc constructing from small static array of chars

static foreach (const n; 0 .. SSOString.smallCapacity + 1)
{
    {
        immutable(char)[n] x;
        assert(!SSOString(x).isNull);
    }
}

verify isNull when constructing from large static array of chars

static foreach (const n; SSOString.smallCapacity + 1 .. 32)
{
    {
        immutable(char)[n] x;
        assert(!SSOString(x).isNull);
    }
}

verify isNull when constructing from dynamic array of chars

foreach (const n; 0 .. 32)
{
    scope x = new immutable(char)[n];
    assert(!SSOString(x).isNull);
}

test behaviour of == and is operator

1 const SSOString x = "42";
2 assert(!x.isNull);
3 assert(x == "42");
4 
5 const SSOString y = "42";
6 assert(!y.isNull);
7 assert(y == "42");
8 
9 assert(x == y);
10 assert(x == y[]);
11 assert(x[] == y);
12 assert(x[] == y[]);
13 assert(x[] is x[]);
14 assert(y[] is y[]);
15 assert(x[] !is y[]);
16 assert(x.ptr !is y.ptr);
17 
18 const SSOString z = "43";
19 assert(!z.isNull);
20 assert(z == "43");
21 assert(x != z);
22 assert(x[] != z[]);
23 assert(x !is z);
24 assert(x[] !is z[]);
1 static assert(SSOString.smallCapacity == 15);
2 
3 import nxt.gc_traits : mustAddGCRange;
4 static assert(mustAddGCRange!SSOString); // `Large large.ptr` must be scanned
5 
6 static assert(__traits(isZeroInit, SSOString));
7 // TODO assert(SSOString.init == SSOString.nullValue);
8 
9 auto s0 = SSOString.init;
10 assert(s0.isNull);
11 assert(s0.length == 0);
12 assert(s0.isLarge);
13 assert(s0[] == []);
14 
15 char[SSOString.smallCapacity] charsSmallCapacity = "123456789_12345"; // fits in small string
16 const sSmallCapacity = SSOString(charsSmallCapacity);
17 assert(!sSmallCapacity.isLarge);
18 assert(sSmallCapacity.length == SSOString.smallCapacity);
19 assert(sSmallCapacity == charsSmallCapacity);
20 
21 const s0_ = SSOString("");
22 assert(!s0_.isNull);         // cannot distinguish
23 assert(s0 == s0_);
24 
25 const s7 = SSOString("0123456");
26 assert(!s7.isNull);
27 
28 const s7_ = SSOString("0123456_"[0 .. $ - 1]);
29 assert(s7.ptr !is s7_.ptr); // string data shall not overlap
30 assert(s7 == s7_);
31 
32 const _s7 = SSOString("_0123456"[1 .. $]); // source from other string literal
33 assert(s7.ptr !is _s7.ptr); // string data shall not overlap
34 assert(s7 == _s7);
35 
36 assert(!s7.isLarge);
37 assert(s7.length == 7);
38 assert(s7[] == "0123456");
39 assert(s7[] == "_0123456"[1 .. $]);
40 assert(s7[] == "0123456_"[0 .. $ - 1]);
41 assert(s7[0 .. 4] == "0123");
42 
43 const s15 = SSOString("0123456789abcde");
44 assert(!s15.isNull);
45 static assert(is(typeof(s15[]) == const(char)[]));
46 assert(!s15.isLarge);
47 assert(s15.length == 15);
48 assert(s15[] == "0123456789abcde");
49 assert(s15[0 .. 4] == "0123");
50 assert(s15[10 .. 15] == "abcde");
51 assert(s15[10 .. $] == "abcde");
52 
53 const s16 = SSOString("0123456789abcdef");
54 assert(!s16.isNull);
55 static assert(is(typeof(s16[]) == const(char)[]));
56 assert(s16.isLarge);
57 
58 const s16_ = SSOString("0123456789abcdef_"[0 .. s16.length]);
59 assert(s16.length == s16_.length);
60 assert(s16[] == s16_[]);
61 assert(s16.ptr !is s16_.ptr); // string data shall not overlap
62 assert(s16 == s16_);              // but contents is equal
63 
64 const _s16 = SSOString("_0123456789abcdef"[1 .. $]);
65 assert(s16.length == _s16.length);
66 assert(s16[] == _s16[]);    // contents is equal
67 assert(s16 == _s16);        // contents is equal
68 
69 assert(s16.length == 16);
70 assert(s16[] == "0123456789abcdef");
71 assert(s16[0] == '0');
72 assert(s16[10] == 'a');
73 assert(s16[15] == 'f');
74 assert(s16[0 .. 4] == "0123");
75 assert(s16[10 .. 16] == "abcdef");
76 assert(s16[10 .. $] == "abcdef");

metadata for null string

auto s = SSOString.init;
assert(s.isNull);
foreach (const i; 0 .. 8)
{
    s.metadata = i;
    assert(s.metadata == i);
    assert(s.length == 0);
}

metadata for small string

auto s = SSOString("0123456");
assert(!s.isNull);
assert(!s.isLarge);
foreach (const i; 0 .. 8)
{
    s.metadata = i;
    assert(s.metadata == i);
    assert(s.length == 7);
    assert(!s.isLarge);
    assert(!s.isNull);
}

metadata for small string with maximum length

auto s = SSOString("0123456789abcde");
assert(s.length == SSOString.smallCapacity);
assert(!s.isNull);
assert(!s.isLarge);
foreach (const i; 0 .. 8)
{
    s.metadata = i;
    assert(s.metadata == i);
    assert(s.length == 15);
    assert(!s.isLarge);
    assert(!s.isNull);
}

metadata for large string with minimum length

auto s = SSOString("0123456789abcdef");
assert(s.length == SSOString.smallCapacity + 1);
assert(!s.isNull);
assert(s.isLarge);
assert(!s.empty);
foreach (const i; 0 .. 8)
{
    s.metadata = i;
    assert(s.metadata == i);
    assert(s.length == 16);
    assert(s.isLarge);
    assert(!s.isNull);
}

equality and equivalence

assert(SSOString() == SSOString(""));
assert(SSOString() !is SSOString(""));

hashing of null, empty and non-empty

assert(SSOString().toHash == 0);
assert(SSOString("").toHash == 0);
assert(SSOString("a").toHash != 0);
assert(SSOString("0123456789abcdef").toHash != 0);

construct from static array larger than smallCapacity

char[SSOString.smallCapacity + 1] charsMinLargeCapacity;
const _ = SSOString(charsMinLargeCapacity);

hole handling

assert(!SSOString.init.isHole);
assert(!SSOString("").isHole);
assert(!SSOString("a").isHole);
assert(SSOString.asHole.isHole);

DIP-1000 return ref escape analysis

static if (isDIP1000)
{
    static assert(!__traits(compiles, { immutable(char)* f1() @safe pure nothrow { SSOString x; return x.ptr; } }));
    static assert(!__traits(compiles, { string f1() @safe pure nothrow { SSOString x; return x[]; } }));
    static assert(!__traits(compiles, { string f2() @safe pure nothrow { SSOString x; return x.toString; } }));
    static assert(!__traits(compiles, { ref immutable(char) g() @safe pure nothrow @nogc { SSOString x; return x[0]; } }));
}

ASCII purity and case-conversion

1 // these are all small ASCII
2 assert( SSOString("a").isSmallASCII);
3 assert( SSOString("b").isSmallASCII);
4 assert( SSOString("z").isSmallASCII);
5 assert( SSOString("_").isSmallASCII);
6 assert( SSOString("abcd").isSmallASCII);
7 assert( SSOString("123456789_12345").isSmallASCII);
8 
9 // these are not
10 assert(!SSOString("123456789_123456").isSmallASCII); // too large
11 assert(!SSOString("123456789_123ö").isSmallASCII);
12 assert(!SSOString("ö").isSmallASCII);
13 assert(!SSOString("Ö").isSmallASCII);
14 assert(!SSOString("åäö").isSmallASCII);
15 assert(!SSOString("ö-värld").isSmallASCII);

ASCII purity and case-conversion

1 assert(SSOString("A").toLower[] == "a");
2 assert(SSOString("a").toUpper[] == "A");
3 assert(SSOString("ABCDEFGHIJKLMNO").toLower[] == "abcdefghijklmno"); // small
4 assert(SSOString("abcdefghijklmno").toUpper[] == "ABCDEFGHIJKLMNO"); // small
5 assert(SSOString("ÅÄÖ").toLower[] == "åäö");
6 assert(SSOString("åäö").toUpper[] == "ÅÄÖ");
7 assert(SSOString("ABCDEFGHIJKLMNOP").toLower[] == "abcdefghijklmnop"); // large
8 assert(SSOString("abcdefghijklmnop").toUpper[] == "ABCDEFGHIJKLMNOP"); // large
9 
10 char[6] x = "ÅÄÖ";
11 import std.uni : toLowerInPlace;
12 auto xref = x[];
13 toLowerInPlace(xref);
14 assert(x == "åäö");
15 assert(xref == "åäö");

lexicographic comparison

const SSOString a = SSOString("a");
assert(a == SSOString("a"));

immutable SSOString b = SSOString("b");

assert(a < b);
assert(b > a);
assert(a[] < b[]);

assert("a" < "b");
assert("a" < "å");
assert("Å" < "å");
assert(SSOString("a") < SSOString("å"));
assert(SSOString("ÅÄÖ") < SSOString("åäö"));

cast to bool

// mimics behaviour of casting of `string` to `bool`
assert(!SSOString());
assert(SSOString(""));
assert(SSOString("abc"));

to string conversion

1 // mutable small will GC-allocate
2 {
3     SSOString s = SSOString("123456789_12345");
4     assert(s.ptr is &s.opSlice()[0]);
5     assert(s.ptr !is &s.toString()[0]);
6 }
7 
8 // const small will GC-allocate
9 {
10     const SSOString s = SSOString("123456789_12345");
11     assert(s.ptr is &s.opSlice()[0]);
12     assert(s.ptr !is &s.toString()[0]);
13 }
14 
15 // immutable small will not allocate
16 {
17     immutable SSOString s = SSOString("123456789_12345");
18     assert(s.ptr is &s.opSlice()[0]);
19     assert(s.ptr is &s.toString()[0]);
20     // TODO check return via -dip1000
21 }
22 
23 /* Forbid return of possibly locally scoped `Smll` small stack object
24  * regardless of head-mutability.
25  */
26 static if (isDIP1000)
27 {
28     static assert(!__traits(compiles, { immutable(char)* f1() @safe pure nothrow { SSOString x; return x.ptr; } }));
29     static assert(!__traits(compiles, { immutable(char)* f1() @safe pure nothrow { const SSOString x; return x.ptr; } }));
30     static assert(!__traits(compiles, { immutable(char)* f1() @safe pure nothrow { immutable SSOString x; return x.ptr; } }));
31 
32     /** TODO Enable the following line when DIP-1000 works for opSlice()
33      *
34      * See_Also: https://issues.dlang.org/show_bug.cgi?id=18792
35      */
36     // static assert(!__traits(compiles, { string f1() @safe pure nothrow { immutable SSOString x; return x[]; } }));
37 }
38 
39 // large will never allocate regardless of head-mutability
40 {
41     SSOString s = SSOString("123456789_123456");
42     assert(s.ptr is &s.opSlice()[0]);
43     assert(s.ptr is &s.toString()[0]); // shouldn't this change?
44 }

Meta