From e1e73699072f5d0cf58ea45b523e56d25b420dde Mon Sep 17 00:00:00 2001 From: dcresswell Date: Sat, 4 Jul 2020 16:35:46 -0700 Subject: [PATCH 1/2] Reformats Readme to provide better instructions This makes the Readme much cleaner so new users have an easier time starting out with this library. --- README.md | 156 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 93 insertions(+), 63 deletions(-) diff --git a/README.md b/README.md index 2ef0526..708cd29 100644 --- a/README.md +++ b/README.md @@ -1,95 +1,125 @@ # tomlc99 + TOML in c99; v0.5.0 compliant. - -# Usage +## Usage Please see the `toml.h` file for details. What follows is a simple example that parses this config file: -``` +```toml [server] -    host = "www.example.com" - port = 80 + host = "www.example.com" + port = 80 ``` -For each config param, the code first extracts a raw value and then -convert it to a string or integer depending on context. +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). +5. Then, free up that memory if needed. + +Below is an example of parsing the values from the example table. + +1. Parse the whole TOML file. + +```c +FILE* fp; +toml_table_t* conf; +char errbuf[200]; + +/* Open the file. */ +if (0 == (fp = fopen("path/to/file.toml", "r"))) { + return handle_error(); +} + +/* Run the file through the parser. */ +conf = toml_parse_file(fp, errbuf, sizeof(errbuf)); +if (0 == conf) { + return handle_error(); +} + +fclose(fp); + +/* Alternatively, use `toml_parse` which takes a string rather than a file. */ +conf = toml_parse("A null terminated string that is TOML\0", errbuf, sizeof(errbuf); ``` - FILE* fp; - toml_table_t* conf; - toml_table_t* server; - const char* raw; - char* host; - int64_t port; - char errbuf[200]; +2. Get a single table from the file. - /* open file and parse */ - if (0 == (fp = fopen(FNAME, "r"))) { - return handle_error(); - } - conf = toml_parse_file(fp, errbuf, sizeof(errbuf)); - fclose(fp); - if (0 == conf) { - return handle_error(); - } +```c +toml_table_t* server; - /* locate the [server] table */ - if (0 == (server = toml_table_in(conf, "server"))) { +/* Locate the [server] table. */ +if (0 == (server = toml_table_in(conf, "server"))) { return handle_error(); - } - - /* extract host config value */ - if (0 == (raw = toml_raw_in(server, "host"))) { - return handle_error(); - } - if (toml_rtos(raw, &host)) { - return handle_error(); - } - - /* extract port config value */ - if (0 == (raw = toml_raw_in(server, "port"))) { - return handle_error(); - } - if (toml_rtoi(raw, &port)) { - return handle_error(); - } - - /* done with conf */ - toml_free(conf); - - /* use host and port */ - do_work(host, port); - - /* clean up */ - free(host); +} ``` +3. Find a value from the table. +4. Convert that value to the appropriate type (I.E. string, int). -# Building +```c +const char* raw; +char* host; +int64_t port; + +/* Extract 'host' config value. */ +if (0 == (raw = toml_raw_in(server, "host"))) { + return handle_error(); +} + +/* Convert the raw value into a string. */ +if (toml_rtos(raw, &host)) { + return handle_error(); +} + +/* Extract 'port' config value. */ +if (0 == (raw = toml_raw_in(server, "port"))) { + return handle_error(); +} + +/* Convert the raw value into an int. */ +if (toml_rtoi(raw, &port)) { + return handle_error(); +} +``` + +5. 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(port); +``` + +## Building A normal *make* suffices. Alternately, you can also simply include the `toml.c` and `toml.h` files in your project. -# Testing +## Testing To test against the standard test set provided by BurntSushi/toml-test: -``` - % make - % cd test1 - % bash build.sh # do this once - % bash run.sh # this will run the test suite +```sh +% make +% cd test1 +% bash build.sh # do this once +% bash run.sh # this will run the test suite ``` To test against the standard test set provided by iarna/toml: -``` - % make - % cd test2 - % bash build.sh # do this once - % bash run.sh # this will run the test suite +```sh +% make +% cd test2 +% bash build.sh # do this once +% bash run.sh # this will run the test suite ``` From 5d1d8e33894947949c98eba5d77c096a6a28ff4c Mon Sep 17 00:00:00 2001 From: dcresswell Date: Sat, 4 Jul 2020 16:48:10 -0700 Subject: [PATCH 2/2] Adds toml_raw_t to seperate raw and processed data This just makes it more obvious that toml_raw_at returns a incomplete bit of data. Users can easily see how to use rto* with this. --- README.md | 2 +- toml.c | 17 ++++++++--------- toml.h | 21 ++++++++++++--------- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 708cd29..6b5b544 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ if (0 == (server = toml_table_in(conf, "server"))) { 4. Convert that value to the appropriate type (I.E. string, int). ```c -const char* raw; +toml_raw_t raw; char* host; int64_t port; diff --git a/toml.c b/toml.c index 4fd84a4..a5c8052 100644 --- a/toml.c +++ b/toml.c @@ -1741,8 +1741,7 @@ const char* toml_key_in(const toml_table_t* tab, int keyidx) return 0; } - -const char* toml_raw_in(const toml_table_t* tab, const char* key) +toml_raw_t toml_raw_in(const toml_table_t* tab, const char* key) { int i; for (i = 0; i < tab->nkval; i++) { @@ -1773,7 +1772,7 @@ toml_table_t* toml_table_in(const toml_table_t* tab, const char* key) return 0; } -const char* toml_raw_at(const toml_array_t* arr, int idx) +toml_raw_t toml_raw_at(const toml_array_t* arr, int idx) { if (arr->kind != 'v') return 0; @@ -1848,7 +1847,7 @@ toml_table_t* toml_table_at(const toml_array_t* arr, int idx) } -int toml_rtots(const char* src_, toml_timestamp_t* ret) +int toml_rtots(toml_raw_t src_, toml_timestamp_t* ret) { if (! src_) return -1; @@ -1942,7 +1941,7 @@ int toml_rtots(const char* src_, toml_timestamp_t* ret) /* Raw to boolean */ -int toml_rtob(const char* src, int* ret_) +int toml_rtob(toml_raw_t src, int* ret_) { if (!src) return -1; int dummy; @@ -1961,7 +1960,7 @@ int toml_rtob(const char* src, int* ret_) /* Raw to integer */ -int toml_rtoi(const char* src, int64_t* ret_) +int toml_rtoi(toml_raw_t src, int64_t* ret_) { if (!src) return -1; @@ -2024,7 +2023,7 @@ int toml_rtoi(const char* src, int64_t* ret_) } -int toml_rtod_ex(const char* src, double* ret_, char* buf, int buflen) +int toml_rtod_ex(toml_raw_t src, double* ret_, char* buf, int buflen) { if (!src) return -1; @@ -2086,7 +2085,7 @@ int toml_rtod_ex(const char* src, double* ret_, char* buf, int buflen) return (errno || *endp) ? -1 : 0; } -int toml_rtod(const char* src, double* ret_) +int toml_rtod(toml_raw_t src, double* ret_) { char buf[100]; return toml_rtod_ex(src, ret_, buf, sizeof(buf)); @@ -2095,7 +2094,7 @@ int toml_rtod(const char* src, double* ret_) -int toml_rtos(const char* src, char** ret) +int toml_rtos(toml_raw_t src, char** ret) { int multiline = 0; const char* sp; diff --git a/toml.h b/toml.h index f61135d..ff851ba 100644 --- a/toml.h +++ b/toml.h @@ -39,6 +39,9 @@ typedef struct toml_table_t toml_table_t; typedef struct toml_array_t toml_array_t; +/* A raw value, must be processed by toml_rto* before using. */ +typedef const char* toml_raw_t; + /* Parse a file. Return a table on success, or 0 otherwise. * Caller must toml_free(the-return-value) after use. */ @@ -61,7 +64,7 @@ TOML_EXTERN void toml_free(toml_table_t* tab); TOML_EXTERN const char* toml_key_in(const toml_table_t* tab, int keyidx); /* Lookup table by key. Return the element or 0 if not found. */ -TOML_EXTERN const char* toml_raw_in(const toml_table_t* tab, const char* key); +TOML_EXTERN toml_raw_t toml_raw_in(const toml_table_t* tab, const char* key); TOML_EXTERN toml_array_t* toml_array_in(const toml_table_t* tab, const char* key); TOML_EXTERN toml_table_t* toml_table_in(const toml_table_t* tab, @@ -96,26 +99,26 @@ TOML_EXTERN int toml_table_ntab(const toml_table_t* tab); TOML_EXTERN const char* toml_table_key(const toml_table_t* tab); /* Deref array by index. Return the element at idx or 0 if out of range. */ -TOML_EXTERN const char* toml_raw_at(const toml_array_t* arr, int idx); +TOML_EXTERN toml_raw_t toml_raw_at(const toml_array_t* arr, int idx); TOML_EXTERN toml_array_t* toml_array_at(const toml_array_t* arr, int idx); TOML_EXTERN toml_table_t* toml_table_at(const toml_array_t* arr, int idx); - /* Raw to String. Caller must call free(ret) after use. * Return 0 on success, -1 otherwise. */ -TOML_EXTERN int toml_rtos(const char* s, char** ret); +TOML_EXTERN int toml_rtos(toml_raw_t s, char** ret); /* Raw to Boolean. Return 0 on success, -1 otherwise. */ -TOML_EXTERN int toml_rtob(const char* s, int* ret); +TOML_EXTERN int toml_rtob(toml_raw_t s, int* ret); /* Raw to Integer. Return 0 on success, -1 otherwise. */ -TOML_EXTERN int toml_rtoi(const char* s, int64_t* ret); +TOML_EXTERN int toml_rtoi(toml_raw_t s, int64_t* ret); /* Raw to Double. Return 0 on success, -1 otherwise. */ -TOML_EXTERN int toml_rtod(const char* s, double* ret); +TOML_EXTERN int toml_rtod(toml_raw_t s, double* ret); + /* Same as toml_rtod, but return the sanitized double in string form as well */ -TOML_EXTERN int toml_rtod_ex(const char* s, double* ret, char* buf, int buflen); +TOML_EXTERN int toml_rtod_ex(toml_raw_t s, double* ret, char* buf, int buflen); /* Timestamp types. The year, month, day, hour, minute, second, z * fields may be NULL if they are not relevant. e.g. In a DATE @@ -134,7 +137,7 @@ struct toml_timestamp_t { }; /* Raw to Timestamp. Return 0 on success, -1 otherwise. */ -TOML_EXTERN int toml_rtots(const char* s, toml_timestamp_t* ret); +TOML_EXTERN int toml_rtots(toml_raw_t s, toml_timestamp_t* ret); /* misc */ TOML_EXTERN int toml_utf8_to_ucs(const char* orig, int len, int64_t* ret);