From a33505ffe446d41f64bf107a937ca3b92884fa3b Mon Sep 17 00:00:00 2001 From: Timerix Date: Mon, 10 Nov 2025 05:42:29 +0500 Subject: [PATCH] replaced TomlString with StringBuilder --- dependencies/tlibc.config | 2 +- include/tlibtoml/toml.h | 38 ++-- src/toml.c | 443 ++++++++++++++------------------------ tests/main.c | 10 +- 4 files changed, 182 insertions(+), 311 deletions(-) diff --git a/dependencies/tlibc.config b/dependencies/tlibc.config index f5dfff7..3db058f 100644 --- a/dependencies/tlibc.config +++ b/dependencies/tlibc.config @@ -9,7 +9,7 @@ if [[ "$TASK" = *_dbg ]]; then else dep_build_target="build_static_lib" fi -DEP_PRE_BUILD_COMMAND="setup_user_config" +DEP_PRE_BUILD_COMMAND="" DEP_BUILD_COMMAND="cbuild $dep_build_target" DEP_POST_BUILD_COMMAND="" DEP_CLEAN_COMMAND="cbuild clean" diff --git a/include/tlibtoml/toml.h b/include/tlibtoml/toml.h index b6c5245..c0ae355 100644 --- a/include/tlibtoml/toml.h +++ b/include/tlibtoml/toml.h @@ -11,6 +11,7 @@ extern "C" { #include #include "tlibc/std.h" #include "tlibc/string/str.h" +#include "tlibc/string/StringBuilder.h" typedef struct tm TomlDateTime; @@ -28,12 +29,6 @@ typedef struct { NULLABLE(char*) message; } TomlErr; -typedef struct { - char* s; - u64 len; - u64 _capacity; -} TomlString; - typedef struct _TomlValue TomlValue; typedef struct { @@ -70,17 +65,17 @@ struct _TomlValue { union { TomlTable* table; TomlArray* array; - TomlString* string; - i64 integer; - f64 float_; - TomlDateTime datetime; - bool boolean; + str s; + i64 i; + f64 f; + TomlDateTime dt; + bool b; } value; }; struct _TomlKeyValue { - TomlString* key; - TomlValue* value; + str key; + TomlValue* value; }; typedef struct { @@ -98,28 +93,19 @@ void toml_free(void* p); const TomlErr* toml_err(void); void toml_err_clear(void); -TomlString* toml_string_new(void); -TomlString* toml_string_from_str(str s); -void toml_string_append_char(TomlString* self, char ch); -void toml_string_append_str(TomlString* self, str s); -TomlString* toml_string_clone(const TomlString* self); -void toml_string_free(TomlString* self); -i32 toml_string_equals(const TomlString* self, const TomlString* other); TomlTable* toml_table_new(void); void toml_table_free(TomlTable* self); -void toml_table_set_by_string(TomlTable* self, TomlString* key, TomlValue* value); -TomlValue* toml_table_get_by_string(const TomlTable* self, const TomlString* key); void toml_table_set(TomlTable* self, str key, TomlValue* value); TomlValue* toml_table_get(const TomlTable* self, str key); TomlTable* toml_table_get_table(const TomlTable* self, str key); TomlArray* toml_table_get_array(const TomlTable* self, str key); -TomlString* toml_table_get_string(const TomlTable* self, str key); +str toml_table_get_str(const TomlTable* self, str key); i64 toml_table_get_integer(const TomlTable* self, str key); f64 toml_table_get_float(const TomlTable* self, str key); const TomlDateTime* toml_table_get_datetime(const TomlTable* self, str key); -i32 toml_table_get_boolean(const TomlTable* self, str key); +bool toml_table_get_bool(const TomlTable* self, str key); TomlTableIter toml_table_iter_new(TomlTable* table); TomlKeyValue* toml_table_iter_get(TomlTableIter* self); @@ -137,7 +123,7 @@ TomlValue* toml_value_new_array(void); TomlValue* toml_value_new_integer(i64 integer); TomlValue* toml_value_new_float(f64 flt); TomlValue* toml_value_new_datetime(void); -TomlValue* toml_value_new_boolean(i32 boolean); +TomlValue* toml_value_new_bool(bool b); TomlValue* toml_value_from_str(str s); void toml_value_free(TomlValue* self); @@ -146,7 +132,7 @@ TomlTable* toml_load_file(FILE* file); TomlTable* toml_load_filename(cstr filename); /* TODO: implement dump functions -TomlString* toml_dump_str(const TomlTable* self, TomlErr *err); +str toml_dump_str(const TomlTable* self, TomlErr *err); void toml_dump_file(const TomlTable* self, FILE* file, TomlErr *err); */ diff --git a/src/toml.c b/src/toml.c index 311f657..667534f 100644 --- a/src/toml.c +++ b/src/toml.c @@ -87,96 +87,7 @@ static inline void toml_err_set(TomlErrCode code, cstr format, ...) va_end(args); } -static inline u64 toml_roundup_pow_of_two_u64(u64 v) -{ - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v |= v >> 32; - v++; - return v; -} -TomlString* toml_string_new(void) -{ - TomlString* self = toml_malloc(sizeof(TomlString)); - self->s = NULL; - self->len = 0; - self->_capacity = 0; - return self; -} - -TomlString* toml_string_from_str(str s) -{ - TomlString* self = toml_string_new(); - toml_string_append_str(self, s); - return self; -} - -static inline void toml_string_expand_if_necessary(TomlString* self, u64 len_to_add) -{ - if (self->len + len_to_add + 1 > self->_capacity) { - u64 new_capacity = toml_roundup_pow_of_two_u64(self->len + len_to_add + 1); - new_capacity = new_capacity >= 8 ? new_capacity : 8; - self->s = toml_realloc(self->s, new_capacity); - self->_capacity = new_capacity; - } -} - -void toml_string_append_char(TomlString* self, char ch) -{ - toml_string_expand_if_necessary(self, 1); - self->s[self->len] = ch; - self->s[self->len + 1] = 0; - self->len++; -} - -void toml_string_append_str(TomlString* self, str s) -{ - toml_string_expand_if_necessary(self, s.size); - memcpy(self->s + self->len, s.data, s.size); - self->len += s.size; - self->s[self->len] = 0; -} - -void toml_string_free(TomlString* self) -{ - if (self != NULL) { - free(self->s); - free(self); - } -} - -TomlString* toml_string_clone(const TomlString* self) -{ - return toml_string_from_str(str_construct(self->s, self->len, true)); -} - -i32 toml_string_equals(const TomlString* self, const TomlString* other) -{ - if (self == other) { - return true; - } - - if (self->len != other->len) { - return false; - } - - if (self->s == other->s) { - return true; - } - - for (u64 i = 0; i < self->len; i++) { - if (self->s[i] != other->s[i]) { - return false; - } - } - - return true; -} TomlTable* toml_table_new(void) { @@ -191,7 +102,7 @@ void toml_table_free(TomlTable* self) { if (self != NULL) { for (u64 i = 0; i < self->len; i++) { - toml_string_free(self->_keyvals[i].key); + free(self->_keyvals[i].key.data); toml_value_free(self->_keyvals[i].value); } free(self->_keyvals); @@ -209,18 +120,19 @@ void toml_table_expand_if_necessary(TomlTable* self) } } -void toml_table_set_by_string(TomlTable* self, TomlString* key, TomlValue* value) +void toml_table_set(TomlTable* self, str key, TomlValue* value) { + assert(key.data != NULL); TomlValue** slot = NULL; for (u64 i = 0; i < self->len; i++) { - if (toml_string_equals(self->_keyvals[i].key, key)) { + if (str_equals(self->_keyvals[i].key, key)) { slot = &self->_keyvals[i].value; } } if (slot == NULL) { toml_table_expand_if_necessary(self); - self->_keyvals[self->len].key = key; + self->_keyvals[self->len].key = str_copy(key); self->_keyvals[self->len].value = value; self->len++; } else { @@ -228,23 +140,18 @@ void toml_table_set_by_string(TomlTable* self, TomlString* key, TomlValue* value } } -TomlValue* toml_table_get_by_string(const TomlTable* self, const TomlString* key) +TomlValue* toml_table_get(const TomlTable* self, const str key) { + assert(key.data != NULL); TomlValue* value = NULL; for (u64 i = 0; i < self->len; i++) { - if (toml_string_equals(self->_keyvals[i].key, key)) { + if (str_equals(self->_keyvals[i].key, key)) { value = self->_keyvals[i].value; } } return value; } -TomlValue* toml_table_get(const TomlTable* self, str key) -{ - TomlString s = {(char*)key.data, key.size, 0}; - return toml_table_get_by_string(self, &s); -} - TomlTable* toml_table_get_table(const TomlTable* self, str key) { TomlValue* v = toml_table_get(self, key); @@ -261,12 +168,12 @@ TomlArray* toml_table_get_array(const TomlTable* self, str key) return v->value.array; } -TomlString* toml_table_get_string(const TomlTable* self, str key) +str toml_table_get_str(const TomlTable* self, str key) { TomlValue* v = toml_table_get(self, key); assert(v != NULL); assert(v->type == TOML_STRING); - return v->value.string; + return v->value.s; } i64 toml_table_get_integer(const TomlTable* self, str key) @@ -274,7 +181,7 @@ i64 toml_table_get_integer(const TomlTable* self, str key) TomlValue* v = toml_table_get(self, key); assert(v != NULL); assert(v->type == TOML_INTEGER); - return v->value.integer; + return v->value.i; } f64 toml_table_get_float(const TomlTable* self, str key) @@ -282,7 +189,7 @@ f64 toml_table_get_float(const TomlTable* self, str key) TomlValue* v = toml_table_get(self, key); assert(v != NULL); assert(v->type == TOML_FLOAT); - return v->value.float_; + return v->value.f; } const TomlDateTime* toml_table_get_datetime(const TomlTable* self, str key) @@ -290,21 +197,15 @@ const TomlDateTime* toml_table_get_datetime(const TomlTable* self, str key) TomlValue* v = toml_table_get(self, key); assert(v != NULL); assert(v->type == TOML_DATETIME); - return &v->value.datetime; + return &v->value.dt; } -i32 toml_table_get_boolean(const TomlTable* self, str key) +bool toml_table_get_bool(const TomlTable* self, str key) { TomlValue* v = toml_table_get(self, key); assert(v != NULL); assert(v->type == TOML_BOOLEAN); - return v->value.boolean; -} - -void toml_table_set(TomlTable* self, str key, TomlValue* value) -{ - TomlString* s = toml_string_from_str(key); - toml_table_set_by_string(self, s, value); + return v->value.b; } TomlTableIter toml_table_iter_new(TomlTable* table) @@ -382,19 +283,19 @@ TomlValue* toml_value_new(TomlType type) self->value.array = NULL; break; case TOML_STRING: - self->value.string = NULL; + self->value.s = str_null; break; case TOML_INTEGER: - self->value.integer = 0; + self->value.i = 0; break; case TOML_FLOAT: - self->value.float_ = 0.0; + self->value.f = 0.0; break; case TOML_BOOLEAN: - self->value.boolean = false; + self->value.b = false; break; case TOML_DATETIME: - memset(&self->value.datetime, 0, sizeof(TomlDateTime)); + memset(&self->value.dt, 0, sizeof(TomlDateTime)); break; } return self; @@ -403,7 +304,7 @@ TomlValue* toml_value_new(TomlType type) TomlValue* toml_value_from_str(str s) { TomlValue* self = toml_malloc(sizeof(TomlValue)); - self->value.string = toml_string_from_str(s); + self->value.s = str_copy(s); self->type = TOML_STRING; return self; } @@ -427,7 +328,7 @@ TomlValue* toml_value_new_array(void) TomlValue* toml_value_new_integer(i64 integer) { TomlValue* self = toml_malloc(sizeof(TomlValue)); - self->value.integer = integer; + self->value.i = integer; self->type = TOML_INTEGER; return self; } @@ -435,7 +336,7 @@ TomlValue* toml_value_new_integer(i64 integer) TomlValue* toml_value_new_float(f64 float_) { TomlValue* self = toml_malloc(sizeof(TomlValue)); - self->value.float_ = float_; + self->value.f = float_; self->type = TOML_FLOAT; return self; } @@ -445,10 +346,10 @@ TomlValue* toml_value_new_datetime(void) return toml_value_new(TOML_DATETIME); } -TomlValue* toml_value_new_boolean(i32 boolean) +TomlValue* toml_value_new_bool(bool b) { TomlValue* self = toml_malloc(sizeof(TomlValue)); - self->value.boolean = boolean; + self->value.b = b; self->type = TOML_BOOLEAN; return self; } @@ -458,7 +359,7 @@ void toml_value_free(TomlValue* self) if (self != NULL) { switch (self->type) { case TOML_STRING: - toml_string_free(self->value.string); + str_free(self->value.s); break; case TOML_TABLE: toml_table_free(self->value.table); @@ -467,7 +368,7 @@ void toml_value_free(TomlValue* self) toml_array_free(self->value.array); break; case TOML_DATETIME: - memset(&self->value.datetime, 0, sizeof(TomlDateTime)); + memset(&self->value.dt, 0, sizeof(TomlDateTime)); break; default: break; @@ -485,7 +386,7 @@ typedef struct _TomlParser { char* filename; } TomlParser; -TomlParser* toml_parser_new(str s) +TomlParser* toml_parser_new(str s, cstr filename) { TomlParser* self = toml_malloc(sizeof(TomlParser)); self->begin = s.data; @@ -493,7 +394,8 @@ TomlParser* toml_parser_new(str s) self->ptr = s.data; self->lineno = 1; self->colno = 1; - self->filename = NULL; + // TODO: remove copy filename? + self->filename = str_copy(str_from_cstr(filename)).data; return self; } @@ -525,7 +427,7 @@ void toml_next_n(TomlParser* self, i32 n) } } -TomlString* toml_parse_bare_key(TomlParser* self) +str toml_parse_bare_key(TomlParser* self) { cstr s = self->ptr; u64 len = 0; @@ -540,7 +442,7 @@ TomlString* toml_parse_bare_key(TomlParser* self) toml_move_next(self); } - return toml_string_from_str(str_construct((char*)s, len, false)); + return str_copy(str_construct((char*)s, len, false)); } char toml_hex_char_to_int(char ch) @@ -556,7 +458,7 @@ char toml_hex_char_to_int(char ch) return 0; } -i32 toml_encode_unicode_scalar(TomlString* result, TomlParser* parser, i32 n) +i32 toml_encode_unicode_scalar(StringBuilder* sb_ptr, TomlParser* parser, i32 n) { u32 scalar = 0; @@ -586,47 +488,47 @@ i32 toml_encode_unicode_scalar(TomlString* result, TomlParser* parser, i32 n) } if (scalar <= 0x7f) { - toml_string_append_char(result, (char)scalar); + StringBuilder_append_char(sb_ptr, (char)scalar); return 0; } if (scalar <= 0x7ff) { - toml_string_append_char(result, (char)(0xc0 | (scalar >> 6))); - toml_string_append_char(result, (char)(0x80 | (scalar & 0x3f))); + StringBuilder_append_char(sb_ptr, (char)(0xc0 | (scalar >> 6))); + StringBuilder_append_char(sb_ptr, (char)(0x80 | (scalar & 0x3f))); return 0; } if (scalar <= 0xffff) { - toml_string_append_char(result, (char)(0xe0 | (scalar >> 12))); - toml_string_append_char(result, (char)(0x80 | ((scalar >> 6) & 0x3f))); - toml_string_append_char(result, (char)(0x80 | (scalar & 0x3f))); + StringBuilder_append_char(sb_ptr, (char)(0xe0 | (scalar >> 12))); + StringBuilder_append_char(sb_ptr, (char)(0x80 | ((scalar >> 6) & 0x3f))); + StringBuilder_append_char(sb_ptr, (char)(0x80 | (scalar & 0x3f))); return 0; } if (scalar <= 0x1fffff) { - toml_string_append_char(result, (char)(0xf0 | (scalar >> 18))); - toml_string_append_char(result, (char)(0x80 | ((scalar >> 12) & 0x3f))); - toml_string_append_char(result, (char)(0x80 | ((scalar >> 6) & 0x3f))); - toml_string_append_char(result, (char)(0x80 | (scalar & 0x3f))); + StringBuilder_append_char(sb_ptr, (char)(0xf0 | (scalar >> 18))); + StringBuilder_append_char(sb_ptr, (char)(0x80 | ((scalar >> 12) & 0x3f))); + StringBuilder_append_char(sb_ptr, (char)(0x80 | ((scalar >> 6) & 0x3f))); + StringBuilder_append_char(sb_ptr, (char)(0x80 | (scalar & 0x3f))); return 0; } if (scalar <= 0x3ffffff) { - toml_string_append_char(result, (char)(0xf8 | (scalar >> 24))); - toml_string_append_char(result, (char)(0x80 | ((scalar >> 18) & 0x3f))); - toml_string_append_char(result, (char)(0x80 | ((scalar >> 12) & 0x3f))); - toml_string_append_char(result, (char)(0x80 | ((scalar >> 6) & 0x3f))); - toml_string_append_char(result, (char)(0x80 | (scalar & 0x3f))); + StringBuilder_append_char(sb_ptr, (char)(0xf8 | (scalar >> 24))); + StringBuilder_append_char(sb_ptr, (char)(0x80 | ((scalar >> 18) & 0x3f))); + StringBuilder_append_char(sb_ptr, (char)(0x80 | ((scalar >> 12) & 0x3f))); + StringBuilder_append_char(sb_ptr, (char)(0x80 | ((scalar >> 6) & 0x3f))); + StringBuilder_append_char(sb_ptr, (char)(0x80 | (scalar & 0x3f))); return 0; } if (scalar <= 0x7fffffff) { - toml_string_append_char(result, (char)(0xfc | (scalar >> 30))); - toml_string_append_char(result, (char)(0x80 | ((scalar >> 24) & 0x3f))); - toml_string_append_char(result, (char)(0x80 | ((scalar >> 18) & 0x3f))); - toml_string_append_char(result, (char)(0x80 | ((scalar >> 12) & 0x3f))); - toml_string_append_char(result, (char)(0x80 | ((scalar >> 6) & 0x3f))); - toml_string_append_char(result, (char)(0x80 | (scalar & 0x3f))); + StringBuilder_append_char(sb_ptr, (char)(0xfc | (scalar >> 30))); + StringBuilder_append_char(sb_ptr, (char)(0x80 | ((scalar >> 24) & 0x3f))); + StringBuilder_append_char(sb_ptr, (char)(0x80 | ((scalar >> 18) & 0x3f))); + StringBuilder_append_char(sb_ptr, (char)(0x80 | ((scalar >> 12) & 0x3f))); + StringBuilder_append_char(sb_ptr, (char)(0x80 | ((scalar >> 6) & 0x3f))); + StringBuilder_append_char(sb_ptr, (char)(0x80 | (scalar & 0x3f))); return 0; } @@ -636,9 +538,9 @@ i32 toml_encode_unicode_scalar(TomlString* result, TomlParser* parser, i32 n) return TOML_ERR_UNICODE; } -TomlString* toml_parse_basic_string(TomlParser* self) +str toml_parse_basic_string(TomlParser* self) { - TomlString* result = toml_string_new(); + StringBuilder sb = StringBuilder_alloc(64); while (self->ptr < self->end &&* self->ptr != '\"' &&* self->ptr != '\n') { char ch1 = *self->ptr; @@ -649,46 +551,46 @@ TomlString* toml_parse_basic_string(TomlParser* self) char ch2 = *self->ptr; if (ch2 == '\"') { - toml_string_append_char(result, '\"'); + StringBuilder_append_char(&sb, '\"'); toml_move_next(self); } else if (ch2 == 'b') { - toml_string_append_char(result, '\b'); + StringBuilder_append_char(&sb, '\b'); toml_move_next(self); } else if (ch2 == 't') { - toml_string_append_char(result, '\t'); + StringBuilder_append_char(&sb, '\t'); toml_move_next(self); } else if (ch2 == 'n') { - toml_string_append_char(result, '\n'); + StringBuilder_append_char(&sb, '\n'); toml_move_next(self); } else if (ch2 == 'f') { - toml_string_append_char(result, '\f'); + StringBuilder_append_char(&sb, '\f'); toml_move_next(self); } else if (ch2 == 'r') { - toml_string_append_char(result, '\r'); + StringBuilder_append_char(&sb, '\r'); toml_move_next(self); } else if (ch2 == '\\') { - toml_string_append_char(result, '\\'); + StringBuilder_append_char(&sb, '\\'); toml_move_next(self); } else if (ch2 == 'u') { toml_move_next(self); - if (toml_encode_unicode_scalar(result, self, 4) != 0) { - toml_string_free(result); - return NULL; + if (toml_encode_unicode_scalar(&sb, self, 4) != 0) { + StringBuilder_destroy(&sb); + return str_null; } } else if (ch2 == 'U') { toml_move_next(self); - if (toml_encode_unicode_scalar(result, self, 8) != 0) { - toml_string_free(result); - return NULL; + if (toml_encode_unicode_scalar(&sb, self, 8) != 0) { + StringBuilder_destroy(&sb); + return str_null; } } else { toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid escape character", self->filename, self->lineno, self->colno); - toml_string_free(result); - return NULL; + StringBuilder_destroy(&sb); + return str_null; } } else { - toml_string_append_char(result, ch1); + StringBuilder_append_char(&sb, ch1); toml_move_next(self); } } @@ -696,61 +598,61 @@ TomlString* toml_parse_basic_string(TomlParser* self) if (self->ptr >= self->end ||* self->ptr != '\"' ||* self->ptr == '\n') { toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: unterminated basic string", self->filename, self->lineno, self->colno); - toml_string_free(result); - return NULL; + StringBuilder_destroy(&sb); + return str_null; } toml_move_next(self); - return result; + return StringBuilder_getStr(&sb); } -TomlString* toml_parse_literal_string(TomlParser* self) +str toml_parse_literal_string(TomlParser* self) { - TomlString* result = toml_string_new(); + StringBuilder sb = StringBuilder_alloc(64); while (self->ptr < self->end &&* self->ptr != '\'' &&* self->ptr != '\n') { - toml_string_append_char(result,* self->ptr); + StringBuilder_append_char(&sb,* self->ptr); toml_move_next(self); } if (self->ptr >= self->end ||* self->ptr != '\'' ||* self->ptr == '\n') { toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: unterminated literal string", self->filename, self->lineno, self->colno); - toml_string_free(result); - return NULL; + StringBuilder_destroy(&sb); + return str_null; } toml_move_next(self); - return result; + return StringBuilder_getStr(&sb); } TomlValue* toml_parse_basic_string_value(TomlParser* self) { - TomlString* string = toml_parse_basic_string(self); - if (string == NULL) + str s = toml_parse_basic_string(self); + if (s.data == NULL) return NULL; TomlValue* value = toml_value_new(TOML_STRING); - value->value.string = string; + value->value.s = s; return value; } TomlValue* toml_parse_literal_string_value(TomlParser* self) { - TomlString* string = toml_parse_literal_string(self); - if (string == NULL) + str s = toml_parse_literal_string(self); + if (s.data == NULL) return NULL; TomlValue* value = toml_value_new(TOML_STRING); - value->value.string = string; + value->value.s = s; return value; } TomlValue* toml_parse_multi_line_basic_string(TomlParser* self) { - TomlString* result = toml_string_new(); + StringBuilder sb = StringBuilder_alloc(64); if (*self->ptr == '\n') { toml_move_next(self); @@ -767,36 +669,36 @@ TomlValue* toml_parse_multi_line_basic_string(TomlParser* self) char ch2 = *self->ptr; if (ch2 == '\"') { - toml_string_append_char(result, '\"'); + StringBuilder_append_char(&sb, '\"'); toml_move_next(self); } else if (ch2 == 'b') { - toml_string_append_char(result, '\b'); + StringBuilder_append_char(&sb, '\b'); toml_move_next(self); } else if (ch2 == 't') { - toml_string_append_char(result, '\t'); + StringBuilder_append_char(&sb, '\t'); toml_move_next(self); } else if (ch2 == 'n') { - toml_string_append_char(result, '\n'); + StringBuilder_append_char(&sb, '\n'); toml_move_next(self); } else if (ch2 == 'f') { - toml_string_append_char(result, '\f'); + StringBuilder_append_char(&sb, '\f'); toml_move_next(self); } else if (ch2 == 'r') { - toml_string_append_char(result, '\r'); + StringBuilder_append_char(&sb, '\r'); toml_move_next(self); } else if (ch2 == '\\') { - toml_string_append_char(result, '\\'); + StringBuilder_append_char(&sb, '\\'); toml_move_next(self); } else if (ch2 == 'u') { toml_move_next(self); - if (toml_encode_unicode_scalar(result, self, 4) != 0) { - toml_string_free(result); + if (toml_encode_unicode_scalar(&sb, self, 4) != 0) { + StringBuilder_destroy(&sb); return NULL; } } else if (ch2 == 'U') { toml_move_next(self); - if (toml_encode_unicode_scalar(result, self, 8) != 0) { - toml_string_free(result); + if (toml_encode_unicode_scalar(&sb, self, 8) != 0) { + StringBuilder_destroy(&sb); return NULL; } } else if (ch2 == '\n') { @@ -806,11 +708,11 @@ TomlValue* toml_parse_multi_line_basic_string(TomlParser* self) } else { toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid escape character", self->filename, self->lineno, self->colno); - toml_string_free(result); + StringBuilder_destroy(&sb); return NULL; } } else { - toml_string_append_char(result, ch1); + StringBuilder_append_char(&sb, ch1); toml_move_next(self); } } @@ -818,42 +720,41 @@ TomlValue* toml_parse_multi_line_basic_string(TomlParser* self) if (self->ptr + 3 > self->end || strncmp(self->ptr, "\"\"\"", 3) != 0) { toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: unterminated multi-line basic string", self->filename, self->lineno, self->colno); - toml_string_free(result); + StringBuilder_destroy(&sb); return NULL; } toml_next_n(self, 3); TomlValue* value = toml_value_new(TOML_STRING); - value->value.string = result; + value->value.s = StringBuilder_getStr(&sb); return value; } TomlValue* toml_parse_multi_line_literal_string(TomlParser* self) { - TomlString* result = toml_string_new(); + StringBuilder sb = StringBuilder_alloc(64); if (*self->ptr == '\n') { toml_move_next(self); } while (self->ptr + 3 <= self->end && strncmp(self->ptr, "\'\'\'", 3) != 0) { - toml_string_append_char(result,* self->ptr); + StringBuilder_append_char(&sb,* self->ptr); toml_move_next(self); } if (self->ptr + 3 > self->end || strncmp(self->ptr, "\'\'\'", 3) != 0) { toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: unterminated multi-line literal string", self->filename, self->lineno, self->colno); - toml_string_free(result); + StringBuilder_destroy(&sb); return NULL; } toml_next_n(self, 3); TomlValue* value = toml_value_new(TOML_STRING); - value->value.string = result; - + value->value.s = StringBuilder_getStr(&sb); return value; } @@ -871,7 +772,7 @@ TomlValue* toml_parse_int_or_float_or_time(TomlParser* self) char type = 'i'; i32 base = 10; - TomlString* s = toml_string_new(); + StringBuilder sb = StringBuilder_alloc(64); // Determine nan and inf type as float, as we cannot determine by dot. // But do not strip it because we will append it to the string later @@ -912,7 +813,7 @@ TomlValue* toml_parse_int_or_float_or_time(TomlParser* self) type = 'f'; has_exp = true; } - toml_string_append_char(s,* self->ptr); + StringBuilder_append_char(&sb,* self->ptr); } else { break; } @@ -921,34 +822,34 @@ TomlValue* toml_parse_int_or_float_or_time(TomlParser* self) type = 'f'; } - toml_string_append_char(s,* self->ptr); + StringBuilder_append_char(&sb,* self->ptr); } else if (*self->ptr == '.') { if (type == 'i') { type = 'f'; - toml_string_append_char(s,* self->ptr); + StringBuilder_append_char(&sb,* self->ptr); } else { toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid float", self->filename, self->lineno, self->colno); - toml_string_free(s); + StringBuilder_destroy(&sb); return NULL; } } else if (*self->ptr == '_') { if (type == 't') { toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid datetime", self->filename, self->lineno, self->colno); - toml_string_free(s); + StringBuilder_destroy(&sb); return NULL; } if (!isalnum(last_char)) { toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid integer or float", self->filename, self->lineno, self->colno); - toml_string_free(s); + StringBuilder_destroy(&sb); return NULL; } } else if (*self->ptr == '-') { type = 't'; - toml_string_append_char(s,* self->ptr); + StringBuilder_append_char(&sb,* self->ptr); } else { break; } @@ -960,35 +861,35 @@ TomlValue* toml_parse_int_or_float_or_time(TomlParser* self) if (last_char == '_') { toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid integer or float or datetime", self->filename, self->lineno, self->colno); - toml_string_free(s); + StringBuilder_destroy(&sb); return NULL; } if (type == 'i') { char* end = NULL; - i64 n = strtoll(s->s, &end, base); - if (end < s->s + s->len) { + i64 n = strtoll(StringBuilder_getStr(&sb).data, &end, base); + if (end < (char*)sb.buffer.data + sb.buffer.size) { toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid integer", self->filename, self->lineno, self->colno); - toml_string_free(s); + StringBuilder_destroy(&sb); return NULL; } result = toml_value_new_integer(n); } else if (type == 'f') { char* end = NULL; - f64 n = strtod(s->s, &end); - if (end < s->s + s->len) { + f64 n = strtod(StringBuilder_getStr(&sb).data, &end); + if (end < (char*)sb.buffer.data + sb.buffer.size) { toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid float", self->filename, self->lineno, self->colno); goto cleanup; } result = toml_value_new_float(n); } else if (type == 't') { - result = toml_parse_datetime(str_construct(s->s, s->len, false)); + result = toml_parse_datetime(StringBuilder_getStr(&sb)); } cleanup: - toml_string_free(s); + StringBuilder_destroy(&sb); return result; } @@ -997,13 +898,13 @@ TomlValue* toml_parse_bool(TomlParser* self) if (self->ptr + 4 <= self->end && strncmp(self->ptr, "true", 4) == 0 && (self->ptr + 4 == self->end || isspace(*(self->ptr + 4)) || *(self->ptr + 4) == ',' || *(self->ptr + 4) == ']' || *(self->ptr + 4) == '}')) { toml_next_n(self, 4); - return toml_value_new_boolean(true); + return toml_value_new_bool(true); } if (self->ptr + 5 <= self->end && strncmp(self->ptr, "false", 5) == 0 && (self->ptr + 5 == self->end || isspace(*(self->ptr + 5)) || *(self->ptr + 5) == ',' || *(self->ptr + 5) == ']' || *(self->ptr + 5) == '}')) { toml_next_n(self, 5); - return toml_value_new_boolean(false); + return toml_value_new_bool(false); } return NULL; @@ -1050,7 +951,7 @@ TomlValue* toml_parse_value(TomlParser* self) TomlErrCode toml_parse_key_value(TomlParser* self, TomlTable* table) { - TomlString* key = NULL; + str key = str_null; TomlValue* value = NULL; while (self->ptr < self->end) { @@ -1066,17 +967,17 @@ TomlErrCode toml_parse_key_value(TomlParser* self, TomlTable* table) if (isalnum(ch) || ch == '_') { key = toml_parse_bare_key(self); - if (key == NULL) + if (key.data == NULL) return toml_err()->code; } else if (ch == '\"') { toml_move_next(self); key = toml_parse_basic_string(self); - if (key == NULL) + if (key.data == NULL) return toml_err()->code; } else if (ch == '\'') { toml_move_next(self); key = toml_parse_literal_string(self); - if (key == NULL) + if (key.data == NULL) return toml_err()->code; } else if (ch == '[') { break; @@ -1129,10 +1030,8 @@ TomlErrCode toml_parse_key_value(TomlParser* self, TomlTable* table) if (value == NULL) return toml_err()->code; - toml_table_set_by_string(table, key, value); - - key = NULL; - value = NULL; + toml_table_set(table, key, value); + str_free(key); while (self->ptr < self->end && (*self->ptr == ' ' ||* self->ptr == '\t')) { toml_move_next(self); @@ -1156,8 +1055,6 @@ TomlErrCode toml_parse_key_value(TomlParser* self, TomlTable* table) } else { toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: new line expected", self->filename, self->lineno, self->colno); - toml_value_free(value); - toml_string_free(key); return TOML_ERR_SYNTAX; } } @@ -1231,11 +1128,10 @@ end: TomlValue* toml_parse_inline_table(TomlParser* self) { TomlValue* table = toml_value_new_table(); + str key = str_null; + TomlValue* value = NULL; while (self->ptr < self->end) { - TomlString* key = NULL; - TomlValue* value = NULL; - char ch = *self->ptr; while (self->ptr < self->end && (ch == ' ' || ch == '\t')) { toml_move_next(self); @@ -1244,17 +1140,17 @@ TomlValue* toml_parse_inline_table(TomlParser* self) if (isalnum(ch) || ch == '_') { key = toml_parse_bare_key(self); - if (key == NULL) + if (key.data == NULL) goto error; } else if (ch == '\"') { toml_move_next(self); key = toml_parse_basic_string(self); - if (key == NULL) + if (key.data == NULL) goto error; } else if (ch == '\'') { toml_move_next(self); key = toml_parse_literal_string(self); - if (key == NULL) + if (key.data == NULL) goto error; } else if (ch == '}') { break; @@ -1300,7 +1196,8 @@ TomlValue* toml_parse_inline_table(TomlParser* self) if (value == NULL) goto error; - toml_table_set_by_string(table->value.table, key, value); + toml_table_set(table->value.table, key, value); + str_free(key); while (self->ptr < self->end && (*self->ptr == ' ' ||* self->ptr == '\t')) { toml_move_next(self); @@ -1331,20 +1228,17 @@ TomlTable* toml_walk_table_path(TomlParser* parser, TomlTable* table, TomlTable* real_table = table; TomlValue* new_table = NULL; TomlValue* array = NULL; - TomlString* part_copy = NULL; if (is_array) { u64 i = 0; for (; i < key_path->len - 1; i++) { - TomlString* part = key_path->elements[i]->value.string; - TomlValue* t = toml_table_get_by_string(real_table, part); + str part = key_path->elements[i]->value.s; + TomlValue* t = toml_table_get(real_table, part); if (t == NULL) { if (create_if_not_exist) { new_table = toml_value_new_table(); - part_copy = toml_string_clone(part); - toml_table_set_by_string(real_table, part_copy, new_table); + toml_table_set(real_table, part, new_table); real_table = new_table->value.table; - part_copy = NULL; new_table = NULL; } else { real_table = NULL; @@ -1355,17 +1249,15 @@ TomlTable* toml_walk_table_path(TomlParser* parser, TomlTable* table, } } - TomlString* part = key_path->elements[i]->value.string; - TomlValue* t = toml_table_get_by_string(real_table, part); + str part = key_path->elements[i]->value.s; + TomlValue* t = toml_table_get(real_table, part); if (t == NULL) { if (create_if_not_exist) { array = toml_value_new_array(); new_table = toml_value_new_table(); toml_array_append(array->value.array, new_table); - part_copy = toml_string_clone(part); - toml_table_set_by_string(real_table, part_copy, array); + toml_table_set(real_table, part, array); real_table = new_table->value.table; - part_copy = NULL; array = NULL; new_table = NULL; } else { @@ -1385,15 +1277,13 @@ TomlTable* toml_walk_table_path(TomlParser* parser, TomlTable* table, } } else { for (u64 i = 0; i < key_path->len; i++) { - TomlString* part = key_path->elements[i]->value.string; - TomlValue* t = toml_table_get_by_string(real_table, part); + str part = key_path->elements[i]->value.s; + TomlValue* t = toml_table_get(real_table, part); if (t == NULL) { if (create_if_not_exist) { new_table = toml_value_new_table(); - part_copy = toml_string_clone(part); - toml_table_set_by_string(real_table, part_copy, new_table); + toml_table_set(real_table, part, new_table); real_table = new_table->value.table; - part_copy = NULL; new_table = NULL; } else { real_table = NULL; @@ -1412,7 +1302,6 @@ TomlTable* toml_walk_table_path(TomlParser* parser, TomlTable* table, goto end; error: - toml_string_free(part_copy); toml_value_free(new_table); toml_value_free(array); real_table = NULL; @@ -1451,22 +1340,22 @@ TomlErrCode toml_parse_table(TomlParser* self, TomlTable* table) break; } } else { - TomlString* key_part = NULL; + str key_part = str_null; TomlValue* key_part_value = NULL; if (isalnum(*self->ptr) ||* self->ptr == '_') { key_part = toml_parse_bare_key(self); - if (key_part == NULL) + if (key_part.data == NULL) goto cleanup; } else if (*self->ptr == '\"') { toml_move_next(self); key_part = toml_parse_basic_string(self); - if (key_part == NULL) + if (key_part.data == NULL) goto cleanup; } else if (*self->ptr == '\'') { toml_move_next(self); key_part = toml_parse_literal_string(self); - if (key_part == NULL) + if (key_part.data == NULL) goto cleanup; } else { toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: unexpected token", @@ -1475,7 +1364,7 @@ TomlErrCode toml_parse_table(TomlParser* self, TomlTable* table) } key_part_value = toml_value_new(TOML_STRING); - key_part_value->value.string = key_part; + key_part_value->value.s = key_part; toml_array_append(key_path, key_part_value); @@ -1511,7 +1400,8 @@ TomlErrCode toml_parse_table(TomlParser* self, TomlTable* table) if (real_table == NULL) goto error; - toml_parse_key_value(self, real_table); + if(toml_parse_key_value(self, real_table) != TOML_OK) + goto error; goto cleanup; @@ -1562,8 +1452,7 @@ TomlTable* toml_parse(TomlParser* self) TomlTable* toml_load_str_filename(str s, cstr filename) { - TomlParser* parser = toml_parser_new(s); - parser->filename = str_copy(str_from_cstr(filename)).data; + TomlParser* parser = toml_parser_new(s, filename); TomlTable* table = toml_parse(parser); @@ -1579,30 +1468,28 @@ TomlTable* toml_load_str(str s) TomlTable* toml_load_file_filename(FILE* file, cstr filename) { TomlTable* table = NULL; - TomlString* s = toml_string_new(); - toml_string_expand_if_necessary(s, 4095); + const u32 file_chunk_size = 8*1024; + StringBuilder sb = StringBuilder_alloc(file_chunk_size); u64 count = 0; u64 remaining_capacity = 0; do { - remaining_capacity = s->_capacity - s->len; - count = fread(s->s + s->len, 1, remaining_capacity, file); + remaining_capacity = sb.buffer.allocated_size - sb.buffer.size; + count = fread((char*)sb.buffer.data + sb.buffer.size, 1, remaining_capacity, file); if (ferror(file)) { toml_err_set(TOML_ERR_OS, "Error when reading %s [errno %d: %s]", filename, errno, strerror(errno)); goto error; } - s->len += count; + sb.buffer.size += count; - if (s->len + 1 >= s->_capacity) { - toml_string_expand_if_necessary(s, s->_capacity * 2); + if (sb.buffer.size + 1 >= sb.buffer.allocated_size) { + StringBuilder_expand(&sb, file_chunk_size); } } while (count == remaining_capacity); - s->s[s->len] = 0; - - table = toml_load_str_filename(str_construct(s->s, s->len, false), filename); + table = toml_load_str_filename(StringBuilder_getStr(&sb), filename); goto cleanup; @@ -1611,7 +1498,7 @@ error: table = NULL; cleanup: - toml_string_free(s); + StringBuilder_destroy(&sb); return table; } @@ -1643,5 +1530,3 @@ cleanup: fclose(f); return table; } - -// vim: sw=4 ts=8 sts=4 et diff --git a/tests/main.c b/tests/main.c index 34a3cf6..a543b42 100644 --- a/tests/main.c +++ b/tests/main.c @@ -34,26 +34,26 @@ void print_value(const TomlValue* value) print_array(value->value.array); break; case TOML_STRING: - printf("\"%s\"", value->value.string->s); + printf("\"%s\"", value->value.s.data); break; case TOML_INTEGER: - printf("%" PRId64, value->value.integer); + printf("%" PRId64, value->value.i); break; case TOML_FLOAT: - printf("%f", value->value.float_); + printf("%f", value->value.f); break; case TOML_DATETIME: printf("(datetime)"); break; case TOML_BOOLEAN: - printf("%s", value->value.boolean ? "true" : "false"); + printf("%s", value->value.b ? "true" : "false"); break; } } void print_keyval(const TomlKeyValue *keyval) { - printf("\"%s\": ", keyval->key->s); + printf("\"%s\": ", keyval->key.data); print_value(keyval->value); }