| ... | @@ -227,6 +227,8 @@ test "ascii character classes" { | ... | @@ -227,6 +227,8 @@ test "ascii character classes" { |
| 227 | testing.expect(isSpace(' ')); | 227 | testing.expect(isSpace(' ')); |
| 228 | } | 228 | } |
| 229 | | 229 | |
| | 230 | /// Allocates a lower case copy of `ascii_string`. |
| | 231 | /// Caller owns returned string and must free with `allocator`. |
| 230 | pub fn allocLowerString(allocator: *std.mem.Allocator, ascii_string: []const u8) ![]u8 { | 232 | pub fn allocLowerString(allocator: *std.mem.Allocator, ascii_string: []const u8) ![]u8 { |
| 231 | const result = try allocator.alloc(u8, ascii_string.len); | 233 | const result = try allocator.alloc(u8, ascii_string.len); |
| 232 | for (result) |*c, i| { | 234 | for (result) |*c, i| { |
| ... | @@ -241,6 +243,23 @@ test "allocLowerString" { | ... | @@ -241,6 +243,23 @@ test "allocLowerString" { |
| 241 | std.testing.expect(std.mem.eql(u8, "abcdefghijklmnopqrst0234+💩!", result)); | 243 | std.testing.expect(std.mem.eql(u8, "abcdefghijklmnopqrst0234+💩!", result)); |
| 242 | } | 244 | } |
| 243 | | 245 | |
| | 246 | /// Allocates an upper case copy of `ascii_string`. |
| | 247 | /// Caller owns returned string and must free with `allocator`. |
| | 248 | pub fn allocUpperString(allocator: *std.mem.Allocator, ascii_string: []const u8) ![]u8 { |
| | 249 | const result = try allocator.alloc(u8, ascii_string.len); |
| | 250 | for (result) |*c, i| { |
| | 251 | c.* = toUpper(ascii_string[i]); |
| | 252 | } |
| | 253 | return result; |
| | 254 | } |
| | 255 | |
| | 256 | test "allocUpperString" { |
| | 257 | const result = try allocUpperString(std.testing.allocator, "aBcDeFgHiJkLmNOPqrst0234+💩!"); |
| | 258 | defer std.testing.allocator.free(result); |
| | 259 | std.testing.expect(std.mem.eql(u8, "ABCDEFGHIJKLMNOPQRST0234+💩!", result)); |
| | 260 | } |
| | 261 | |
| | 262 | /// Compares strings `a` and `b` case insensitively and returns whether they are equal. |
| 244 | pub fn eqlIgnoreCase(a: []const u8, b: []const u8) bool { | 263 | pub fn eqlIgnoreCase(a: []const u8, b: []const u8) bool { |
| 245 | if (a.len != b.len) return false; | 264 | if (a.len != b.len) return false; |
| 246 | for (a) |a_c, i| { | 265 | for (a) |a_c, i| { |
| ... | @@ -255,7 +274,7 @@ test "eqlIgnoreCase" { | ... | @@ -255,7 +274,7 @@ test "eqlIgnoreCase" { |
| 255 | std.testing.expect(!eqlIgnoreCase("hElLo!", "helro!")); | 274 | std.testing.expect(!eqlIgnoreCase("hElLo!", "helro!")); |
| 256 | } | 275 | } |
| 257 | | 276 | |
| 258 | /// Finds `substr` in `container`, starting at `start_index`. | 277 | /// Finds `substr` in `container`, ignoring case, starting at `start_index`. |
| 259 | /// TODO boyer-moore algorithm | 278 | /// TODO boyer-moore algorithm |
| 260 | pub fn indexOfIgnoreCasePos(container: []const u8, start_index: usize, substr: []const u8) ?usize { | 279 | pub fn indexOfIgnoreCasePos(container: []const u8, start_index: usize, substr: []const u8) ?usize { |
| 261 | if (substr.len > container.len) return null; | 280 | if (substr.len > container.len) return null; |
| ... | @@ -268,7 +287,7 @@ pub fn indexOfIgnoreCasePos(container: []const u8, start_index: usize, substr: [ | ... | @@ -268,7 +287,7 @@ pub fn indexOfIgnoreCasePos(container: []const u8, start_index: usize, substr: [ |
| 268 | return null; | 287 | return null; |
| 269 | } | 288 | } |
| 270 | | 289 | |
| 271 | /// Finds `substr` in `container`, starting at `start_index`. | 290 | /// Finds `substr` in `container`, ignoring case, starting at index 0. |
| 272 | pub fn indexOfIgnoreCase(container: []const u8, substr: []const u8) ?usize { | 291 | pub fn indexOfIgnoreCase(container: []const u8, substr: []const u8) ?usize { |
| 273 | return indexOfIgnoreCasePos(container, 0, substr); | 292 | return indexOfIgnoreCasePos(container, 0, substr); |
| 274 | } | 293 | } |