replaced TomlTable with HashMap
This commit is contained in:
parent
a33505ffe4
commit
c49a8cb1e5
@ -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);
|
||||||
|
|||||||
458
src/toml.c
458
src/toml.c
@ -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);
|
||||||
|
|
||||||
|
|||||||
23
tests/main.c
23
tests/main.c
@ -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("}");
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user