| ... | @@ -2030,6 +2030,79 @@ test "rotate" { | ... | @@ -2030,6 +2030,79 @@ test "rotate" { |
| 2030 | testing.expect(eql(i32, &arr, &[_]i32{ 1, 2, 4, 5, 3 })); | 2030 | testing.expect(eql(i32, &arr, &[_]i32{ 1, 2, 4, 5, 3 })); |
| 2031 | } | 2031 | } |
| 2032 | | 2032 | |
| | 2033 | /// Replace needle with replacement as many times as possible, writing to an output buffer which is assumed to be of |
| | 2034 | /// appropriate size. Use replacementSize to calculate an appropriate buffer size. |
| | 2035 | pub fn replace(comptime T: type, input: []const T, needle: []const T, replacement: []const T, output: []T) usize { |
| | 2036 | var i: usize = 0; |
| | 2037 | var slide: usize = 0; |
| | 2038 | var replacements: usize = 0; |
| | 2039 | while (slide < input.len) { |
| | 2040 | if (mem.indexOf(T, input[slide..], needle) == @as(usize, 0)) { |
| | 2041 | mem.copy(T, output[i..i + replacement.len], replacement); |
| | 2042 | i += replacement.len; |
| | 2043 | slide += needle.len; |
| | 2044 | replacements += 1; |
| | 2045 | } else { |
| | 2046 | output[i] = input[slide]; |
| | 2047 | i += 1; |
| | 2048 | slide += 1; |
| | 2049 | } |
| | 2050 | } |
| | 2051 | |
| | 2052 | return replacements; |
| | 2053 | } |
| | 2054 | |
| | 2055 | test "replace" { |
| | 2056 | var output: [29]u8 = undefined; |
| | 2057 | var replacements = replace(u8, "All your base are belong to us", "base", "Zig", output[0..]); |
| | 2058 | testing.expect(replacements == 1); |
| | 2059 | testing.expect(eql(u8, output[0..], "All your Zig are belong to us")); |
| | 2060 | |
| | 2061 | replacements = replace(u8, "Favor reading code over writing code.", "code", "", output[0..]); |
| | 2062 | testing.expect(replacements == 2); |
| | 2063 | testing.expect(eql(u8, output[0..], "Favor reading over writing .")); |
| | 2064 | } |
| | 2065 | |
| | 2066 | /// Calculate the size needed in an output buffer to perform a replacement. |
| | 2067 | pub fn replacementSize(comptime T: type, input: []const T, needle: []const T, replacement: []const T) usize { |
| | 2068 | var i: usize = 0; |
| | 2069 | var size: usize = input.len; |
| | 2070 | while (i < input.len) : (i += 1) { |
| | 2071 | if (mem.indexOf(T, input[i..], needle) == @as(usize, 0)) { |
| | 2072 | size = size - needle.len + replacement.len; |
| | 2073 | i += needle.len; |
| | 2074 | } |
| | 2075 | } |
| | 2076 | |
| | 2077 | return size; |
| | 2078 | } |
| | 2079 | |
| | 2080 | test "replacementSize" { |
| | 2081 | testing.expect(replacementSize(u8, "All your base are belong to us", "base", "Zig") == 29); |
| | 2082 | testing.expect(replacementSize(u8, "", "", "") == 0); |
| | 2083 | testing.expect(replacementSize(u8, "Favor reading code over writing code.", "code", "") == 29); |
| | 2084 | testing.expect(replacementSize(u8, "Only one obvious way to do things.", "things.", "things in Zig.") == 41); |
| | 2085 | } |
| | 2086 | |
| | 2087 | /// Perform a replacement on an allocated buffer of pre-determined size. Caller must free returned memory. |
| | 2088 | pub fn replaceOwned(comptime T: type, allocator: *Allocator, input: []const T, needle: []const T, replacement: []const T) Allocator.Error![]T { |
| | 2089 | var output = try allocator.alloc(T, replacementSize(T, input, needle, replacement)); |
| | 2090 | _ = replace(T, input, needle, replacement, output); |
| | 2091 | return output; |
| | 2092 | } |
| | 2093 | |
| | 2094 | test "replaceOwned" { |
| | 2095 | const allocator = std.heap.page_allocator; |
| | 2096 | |
| | 2097 | const base_replace = replaceOwned(u8, allocator, "All your base are belong to us", "base", "Zig") catch unreachable; |
| | 2098 | defer allocator.free(base_replace); |
| | 2099 | testing.expect(eql(u8, base_replace, "All your Zig are belong to us")); |
| | 2100 | |
| | 2101 | const zen_replace = replaceOwned(u8, allocator, "Favor reading code over writing code.", " code", "") catch unreachable; |
| | 2102 | defer allocator.free(zen_replace); |
| | 2103 | testing.expect(eql(u8, zen_replace, "Favor reading over writing.")); |
| | 2104 | } |
| | 2105 | |
| 2033 | /// Converts a little-endian integer to host endianness. | 2106 | /// Converts a little-endian integer to host endianness. |
| 2034 | pub fn littleToNative(comptime T: type, x: T) T { | 2107 | pub fn littleToNative(comptime T: type, x: T) T { |
| 2035 | return switch (builtin.endian) { | 2108 | return switch (builtin.endian) { |