diff --git a/include/tlibtoml/toml.h b/include/tlibtoml/toml.h index c0ae355..bafde18 100644 --- a/include/tlibtoml/toml.h +++ b/include/tlibtoml/toml.h @@ -11,9 +11,10 @@ extern "C" { #include #include "tlibc/std.h" #include "tlibc/string/str.h" -#include "tlibc/string/StringBuilder.h" +#include "tlibc/collections/HashMap.h" typedef struct tm TomlDateTime; +typedef HashMap(TomlValue) TomlTable; typedef enum { TOML_OK, @@ -29,28 +30,17 @@ typedef struct { NULLABLE(char*) message; } TomlErr; -typedef struct _TomlValue TomlValue; +typedef struct TomlValue TomlValue; typedef struct { - TomlValue** elements; + TomlValue* elements; u64 len; u64 _capacity; } TomlArray; -typedef struct _TomlKeyValue TomlKeyValue; - -typedef struct { - u64 _capacity; - u64 len; - TomlKeyValue* _keyvals; -} TomlTable; - -typedef struct { - TomlTable* _table; - TomlKeyValue* _keyval; -} TomlTableIter; typedef enum { + TOML_INVALID_TYPE, TOML_TABLE, TOML_ARRAY, TOML_STRING, @@ -60,7 +50,7 @@ typedef enum { TOML_BOOLEAN, } TomlType; -struct _TomlValue { +struct TomlValue { TomlType type; union { TomlTable* table; @@ -68,16 +58,11 @@ struct _TomlValue { str s; i64 i; f64 f; - TomlDateTime dt; + TomlDateTime* dt; bool b; } value; }; -struct _TomlKeyValue { - str key; - TomlValue* value; -}; - typedef struct { void* (*malloc)(void* context, u64 size); void* (*realloc)(void* context, void* p, u64 size); @@ -97,35 +82,30 @@ void toml_err_clear(void); TomlTable* toml_table_new(void); void toml_table_free(TomlTable* self); -void toml_table_set(TomlTable* self, str key, TomlValue* value); +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); 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); +TomlDateTime* toml_table_get_datetime(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); -i32 toml_table_iter_has_next(TomlTableIter* self); -void toml_table_iter_next(TomlTableIter* self); - TomlArray* toml_array_new(void); void toml_array_free(TomlArray* self); -void toml_array_append(TomlArray* self, TomlValue* value); +void toml_array_append(TomlArray* self, TomlValue value); -TomlValue* toml_value_new(TomlType type); -TomlValue* toml_value_new_string(TomlType type); -TomlValue* toml_value_new_table(void); -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_bool(bool b); -TomlValue* toml_value_from_str(str s); -void toml_value_free(TomlValue* self); +TomlValue TomlValue_new(TomlType type); +TomlValue TomlValue_new_string(TomlType type); +TomlValue TomlValue_new_table(void); +TomlValue TomlValue_new_array(void); +TomlValue TomlValue_new_integer(i64 integer); +TomlValue TomlValue_new_float(f64 flt); +TomlValue TomlValue_new_datetime(void); +TomlValue TomlValue_new_bool(bool b); +TomlValue TomlValue_from_str(str s); +void TomlValue_destroy(TomlValue* self); TomlTable* toml_load_str(str s); TomlTable* toml_load_file(FILE* file); diff --git a/src/toml.c b/src/toml.c index 667534f..3eb758d 100644 --- a/src/toml.c +++ b/src/toml.c @@ -7,6 +7,8 @@ #include "tlibtoml/toml.h" #include "tlibc/errors.h" #include "tlibc/string/StringBuilder.h" +#include "tlibc/collections/HashMap.h" +#include "tlibc/collections/List.h" static ATTRIBUTE_THREAD_LOCAL TomlErr g_err = { TOML_OK, NULL }; @@ -85,70 +87,38 @@ static inline void toml_err_set(TomlErrCode code, cstr format, ...) g_err.code = code; g_err.message = vsprintf_malloc(format, args); va_end(args); + + printfe("ERROR: %s\n", toml_err()->message); + fflush(stderr); } TomlTable* toml_table_new(void) { - TomlTable* self = toml_malloc(sizeof(TomlTable)); - self->_capacity = 0; - self->_keyvals = NULL; - self->len = 0; - return self; + TomlTable* table = toml_malloc(sizeof(TomlTable)); + HashMap_construct(table, TomlValue, (FreeFunction)TomlValue_destroy); + return table; } void toml_table_free(TomlTable* self) { - if (self != NULL) { - for (u64 i = 0; i < self->len; i++) { - free(self->_keyvals[i].key.data); - toml_value_free(self->_keyvals[i].value); - } - free(self->_keyvals); - free(self); - } + if(!self) + return; + HashMap_destroy(self); + free(self); } -void toml_table_expand_if_necessary(TomlTable* self) -{ - if (self->len + 1 > self->_capacity) { - u64 new_capacity = self->_capacity > 0 ? self->_capacity * 2 : 8; - void* p = toml_realloc(self->_keyvals, sizeof(TomlKeyValue) * new_capacity); - self->_keyvals = p; - self->_capacity = new_capacity; - } -} - -void toml_table_set(TomlTable* self, str 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 (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 = str_copy(key); - self->_keyvals[self->len].value = value; - self->len++; - } else { - *slot = value; - } + HashMap_pushOrUpdate(self, key, &value); } 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 (str_equals(self->_keyvals[i].key, key)) { - value = self->_keyvals[i].value; - } - } + TomlValue* value = HashMap_tryGetPtr(self, key); return value; } @@ -192,12 +162,12 @@ f64 toml_table_get_float(const TomlTable* self, str key) return v->value.f; } -const TomlDateTime* toml_table_get_datetime(const TomlTable* self, str key) +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.dt; + return v->value.dt; } bool toml_table_get_bool(const TomlTable* self, str key) @@ -208,47 +178,20 @@ bool toml_table_get_bool(const TomlTable* self, str key) return v->value.b; } -TomlTableIter toml_table_iter_new(TomlTable* table) -{ - TomlTableIter self = { table, table->_keyvals }; - return self; -} - -TomlKeyValue* toml_table_iter_get(TomlTableIter* self) -{ - return self->_keyval; -} - -i32 toml_table_iter_has_next(TomlTableIter* self) -{ - return self->_keyval != NULL; -} - -void toml_table_iter_next(TomlTableIter* self) -{ - if (self->_keyval < self->_table->_keyvals + self->_table->len) { - self->_keyval++; - } - - if (self->_keyval >= self->_table->_keyvals + self->_table->len) { - self->_keyval = NULL; - } -} - TomlArray *toml_array_new(void) { - TomlArray* self = toml_malloc(sizeof(TomlArray)); - self->elements = NULL; - self->len = 0; - self->_capacity = 0; - return self; + TomlArray* array = toml_malloc(sizeof(TomlArray)); + array->elements = NULL; + array->len = 0; + array->_capacity = 0; + return array; } void toml_array_free(TomlArray* self) { if (self != NULL) { for (u64 i = 0; i < self->len; i++) { - toml_value_free(self->elements[i]); + TomlValue_destroy(&self->elements[i]); } free(self->elements); free(self); @@ -259,107 +202,111 @@ void toml_array_expand_if_necessary(TomlArray* self) { if (self->len + 1 > self->_capacity) { u64 new_capacity = self->_capacity > 0 ? self->_capacity * 2 : 8; - void* p = toml_realloc(self->elements, sizeof(TomlValue*) * new_capacity); + void* p = toml_realloc(self->elements, sizeof(TomlValue) * new_capacity); self->elements = p; self->_capacity = new_capacity; } } -void toml_array_append(TomlArray* self, TomlValue* value) +void toml_array_append(TomlArray* self, TomlValue value) { toml_array_expand_if_necessary(self); self->elements[self->len++] = value; } -TomlValue* toml_value_new(TomlType type) +TomlValue TomlValue_new(TomlType type) { - TomlValue* self = toml_malloc(sizeof(TomlValue)); - self->type = type; + TomlValue value = {0}; + value.type = type; switch (type) { + default: + assert(false && "invalid type"); + break; case TOML_TABLE: - self->value.table = NULL; + value.value.table = NULL; break; case TOML_ARRAY: - self->value.array = NULL; + value.value.array = NULL; break; case TOML_STRING: - self->value.s = str_null; + value.value.s = str_null; break; case TOML_INTEGER: - self->value.i = 0; + value.value.i = 0; break; case TOML_FLOAT: - self->value.f = 0.0; + value.value.f = 0.0; break; case TOML_BOOLEAN: - self->value.b = false; + value.value.b = false; break; case TOML_DATETIME: - memset(&self->value.dt, 0, sizeof(TomlDateTime)); + value.value.dt = (TomlDateTime*)toml_malloc(sizeof(TomlDateTime)); + memset(value.value.dt, 0, sizeof(TomlDateTime)); break; } - return self; + return value; } -TomlValue* toml_value_from_str(str s) +TomlValue TomlValue_from_str(str s) { - TomlValue* self = toml_malloc(sizeof(TomlValue)); - self->value.s = str_copy(s); - self->type = TOML_STRING; - return self; + TomlValue value = {0}; + value.value.s = str_copy(s); + value.type = TOML_STRING; + return value; } -TomlValue* toml_value_new_table(void) +TomlValue TomlValue_new_table(void) { - TomlValue* self = toml_malloc(sizeof(TomlValue)); - self->value.table = toml_table_new(); - self->type = TOML_TABLE; - return self; + TomlValue value = {0}; + value.value.table = toml_table_new(); + value.type = TOML_TABLE; + return value; } -TomlValue* toml_value_new_array(void) +TomlValue TomlValue_new_array(void) { - TomlValue* self = toml_malloc(sizeof(TomlValue)); - self->value.array = toml_array_new(); - self->type = TOML_ARRAY; - return self; + TomlValue value = {0}; + value.value.array = toml_array_new(); + value.type = TOML_ARRAY; + return value; } -TomlValue* toml_value_new_integer(i64 integer) +TomlValue TomlValue_new_integer(i64 integer) { - TomlValue* self = toml_malloc(sizeof(TomlValue)); - self->value.i = integer; - self->type = TOML_INTEGER; - return self; + TomlValue value = {0}; + value.value.i = integer; + value.type = TOML_INTEGER; + return value; } -TomlValue* toml_value_new_float(f64 float_) +TomlValue TomlValue_new_float(f64 float_) { - TomlValue* self = toml_malloc(sizeof(TomlValue)); - self->value.f = float_; - self->type = TOML_FLOAT; - return self; + TomlValue value = {0}; + value.value.f = float_; + value.type = TOML_FLOAT; + return value; } -TomlValue* toml_value_new_datetime(void) +TomlValue TomlValue_new_datetime(void) { - return toml_value_new(TOML_DATETIME); + return TomlValue_new(TOML_BOOLEAN); } -TomlValue* toml_value_new_bool(bool b) +TomlValue TomlValue_new_bool(bool b) { - TomlValue* self = toml_malloc(sizeof(TomlValue)); - self->value.b = b; - self->type = TOML_BOOLEAN; - return self; + TomlValue value = {0}; + value.value.b = b; + value.type = TOML_BOOLEAN; + return value; } -void toml_value_free(TomlValue* self) +void TomlValue_destroy(TomlValue* self) { if (self != NULL) { switch (self->type) { case TOML_STRING: - str_free(self->value.s); + str_destroy(self->value.s); break; case TOML_TABLE: toml_table_free(self->value.table); @@ -368,12 +315,11 @@ void toml_value_free(TomlValue* self) toml_array_free(self->value.array); break; case TOML_DATETIME: - memset(&self->value.dt, 0, sizeof(TomlDateTime)); + free(self->value.dt); break; default: break; } - free(self); } } @@ -388,15 +334,15 @@ typedef struct _TomlParser { TomlParser* toml_parser_new(str s, cstr filename) { - TomlParser* self = toml_malloc(sizeof(TomlParser)); - self->begin = s.data; - self->end = s.data + s.size; - self->ptr = s.data; - self->lineno = 1; - self->colno = 1; + TomlParser* parser = toml_malloc(sizeof(TomlParser)); + parser->begin = s.data; + parser->end = s.data + s.size; + parser->ptr = s.data; + parser->lineno = 1; + parser->colno = 1; // TODO: remove copy filename? - self->filename = str_copy(str_from_cstr(filename)).data; - return self; + parser->filename = str_copy(str_from_cstr(filename)).data; + return parser; } void toml_parser_free(TomlParser* self) @@ -540,7 +486,7 @@ i32 toml_encode_unicode_scalar(StringBuilder* sb_ptr, TomlParser* parser, i32 n) str toml_parse_basic_string(TomlParser* self) { - StringBuilder sb = StringBuilder_alloc(64); + StringBuilder sb = StringBuilder_alloc(0); while (self->ptr < self->end &&* self->ptr != '\"' &&* self->ptr != '\n') { char ch1 = *self->ptr; @@ -609,7 +555,7 @@ str toml_parse_basic_string(TomlParser* self) str toml_parse_literal_string(TomlParser* self) { - StringBuilder sb = StringBuilder_alloc(64); + StringBuilder sb = StringBuilder_alloc(0); while (self->ptr < self->end &&* self->ptr != '\'' &&* self->ptr != '\n') { StringBuilder_append_char(&sb,* self->ptr); @@ -628,31 +574,31 @@ str toml_parse_literal_string(TomlParser* self) return StringBuilder_getStr(&sb); } -TomlValue* toml_parse_basic_string_value(TomlParser* self) +TomlValue toml_parse_basic_string_value(TomlParser* self) { str s = toml_parse_basic_string(self); - if (s.data == NULL) - return NULL; + //TODO: error handling + assert(s.data != NULL); - TomlValue* value = toml_value_new(TOML_STRING); - value->value.s = s; + TomlValue value = TomlValue_new(TOML_STRING); + value.value.s = s; return value; } -TomlValue* toml_parse_literal_string_value(TomlParser* self) +TomlValue toml_parse_literal_string_value(TomlParser* self) { str s = toml_parse_literal_string(self); - if (s.data == NULL) - return NULL; + //TODO: error handling + assert(s.data != NULL); - TomlValue* value = toml_value_new(TOML_STRING); - value->value.s = s; + TomlValue value = TomlValue_new(TOML_STRING); + value.value.s = s; return value; } -TomlValue* toml_parse_multi_line_basic_string(TomlParser* self) +TomlValue toml_parse_multi_line_basic_string(TomlParser* self) { - StringBuilder sb = StringBuilder_alloc(64); + StringBuilder sb = StringBuilder_alloc(0); if (*self->ptr == '\n') { toml_move_next(self); @@ -693,13 +639,15 @@ TomlValue* toml_parse_multi_line_basic_string(TomlParser* self) toml_move_next(self); if (toml_encode_unicode_scalar(&sb, self, 4) != 0) { StringBuilder_destroy(&sb); - return NULL; + //TODO: error handling + assert(false && "TODO error handling"); } } else if (ch2 == 'U') { toml_move_next(self); if (toml_encode_unicode_scalar(&sb, self, 8) != 0) { StringBuilder_destroy(&sb); - return NULL; + //TODO: error handling + assert(false && "TODO error handling"); } } else if (ch2 == '\n') { do { @@ -709,7 +657,8 @@ TomlValue* toml_parse_multi_line_basic_string(TomlParser* self) toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid escape character", self->filename, self->lineno, self->colno); StringBuilder_destroy(&sb); - return NULL; + //TODO: error handling + assert(false && "TODO error handling"); } } else { StringBuilder_append_char(&sb, ch1); @@ -721,19 +670,20 @@ TomlValue* toml_parse_multi_line_basic_string(TomlParser* self) toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: unterminated multi-line basic string", self->filename, self->lineno, self->colno); StringBuilder_destroy(&sb); - return NULL; + //TODO: error handling + assert(false && "TODO error handling"); } toml_next_n(self, 3); - TomlValue* value = toml_value_new(TOML_STRING); - value->value.s = StringBuilder_getStr(&sb); + TomlValue value = TomlValue_new(TOML_STRING); + value.value.s = StringBuilder_getStr(&sb); return value; } -TomlValue* toml_parse_multi_line_literal_string(TomlParser* self) +TomlValue toml_parse_multi_line_literal_string(TomlParser* self) { - StringBuilder sb = StringBuilder_alloc(64); + StringBuilder sb = StringBuilder_alloc(0); if (*self->ptr == '\n') { toml_move_next(self); @@ -748,31 +698,32 @@ TomlValue* toml_parse_multi_line_literal_string(TomlParser* self) toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: unterminated multi-line literal string", self->filename, self->lineno, self->colno); StringBuilder_destroy(&sb); - return NULL; + //TODO: error handling + assert(false && "TODO error handling"); } toml_next_n(self, 3); - TomlValue* value = toml_value_new(TOML_STRING); - value->value.s = StringBuilder_getStr(&sb); + TomlValue value = TomlValue_new(TOML_STRING); + value.value.s = StringBuilder_getStr(&sb); return value; } -TomlValue* toml_parse_datetime(str s) +TomlValue toml_parse_datetime(str s) { (void)s; //TODO: parse datetime - return toml_value_new(TOML_DATETIME); + return TomlValue_new(TOML_DATETIME); } -TomlValue* toml_parse_int_or_float_or_time(TomlParser* self) +TomlValue toml_parse_int_or_float_or_time(TomlParser* self) { - TomlValue* result = NULL; + TomlValue value = {0}; char type = 'i'; i32 base = 10; - StringBuilder sb = StringBuilder_alloc(64); + StringBuilder sb = StringBuilder_alloc(0); // 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 @@ -831,21 +782,24 @@ TomlValue* toml_parse_int_or_float_or_time(TomlParser* self) toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid float", self->filename, self->lineno, self->colno); StringBuilder_destroy(&sb); - return NULL; + //TODO: error handling + assert(false && "TODO error handling"); } } else if (*self->ptr == '_') { if (type == 't') { toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid datetime", self->filename, self->lineno, self->colno); StringBuilder_destroy(&sb); - return NULL; + //TODO: error handling + assert(false && "TODO error handling"); } if (!isalnum(last_char)) { toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid integer or float", self->filename, self->lineno, self->colno); StringBuilder_destroy(&sb); - return NULL; + //TODO: error handling + assert(false && "TODO error handling"); } } else if (*self->ptr == '-') { type = 't'; @@ -862,62 +816,70 @@ TomlValue* toml_parse_int_or_float_or_time(TomlParser* self) toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid integer or float or datetime", self->filename, self->lineno, self->colno); StringBuilder_destroy(&sb); - return NULL; + //TODO: error handling + assert(false && "TODO error handling"); } if (type == 'i') { char* end = NULL; - i64 n = strtoll(StringBuilder_getStr(&sb).data, &end, base); - if (end < (char*)sb.buffer.data + sb.buffer.size) { + char* start = StringBuilder_getStr(&sb).data; + i64 n = strtoll(start, &end, base); + if (end < start + sb.buffer.size) { toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid integer", self->filename, self->lineno, self->colno); + //TODO: error handling + printfe("%i < %u '%s'\n", (i32)(end-start), sb.buffer.size, start); + fflush(stderr); StringBuilder_destroy(&sb); - return NULL; + assert(false && "TODO error handling"); } - result = toml_value_new_integer(n); + value = TomlValue_new_integer(n); } else if (type == 'f') { char* end = NULL; - f64 n = strtod(StringBuilder_getStr(&sb).data, &end); - if (end < (char*)sb.buffer.data + sb.buffer.size) { + char* start = StringBuilder_getStr(&sb).data; + f64 n = strtod(start, &end); + if (end < start + 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); + value = TomlValue_new_float(n); } else if (type == 't') { - result = toml_parse_datetime(StringBuilder_getStr(&sb)); + value = toml_parse_datetime(StringBuilder_getStr(&sb)); } cleanup: StringBuilder_destroy(&sb); - return result; + return value; } -TomlValue* toml_parse_bool(TomlParser* self) +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_bool(true); + return TomlValue_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_bool(false); + return TomlValue_new_bool(false); } - return NULL; + //TODO: error handling + assert(false && "TODO error handling"); + return TomlValue_new(TOML_INVALID_TYPE); } -TomlValue* toml_parse_array(TomlParser* self); -TomlValue* toml_parse_inline_table(TomlParser* self); +TomlValue toml_parse_array(TomlParser* self); +TomlValue toml_parse_inline_table(TomlParser* self); -TomlValue* toml_parse_value(TomlParser* self) +TomlValue toml_parse_value(TomlParser* self) { - TomlValue* value = NULL; char ch = *self->ptr; + TomlValue value; if (strncmp(self->ptr, "\"\"\"", 3) == 0) { toml_next_n(self, 3); value = toml_parse_multi_line_basic_string(self); @@ -943,7 +905,8 @@ TomlValue* toml_parse_value(TomlParser* self) } else { toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: unexpected token", self->filename, self->lineno, self->colno); - return NULL; + //TODO: error handling + assert(false && "TODO error handling"); } return value; @@ -951,9 +914,6 @@ TomlValue* toml_parse_value(TomlParser* self) TomlErrCode toml_parse_key_value(TomlParser* self, TomlTable* table) { - str key = str_null; - TomlValue* value = NULL; - while (self->ptr < self->end) { char ch; @@ -965,6 +925,7 @@ TomlErrCode toml_parse_key_value(TomlParser* self, TomlTable* table) if (self->ptr == self->end) break; + str key; if (isalnum(ch) || ch == '_') { key = toml_parse_bare_key(self); if (key.data == NULL) @@ -1026,12 +987,12 @@ TomlErrCode toml_parse_key_value(TomlParser* self, TomlTable* table) return TOML_ERR_SYNTAX; } - value = toml_parse_value(self); - if (value == NULL) + TomlValue value = toml_parse_value(self); + if (value.type == TOML_INVALID_TYPE) return toml_err()->code; toml_table_set(table, key, value); - str_free(key); + str_destroy(key); while (self->ptr < self->end && (*self->ptr == ' ' ||* self->ptr == '\t')) { toml_move_next(self); @@ -1062,12 +1023,9 @@ TomlErrCode toml_parse_key_value(TomlParser* self, TomlTable* table) return TOML_OK; } -TomlValue* toml_parse_array(TomlParser* self) +TomlValue toml_parse_array(TomlParser* self) { - TomlValue* array = NULL; - TomlValue* value = NULL; - - array = toml_value_new_array(); + TomlValue array_value = TomlValue_new_array(); while (self->ptr < self->end) { if (isspace(*self->ptr)) { @@ -1085,14 +1043,14 @@ TomlValue* toml_parse_array(TomlParser* self) toml_move_next(self); break; } else { - value = toml_parse_value(self); - if (value == NULL) { - goto error; + TomlValue value = toml_parse_value(self); + if (value.type == TOML_INVALID_TYPE) { + TomlValue_destroy(&array_value); + //TODO: error handling + assert(false && "TODO error handling"); } - toml_array_append(array->value.array, value); - - value = NULL; + toml_array_append(array_value.value.array, value); while (self->ptr < self->end) { if (isspace(*self->ptr)) { @@ -1114,22 +1072,12 @@ TomlValue* toml_parse_array(TomlParser* self) } } - goto end; - -error: - toml_value_free(value); - toml_value_free(array); - array = NULL; - -end: - return array; + return array_value; } -TomlValue* toml_parse_inline_table(TomlParser* self) +TomlValue toml_parse_inline_table(TomlParser* self) { - TomlValue* table = toml_value_new_table(); - str key = str_null; - TomlValue* value = NULL; + TomlValue table_value = TomlValue_new_table(); while (self->ptr < self->end) { char ch = *self->ptr; @@ -1138,6 +1086,7 @@ TomlValue* toml_parse_inline_table(TomlParser* self) ch = *self->ptr; } + str key; if (isalnum(ch) || ch == '_') { key = toml_parse_bare_key(self); if (key.data == NULL) @@ -1192,12 +1141,12 @@ TomlValue* toml_parse_inline_table(TomlParser* self) goto error; } - value = toml_parse_value(self); - if (value == NULL) + TomlValue value = toml_parse_value(self); + if (value.type == TOML_INVALID_TYPE) goto error; - toml_table_set(table->value.table, key, value); - str_free(key); + toml_table_set(table_value.value.table, key, value); + str_destroy(key); while (self->ptr < self->end && (*self->ptr == ' ' ||* self->ptr == '\t')) { toml_move_next(self); @@ -1214,11 +1163,11 @@ TomlValue* toml_parse_inline_table(TomlParser* self) goto end; error: - toml_value_free(table); - table = NULL; - + TomlValue_destroy(&table_value); + //TODO: error handling + assert(false && "TODO error handling"); end: - return table; + return table_value; } TomlTable* toml_walk_table_path(TomlParser* parser, TomlTable* table, @@ -1226,20 +1175,17 @@ TomlTable* toml_walk_table_path(TomlParser* parser, TomlTable* table, i32 create_if_not_exist) { TomlTable* real_table = table; - TomlValue* new_table = NULL; - TomlValue* array = NULL; if (is_array) { u64 i = 0; for (; i < key_path->len - 1; i++) { - str part = key_path->elements[i]->value.s; + 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(); - toml_table_set(real_table, part, new_table); - real_table = new_table->value.table; - new_table = NULL; + TomlValue new_table_value = TomlValue_new_table(); + toml_table_set(real_table, part, new_table_value); + real_table = new_table_value.value.table; } else { real_table = NULL; break; @@ -1249,17 +1195,15 @@ TomlTable* toml_walk_table_path(TomlParser* parser, TomlTable* table, } } - str part = key_path->elements[i]->value.s; + 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); - toml_table_set(real_table, part, array); - real_table = new_table->value.table; - array = NULL; - new_table = NULL; + TomlValue array_value = TomlValue_new_array(); + TomlValue new_table_value = TomlValue_new_table(); + toml_array_append(array_value.value.array, new_table_value); + toml_table_set(real_table, part, array_value); + real_table = new_table_value.value.table; } else { real_table = NULL; } @@ -1270,28 +1214,26 @@ TomlTable* toml_walk_table_path(TomlParser* parser, TomlTable* table, goto error; } - new_table = toml_value_new_table(); - toml_array_append(t->value.array, new_table); - real_table = new_table->value.table; - new_table = NULL; + TomlValue new_table_value = TomlValue_new_table(); + toml_array_append(t->value.array, new_table_value); + real_table = new_table_value.value.table; } } else { for (u64 i = 0; i < key_path->len; i++) { - str part = key_path->elements[i]->value.s; + 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(); - toml_table_set(real_table, part, new_table); - real_table = new_table->value.table; - new_table = NULL; + TomlValue new_table_value = TomlValue_new_table(); + toml_table_set(real_table, part, new_table_value); + real_table = new_table_value.value.table; } else { real_table = NULL; break; } } else { if (t->type == TOML_ARRAY) { - real_table = t->value.array->elements[t->value.array->len - 1]->value.table; + real_table = t->value.array->elements[t->value.array->len - 1].value.table; } else if (t->type == TOML_TABLE) { real_table = t->value.table; } @@ -1302,9 +1244,9 @@ TomlTable* toml_walk_table_path(TomlParser* parser, TomlTable* table, goto end; error: - toml_value_free(new_table); - toml_value_free(array); real_table = NULL; + //TODO: error handling + assert(false && "TODO error handling"); end: return real_table; @@ -1340,9 +1282,7 @@ TomlErrCode toml_parse_table(TomlParser* self, TomlTable* table) break; } } else { - str key_part = str_null; - TomlValue* key_part_value = NULL; - + str key_part; if (isalnum(*self->ptr) ||* self->ptr == '_') { key_part = toml_parse_bare_key(self); if (key_part.data == NULL) @@ -1363,8 +1303,8 @@ TomlErrCode toml_parse_table(TomlParser* self, TomlTable* table) goto cleanup; } - key_part_value = toml_value_new(TOML_STRING); - key_part_value->value.s = key_part; + TomlValue key_part_value = TomlValue_new(TOML_STRING); + key_part_value.value.s = key_part; toml_array_append(key_path, key_part_value); @@ -1485,7 +1425,7 @@ TomlTable* toml_load_file_filename(FILE* file, cstr filename) sb.buffer.size += count; if (sb.buffer.size + 1 >= sb.buffer.allocated_size) { - StringBuilder_expand(&sb, file_chunk_size); + StringBuilder_increaseCapacity(&sb, file_chunk_size); } } while (count == remaining_capacity); diff --git a/tests/main.c b/tests/main.c index a543b42..420aeab 100644 --- a/tests/main.c +++ b/tests/main.c @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include +#include #include "tlibtoml/toml.h" #ifndef PROJECT_SOURCE_DIR @@ -19,7 +20,7 @@ void print_array(const TomlArray *array) if (i > 0) { printf(", "); } - print_value(array->elements[i]); + print_value(&array->elements[i]); } printf("]"); } @@ -27,6 +28,9 @@ void print_array(const TomlArray *array) void print_value(const TomlValue* value) { switch (value->type) { + default: + assert(false && "invalid type"); + break; case TOML_TABLE: print_table(value->value.table); break; @@ -51,7 +55,7 @@ void print_value(const TomlValue* value) } } -void print_keyval(const TomlKeyValue *keyval) +void print_keyval(HashMapKeyValue* keyval) { printf("\"%s\": ", keyval->key.data); print_value(keyval->value); @@ -59,19 +63,16 @@ void print_keyval(const TomlKeyValue *keyval) void print_table(const TomlTable* table) { - TomlTableIter it = toml_table_iter_new((TomlTable*)table); + HashMapIter it = HashMapIter_create(table); printf("{"); u64 i = 0; - while (toml_table_iter_has_next(&it)) { - TomlKeyValue *keyval = toml_table_iter_get(&it); - - if (i > 0) { + HashMapKeyValue keyval; + while (HashMapIter_moveNext(&it)) { + assert(HashMapIter_getCurrent(&it, &keyval)); + if (i > 0) printf(", "); - } - print_keyval(keyval); - - toml_table_iter_next(&it); + print_keyval(&keyval); i++; } printf("}");