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 "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);

View File

@ -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);
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);

View File

@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <inttypes.h>
#include <assert.h>
#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("}");