diff --git a/lib/std/core/conv.c3 b/lib/std/core/conv.c3 index bd563abca..b839893db 100644 --- a/lib/std/core/conv.c3 +++ b/lib/std/core/conv.c3 @@ -104,24 +104,28 @@ fn void! char16_to_utf8_unsafe(Char16 *ptr, usz *available, char** output) * @param c `The utf32 codepoint to convert` * @param [inout] output `the resulting buffer` **/ -fn void char32_to_utf8_unsafe(Char32 c, char** output) +fn usz char32_to_utf8_unsafe(Char32 c, char** output) { - switch (true) + switch { case c < 0x7f: (*output)++[0] = (char)c; + return 1; case c < 0x7ff: (*output)++[0] = (char)(0xC0 | c >> 6); (*output)++[0] = (char)(0x80 | (c & 0x3F)); + return 2; case c < 0xffff: (*output)++[0] = (char)(0xE0 | c >> 12); (*output)++[0] = (char)(0x80 | (c >> 6 & 0x3F)); (*output)++[0] = (char)(0x80 | (c & 0x3F)); + return 3; default: (*output)++[0] = (char)(0xF0 | c >> 18); (*output)++[0] = (char)(0x80 | (c >> 12 & 0x3F)); (*output)++[0] = (char)(0x80 | (c >> 6 & 0x3F)); (*output)++[0] = (char)(0x80 | (c & 0x3F)); + return 4; } } diff --git a/lib/std/core/dstring.c3 b/lib/std/core/dstring.c3 index cbac0991f..c3f3657b5 100644 --- a/lib/std/core/dstring.c3 +++ b/lib/std/core/dstring.c3 @@ -136,8 +136,7 @@ fn void DString.append_char32(&self, Char32 c) { char[4] buffer @noinit; char* p = &buffer; - conv::char32_to_utf8_unsafe(c, &p); - usz n = p - (char*)&buffer; + usz n = conv::char32_to_utf8_unsafe(c, &p); self.reserve(n); StringData* data = self.data(); data.chars[data.len:n] = buffer[:n]; diff --git a/lib/std/io/formatter_private.c3 b/lib/std/io/formatter_private.c3 index 3235e38b5..df375ae34 100644 --- a/lib/std/io/formatter_private.c3 +++ b/lib/std/io/formatter_private.c3 @@ -11,15 +11,17 @@ fn usz! Formatter.adjust(&self, usz len) @local fn uint128! int_from_any(any* arg, bool *is_neg) @private { + switch (arg.type.kindof) + { + case TypeKind.POINTER: + *is_neg = false; + return (uint128)(uptr)*(void**)arg.ptr; + case TypeKind.DISTINCT: + case TypeKind.ENUM: + return int_from_any(arg.as_inner(), is_neg); + default: + } *is_neg = false; - if (arg.type.kindof == TypeKind.POINTER) - { - return (uint128)(uptr)*(void**)arg.ptr; - } - if (arg.type.kindof == TypeKind.DISTINCT) - { - return int_from_any(arg.as_inner(), is_neg); - } switch (arg) { case bool: diff --git a/test/unit/stdlib/core/dstring.c3 b/test/unit/stdlib/core/dstring.c3 index b8cfb879b..fe9924379 100644 --- a/test/unit/stdlib/core/dstring.c3 +++ b/test/unit/stdlib/core/dstring.c3 @@ -1,4 +1,128 @@ -module std::core::dstring::tests @test; +module std::core::dstring2 @test; + +const TEST_STRING = "hello world"; + +fn void test_append() +{ + DString str = dstring::new(TEST_STRING); + defer str.free(); + String s; + + assert(str.len() == TEST_STRING.len); + assert(str.capacity() == 16); + + s = str.str_view(); + assert(s == TEST_STRING, "got '%s'; want '%s'", s, TEST_STRING); + ZString zs; + zs = str.zstr_view(); + assert(s.ptr[s.len] == 0, "got '%c'; want 0", s.ptr[s.len]); + + str.chop(5); + s = str.str_view(); + assert(s == TEST_STRING[:5], "got '%s'; want '%s'", s, TEST_STRING[:5]); + + str.append(TEST_STRING[5..]); + s = str.str_view(); + assert(s == TEST_STRING, "got '%s'; want '%s'", s, TEST_STRING); + + str.append_char('x'); + s = str.str_view(); + assert(s[^1] == 'x', "got '%c'; want 'x'", s[^1]); + + str.append('y'); + s = str.str_view(); + assert(s[^1] == 'y', "got '%c'; want 'y'", s[^1]); + + str.set(0, 'z'); + s = str.str_view(); + assert(s[0] == 'z', "got '%c'; want 'z'", s[0]); + + str.clear(); + assert(str.len() == 0); + + str.append_char32('é'); + s = str.str_view(); + assert(s == "é", "got '%s'; want 'é'", s); + + str.append_utf32({ 'è', 'à' }); + s = str.str_view(); + assert(s == "éèà", "got '%s'; want 'éèà'", s); + str.clear(); + + str.append_chars("foo"); + s = str.str_view(); + assert(s == "foo", "got '%s'; want 'foo'", s); + str.clear(); + + str.append_repeat('x', 3); + s = str.str_view(); + assert(s == "xxx", "got '%s'; want 'xxx'", s); + + DString str2 = dstring::new("yyy"); + defer str2.free(); + DString str3 = str.new_concat(str2); + defer str3.free(); + s = str3.str_view(); + assert(s == "xxxyyy", "got '%s'; want 'xxxyyy'", s); + + str3.clear(); + str3.append_string(str2); + s = str3.str_view(); + assert(s == "yyy", "got '%s'; want 'yyy'", s); +} + +fn void test_print() +{ + DString str = dstring::new(""); + defer str.free(); + String s; + + str.printf("_%s_", "foo"); + s = str.str_view(); + assert(s == "_foo_", "got '%s'; want '_foo_'", s); + + str.clear(); + str.printfn("_%s_", "foo"); + s = str.str_view(); + assert(s == "_foo_\n", "got '%s'; want '_foo_\n'", s); +} + +fn void test_copy() +{ + DString str = dstring::new(TEST_STRING); + defer str.free(); + String s; + + DString str2 = str.copy(); + defer str2.free(); + s = str2.str_view(); + assert(s == TEST_STRING, "got '%s'; want '%s'", s, TEST_STRING); +} + +fn void test_cmp() +{ + DString str = dstring::new(TEST_STRING); + defer str.free(); + + DString str2 = dstring::new(TEST_STRING); + defer str2.free(); + + assert(str.equals(str2)); + + str2.clear(); + str2.append("hello you.."); + assert(str.len() == str2.len()); + assert(!str.less(str2)); +} + +fn void test_join() +{ + DString str = dstring::new_join({"hello", "world"}, " "); + defer str.free(); + + String s = str.str_view(); + assert(s == TEST_STRING, "got '%s'; want '%s'", s, TEST_STRING); +} fn void test_insert_at() { diff --git a/test/unit/stdlib/io/printf.c3 b/test/unit/stdlib/io/printf.c3 index 302bb03c9..445a7104e 100644 --- a/test/unit/stdlib/io/printf.c3 +++ b/test/unit/stdlib/io/printf.c3 @@ -50,4 +50,25 @@ fn void printf_a() String ss = "hello world"; s = string::printf("%.4s %.5s", ss, ss); assert(s == "hell hello", "got '%s'; want 'hell hello'", s); +} + +enum PrintfTest : ushort +{ + ENUMA, + ENUMB, +} + +fn void printf_enum() +{ + String s; + + s = string::printf("%s", PrintfTest.ENUMA); + assert(s == "ENUMA", "got '%s'; want 'ENUMA'", s); + s = string::printf("%s", PrintfTest.ENUMB); + assert(s == "ENUMB", "got '%s'; want 'ENUMB'", s); + + s = string::printf("%d", PrintfTest.ENUMA); + assert(s == "0", "got '%s'; want '0'", s); + s = string::printf("%d", PrintfTest.ENUMB); + assert(s == "1", "got '%s'; want '1'", s); } \ No newline at end of file