| ... | @@ -96,7 +96,15 @@ pub fn utf8ValidateSlice(s: []const u8) bool { | ... | @@ -96,7 +96,15 @@ pub fn utf8ValidateSlice(s: []const u8) bool { |
| 96 | return true; | 96 | return true; |
| 97 | } | 97 | } |
| 98 | | 98 | |
| 99 | const Utf8View = struct { | 99 | /// Utf8View makes it easy to iterate the code points of a utf-8 encoded string. |
| | 100 | /// |
| | 101 | /// ``` |
| | 102 | /// var utf8 = (try std.unicode.Utf8View.init("hi there")).iterator(); |
| | 103 | /// while (utf8.nextCodepointSlice()) |codepoint| { |
| | 104 | /// std.debug.warn("got codepoint {}\n", codepoint); |
| | 105 | /// } |
| | 106 | /// ``` |
| | 107 | pub const Utf8View = struct { |
| 100 | bytes: []const u8, | 108 | bytes: []const u8, |
| 101 | | 109 | |
| 102 | pub fn init(s: []const u8) !Utf8View { | 110 | pub fn init(s: []const u8) !Utf8View { |
| ... | @@ -124,7 +132,7 @@ const Utf8View = struct { | ... | @@ -124,7 +132,7 @@ const Utf8View = struct { |
| 124 | } | 132 | } |
| 125 | } | 133 | } |
| 126 | | 134 | |
| 127 | pub fn Iterator(s: &const Utf8View) Utf8Iterator { | 135 | pub fn iterator(s: &const Utf8View) Utf8Iterator { |
| 128 | return Utf8Iterator { | 136 | return Utf8Iterator { |
| 129 | .bytes = s.bytes, | 137 | .bytes = s.bytes, |
| 130 | .i = 0, | 138 | .i = 0, |
| ... | @@ -165,13 +173,13 @@ const Utf8Iterator = struct { | ... | @@ -165,13 +173,13 @@ const Utf8Iterator = struct { |
| 165 | test "utf8 iterator on ascii" { | 173 | test "utf8 iterator on ascii" { |
| 166 | const s = Utf8View.initComptime("abc"); | 174 | const s = Utf8View.initComptime("abc"); |
| 167 | | 175 | |
| 168 | var it1 = s.Iterator(); | 176 | var it1 = s.iterator(); |
| 169 | debug.assert(std.mem.eql(u8, "a", ??it1.nextCodepointSlice())); | 177 | debug.assert(std.mem.eql(u8, "a", ??it1.nextCodepointSlice())); |
| 170 | debug.assert(std.mem.eql(u8, "b", ??it1.nextCodepointSlice())); | 178 | debug.assert(std.mem.eql(u8, "b", ??it1.nextCodepointSlice())); |
| 171 | debug.assert(std.mem.eql(u8, "c", ??it1.nextCodepointSlice())); | 179 | debug.assert(std.mem.eql(u8, "c", ??it1.nextCodepointSlice())); |
| 172 | debug.assert(it1.nextCodepointSlice() == null); | 180 | debug.assert(it1.nextCodepointSlice() == null); |
| 173 | | 181 | |
| 174 | var it2 = s.Iterator(); | 182 | var it2 = s.iterator(); |
| 175 | debug.assert(??it2.nextCodepoint() == 'a'); | 183 | debug.assert(??it2.nextCodepoint() == 'a'); |
| 176 | debug.assert(??it2.nextCodepoint() == 'b'); | 184 | debug.assert(??it2.nextCodepoint() == 'b'); |
| 177 | debug.assert(??it2.nextCodepoint() == 'c'); | 185 | debug.assert(??it2.nextCodepoint() == 'c'); |
| ... | @@ -189,13 +197,13 @@ test "utf8 view bad" { | ... | @@ -189,13 +197,13 @@ test "utf8 view bad" { |
| 189 | test "utf8 view ok" { | 197 | test "utf8 view ok" { |
| 190 | const s = Utf8View.initComptime("東京市"); | 198 | const s = Utf8View.initComptime("東京市"); |
| 191 | | 199 | |
| 192 | var it1 = s.Iterator(); | 200 | var it1 = s.iterator(); |
| 193 | debug.assert(std.mem.eql(u8, "東", ??it1.nextCodepointSlice())); | 201 | debug.assert(std.mem.eql(u8, "東", ??it1.nextCodepointSlice())); |
| 194 | debug.assert(std.mem.eql(u8, "京", ??it1.nextCodepointSlice())); | 202 | debug.assert(std.mem.eql(u8, "京", ??it1.nextCodepointSlice())); |
| 195 | debug.assert(std.mem.eql(u8, "市", ??it1.nextCodepointSlice())); | 203 | debug.assert(std.mem.eql(u8, "市", ??it1.nextCodepointSlice())); |
| 196 | debug.assert(it1.nextCodepointSlice() == null); | 204 | debug.assert(it1.nextCodepointSlice() == null); |
| 197 | | 205 | |
| 198 | var it2 = s.Iterator(); | 206 | var it2 = s.iterator(); |
| 199 | debug.assert(??it2.nextCodepoint() == 0x6771); | 207 | debug.assert(??it2.nextCodepoint() == 0x6771); |
| 200 | debug.assert(??it2.nextCodepoint() == 0x4eac); | 208 | debug.assert(??it2.nextCodepoint() == 0x4eac); |
| 201 | debug.assert(??it2.nextCodepoint() == 0x5e02); | 209 | debug.assert(??it2.nextCodepoint() == 0x5e02); |