authorgravatar for kris.tate+github@gmail.comkristopher tate <kris.tate+github@gmail.com> 2018-11-26 01:09:12+09:00
committergravatar for kris.tate+github@gmail.comkristopher tate <kris.tate+github@gmail.com> 2018-11-26 02:02:17+09:00
log0f7de58b642539ad6a71368940f43f59a41e71b2
tree085adcf08f542bd6937e80545b8910fb1fa23511
parentf6cd02be6551f3ca702b76b7ca2ab7567effe680
signature Commit is signed but in an unrecognized format.

std.mem: add new separate method and rework SplitIterator;


2 files changed, 103 insertions(+), 15 deletions(-)

std/mem.zig+95-9
...@@ -607,11 +607,15 @@ pub fn eql_slice_u8(a: []const u8, b: []const u8) bool {...@@ -607,11 +607,15 @@ pub fn eql_slice_u8(a: []const u8, b: []const u8) bool {
607/// any of the bytes in `split_bytes`.607/// any of the bytes in `split_bytes`.
608/// split(" abc def ghi ", " ")608/// split(" abc def ghi ", " ")
609/// Will return slices for "abc", "def", "ghi", null, in that order.609/// Will return slices for "abc", "def", "ghi", null, in that order.
610/// If `split_bytes` does not exist in buffer,
611/// the iterator will return `buffer`, null, in that order.
610pub fn split(buffer: []const u8, split_bytes: []const u8) SplitIterator {612pub fn split(buffer: []const u8, split_bytes: []const u8) SplitIterator {
611 return SplitIterator{613 return SplitIterator{
612 .index = 0,614 .index = 0,
613 .buffer = buffer,615 .buffer = buffer,
614 .split_bytes = split_bytes,616 .split_bytes = split_bytes,
617 .glob = true,
618 .spun = false,
615 };619 };
616}620}
617621
...@@ -621,6 +625,76 @@ test "mem.split" {...@@ -621,6 +625,76 @@ test "mem.split" {
621 assert(eql(u8, it.next().?, "def"));625 assert(eql(u8, it.next().?, "def"));
622 assert(eql(u8, it.next().?, "ghi"));626 assert(eql(u8, it.next().?, "ghi"));
623 assert(it.next() == null);627 assert(it.next() == null);
628
629 it = split("..\\bob", "\\");
630 assert(eql(u8, it.next().?, ".."));
631 assert(eql(u8, "..", "..\\bob"[0..it.index]));
632 assert(eql(u8, it.next().?, "bob"));
633 assert(it.next() == null);
634
635 it = split("//a/b", "/");
636 assert(eql(u8, it.next().?, "a"));
637 assert(eql(u8, it.next().?, "b"));
638 assert(eql(u8, "//a/b", "//a/b"[0..it.index]));
639 assert(it.next() == null);
640
641 it = split("|", "|");
642 assert(it.next() == null);
643
644 it = split("", "|");
645 assert(eql(u8, it.next().?, ""));
646 assert(it.next() == null);
647
648 it = split("hello", "");
649 assert(eql(u8, it.next().?, "hello"));
650 assert(it.next() == null);
651
652 it = split("hello", " ");
653 assert(eql(u8, it.next().?, "hello"));
654 assert(it.next() == null);
655}
656
657/// Returns an iterator that iterates over the slices of `buffer` that
658/// seperates by bytes in `delimiter`.
659/// separate("abc|def||ghi", "|")
660/// Will return slices for "abc", "def", "", "ghi", null, in that order.
661/// If `delimiter` does not exist in buffer,
662/// the iterator will return `buffer`, null, in that order.
663pub fn separate(buffer: []const u8, delimiter: []const u8) SplitIterator {
664 return SplitIterator{
665 .index = 0,
666 .buffer = buffer,
667 .split_bytes = delimiter,
668 .glob = false,
669 .spun = false,
670 };
671}
672
673test "mem.separate" {
674 var it = separate("abc|def||ghi", "|");
675 assert(eql(u8, it.next().?, "abc"));
676 assert(eql(u8, it.next().?, "def"));
677 assert(eql(u8, it.next().?, ""));
678 assert(eql(u8, it.next().?, "ghi"));
679 assert(it.next() == null);
680
681 it = separate("", "|");
682 assert(eql(u8, it.next().?, ""));
683 assert(it.next() == null);
684
685 it = separate("|", "|");
686 assert(eql(u8, it.next().?, ""));
687 assert(eql(u8, it.next().?, ""));
688 assert(it.next() == null);
689
690 it = separate("hello", "");
691 assert(eql(u8, it.next().?, "hello"));
692 assert(it.next() == null);
693
694 it = separate("hello", " ");
695 assert(eql(u8, it.next().?, "hello"));
696 assert(it.next() == null);
697
624}698}
625699
626pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool {700pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool {
...@@ -645,20 +719,32 @@ pub const SplitIterator = struct {...@@ -645,20 +719,32 @@ pub const SplitIterator = struct {
645 buffer: []const u8,719 buffer: []const u8,
646 split_bytes: []const u8,720 split_bytes: []const u8,
647 index: usize,721 index: usize,
722 glob: bool,
723 spun: bool,
648724
725 /// Iterates and returns null or optionally a slice the next split segment
649 pub fn next(self: *SplitIterator) ?[]const u8 {726 pub fn next(self: *SplitIterator) ?[]const u8 {
650 // move to beginning of token727 if (self.spun) {
651 while (self.index < self.buffer.len and self.isSplitByte(self.buffer[self.index])) : (self.index += 1) {}728 if (self.index + 1 > self.buffer.len) return null;
652 const start = self.index;729 self.index += 1;
653 if (start == self.buffer.len) {730 }
654 return null;731
732 self.spun = true;
733
734 if (self.glob) {
735 while (self.index < self.buffer.len and self.isSplitByte(self.buffer[self.index])) : (self.index += 1) {}
655 }736 }
656737
657 // move to end of token738 var cursor = self.index;
658 while (self.index < self.buffer.len and !self.isSplitByte(self.buffer[self.index])) : (self.index += 1) {}739 while (cursor < self.buffer.len and !self.isSplitByte(self.buffer[cursor])) : (cursor += 1) {}
659 const end = self.index;740
741 defer self.index = cursor;
742
743 if (cursor == self.buffer.len) {
744 return if (self.glob and self.index == cursor and self.index > 0) null else self.buffer[self.index..];
745 }
660746
661 return self.buffer[start..end];747 return self.buffer[self.index..cursor];
662 }748 }
663749
664 /// Returns a slice of the remaining bytes. Does not affect iterator state.750 /// Returns a slice of the remaining bytes. Does not affect iterator state.
std/os/path.zig+8-6
...@@ -967,12 +967,14 @@ pub fn relativeWindows(allocator: *Allocator, from: []const u8, to: []const u8)...@@ -967,12 +967,14 @@ pub fn relativeWindows(allocator: *Allocator, from: []const u8, to: []const u8)
967 // shave off the trailing slash967 // shave off the trailing slash
968 result_index -= 1;968 result_index -= 1;
969969
970 var rest_it = mem.split(to_rest, "/\\");970 if (to_rest.len > 0) {
971 while (rest_it.next()) |to_component| {971 var rest_it = mem.split(to_rest, "/\\");
972 result[result_index] = '\\';972 while (rest_it.next()) |to_component| {
973 result_index += 1;973 result[result_index] = '\\';
974 mem.copy(u8, result[result_index..], to_component);974 result_index += 1;
975 result_index += to_component.len;975 mem.copy(u8, result[result_index..], to_component);
976 result_index += to_component.len;
977 }
976 }978 }
977979
978 return result[0..result_index];980 return result[0..result_index];