Searching, comparing, splitting, trimming and scanning strings, and working with file paths.
Strings are bytes. Case-insensitive procedures fold only the ASCII letters, and nothing here
decodes UTF-8; use Unicode for that. Procedures that return a part of their input (trim,
the splits, path_filename) return a view into it, not a copy. Procedures that build a new string
(join, replace, to_lower_copy, path_join) allocate it with the context allocator, and the
caller frees it. A search that finds nothing returns -1, or false with an empty or whole string.
Reads the next token and reads it as true or false, in either case. The second result is false
when the token is anything else or there is none; the token is removed from line anyway.
line := "True rest";
value, ok := parse_bool(*line);
assert(ok && value && line == " rest");
Reads the next token and looks it up by name among the values of the enum type T. The second result is
false when no value has that name, and then the value is zero. The name is case sensitive.
Color :: enum { RED; GREEN; }
line := "GREEN;";
value, ok := parse_enum(*line, Color);
assert(ok && value == .GREEN && line == ";");
Splits name into its directory (with the trailing separator), its name without the extension, the
extension without the dot, and the name with the extension. All four point into name; a missing
part is empty.
path when its extension is already extension (without the dot); otherwise a new string with
.extension added. Another extension is kept, so a.txt becomes a.txt.png.
The components one after another with separator between them. A trailing separator on a component
is dropped first, so no separator is doubled. Empty components still add a separator.
Splits name into its directory (with the trailing separator), its name without the extension, the
extension without the dot, and the name with the extension. All four point into name; a missing
part is empty.
The part of s that starts at index and holds at most count bytes; empty when index is
past the end. Both must not be negative: a negative one fails an assert.
The index where substring first appears in s when ASCII letters are matched in either case, and
whether it was found. When it is not found the index is -1. An empty substring, or one longer than s,
is never found.
index, found := index_of_string_nocase("Hello World", "WORLD");
assert(found && index == 6);
Whether substring appears in s, and the part of s after its first match. When it does not appear the
remainder is empty. An empty substring is never found. The remainder points into s.
Whether any of the substrings appears in s, and the part of s after the earliest match. At one
position the first substring listed wins. Empty substrings are ignored.
Turns the ASCII capitals of s into lower case, in place. Other bytes are left as they are, so UTF-8
text is not folded. s must be writable, not a string literal.
text := copy_string("MiXeD");
defer free(text);
to_lower_in_place(text);
assert(text == "mixed");
Splits s at the first byte. Returns whether it was found, the part before it and the part after it.
found, left, right := split_from_left("key=a=b", #char"=");
assert(found && left == "key" && right == "a=b");
found, left, right = split_from_left("none", #char"=");
assert(!found && left == "none" && right == "");
Splits s at the last byte. Returns whether it was found, the part before it and the part after it.
found, left, right := split_from_right("a.b.c", #char".");
assert(found && left == "a.b" && right == "c");
found, left, right = split_from_right("abc", #char".");
assert(!found && left == "abc" && right == "");
Splits s at the first byte that is in bytes. Returns whether one was found, the part before it and
the part after it. When none is found the result is false, all of s and an empty string.
found, left, right := split_from_left_by_any("a,b;c", ",;");
assert(found && left == "a" && right == "b;c");
Splits s at the last byte that is in bytes. Returns whether one was found, the part before it and
the part after it. When none is found the result is false, all of s and an empty string.
found, left, right := split_from_right_by_any("a,b;c", ",;");
assert(found && left == "a,b" && right == "c");