A string is a sequence of characters. In Jai, a string is represented as an array view of bytes (u8
). Unlike the C programming language, Jai strings are NOT zero-terminated. The strings in Jai are UTF-8, and do not support unicode.
Here is a basic struct definition of a string:
string :: struct {
count: int; // amount of characters in the string
data: *u8; // pointer to the start of the characters
}
Strings as boolean values
Strings implicitly cast to boolean values that can be then used in if statements. if str
is true, then str
has charaters in it. If str
is false, str
is the empty string.
str : string = "Hello.";
if str {
} else {
}
Multi-line String
Multi-line strings can be declared first by typing in the identifier, followed by an assign statement, #string
, following by a token indicator for the end of the string, followed by the multi-line string.
multi_line_string := #string END_STRING
This
is
a
multi-line
string.
END_STRING
print(multi_line_string);
In the example above, multi_line_string
prints out:
This
is
a
multi-line
string.
String operations
Here are some common string operations people may use that are available in the String
and Basic
module:
// string comparing functions
equal :: (a: string, b: string) -> bool;
compare :: (a: string, b: string) -> int;
contains :: (str: string, substring: string) -> bool;
(read about what #must does)
equal
checks if two strings are equal. Returns true if both strings are equal. Returns false if not equal. compare
compares two strings a
and b
. Returns -1 if a
is less than b
, 1 if a
is greater than b
, and 0 if they are equal. Similar to strcmp
in C. contains
returns true
if the string contains substring
.
// string begins with and ends with functions
begins_with :: (str: string, prefix: string) -> bool;
ends_with :: (str: string, suffix: string) -> bool;
begins_with
checks if a given string begins with a specified prefix. ends_with
checks if a given string ends with a specified suffix.
// concatenating and spliting strings
join :: (inputs: string, separator := "", before_first := false, after_last := false) -> string;
split :: (str: string, separator: string) -> [] string;
Joins all the string inputs together to form a larger string. For example: join("a","b","c","d")
outputs “abcd”. split
splits an input string according to a separator.
// string to int/float and parsing functions
string_to_int :: (str: string) -> int, bool;
string_to_float :: (str: string) -> float, bool;
parse_float :: (line: *string) -> float, bool;
parse_int :: (line: *string) -> int, bool;
parse_token :: (line: *string) -> string, bool;
Attempts to parse a string into a float, token, or int.
sprint :: (fmt: string, args: ..Any) -> string;
// prints out "Congratulations John! You won with a score of: 1000"
name := "John";
score := 1000;
str := sprint("Congratulations %! You won with a score of: %\n", name, score);
sprint
functions similar to print, except instead of printing directly to the console, it outputs a string as a return value.
// c string manipulation functions
to_c_string :: (str: string) -> *u8; // NOTE: This function heap allocates memory
c_style_strlen :: (ptr: *u8) -> int;
These functions manipulate c-strings received from c-libraries.
String Builder
init_string_builder :: (builder: *String_Builder, buffer_size := -1)
This function initializes the String Builder
.
builder: String_Builder;
builder.allocator = temp;
This line of code sets the String_Builder
's allocator to whatever context allocator one wants. In this case, we set it to the temporary allocator.
free_buffers :: (builder: *String_Builder)
This function deallocates the String Builder
memory.
append :: (builder: *String_Builder, s: *u8, length: s64)
append :: (builder: *String_Builder, s: string)
append :: (builder: *String_Builder, byte: u8)
Appends a string to the buffer. Used to concatenate multiple strings together, for example, when in a loop.
print_to_builder :: (builder: *String_Builder, format_string: string, args: ..Any) -> bool
Prints out the items to the String_Builder. Has a format similar to the print
function. Here is an example use case:
builder: String_Builder;
number := 42;
print_to_builder(*builder, "My name is: %1 %2. My favorite number is: %3\n", "Issac", "Newton", number);
print("String_Builder output is: [%]\n", builder_to_string(*builder));
builder_to_string :: (builder: *String_Builder, allocator := context.allocator, extra_bytes_to_prepend := 0) -> string
Takes the String_Builder
contents and returns a string.