| ... | @@ -425,6 +425,15 @@ pub const Utf8Iterator = struct { | ... | @@ -425,6 +425,15 @@ pub const Utf8Iterator = struct { |
| 425 | | 425 | |
| 426 | return it.bytes[original_i..end_ix]; | 426 | return it.bytes[original_i..end_ix]; |
| 427 | } | 427 | } |
| | 428 | |
| | 429 | /// Look ahead at the next codepoint without advancing the iterator. |
| | 430 | /// If no codepoints exist, then returns null. |
| | 431 | pub fn peekCodepoint(it: *Utf8Iterator) ?u21 { |
| | 432 | const original_i = it.i; |
| | 433 | defer it.i = original_i; |
| | 434 | |
| | 435 | return it.nextCodepoint(); |
| | 436 | } |
| 428 | }; | 437 | }; |
| 429 | | 438 | |
| 430 | pub fn utf16IsHighSurrogate(c: u16) bool { | 439 | pub fn utf16IsHighSurrogate(c: u16) bool { |
| ... | @@ -768,6 +777,9 @@ fn testMiscInvalidUtf8() !void { | ... | @@ -768,6 +777,9 @@ fn testMiscInvalidUtf8() !void { |
| 768 | test "utf8 iterator peeking" { | 777 | test "utf8 iterator peeking" { |
| 769 | try comptime testUtf8Peeking(); | 778 | try comptime testUtf8Peeking(); |
| 770 | try testUtf8Peeking(); | 779 | try testUtf8Peeking(); |
| | 780 | |
| | 781 | comptime try testUtf8PeekCodepoint(); |
| | 782 | try testUtf8PeekCodepoint(); |
| 771 | } | 783 | } |
| 772 | | 784 | |
| 773 | fn testUtf8Peeking() !void { | 785 | fn testUtf8Peeking() !void { |
| ... | @@ -790,6 +802,20 @@ fn testUtf8Peeking() !void { | ... | @@ -790,6 +802,20 @@ fn testUtf8Peeking() !void { |
| 790 | try testing.expect(mem.eql(u8, &[_]u8{}, it.peek(1))); | 802 | try testing.expect(mem.eql(u8, &[_]u8{}, it.peek(1))); |
| 791 | } | 803 | } |
| 792 | | 804 | |
| | 805 | fn testUtf8PeekCodepoint() !void { |
| | 806 | const s = Utf8View.initComptime("東京市"); |
| | 807 | var it = s.iterator(); |
| | 808 | |
| | 809 | try testing.expect(it.peekCodepoint().? == 0x6771); |
| | 810 | try testing.expect(it.peekCodepoint().? == 0x6771); |
| | 811 | _ = it.nextCodepoint(); |
| | 812 | try testing.expect(it.peekCodepoint().? == 0x4eac); |
| | 813 | _ = it.nextCodepoint(); |
| | 814 | try testing.expect(it.peekCodepoint().? == 0x5e02); |
| | 815 | _ = it.nextCodepoint(); |
| | 816 | try testing.expect(it.peekCodepoint() == null); |
| | 817 | } |
| | 818 | |
| 793 | fn testError(bytes: []const u8, expected_err: anyerror) !void { | 819 | fn testError(bytes: []const u8, expected_err: anyerror) !void { |
| 794 | try testing.expectError(expected_err, testDecode(bytes)); | 820 | try testing.expectError(expected_err, testDecode(bytes)); |
| 795 | } | 821 | } |
| ... | @@ -1758,6 +1784,15 @@ pub const Wtf8Iterator = struct { | ... | @@ -1758,6 +1784,15 @@ pub const Wtf8Iterator = struct { |
| 1758 | | 1784 | |
| 1759 | return it.bytes[original_i..end_ix]; | 1785 | return it.bytes[original_i..end_ix]; |
| 1760 | } | 1786 | } |
| | 1787 | |
| | 1788 | /// Look ahead at the next codepoint without advancing the iterator. |
| | 1789 | /// If no codepoints exist, then returns null. |
| | 1790 | pub fn peekCodepoint(it: *Wtf8Iterator) ?u21 { |
| | 1791 | const original_i = it.i; |
| | 1792 | defer it.i = original_i; |
| | 1793 | |
| | 1794 | return it.nextCodepoint(); |
| | 1795 | } |
| 1761 | }; | 1796 | }; |
| 1762 | | 1797 | |
| 1763 | pub fn wtf16LeToWtf8ArrayList(result: *std.array_list.Managed(u8), utf16le: []const u16) Allocator.Error!void { | 1798 | pub fn wtf16LeToWtf8ArrayList(result: *std.array_list.Managed(u8), utf16le: []const u16) Allocator.Error!void { |