aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/TUI/module.jai6
-rw-r--r--modules/UTF8.jai60
-rw-r--r--ttt.jai11
3 files changed, 39 insertions, 38 deletions
diff --git a/modules/TUI/module.jai b/modules/TUI/module.jai
index e25672f..7c3a71d 100644
--- a/modules/TUI/module.jai
+++ b/modules/TUI/module.jai
@@ -398,7 +398,7 @@ get_key :: (timeout_milliseconds: s32 = -1) -> Key {
// By default, parse a single UTF8 character (1 to 4 bytes).
to_parse := input_string;
- to_parse.count = count_utf8_bytes(input_string[0]);
+ to_parse.count = count_character_bytes(input_string[0]);
defer advance(*input_string, to_parse.count); // Advance over parsed input.
// Try to parse escape code.
@@ -555,7 +555,7 @@ read_input_line :: (count_limit: int, is_visible: bool = true) -> string, Key {
case;
if is_escape_code(key) continue;
- buff_idx := map_character_to_buffer_idx(str, idx);
+ buff_idx := get_byte_idx(str, idx);
key_str := to_string(key,, allocator = temporary_allocator);
// Make sure we have space to append the new character at the end (in case we're trying to do it).
@@ -572,7 +572,7 @@ read_input_line :: (count_limit: int, is_visible: bool = true) -> string, Key {
idx += 1;
// Truncate string to avoid incomplete utf8 codes on the string tail.
- str.count = truncate_string(str, count_limit);
+ truncate(*str, count_limit);
}
}
diff --git a/modules/UTF8.jai b/modules/UTF8.jai
index eba4585..b583809 100644
--- a/modules/UTF8.jai
+++ b/modules/UTF8.jai
@@ -1,25 +1,29 @@
-// BBBB BBBB & 1100 0000 == 10XX XXXX -> is continuation byte
-// TODO Maybe rename to: is_continuation_byte
-is_utf8_continuation_byte :: inline (byte: u8) -> bool {
+// Some procedures to help working with UTF8 strings.
+// https://en.wikipedia.org/wiki/UTF-8
+
+// Returns true if argument is a continuation byte.
+is_continuation_byte :: inline (byte: u8) -> bool {
+ // BBBB BBBB & 1100 0000 == 10XX XXXX -> is continuation byte
return (byte & 0xC0) == 0x80;
}
-// BBBB BBBB & 1110 0000 == 110X XXXX -> 1 initial + 1 continuation byte
-// BBBB BBBB & 1111 0000 == 1110 XXXX -> 1 initial + 2 continuation byte
-// BBBB BBBB & 1111 1000 == 1111 0XXX -> 1 initial + 3 continuation byte
-// TODO Maybe rename to: count_character_bytes
-count_utf8_bytes :: inline (byte: u8) -> int {
- if (byte & 0xE0) == 0xC0 return 1+1;
- if (byte & 0xF0) == 0xE0 return 1+2;
- if (byte & 0xF8) == 0xF0 return 1+3;
+// Given a leading_byte, returns the number of bytes on the character.
+count_character_bytes :: inline (leading_byte: u8) -> int {
+ // BBBB BBBB & 1110 0000 == 110X XXXX -> 1 initial + 1 continuation byte
+ if (leading_byte & 0xE0) == 0xC0 return 1+1;
+
+ // BBBB BBBB & 1111 0000 == 1110 XXXX -> 1 initial + 2 continuation byte
+ if (leading_byte & 0xF0) == 0xE0 return 1+2;
+
+ // BBBB BBBB & 1111 1000 == 1111 0XXX -> 1 initial + 3 continuation byte
+ if (leading_byte & 0xF8) == 0xF0 return 1+3;
+
return 1;
}
-// Truncates the string to the length provided or shorter, in case of UTF8 strings that require so.
-// Truncation is done by zeroing the tail of the string in place.
-// Returns length of truncated string.
-// TODO Maybe rename to: truncate
-truncate_string :: (str: string, length: int) -> length: int {
+// Truncates the string to the provided length and zeroes the discarded bytes.
+// Returns the length of truncated string or -1 if string has no data.
+truncate :: (str: *string, length: int) -> length: int {
if str.data == null then return -1;
if str.count < length then length = str.count;
@@ -29,7 +33,7 @@ truncate_string :: (str: string, length: int) -> length: int {
// Find index of first continuation byte.
idx := length;
- while (idx > 0 && is_utf8_continuation_byte(data[idx - 1])) {
+ while (idx > 0 && is_continuation_byte(data[idx - 1])) {
idx -= 1;
}
continuation_bytes := length - idx;
@@ -50,13 +54,12 @@ truncate_string :: (str: string, length: int) -> length: int {
}
memset(data + length, 0, count - length);
- // str.count = length; TODO We should be doing this...
+ str.count = length;
return length;
}
// Returns true when the string is empty or consists of space characters.
-// TODO Maybe rename to: is_empty
-is_empty_string :: (str: string) -> bool {
+is_empty :: (str: string) -> bool {
for 0..str.count-1 {
if str[it] == {
case #char "\0"; #through;
@@ -74,21 +77,21 @@ is_empty_string :: (str: string) -> bool {
return true;
}
-// Counts number of characters in string.
+// Counts the number of characters.
count_characters :: (str: string) -> int {
characters := 0;
idx := 0;
while idx < str.count {
- idx += count_utf8_bytes(str[idx]);
+ idx += count_character_bytes(str[idx]);
characters += 1;
}
return characters;
}
-// Delete character.
+// Deletes character by it's index, and moves tail data to take its place.
delete_character :: (str: *string, character_idx: int) {
- buffer_idx := map_character_to_buffer_idx(str.*, character_idx);
- bytes_to_delete := count_utf8_bytes(str.data[buffer_idx]);
+ buffer_idx := get_byte_idx(str.*, character_idx);
+ bytes_to_delete := count_character_bytes(str.data[buffer_idx]);
for buffer_idx..str.count-1-bytes_to_delete {
str.data[it] = str.data[it+bytes_to_delete];
@@ -100,9 +103,8 @@ delete_character :: (str: *string, character_idx: int) {
str.count -= bytes_to_delete;
}
-// Get character index.
-// TODO Maybe rename to: map_character_to_byte_idx or get_character_byte_idx
-map_character_to_buffer_idx :: (str: string, character_idx: int) -> buffer_idx: int, success: bool {
+// Searches for the given character index and returns its byte index on the string.
+get_byte_idx :: (str: string, character_idx: int) -> buffer_idx: int, success: bool {
if character_idx < 0 then return -1, false;
if character_idx > str.count then return -2, false;
if character_idx == 0 then return 0, true;
@@ -110,7 +112,7 @@ map_character_to_buffer_idx :: (str: string, character_idx: int) -> buffer_idx:
buff_idx := 0;
char_idx := 0;
while buff_idx < str.count && char_idx != character_idx {
- buff_idx += count_utf8_bytes(str[buff_idx]);
+ buff_idx += count_character_bytes(str[buff_idx]);
char_idx += 1;
}
return buff_idx, char_idx == character_idx;
diff --git a/ttt.jai b/ttt.jai
index 3f7ac59..0802220 100644
--- a/ttt.jai
+++ b/ttt.jai
@@ -718,10 +718,9 @@ import_from_csv :: (db: *Database, path: string) -> bool {
task: Task;
csv_values := split(line, ",",, temporary_allocator);
- // Import task name.
- name_length := min(task.name.count, csv_values[0].count);
- memcpy(task.name.data, csv_values[0].data, name_length);
- truncate_string(xx task.name, name_length);
+ // Truncate and import task name.
+ truncate(*csv_values[0], task.name.count);
+ memcpy(task.name.data, csv_values[0].data, csv_values[0].count);
advance(*csv_values);
for csv_values
@@ -1466,7 +1465,7 @@ main :: () {
// Change task name.
TUI.using_style(action_style);
input := read_input_string(2, selected_task_row, Task.name.count, size_x - 2 - Task.name.count,, temporary_allocator);
- if is_empty_string(input) == false {
+ if is_empty(input) == false {
replace_chars(input, "\t\x0B\x0C\r", #char " "); // Replace weird spaces with space.
memset(selected_task.name.data, 0, Task.name.count);
memcpy(selected_task.name.data, input.data, min(Task.name.count, input.count));
@@ -1516,7 +1515,7 @@ main :: () {
input := read_input_string(input_pos_x, selected_task_row, input_width,, temporary_allocator);
// Abort if input if empty.
- if is_empty_string(input) continue;
+ if is_empty(input) continue;
// Search for assign '=' operator and discard everything before it.
assign_idx := find_index_from_left(input, "=");