summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/code_point.zig55
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
271inline fn followbyte(b: u8) bool { 301inline 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
415const std = @import("std"); 462const std = @import("std");