authorgravatar for 1668550+Jared-Miller@users.noreply.github.comJared Miller <1668550+Jared-Miller@users.noreply.github.com> 2020-02-20 15:25:24-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-07 19:21:28-05:00
logcf38ce970155512577cfb0cc281d1a308af7e7e9
tree16f8ac7200a2d1d5084ee523c51bbc3e8311b689
parent6ac76bc25e2636bd9b2f7bb2fc5710e2aef4f8ed

Implement UTF-8 to UTF-16LE literal conversion


1 files changed, 68 insertions(+), 0 deletions(-)

lib/std/unicode.zig+68
...@@ -629,3 +629,71 @@ test "utf8ToUtf16LeWithNull" {...@@ -629,3 +629,71 @@ test "utf8ToUtf16LeWithNull" {
629 testing.expect(utf16[2] == 0);629 testing.expect(utf16[2] == 0);
630 }630 }
631}631}
632
633/// Converts a UTF-8 string literal into a UTF-16LE string literal.
634pub fn utf8ToUtf16LeStringLiteral(comptime utf8: []const u8) *const [calcUtf16LeLen(utf8) :0] u16 {
635 comptime {
636 const len: usize = calcUtf16LeLen(utf8);
637 var utf16le: [len :0]u16 = [_ :0]u16{0} ** len;
638 const utf16le_len = utf8ToUtf16Le(&utf16le, utf8[0..]) catch |err| @compileError(err);
639 assert(len == utf16le_len);
640 return &utf16le;
641 }
642}
643
644/// Returns length of a supplied UTF-8 string literal. Asserts that the data is valid UTF-8.
645fn calcUtf16LeLen(utf8: []const u8) usize {
646 var src_i: usize = 0;
647 var dest_len: usize = 0;
648 while (src_i < utf8.len) {
649 const n = utf8ByteSequenceLength(utf8[src_i]) catch unreachable;
650 const next_src_i = src_i + n;
651 const codepoint = utf8Decode(utf8[src_i..next_src_i]) catch unreachable;
652 if (codepoint < 0x10000) {
653 dest_len += 1;
654 } else {
655 dest_len += 2;
656 }
657 src_i = next_src_i;
658 }
659 return dest_len;
660}
661
662test "utf8ToUtf16LeStringLiteral" {
663{
664 const bytes = [_:0]u16{ 0x41 };
665 const utf16 = utf8ToUtf16LeStringLiteral("A");
666 testing.expectEqualSlices(u16, &bytes, utf16);
667 testing.expect(utf16[1] == 0);
668 }
669 {
670 const bytes = [_:0]u16{ 0xD801, 0xDC37 };
671 const utf16 = utf8ToUtf16LeStringLiteral("𐐷");
672 testing.expectEqualSlices(u16, &bytes, utf16);
673 testing.expect(utf16[2] == 0);
674 }
675 {
676 const bytes = [_:0]u16{ 0x02FF };
677 const utf16 = utf8ToUtf16LeStringLiteral("\u{02FF}");
678 testing.expectEqualSlices(u16, &bytes, utf16);
679 testing.expect(utf16[1] == 0);
680 }
681 {
682 const bytes = [_:0]u16{ 0x7FF };
683 const utf16 = utf8ToUtf16LeStringLiteral("\u{7FF}");
684 testing.expectEqualSlices(u16, &bytes, utf16);
685 testing.expect(utf16[1] == 0);
686 }
687 {
688 const bytes = [_:0]u16{ 0x801 };
689 const utf16 = utf8ToUtf16LeStringLiteral("\u{801}");
690 testing.expectEqualSlices(u16, &bytes, utf16);
691 testing.expect(utf16[1] == 0);
692 }
693 {
694 const bytes = [_:0]u16{ 0xDBFF, 0xDFFF };
695 const utf16 = utf8ToUtf16LeStringLiteral("\u{10FFFF}");
696 testing.expectEqualSlices(u16, &bytes, utf16);
697 testing.expect(utf16[2] == 0);
698 }
699}