string code docs

This commit is contained in:
Jon Lipstate
2023-03-27 20:09:51 -07:00
parent aa6299f114
commit bf82c40964
6 changed files with 1810 additions and 513 deletions
+202 -44
View File
@@ -4,6 +4,20 @@ import "core:io"
import "core:unicode"
import "core:unicode/utf8"
/*
Converts invalid UTF-8 sequences in the input string `s` to the `replacement` string.
*Allocates Using Provided Allocator*
Inputs:
- s: Input string that may contain invalid UTF-8 sequences.
- replacement: String to replace invalid UTF-8 sequences with.
- allocator: (default: context.allocator).
WARNING: Allocation does not occur when len(s) == 0
Returns: A valid UTF-8 string with invalid sequences replaced by `replacement`.
*/
to_valid_utf8 :: proc(s, replacement: string, allocator := context.allocator) -> string {
if len(s) == 0 {
return ""
@@ -33,7 +47,7 @@ to_valid_utf8 :: proc(s, replacement: string, allocator := context.allocator) ->
invalid := false
for i := 0; i < len(s); /**/ {
for i := 0; i < len(s); /**/{
c := s[i]
if c < utf8.RUNE_SELF {
i += 1
@@ -57,13 +71,20 @@ to_valid_utf8 :: proc(s, replacement: string, allocator := context.allocator) ->
}
return to_string(b)
}
/*
returns the input string `s` with all runes set to lowered case
always allocates using the `allocator`
Converts the input string `s` to all lowercase characters.
strings.to_lower("test") -> test
strings.to_lower("Test") -> test
*Allocates Using Provided Allocator*
Inputs:
- s: Input string to be converted.
- allocator: (default: context.allocator).
Example:
```odin
strings.to_lower("TeST") -> test
```
Returns: A new string with all characters converted to lowercase.
*/
to_lower :: proc(s: string, allocator := context.allocator) -> string {
b: Builder
@@ -73,13 +94,20 @@ to_lower :: proc(s: string, allocator := context.allocator) -> string {
}
return to_string(b)
}
/*
returns the input string `s` with all runes set to upper case
always allocates using the `allocator`
Converts the input string `s` to all uppercase characters.
strings.to_upper("test") -> TEST
*Allocates Using Provided Allocator*
Inputs:
- s: Input string to be converted.
- allocator: (default: context.allocator).
Example:
```odin
strings.to_upper("Test") -> TEST
```
Returns: A new string with all characters converted to uppercase.
*/
to_upper :: proc(s: string, allocator := context.allocator) -> string {
b: Builder
@@ -89,21 +117,36 @@ to_upper :: proc(s: string, allocator := context.allocator) -> string {
}
return to_string(b)
}
/*
Checks if the rune `c` is a delimiter (' ', '-', or '_').
// returns true when the `c` rune is a space, '-' or '_'
// useful when treating strings like words in a text editor or html paths
Inputs:
- c: Rune to check for delimiter status.
Returns: True if `c` is a delimiter, false otherwise.
*/
is_delimiter :: proc(c: rune) -> bool {
return c == '-' || c == '_' || is_space(c)
}
/*
Checks if the rune `r` is a non-alphanumeric or space character.
// returns true when the `r` rune is a non alpha or `unicode.is_space` rune
Inputs:
- r: Rune to check for separator status.
Returns: True if `r` is a non-alpha or `unicode.is_space` rune.
*/
is_separator :: proc(r: rune) -> bool {
if r <= 0x7f {
switch r {
case '0'..='9': return false
case 'a'..='z': return false
case 'A'..='Z': return false
case '_': return false
case '0' ..= '9':
return false
case 'a' ..= 'z':
return false
case 'A' ..= 'Z':
return false
case '_':
return false
}
return true
}
@@ -115,12 +158,32 @@ is_separator :: proc(r: rune) -> bool {
return unicode.is_space(r)
}
/*
iterator that loops through the string and calls the callback with the `prev`, `curr` and `next` rune
on empty string `s` the callback gets called once with empty runes
Iterates over a string, calling a callback for each rune with the previous, current, and next runes as arguments.
Inputs:
- w: An io.Writer to be used by the callback for writing output.
- s: The input string to be iterated over.
- callback: A procedure to be called for each rune in the string, with arguments (w: io.Writer, prev, curr, next: rune).
The callback can utilize the provided io.Writer to write output during the iteration.
Example:
```odin
my_callback :: proc(w: io.Writer, prev, curr, next: rune) {
fmt.println("my_callback", curr) // <-- Custom logic here
}
s := "hello world"
b: strings.Builder
strings.builder_init_len(&b, len(s))
w := strings.to_writer(&b)
strings.string_case_iterator(w, s, my_callback)
```
*/
string_case_iterator :: proc(w: io.Writer, s: string, callback: proc(w: io.Writer, prev, curr, next: rune)) {
string_case_iterator :: proc(
w: io.Writer,
s: string,
callback: proc(w: io.Writer, prev, curr, next: rune),
) {
prev, curr: rune
for next in s {
if curr == 0 {
@@ -139,10 +202,19 @@ string_case_iterator :: proc(w: io.Writer, s: string, callback: proc(w: io.Write
callback(w, prev, curr, 0)
}
}
// Alias to `to_camel_case`
to_lower_camel_case :: to_camel_case
/*
Converts the input string `s` to "lowerCamelCase".
// converts the `s` string to "lowerCamelCase"
*Allocates Using Provided Allocator*
Inputs:
- s: Input string to be converted.
- allocator: (default: context.allocator).
Returns: A "lowerCamelCase" formatted string.
*/
to_camel_case :: proc(s: string, allocator := context.allocator) -> string {
s := s
s = trim_space(s)
@@ -164,10 +236,19 @@ to_camel_case :: proc(s: string, allocator := context.allocator) -> string {
return to_string(b)
}
// Alias to `to_pascal_case`
to_upper_camel_case :: to_pascal_case
/*
Converts the input string `s` to "UpperCamelCase" (PascalCase).
// converts the `s` string to "PascalCase"
*Allocates Using Provided Allocator*
Inputs:
- s: Input string to be converted.
- allocator: (default: context.allocator).
Returns: A "PascalCase" formatted string.
*/
to_pascal_case :: proc(s: string, allocator := context.allocator) -> string {
s := s
s = trim_space(s)
@@ -189,17 +270,31 @@ to_pascal_case :: proc(s: string, allocator := context.allocator) -> string {
return to_string(b)
}
/*
Returns a string converted to a delimiter-separated case with configurable casing
/*
returns the `s` string to words seperated by the given `delimiter` rune
all runes will be upper or lowercased based on the `all_uppercase` bool
*Allocates Using Provided Allocator*
strings.to_delimiter_case("Hello World", '_', false) -> hello_world
strings.to_delimiter_case("Hello World", ' ', true) -> HELLO WORLD
strings.to_delimiter_case("Hello World", ' ', true) -> HELLO WORLD
strings.to_delimiter_case("aBC", '_', false) -> a_b_c
Inputs:
- s: The input string to be converted
- delimiter: The rune to be used as the delimiter between words
- all_upper_case: A boolean indicating if the output should be all uppercased (true) or lowercased (false)
- allocator: (default: context.allocator).
Example:
```odin
strings.to_delimiter_case("Hello World", '_', false) // -> "hello_world"
strings.to_delimiter_case("Hello World", ' ', true) // -> "HELLO WORLD"
strings.to_delimiter_case("aBC", '_', false) // -> "a_b_c"
```
Returns: The converted string
*/
to_delimiter_case :: proc(s: string, delimiter: rune, all_upper_case: bool, allocator := context.allocator) -> string {
to_delimiter_case :: proc(
s: string,
delimiter: rune,
all_upper_case: bool,
allocator := context.allocator,
) -> string {
s := s
s = trim_space(s)
b: Builder
@@ -237,35 +332,96 @@ to_delimiter_case :: proc(s: string, delimiter: rune, all_upper_case: bool, allo
return to_string(b)
}
/*
Converts a string to "snake_case" with all runes lowercased
/*
converts the `s` string to "snake_case" with all runes lowercased
strings.to_snake_case("HelloWorld") -> hello_world
strings.to_snake_case("Hello World") -> hello_world
*Allocates Using Provided Allocator*
Inputs:
- s: The input string to be converted
- allocator: (default: context.allocator).
Example:
```odin
strings.to_snake_case("HelloWorld") // -> "hello_world"
strings.to_snake_case("Hello World") // -> "hello_world"
```
Returns: The converted string
*/
to_snake_case :: proc(s: string, allocator := context.allocator) -> string {
return to_delimiter_case(s, '_', false, allocator)
}
// Alias for `to_upper_snake_case`
to_screaming_snake_case :: to_upper_snake_case
/*
Converts a string to "SNAKE_CASE" with all runes uppercased
// converts the `s` string to "SNAKE_CASE" with all runes uppercased
*Allocates Using Provided Allocator*
Inputs:
- s: The input string to be converted
- allocator: (default: context.allocator).
Example:
```odin
strings.to_upper_snake_case("HelloWorld") // -> "HELLO_WORLD"
```
Returns: The converted string
*/
to_upper_snake_case :: proc(s: string, allocator := context.allocator) -> string {
return to_delimiter_case(s, '_', true, allocator)
}
/*
Converts a string to "kebab-case" with all runes lowercased
// converts the `s` string to "kebab-case" with all runes lowercased
*Allocates Using Provided Allocator*
Inputs:
- s: The input string to be converted
- allocator: (default: context.allocator).
Example:
```odin
strings.to_kebab_case("HelloWorld") // -> "hello-world"
```
Returns: The converted string
*/
to_kebab_case :: proc(s: string, allocator := context.allocator) -> string {
return to_delimiter_case(s, '-', false, allocator)
}
/*
Converts a string to "KEBAB-CASE" with all runes uppercased
// converts the `s` string to "KEBAB-CASE" with all runes uppercased
*Allocates Using Provided Allocator*
Inputs:
- s: The input string to be converted
- allocator: (default: context.allocator).
Example:
```odin
strings.to_upper_kebab_case("HelloWorld") // -> "HELLO-WORLD"
```
Returns: The converted string
*/
to_upper_kebab_case :: proc(s: string, allocator := context.allocator) -> string {
return to_delimiter_case(s, '-', true, allocator)
}
/*
Converts a string to "Ada_Case"
// converts the `s` string to "Ada_Case"
*Allocates Using Provided Allocator*
Inputs:
- s: The input string to be converted
- allocator: (default: context.allocator).
Example:
```odin
strings.to_ada_case("HelloWorld") // -> "Hello_World"
```
Returns: The converted string
*/
to_ada_case :: proc(s: string, allocator := context.allocator) -> string {
s := s
s = trim_space(s)
@@ -275,7 +431,9 @@ to_ada_case :: proc(s: string, allocator := context.allocator) -> string {
string_case_iterator(w, s, proc(w: io.Writer, prev, curr, next: rune) {
if !is_delimiter(curr) {
if is_delimiter(prev) || prev == 0 || (unicode.is_lower(prev) && unicode.is_upper(curr)) {
if is_delimiter(prev) ||
prev == 0 ||
(unicode.is_lower(prev) && unicode.is_upper(curr)) {
if prev != 0 {
io.write_rune(w, '_')
}