From 71a9fd9772a3a669b7987353467a24315f716ecf Mon Sep 17 00:00:00 2001 From: CK Tan Date: Sun, 1 Nov 2020 17:52:57 -0800 Subject: [PATCH] Add enhanced access methods --- Makefile | 3 ++ README.md | 34 +++++++---------- toml.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ toml.h | 31 ++++++++++++++- 4 files changed, 157 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index fe6a54c..039d83a 100644 --- a/Makefile +++ b/Makefile @@ -30,6 +30,9 @@ toml_json: toml_json.c $(LIB) toml_cat: toml_cat.c $(LIB) + +tomlcpp.o: tomlcpp.cpp + prefix ?= /usr/local install: all diff --git a/README.md b/README.md index c3ed79c..0d3ef8b 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,7 @@ The steps for getting values from our file is usually : 1. Parse the whole TOML file. 2. Get a single table from the file. 3. Find a value from the table. -4. Convert that value to the appropriate type, i.e., string, int, etc. -5. Then, free up that memory if needed. +4. Then, free up that memory if needed. Below is an example of parsing the values from the example table. @@ -59,42 +58,35 @@ if (0 == (server = toml_table_in(conf, "server"))) { ``` 3. Find a value from the table. -4. Convert that value to the appropriate type (I.E. string, int). ```c -toml_raw_t raw; -char* host; -int64_t port; - /* Extract 'host' config value. */ -if (0 == (raw = toml_raw_in(server, "host"))) { +toml_access_t host = toml_string_in(server, "host"); +if (!host.ok) { + toml_free(conf); return handle_error(); } -/* Convert the raw value into a string. */ -if (toml_rtos(raw, &host)) { +toml_access_t port = toml_int_in(server, "port"); +if (!port.ok) { + toml_free(conf); + free(host.u.s); return handle_error(); } -/* Extract 'port' config value. */ -if (0 == (raw = toml_raw_in(server, "port"))) { - return handle_error(); -} +printf("host %s\n", host.u.s); +printf("port %d\n", port.u.i); -/* Convert the raw value into an int. */ -if (toml_rtoi(raw, &port)) { - return handle_error(); -} ``` -5. Then, free up that memory if needed. +4. Then, free up that memory if needed. ```c /* Use `toml_free` on the table returned from `toml_parse[_file]`. */ toml_free(conf); -/* Free any values returned from `toml_rto*`. */ -free(host); +/* Free any string values returned from access functions. */ +free(host.u.s); ``` ## Building diff --git a/toml.c b/toml.c index 1db5a5b..0a5c569 100644 --- a/toml.c +++ b/toml.c @@ -2147,3 +2147,114 @@ int toml_rtos(toml_raw_t src, char** ret) return *ret ? 0 : -1; } + + +toml_access_t toml_string_at(const toml_array_t* arr, int idx) +{ + toml_access_t ret; + memset(&ret, 0, sizeof(ret)); + toml_raw_t raw = toml_raw_at(arr, idx); + if (raw) { + ret.ok = (0 == toml_rtos(raw, &ret.u.s)); + } + return ret; +} + +toml_access_t toml_bool_at(const toml_array_t* arr, int idx) +{ + toml_access_t ret; + memset(&ret, 0, sizeof(ret)); + toml_raw_t raw = toml_raw_at(arr, idx); + if (raw) { + ret.ok = (0 == toml_rtob(raw, &ret.u.b)); + } + return ret; +} + +toml_access_t toml_int_at(const toml_array_t* arr, int idx) +{ + toml_access_t ret; + memset(&ret, 0, sizeof(ret)); + toml_raw_t raw = toml_raw_at(arr, idx); + if (raw) { + ret.ok = (0 == toml_rtoi(raw, &ret.u.i)); + } + return ret; +} + +toml_access_t toml_double_at(const toml_array_t* arr, int idx) +{ + toml_access_t ret; + memset(&ret, 0, sizeof(ret)); + toml_raw_t raw = toml_raw_at(arr, idx); + if (raw) { + ret.ok = (0 == toml_rtod(raw, &ret.u.d)); + } + return ret; +} + +toml_access_t toml_timestamp_at(const toml_array_t* arr, int idx) +{ + toml_access_t ret; + memset(&ret, 0, sizeof(ret)); + toml_raw_t raw = toml_raw_at(arr, idx); + if (raw) { + ret.ok = (0 == toml_rtots(raw, &ret.u.ts)); + } + return ret; +} + +toml_access_t toml_string_in(const toml_table_t* arr, const char* key) +{ + toml_access_t ret; + memset(&ret, 0, sizeof(ret)); + toml_raw_t raw = toml_raw_in(arr, key); + if (raw) { + ret.ok = (0 == toml_rtos(raw, &ret.u.s)); + } + return ret; +} + +toml_access_t toml_bool_in(const toml_table_t* arr, const char* key) +{ + toml_access_t ret; + memset(&ret, 0, sizeof(ret)); + toml_raw_t raw = toml_raw_in(arr, key); + if (raw) { + ret.ok = (0 == toml_rtob(raw, &ret.u.b)); + } + return ret; +} + +toml_access_t toml_int_in(const toml_table_t* arr, const char* key) +{ + toml_access_t ret; + memset(&ret, 0, sizeof(ret)); + toml_raw_t raw = toml_raw_in(arr, key); + if (raw) { + ret.ok = (0 == toml_rtoi(raw, &ret.u.i)); + } + return ret; +} + +toml_access_t toml_double_in(const toml_table_t* arr, const char* key) +{ + toml_access_t ret; + memset(&ret, 0, sizeof(ret)); + toml_raw_t raw = toml_raw_in(arr, key); + if (raw) { + ret.ok = (0 == toml_rtod(raw, &ret.u.d)); + } + return ret; +} + +toml_access_t toml_timestamp_in(const toml_table_t* arr, const char* key) +{ + toml_access_t ret; + memset(&ret, 0, sizeof(ret)); + toml_raw_t raw = toml_raw_in(arr, key); + if (raw) { + ret.ok = (0 == toml_rtots(raw, &ret.u.ts)); + } + return ret; +} diff --git a/toml.h b/toml.h index d541ec8..b433b54 100644 --- a/toml.h +++ b/toml.h @@ -36,8 +36,10 @@ #define TOML_EXTERN extern #endif +typedef struct toml_timestamp_t toml_timestamp_t; typedef struct toml_table_t toml_table_t; typedef struct toml_array_t toml_array_t; +typedef struct toml_access_t toml_access_t; /* A raw value, must be processed by toml_rto* before using. */ typedef const char* toml_raw_t; @@ -124,7 +126,6 @@ TOML_EXTERN int toml_rtod_ex(toml_raw_t s, double* ret, char* buf, int buflen); * fields may be NULL if they are not relevant. e.g. In a DATE * type, the hour, minute, second and z fields will be NULLs. */ -typedef struct toml_timestamp_t toml_timestamp_t; struct toml_timestamp_t { struct { /* internal. do not use. */ int year, month, day; @@ -139,10 +140,38 @@ struct toml_timestamp_t { /* Raw to Timestamp. Return 0 on success, -1 otherwise. */ TOML_EXTERN int toml_rtots(toml_raw_t s, toml_timestamp_t* ret); +/* Enhanced access methods */ +struct toml_access_t { + int ok; + union { + char* s; /* string value. s must be freed after use */ + int b; /* bool value */ + int64_t i; /* int value */ + double d; /* double value */ + toml_timestamp_t ts; + } u; +}; +TOML_EXTERN toml_access_t toml_string_at(const toml_array_t* arr, int idx); +TOML_EXTERN toml_access_t toml_bool_at(const toml_array_t* arr, int idx); +TOML_EXTERN toml_access_t toml_int_at(const toml_array_t* arr, int idx); +TOML_EXTERN toml_access_t toml_double_at(const toml_array_t* arr, int idx); +TOML_EXTERN toml_access_t toml_timestamp_at(const toml_array_t* arr, int idx); + +TOML_EXTERN toml_access_t toml_string_in(const toml_table_t* arr, const char* key); +TOML_EXTERN toml_access_t toml_bool_in(const toml_table_t* arr, const char* key); +TOML_EXTERN toml_access_t toml_int_in(const toml_table_t* arr, const char* key); +TOML_EXTERN toml_access_t toml_double_in(const toml_table_t* arr, const char* key); +TOML_EXTERN toml_access_t toml_timestamp_in(const toml_table_t* arr, const char* key); + + /* misc */ TOML_EXTERN int toml_utf8_to_ucs(const char* orig, int len, int64_t* ret); TOML_EXTERN int toml_ucs_to_utf8(int64_t code, char buf[6]); TOML_EXTERN void toml_set_memutil(void* (*xxmalloc)(size_t), void (*xxfree)(void*)); + + + + #endif /* TOML_H */