diff options
| -rw-r--r-- | src/code_point.zig | 55 |
1 files changed, 51 insertions, 4 deletions
diff --git a/src/code_point.zig b/src/code_point.zig index a319d36..b3c9aea 100644 --- a/src/code_point.zig +++ b/src/code_point.zig | |||
| @@ -48,12 +48,22 @@ pub fn decodeAtCursor(bytes: []const u8, cursor: *u32) ?CodePoint { | |||
| 48 | }; | 48 | }; |
| 49 | // Multibyte | 49 | // Multibyte |
| 50 | 50 | ||
| 51 | <<<<<<< HEAD | ||
| 51 | // Second: | 52 | // Second: |
| 52 | var class: u4 = @intCast(u8dfa[byte]); | 53 | var class: u4 = @intCast(u8dfa[byte]); |
| 53 | var st: u32 = state_dfa[class]; | 54 | var st: u32 = state_dfa[class]; |
| 54 | if (st == RUNE_REJECT or cursor.* == bytes.len) { | 55 | if (st == RUNE_REJECT or cursor.* == bytes.len) { |
| 55 | @branchHint(.cold); | 56 | @branchHint(.cold); |
| 56 | // First one is never a truncation | 57 | // First one is never a truncation |
| 58 | ||||||| parent of ad4b046 (Various small iterator improvements) | ||
| 59 | // Return replacement if we don' have a complete codepoint remaining. Consumes only one byte | ||
| 60 | if (cp.len > bytes.len) { | ||
| 61 | // Unicode replacement code point. | ||
| 62 | ======= | ||
| 63 | // Return replacement if we don't have a complete codepoint remaining. Consumes only one byte. | ||
| 64 | if (cp.len > bytes.len) { | ||
| 65 | // Unicode replacement code point. | ||
| 66 | >>>>>>> ad4b046 (Various small iterator improvements) | ||
| 57 | return .{ | 67 | return .{ |
| 58 | .code = 0xfffd, | 68 | .code = 0xfffd, |
| 59 | .len = 1, | 69 | .len = 1, |
| @@ -158,10 +168,19 @@ pub const Iterator = struct { | |||
| 158 | return decodeAtCursor(self.bytes, &self.i); | 168 | return decodeAtCursor(self.bytes, &self.i); |
| 159 | } | 169 | } |
| 160 | 170 | ||
| 161 | pub fn peek(self: *Iterator) ?CodePoint { | 171 | pub fn peek(iter: *Iterator) ?CodePoint { |
| 162 | const saved_i = self.i; | 172 | const saved_i = iter.i; |
| 163 | defer self.i = saved_i; | 173 | defer iter.i = saved_i; |
| 164 | return self.next(); | 174 | return iter.next(); |
| 175 | } | ||
| 176 | |||
| 177 | /// Create a backward iterator at this point. It will repeat | ||
| 178 | /// the last CodePoint seen. | ||
| 179 | pub fn reverseIterator(iter: *Iterator) ReverseIterator { | ||
| 180 | if (iter.i == iter.bytes.len) { | ||
| 181 | return .init(iter.bytes); | ||
| 182 | } | ||
| 183 | return .{ .i = iter.i, .bytes = iter.bytes }; | ||
| 165 | } | 184 | } |
| 166 | }; | 185 | }; |
| 167 | 186 | ||
| @@ -266,6 +285,17 @@ pub const ReverseIterator = struct { | |||
| 266 | defer iter.i = saved_i; | 285 | defer iter.i = saved_i; |
| 267 | return iter.prev(); | 286 | return iter.prev(); |
| 268 | } | 287 | } |
| 288 | |||
| 289 | /// Create a forward iterator at this point. It will repeat the | ||
| 290 | /// last CodePoint seen. | ||
| 291 | pub fn forwardIterator(iter: *ReverseIterator) Iterator { | ||
| 292 | if (iter.i) |i| { | ||
| 293 | var fwd: Iterator = .{ .i = i, .bytes = iter.bytes }; | ||
| 294 | _ = fwd.next(); | ||
| 295 | return fwd; | ||
| 296 | } | ||
| 297 | return .{ .i = 0, .bytes = iter.bytes }; | ||
| 298 | } | ||
| 269 | }; | 299 | }; |
| 270 | 300 | ||
| 271 | inline fn followbyte(b: u8) bool { | 301 | inline fn followbyte(b: u8) bool { |
| @@ -410,6 +440,23 @@ test ReverseIterator { | |||
| 410 | try testing.expectEqual(@as(?CodePoint, null), r_iter.prev()); | 440 | try testing.expectEqual(@as(?CodePoint, null), r_iter.prev()); |
| 411 | try testing.expectEqual(@as(?CodePoint, null), r_iter.prev()); | 441 | try testing.expectEqual(@as(?CodePoint, null), r_iter.prev()); |
| 412 | } | 442 | } |
| 443 | { | ||
| 444 | var r_iter: ReverseIterator = .init("123"); | ||
| 445 | try testing.expectEqual(@as(u21, '3'), r_iter.prev().?.code); | ||
| 446 | try testing.expectEqual(@as(u21, '2'), r_iter.prev().?.code); | ||
| 447 | try testing.expectEqual(@as(u21, '1'), r_iter.prev().?.code); | ||
| 448 | var iter = r_iter.forwardIterator(); | ||
| 449 | try testing.expectEqual(@as(u21, '1'), iter.next().?.code); | ||
| 450 | try testing.expectEqual(@as(u21, '2'), iter.next().?.code); | ||
| 451 | try testing.expectEqual(@as(u21, '3'), iter.next().?.code); | ||
| 452 | r_iter = iter.reverseIterator(); | ||
| 453 | try testing.expectEqual(@as(u21, '3'), r_iter.prev().?.code); | ||
| 454 | try testing.expectEqual(@as(u21, '2'), r_iter.prev().?.code); | ||
| 455 | iter = r_iter.forwardIterator(); | ||
| 456 | r_iter = iter.reverseIterator(); | ||
| 457 | try testing.expectEqual(@as(u21, '2'), iter.next().?.code); | ||
| 458 | try testing.expectEqual(@as(u21, '2'), r_iter.prev().?.code); | ||
| 459 | } | ||
| 413 | } | 460 | } |
| 414 | 461 | ||
| 415 | const std = @import("std"); | 462 | const std = @import("std"); |