diff options
Diffstat (limited to 'std/mem.zig')
| -rw-r--r-- | std/mem.zig | 88 |
1 files changed, 86 insertions, 2 deletions
diff --git a/std/mem.zig b/std/mem.zig index 8a59d6251b..cc3161cddd 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -11,6 +11,8 @@ pub const Allocator = struct { /// Allocate byte_count bytes and return them in a slice, with the /// slice's pointer aligned at least to alignment bytes. /// The returned newly allocated memory is undefined. + /// `alignment` is guaranteed to be >= 1 + /// `alignment` is guaranteed to be a power of 2 allocFn: fn (self: &Allocator, byte_count: usize, alignment: u29) Error![]u8, /// If `new_byte_count > old_mem.len`: @@ -18,10 +20,12 @@ pub const Allocator = struct { /// * alignment >= alignment of old_mem.ptr /// /// If `new_byte_count <= old_mem.len`: - /// * this function must return successfully. + /// * this function must return successfully. /// * alignment <= alignment of old_mem.ptr /// /// The returned newly allocated memory is undefined. + /// `alignment` is guaranteed to be >= 1 + /// `alignment` is guaranteed to be a power of 2 reallocFn: fn (self: &Allocator, old_mem: []u8, new_byte_count: usize, alignment: u29) Error![]u8, /// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn` @@ -170,6 +174,20 @@ pub fn dupe(allocator: &Allocator, comptime T: type, m: []const T) ![]T { return new_buf; } +/// Remove values from the beginning of a slice. +pub fn trimLeft(comptime T: type, slice: []const T, values_to_strip: []const T) []const T { + var begin: usize = 0; + while (begin < slice.len and indexOfScalar(T, values_to_strip, slice[begin]) != null) : (begin += 1) {} + return slice[begin..]; +} + +/// Remove values from the end of a slice. +pub fn trimRight(comptime T: type, slice: []const T, values_to_strip: []const T) []const T { + var end: usize = slice.len; + while (end > 0 and indexOfScalar(T, values_to_strip, slice[end - 1]) != null) : (end -= 1) {} + return slice[0..end]; +} + /// Remove values from the beginning and end of a slice. pub fn trim(comptime T: type, slice: []const T, values_to_strip: []const T) []const T { var begin: usize = 0; @@ -180,6 +198,8 @@ pub fn trim(comptime T: type, slice: []const T, values_to_strip: []const T) []co } test "mem.trim" { + assert(eql(u8, trimLeft(u8, " foo\n ", " \n"), "foo\n ")); + assert(eql(u8, trimRight(u8, " foo\n ", " \n"), " foo")); assert(eql(u8, trim(u8, " foo\n ", " \n"), "foo")); assert(eql(u8, trim(u8, "foo", " \n"), "foo")); } @@ -189,6 +209,17 @@ pub fn indexOfScalar(comptime T: type, slice: []const T, value: T) ?usize { return indexOfScalarPos(T, slice, 0, value); } +/// Linear search for the last index of a scalar value inside a slice. +pub fn lastIndexOfScalar(comptime T: type, slice: []const T, value: T) ?usize { + var i: usize = slice.len; + while (i != 0) { + i -= 1; + if (slice[i] == value) + return i; + } + return null; +} + pub fn indexOfScalarPos(comptime T: type, slice: []const T, start_index: usize, value: T) ?usize { var i: usize = start_index; while (i < slice.len) : (i += 1) { @@ -202,6 +233,18 @@ pub fn indexOfAny(comptime T: type, slice: []const T, values: []const T) ?usize return indexOfAnyPos(T, slice, 0, values); } +pub fn lastIndexOfAny(comptime T: type, slice: []const T, values: []const T) ?usize { + var i: usize = slice.len; + while (i != 0) { + i -= 1; + for (values) |value| { + if (slice[i] == value) + return i; + } + } + return null; +} + pub fn indexOfAnyPos(comptime T: type, slice: []const T, start_index: usize, values: []const T) ?usize { var i: usize = start_index; while (i < slice.len) : (i += 1) { @@ -217,6 +260,22 @@ pub fn indexOf(comptime T: type, haystack: []const T, needle: []const T) ?usize return indexOfPos(T, haystack, 0, needle); } +/// Find the index in a slice of a sub-slice, searching from the end backwards. +/// To start looking at a different index, slice the haystack first. +/// TODO is there even a better algorithm for this? +pub fn lastIndexOf(comptime T: type, haystack: []const T, needle: []const T) ?usize { + if (needle.len > haystack.len) + return null; + + var i: usize = haystack.len - needle.len; + while (true) : (i -= 1) { + if (mem.eql(T, haystack[i..i+needle.len], needle)) + return i; + if (i == 0) + return null; + } +} + // TODO boyer-moore algorithm pub fn indexOfPos(comptime T: type, haystack: []const T, start_index: usize, needle: []const T) ?usize { if (needle.len > haystack.len) @@ -233,9 +292,19 @@ pub fn indexOfPos(comptime T: type, haystack: []const T, start_index: usize, nee test "mem.indexOf" { assert(??indexOf(u8, "one two three four", "four") == 14); + assert(??lastIndexOf(u8, "one two three two four", "two") == 14); assert(indexOf(u8, "one two three four", "gour") == null); + assert(lastIndexOf(u8, "one two three four", "gour") == null); assert(??indexOf(u8, "foo", "foo") == 0); + assert(??lastIndexOf(u8, "foo", "foo") == 0); assert(indexOf(u8, "foo", "fool") == null); + assert(lastIndexOf(u8, "foo", "lfoo") == null); + assert(lastIndexOf(u8, "foo", "fool") == null); + + assert(??indexOf(u8, "foo foo", "foo") == 0); + assert(??lastIndexOf(u8, "foo foo", "foo") == 4); + assert(??lastIndexOfAny(u8, "boo, cat", "abo") == 6); + assert(??lastIndexOfScalar(u8, "boo", 'o') == 2); } /// Reads an integer from memory with size equal to bytes.len. @@ -355,9 +424,24 @@ pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool return if (needle.len > haystack.len) false else eql(T, haystack[0 .. needle.len], needle); } +test "mem.startsWith" { + assert(startsWith(u8, "Bob", "Bo")); + assert(!startsWith(u8, "Needle in haystack", "haystack")); +} + +pub fn endsWith(comptime T: type, haystack: []const T, needle: []const T) bool { + return if (needle.len > haystack.len) false else eql(T, haystack[haystack.len - needle.len ..], needle); +} + + +test "mem.endsWith" { + assert(endsWith(u8, "Needle in haystack", "haystack")); + assert(!endsWith(u8, "Bob", "Bo")); +} + pub const SplitIterator = struct { buffer: []const u8, - split_bytes: []const u8, + split_bytes: []const u8, index: usize, pub fn next(self: &SplitIterator) ?[]const u8 { |
