replaced TomlTable with HashMap

This commit is contained in:
Timerix 2025-11-10 10:31:47 +05:00
parent a33505ffe4
commit c49a8cb1e5
3 changed files with 232 additions and 311 deletions

View File

@ -11,9 +11,10 @@ extern "C" {
#include <time.h> #include <time.h>
#include "tlibc/std.h" #include "tlibc/std.h"
#include "tlibc/string/str.h" #include "tlibc/string/str.h"
#include "tlibc/string/StringBuilder.h" #include "tlibc/collections/HashMap.h"
typedef struct tm TomlDateTime; typedef struct tm TomlDateTime;
typedef HashMap(TomlValue) TomlTable;
typedef enum { typedef enum {
TOML_OK, TOML_OK,
@ -29,28 +30,17 @@ typedef struct {
NULLABLE(char*) message; NULLABLE(char*) message;
} TomlErr; } TomlErr;
typedef struct _TomlValue TomlValue; typedef struct TomlValue TomlValue;
typedef struct { typedef struct {
TomlValue** elements; TomlValue* elements;
u64 len; u64 len;
u64 _capacity; u64 _capacity;
} TomlArray; } TomlArray;
typedef struct _TomlKeyValue TomlKeyValue;
typedef struct {
u64 _capacity;
u64 len;
TomlKeyValue* _keyvals;
} TomlTable;
typedef struct {
TomlTable* _table;
TomlKeyValue* _keyval;
} TomlTableIter;
typedef enum { typedef enum {
TOML_INVALID_TYPE,
TOML_TABLE, TOML_TABLE,
TOML_ARRAY, TOML_ARRAY,
TOML_STRING, TOML_STRING,
@ -60,7 +50,7 @@ typedef enum {
TOML_BOOLEAN, TOML_BOOLEAN,
} TomlType; } TomlType;
struct _TomlValue { struct TomlValue {
TomlType type; TomlType type;
union { union {
TomlTable* table; TomlTable* table;
@ -68,16 +58,11 @@ struct _TomlValue {
str s; str s;
i64 i; i64 i;
f64 f; f64 f;
TomlDateTime dt; TomlDateTime* dt;
bool b; bool b;
} value; } value;
}; };
struct _TomlKeyValue {
str key;
TomlValue* value;
};
typedef struct { typedef struct {
void* (*malloc)(void* context, u64 size); void* (*malloc)(void* context, u64 size);
void* (*realloc)(void* context, void* p, u64 size); void* (*realloc)(void* context, void* p, u64 size);
@ -97,35 +82,30 @@ void toml_err_clear(void);
TomlTable* toml_table_new(void); TomlTable* toml_table_new(void);
void toml_table_free(TomlTable* self); 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); TomlValue* toml_table_get(const TomlTable* self, str key);
TomlTable* toml_table_get_table(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); TomlArray* toml_table_get_array(const TomlTable* self, str key);
str toml_table_get_str(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); i64 toml_table_get_integer(const TomlTable* self, str key);
f64 toml_table_get_float(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); 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); TomlArray* toml_array_new(void);
void toml_array_free(TomlArray* self); 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 TomlValue_new(TomlType type);
TomlValue* toml_value_new_string(TomlType type); TomlValue TomlValue_new_string(TomlType type);
TomlValue* toml_value_new_table(void); TomlValue TomlValue_new_table(void);
TomlValue* toml_value_new_array(void); TomlValue TomlValue_new_array(void);
TomlValue* toml_value_new_integer(i64 integer); TomlValue TomlValue_new_integer(i64 integer);
TomlValue* toml_value_new_float(f64 flt); TomlValue TomlValue_new_float(f64 flt);
TomlValue* toml_value_new_datetime(void); TomlValue TomlValue_new_datetime(void);
TomlValue* toml_value_new_bool(bool b); TomlValue TomlValue_new_bool(bool b);
TomlValue* toml_value_from_str(str s); TomlValue TomlValue_from_str(str s);
void toml_value_free(TomlValue* self); void TomlValue_destroy(TomlValue* self);
TomlTable* toml_load_str(str s); TomlTable* toml_load_str(str s);
TomlTable* toml_load_file(FILE* file); TomlTable* toml_load_file(FILE* file);

View File

@ -7,6 +7,8 @@
#include "tlibtoml/toml.h" #include "tlibtoml/toml.h"
#include "tlibc/errors.h" #include "tlibc/errors.h"
#include "tlibc/string/StringBuilder.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 }; 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.code = code;
g_err.message = vsprintf_malloc(format, args); g_err.message = vsprintf_malloc(format, args);
va_end(args); va_end(args);
printfe("ERROR: %s\n", toml_err()->message);
fflush(stderr);
} }
TomlTable* toml_table_new(void) TomlTable* toml_table_new(void)
{ {
TomlTable* self = toml_malloc(sizeof(TomlTable)); TomlTable* table = toml_malloc(sizeof(TomlTable));
self->_capacity = 0; HashMap_construct(table, TomlValue, (FreeFunction)TomlValue_destroy);
self->_keyvals = NULL; return table;
self->len = 0;
return self;
} }
void toml_table_free(TomlTable* self) void toml_table_free(TomlTable* self)
{ {
if (self != NULL) { if(!self)
for (u64 i = 0; i < self->len; i++) { return;
free(self->_keyvals[i].key.data); HashMap_destroy(self);
toml_value_free(self->_keyvals[i].value);
}
free(self->_keyvals);
free(self); free(self);
} }
}
void toml_table_expand_if_necessary(TomlTable* self) void toml_table_set(TomlTable* self, str key, TomlValue value)
{
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)
{ {
assert(key.data != NULL); assert(key.data != NULL);
TomlValue** slot = NULL; HashMap_pushOrUpdate(self, key, &value);
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;
}
} }
TomlValue* toml_table_get(const TomlTable* self, const str key) TomlValue* toml_table_get(const TomlTable* self, const str key)
{ {
assert(key.data != NULL); assert(key.data != NULL);
TomlValue* value = NULL; TomlValue* value = HashMap_tryGetPtr(self, key);
for (u64 i = 0; i < self->len; i++) {
if (str_equals(self->_keyvals[i].key, key)) {
value = self->_keyvals[i].value;
}
}
return value; return value;
} }
@ -192,12 +162,12 @@ f64 toml_table_get_float(const TomlTable* self, str key)
return v->value.f; 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); TomlValue* v = toml_table_get(self, key);
assert(v != NULL); assert(v != NULL);
assert(v->type == TOML_DATETIME); assert(v->type == TOML_DATETIME);
return &v->value.dt; return v->value.dt;
} }
bool toml_table_get_bool(const TomlTable* self, str key) 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; 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 *toml_array_new(void)
{ {
TomlArray* self = toml_malloc(sizeof(TomlArray)); TomlArray* array = toml_malloc(sizeof(TomlArray));
self->elements = NULL; array->elements = NULL;
self->len = 0; array->len = 0;
self->_capacity = 0; array->_capacity = 0;
return self; return array;
} }
void toml_array_free(TomlArray* self) void toml_array_free(TomlArray* self)
{ {
if (self != NULL) { if (self != NULL) {
for (u64 i = 0; i < self->len; i++) { for (u64 i = 0; i < self->len; i++) {
toml_value_free(self->elements[i]); TomlValue_destroy(&self->elements[i]);
} }
free(self->elements); free(self->elements);
free(self); free(self);
@ -259,107 +202,111 @@ void toml_array_expand_if_necessary(TomlArray* self)
{ {
if (self->len + 1 > self->_capacity) { if (self->len + 1 > self->_capacity) {
u64 new_capacity = self->_capacity > 0 ? self->_capacity * 2 : 8; 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->elements = p;
self->_capacity = new_capacity; 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); toml_array_expand_if_necessary(self);
self->elements[self->len++] = value; self->elements[self->len++] = value;
} }
TomlValue* toml_value_new(TomlType type) TomlValue TomlValue_new(TomlType type)
{ {
TomlValue* self = toml_malloc(sizeof(TomlValue)); TomlValue value = {0};
self->type = type; value.type = type;
switch (type) { switch (type) {
default:
assert(false && "invalid type");
break;
case TOML_TABLE: case TOML_TABLE:
self->value.table = NULL; value.value.table = NULL;
break; break;
case TOML_ARRAY: case TOML_ARRAY:
self->value.array = NULL; value.value.array = NULL;
break; break;
case TOML_STRING: case TOML_STRING:
self->value.s = str_null; value.value.s = str_null;
break; break;
case TOML_INTEGER: case TOML_INTEGER:
self->value.i = 0; value.value.i = 0;
break; break;
case TOML_FLOAT: case TOML_FLOAT:
self->value.f = 0.0; value.value.f = 0.0;
break; break;
case TOML_BOOLEAN: case TOML_BOOLEAN:
self->value.b = false; value.value.b = false;
break; break;
case TOML_DATETIME: 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; break;
} }
return self; return value;
} }
TomlValue* toml_value_from_str(str s) TomlValue TomlValue_from_str(str s)
{ {
TomlValue* self = toml_malloc(sizeof(TomlValue)); TomlValue value = {0};
self->value.s = str_copy(s); value.value.s = str_copy(s);
self->type = TOML_STRING; value.type = TOML_STRING;
return self; return value;
} }
TomlValue* toml_value_new_table(void) TomlValue TomlValue_new_table(void)
{ {
TomlValue* self = toml_malloc(sizeof(TomlValue)); TomlValue value = {0};
self->value.table = toml_table_new(); value.value.table = toml_table_new();
self->type = TOML_TABLE; value.type = TOML_TABLE;
return self; return value;
} }
TomlValue* toml_value_new_array(void) TomlValue TomlValue_new_array(void)
{ {
TomlValue* self = toml_malloc(sizeof(TomlValue)); TomlValue value = {0};
self->value.array = toml_array_new(); value.value.array = toml_array_new();
self->type = TOML_ARRAY; value.type = TOML_ARRAY;
return self; return value;
} }
TomlValue* toml_value_new_integer(i64 integer) TomlValue TomlValue_new_integer(i64 integer)
{ {
TomlValue* self = toml_malloc(sizeof(TomlValue)); TomlValue value = {0};
self->value.i = integer; value.value.i = integer;
self->type = TOML_INTEGER; value.type = TOML_INTEGER;
return self; return value;
} }
TomlValue* toml_value_new_float(f64 float_) TomlValue TomlValue_new_float(f64 float_)
{ {
TomlValue* self = toml_malloc(sizeof(TomlValue)); TomlValue value = {0};
self->value.f = float_; value.value.f = float_;
self->type = TOML_FLOAT; value.type = TOML_FLOAT;
return self; 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)); TomlValue value = {0};
self->value.b = b; value.value.b = b;
self->type = TOML_BOOLEAN; value.type = TOML_BOOLEAN;
return self; return value;
} }
void toml_value_free(TomlValue* self) void TomlValue_destroy(TomlValue* self)
{ {
if (self != NULL) { if (self != NULL) {
switch (self->type) { switch (self->type) {
case TOML_STRING: case TOML_STRING:
str_free(self->value.s); str_destroy(self->value.s);
break; break;
case TOML_TABLE: case TOML_TABLE:
toml_table_free(self->value.table); toml_table_free(self->value.table);
@ -368,12 +315,11 @@ void toml_value_free(TomlValue* self)
toml_array_free(self->value.array); toml_array_free(self->value.array);
break; break;
case TOML_DATETIME: case TOML_DATETIME:
memset(&self->value.dt, 0, sizeof(TomlDateTime)); free(self->value.dt);
break; break;
default: default:
break; break;
} }
free(self);
} }
} }
@ -388,15 +334,15 @@ typedef struct _TomlParser {
TomlParser* toml_parser_new(str s, cstr filename) TomlParser* toml_parser_new(str s, cstr filename)
{ {
TomlParser* self = toml_malloc(sizeof(TomlParser)); TomlParser* parser = toml_malloc(sizeof(TomlParser));
self->begin = s.data; parser->begin = s.data;
self->end = s.data + s.size; parser->end = s.data + s.size;
self->ptr = s.data; parser->ptr = s.data;
self->lineno = 1; parser->lineno = 1;
self->colno = 1; parser->colno = 1;
// TODO: remove copy filename? // TODO: remove copy filename?
self->filename = str_copy(str_from_cstr(filename)).data; parser->filename = str_copy(str_from_cstr(filename)).data;
return self; return parser;
} }
void toml_parser_free(TomlParser* self) 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) 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') { while (self->ptr < self->end &&* self->ptr != '\"' &&* self->ptr != '\n') {
char ch1 = *self->ptr; char ch1 = *self->ptr;
@ -609,7 +555,7 @@ str toml_parse_basic_string(TomlParser* self)
str toml_parse_literal_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') { while (self->ptr < self->end &&* self->ptr != '\'' &&* self->ptr != '\n') {
StringBuilder_append_char(&sb,* self->ptr); StringBuilder_append_char(&sb,* self->ptr);
@ -628,31 +574,31 @@ str toml_parse_literal_string(TomlParser* self)
return StringBuilder_getStr(&sb); 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); str s = toml_parse_basic_string(self);
if (s.data == NULL) //TODO: error handling
return NULL; assert(s.data != NULL);
TomlValue* value = toml_value_new(TOML_STRING); TomlValue value = TomlValue_new(TOML_STRING);
value->value.s = s; value.value.s = s;
return value; 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); str s = toml_parse_literal_string(self);
if (s.data == NULL) //TODO: error handling
return NULL; assert(s.data != NULL);
TomlValue* value = toml_value_new(TOML_STRING); TomlValue value = TomlValue_new(TOML_STRING);
value->value.s = s; value.value.s = s;
return value; 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') { if (*self->ptr == '\n') {
toml_move_next(self); toml_move_next(self);
@ -693,13 +639,15 @@ TomlValue* toml_parse_multi_line_basic_string(TomlParser* self)
toml_move_next(self); toml_move_next(self);
if (toml_encode_unicode_scalar(&sb, self, 4) != 0) { if (toml_encode_unicode_scalar(&sb, self, 4) != 0) {
StringBuilder_destroy(&sb); StringBuilder_destroy(&sb);
return NULL; //TODO: error handling
assert(false && "TODO error handling");
} }
} else if (ch2 == 'U') { } else if (ch2 == 'U') {
toml_move_next(self); toml_move_next(self);
if (toml_encode_unicode_scalar(&sb, self, 8) != 0) { if (toml_encode_unicode_scalar(&sb, self, 8) != 0) {
StringBuilder_destroy(&sb); StringBuilder_destroy(&sb);
return NULL; //TODO: error handling
assert(false && "TODO error handling");
} }
} else if (ch2 == '\n') { } else if (ch2 == '\n') {
do { 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", toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid escape character",
self->filename, self->lineno, self->colno); self->filename, self->lineno, self->colno);
StringBuilder_destroy(&sb); StringBuilder_destroy(&sb);
return NULL; //TODO: error handling
assert(false && "TODO error handling");
} }
} else { } else {
StringBuilder_append_char(&sb, ch1); 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", toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: unterminated multi-line basic string",
self->filename, self->lineno, self->colno); self->filename, self->lineno, self->colno);
StringBuilder_destroy(&sb); StringBuilder_destroy(&sb);
return NULL; //TODO: error handling
assert(false && "TODO error handling");
} }
toml_next_n(self, 3); toml_next_n(self, 3);
TomlValue* value = toml_value_new(TOML_STRING); TomlValue value = TomlValue_new(TOML_STRING);
value->value.s = StringBuilder_getStr(&sb); value.value.s = StringBuilder_getStr(&sb);
return value; 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') { if (*self->ptr == '\n') {
toml_move_next(self); 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", toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: unterminated multi-line literal string",
self->filename, self->lineno, self->colno); self->filename, self->lineno, self->colno);
StringBuilder_destroy(&sb); StringBuilder_destroy(&sb);
return NULL; //TODO: error handling
assert(false && "TODO error handling");
} }
toml_next_n(self, 3); toml_next_n(self, 3);
TomlValue* value = toml_value_new(TOML_STRING); TomlValue value = TomlValue_new(TOML_STRING);
value->value.s = StringBuilder_getStr(&sb); value.value.s = StringBuilder_getStr(&sb);
return value; return value;
} }
TomlValue* toml_parse_datetime(str s) TomlValue toml_parse_datetime(str s)
{ {
(void)s; (void)s;
//TODO: parse datetime //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'; char type = 'i';
i32 base = 10; 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. // 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 // 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", toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid float",
self->filename, self->lineno, self->colno); self->filename, self->lineno, self->colno);
StringBuilder_destroy(&sb); StringBuilder_destroy(&sb);
return NULL; //TODO: error handling
assert(false && "TODO error handling");
} }
} else if (*self->ptr == '_') { } else if (*self->ptr == '_') {
if (type == 't') { if (type == 't') {
toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid datetime", toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid datetime",
self->filename, self->lineno, self->colno); self->filename, self->lineno, self->colno);
StringBuilder_destroy(&sb); StringBuilder_destroy(&sb);
return NULL; //TODO: error handling
assert(false && "TODO error handling");
} }
if (!isalnum(last_char)) { if (!isalnum(last_char)) {
toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid integer or float", toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid integer or float",
self->filename, self->lineno, self->colno); self->filename, self->lineno, self->colno);
StringBuilder_destroy(&sb); StringBuilder_destroy(&sb);
return NULL; //TODO: error handling
assert(false && "TODO error handling");
} }
} else if (*self->ptr == '-') { } else if (*self->ptr == '-') {
type = 't'; 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", toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid integer or float or datetime",
self->filename, self->lineno, self->colno); self->filename, self->lineno, self->colno);
StringBuilder_destroy(&sb); StringBuilder_destroy(&sb);
return NULL; //TODO: error handling
assert(false && "TODO error handling");
} }
if (type == 'i') { if (type == 'i') {
char* end = NULL; char* end = NULL;
i64 n = strtoll(StringBuilder_getStr(&sb).data, &end, base); char* start = StringBuilder_getStr(&sb).data;
if (end < (char*)sb.buffer.data + sb.buffer.size) { i64 n = strtoll(start, &end, base);
if (end < start + sb.buffer.size) {
toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid integer", toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid integer",
self->filename, self->lineno, self->colno); 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); 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') { } else if (type == 'f') {
char* end = NULL; char* end = NULL;
f64 n = strtod(StringBuilder_getStr(&sb).data, &end); char* start = StringBuilder_getStr(&sb).data;
if (end < (char*)sb.buffer.data + sb.buffer.size) { f64 n = strtod(start, &end);
if (end < start + sb.buffer.size) {
toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid float", toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: invalid float",
self->filename, self->lineno, self->colno); self->filename, self->lineno, self->colno);
goto cleanup; goto cleanup;
} }
result = toml_value_new_float(n); value = TomlValue_new_float(n);
} else if (type == 't') { } else if (type == 't') {
result = toml_parse_datetime(StringBuilder_getStr(&sb)); value = toml_parse_datetime(StringBuilder_getStr(&sb));
} }
cleanup: cleanup:
StringBuilder_destroy(&sb); 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 && 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) == '}')) { (self->ptr + 4 == self->end || isspace(*(self->ptr + 4)) || *(self->ptr + 4) == ',' || *(self->ptr + 4) == ']' || *(self->ptr + 4) == '}')) {
toml_next_n(self, 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 && 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) == '}')) { (self->ptr + 5 == self->end || isspace(*(self->ptr + 5)) || *(self->ptr + 5) == ',' || *(self->ptr + 5) == ']' || *(self->ptr + 5) == '}')) {
toml_next_n(self, 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_array(TomlParser* self);
TomlValue* toml_parse_inline_table(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; char ch = *self->ptr;
TomlValue value;
if (strncmp(self->ptr, "\"\"\"", 3) == 0) { if (strncmp(self->ptr, "\"\"\"", 3) == 0) {
toml_next_n(self, 3); toml_next_n(self, 3);
value = toml_parse_multi_line_basic_string(self); value = toml_parse_multi_line_basic_string(self);
@ -943,7 +905,8 @@ TomlValue* toml_parse_value(TomlParser* self)
} else { } else {
toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: unexpected token", toml_err_set(TOML_ERR_SYNTAX, "%s:%d:%d: unexpected token",
self->filename, self->lineno, self->colno); self->filename, self->lineno, self->colno);
return NULL; //TODO: error handling
assert(false && "TODO error handling");
} }
return value; return value;
@ -951,9 +914,6 @@ TomlValue* toml_parse_value(TomlParser* self)
TomlErrCode toml_parse_key_value(TomlParser* self, TomlTable* table) TomlErrCode toml_parse_key_value(TomlParser* self, TomlTable* table)
{ {
str key = str_null;
TomlValue* value = NULL;
while (self->ptr < self->end) { while (self->ptr < self->end) {
char ch; char ch;
@ -965,6 +925,7 @@ TomlErrCode toml_parse_key_value(TomlParser* self, TomlTable* table)
if (self->ptr == self->end) break; if (self->ptr == self->end) break;
str key;
if (isalnum(ch) || ch == '_') { if (isalnum(ch) || ch == '_') {
key = toml_parse_bare_key(self); key = toml_parse_bare_key(self);
if (key.data == NULL) if (key.data == NULL)
@ -1026,12 +987,12 @@ TomlErrCode toml_parse_key_value(TomlParser* self, TomlTable* table)
return TOML_ERR_SYNTAX; return TOML_ERR_SYNTAX;
} }
value = toml_parse_value(self); TomlValue value = toml_parse_value(self);
if (value == NULL) if (value.type == TOML_INVALID_TYPE)
return toml_err()->code; return toml_err()->code;
toml_table_set(table, key, value); toml_table_set(table, key, value);
str_free(key); str_destroy(key);
while (self->ptr < self->end && (*self->ptr == ' ' ||* self->ptr == '\t')) { while (self->ptr < self->end && (*self->ptr == ' ' ||* self->ptr == '\t')) {
toml_move_next(self); toml_move_next(self);
@ -1062,12 +1023,9 @@ TomlErrCode toml_parse_key_value(TomlParser* self, TomlTable* table)
return TOML_OK; return TOML_OK;
} }
TomlValue* toml_parse_array(TomlParser* self) TomlValue toml_parse_array(TomlParser* self)
{ {
TomlValue* array = NULL; TomlValue array_value = TomlValue_new_array();
TomlValue* value = NULL;
array = toml_value_new_array();
while (self->ptr < self->end) { while (self->ptr < self->end) {
if (isspace(*self->ptr)) { if (isspace(*self->ptr)) {
@ -1085,14 +1043,14 @@ TomlValue* toml_parse_array(TomlParser* self)
toml_move_next(self); toml_move_next(self);
break; break;
} else { } else {
value = toml_parse_value(self); TomlValue value = toml_parse_value(self);
if (value == NULL) { if (value.type == TOML_INVALID_TYPE) {
goto error; TomlValue_destroy(&array_value);
//TODO: error handling
assert(false && "TODO error handling");
} }
toml_array_append(array->value.array, value); toml_array_append(array_value.value.array, value);
value = NULL;
while (self->ptr < self->end) { while (self->ptr < self->end) {
if (isspace(*self->ptr)) { if (isspace(*self->ptr)) {
@ -1114,22 +1072,12 @@ TomlValue* toml_parse_array(TomlParser* self)
} }
} }
goto end; return array_value;
error:
toml_value_free(value);
toml_value_free(array);
array = NULL;
end:
return array;
} }
TomlValue* toml_parse_inline_table(TomlParser* self) TomlValue toml_parse_inline_table(TomlParser* self)
{ {
TomlValue* table = toml_value_new_table(); TomlValue table_value = TomlValue_new_table();
str key = str_null;
TomlValue* value = NULL;
while (self->ptr < self->end) { while (self->ptr < self->end) {
char ch = *self->ptr; char ch = *self->ptr;
@ -1138,6 +1086,7 @@ TomlValue* toml_parse_inline_table(TomlParser* self)
ch = *self->ptr; ch = *self->ptr;
} }
str key;
if (isalnum(ch) || ch == '_') { if (isalnum(ch) || ch == '_') {
key = toml_parse_bare_key(self); key = toml_parse_bare_key(self);
if (key.data == NULL) if (key.data == NULL)
@ -1192,12 +1141,12 @@ TomlValue* toml_parse_inline_table(TomlParser* self)
goto error; goto error;
} }
value = toml_parse_value(self); TomlValue value = toml_parse_value(self);
if (value == NULL) if (value.type == TOML_INVALID_TYPE)
goto error; goto error;
toml_table_set(table->value.table, key, value); toml_table_set(table_value.value.table, key, value);
str_free(key); str_destroy(key);
while (self->ptr < self->end && (*self->ptr == ' ' ||* self->ptr == '\t')) { while (self->ptr < self->end && (*self->ptr == ' ' ||* self->ptr == '\t')) {
toml_move_next(self); toml_move_next(self);
@ -1214,11 +1163,11 @@ TomlValue* toml_parse_inline_table(TomlParser* self)
goto end; goto end;
error: error:
toml_value_free(table); TomlValue_destroy(&table_value);
table = NULL; //TODO: error handling
assert(false && "TODO error handling");
end: end:
return table; return table_value;
} }
TomlTable* toml_walk_table_path(TomlParser* parser, TomlTable* table, 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) i32 create_if_not_exist)
{ {
TomlTable* real_table = table; TomlTable* real_table = table;
TomlValue* new_table = NULL;
TomlValue* array = NULL;
if (is_array) { if (is_array) {
u64 i = 0; u64 i = 0;
for (; i < key_path->len - 1; i++) { 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); TomlValue* t = toml_table_get(real_table, part);
if (t == NULL) { if (t == NULL) {
if (create_if_not_exist) { if (create_if_not_exist) {
new_table = toml_value_new_table(); TomlValue new_table_value = TomlValue_new_table();
toml_table_set(real_table, part, new_table); toml_table_set(real_table, part, new_table_value);
real_table = new_table->value.table; real_table = new_table_value.value.table;
new_table = NULL;
} else { } else {
real_table = NULL; real_table = NULL;
break; 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); TomlValue* t = toml_table_get(real_table, part);
if (t == NULL) { if (t == NULL) {
if (create_if_not_exist) { if (create_if_not_exist) {
array = toml_value_new_array(); TomlValue array_value = TomlValue_new_array();
new_table = toml_value_new_table(); TomlValue new_table_value = TomlValue_new_table();
toml_array_append(array->value.array, new_table); toml_array_append(array_value.value.array, new_table_value);
toml_table_set(real_table, part, array); toml_table_set(real_table, part, array_value);
real_table = new_table->value.table; real_table = new_table_value.value.table;
array = NULL;
new_table = NULL;
} else { } else {
real_table = NULL; real_table = NULL;
} }
@ -1270,28 +1214,26 @@ TomlTable* toml_walk_table_path(TomlParser* parser, TomlTable* table,
goto error; goto error;
} }
new_table = toml_value_new_table(); TomlValue new_table_value = TomlValue_new_table();
toml_array_append(t->value.array, new_table); toml_array_append(t->value.array, new_table_value);
real_table = new_table->value.table; real_table = new_table_value.value.table;
new_table = NULL;
} }
} else { } else {
for (u64 i = 0; i < key_path->len; i++) { 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); TomlValue* t = toml_table_get(real_table, part);
if (t == NULL) { if (t == NULL) {
if (create_if_not_exist) { if (create_if_not_exist) {
new_table = toml_value_new_table(); TomlValue new_table_value = TomlValue_new_table();
toml_table_set(real_table, part, new_table); toml_table_set(real_table, part, new_table_value);
real_table = new_table->value.table; real_table = new_table_value.value.table;
new_table = NULL;
} else { } else {
real_table = NULL; real_table = NULL;
break; break;
} }
} else { } else {
if (t->type == TOML_ARRAY) { 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) { } else if (t->type == TOML_TABLE) {
real_table = t->value.table; real_table = t->value.table;
} }
@ -1302,9 +1244,9 @@ TomlTable* toml_walk_table_path(TomlParser* parser, TomlTable* table,
goto end; goto end;
error: error:
toml_value_free(new_table);
toml_value_free(array);
real_table = NULL; real_table = NULL;
//TODO: error handling
assert(false && "TODO error handling");
end: end:
return real_table; return real_table;
@ -1340,9 +1282,7 @@ TomlErrCode toml_parse_table(TomlParser* self, TomlTable* table)
break; break;
} }
} else { } else {
str key_part = str_null; str key_part;
TomlValue* key_part_value = NULL;
if (isalnum(*self->ptr) ||* self->ptr == '_') { if (isalnum(*self->ptr) ||* self->ptr == '_') {
key_part = toml_parse_bare_key(self); key_part = toml_parse_bare_key(self);
if (key_part.data == NULL) if (key_part.data == NULL)
@ -1363,8 +1303,8 @@ TomlErrCode toml_parse_table(TomlParser* self, TomlTable* table)
goto cleanup; goto cleanup;
} }
key_part_value = toml_value_new(TOML_STRING); TomlValue key_part_value = TomlValue_new(TOML_STRING);
key_part_value->value.s = key_part; key_part_value.value.s = key_part;
toml_array_append(key_path, key_part_value); 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; sb.buffer.size += count;
if (sb.buffer.size + 1 >= sb.buffer.allocated_size) { 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); } while (count == remaining_capacity);

View File

@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <inttypes.h> #include <inttypes.h>
#include <assert.h>
#include "tlibtoml/toml.h" #include "tlibtoml/toml.h"
#ifndef PROJECT_SOURCE_DIR #ifndef PROJECT_SOURCE_DIR
@ -19,7 +20,7 @@ void print_array(const TomlArray *array)
if (i > 0) { if (i > 0) {
printf(", "); printf(", ");
} }
print_value(array->elements[i]); print_value(&array->elements[i]);
} }
printf("]"); printf("]");
} }
@ -27,6 +28,9 @@ void print_array(const TomlArray *array)
void print_value(const TomlValue* value) void print_value(const TomlValue* value)
{ {
switch (value->type) { switch (value->type) {
default:
assert(false && "invalid type");
break;
case TOML_TABLE: case TOML_TABLE:
print_table(value->value.table); print_table(value->value.table);
break; 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); printf("\"%s\": ", keyval->key.data);
print_value(keyval->value); print_value(keyval->value);
@ -59,19 +63,16 @@ void print_keyval(const TomlKeyValue *keyval)
void print_table(const TomlTable* table) void print_table(const TomlTable* table)
{ {
TomlTableIter it = toml_table_iter_new((TomlTable*)table); HashMapIter it = HashMapIter_create(table);
printf("{"); printf("{");
u64 i = 0; u64 i = 0;
while (toml_table_iter_has_next(&it)) { HashMapKeyValue keyval;
TomlKeyValue *keyval = toml_table_iter_get(&it); while (HashMapIter_moveNext(&it)) {
assert(HashMapIter_getCurrent(&it, &keyval));
if (i > 0) { if (i > 0)
printf(", "); printf(", ");
} print_keyval(&keyval);
print_keyval(keyval);
toml_table_iter_next(&it);
i++; i++;
} }
printf("}"); printf("}");