Merge pull request #42 from DerekCresswell/reformat-readme
Use custom types to help with clarity between raw and processed types
This commit is contained in:
commit
d879b89737
3 changed files with 113 additions and 81 deletions
154
README.md
154
README.md
|
@ -1,95 +1,125 @@
|
||||||
# tomlc99
|
# tomlc99
|
||||||
|
|
||||||
TOML in c99; v0.5.0 compliant.
|
TOML in c99; v0.5.0 compliant.
|
||||||
|
|
||||||
|
## Usage
|
||||||
# Usage
|
|
||||||
|
|
||||||
Please see the `toml.h` file for details. What follows is a simple example that
|
Please see the `toml.h` file for details. What follows is a simple example that
|
||||||
parses this config file:
|
parses this config file:
|
||||||
|
|
||||||
```
|
```toml
|
||||||
[server]
|
[server]
|
||||||
host = "www.example.com"
|
host = "www.example.com"
|
||||||
port = 80
|
port = 80
|
||||||
```
|
```
|
||||||
|
|
||||||
For each config param, the code first extracts a raw value and then
|
The steps for getting values from our file is usually :
|
||||||
convert it to a string or integer depending on context.
|
|
||||||
|
|
||||||
|
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;
|
2. Get a single table from the file.
|
||||||
toml_table_t* conf;
|
|
||||||
toml_table_t* server;
|
|
||||||
const char* raw;
|
|
||||||
char* host;
|
|
||||||
int64_t port;
|
|
||||||
char errbuf[200];
|
|
||||||
|
|
||||||
/* open file and parse */
|
```c
|
||||||
if (0 == (fp = fopen(FNAME, "r"))) {
|
toml_table_t* server;
|
||||||
return handle_error();
|
|
||||||
}
|
|
||||||
conf = toml_parse_file(fp, errbuf, sizeof(errbuf));
|
|
||||||
fclose(fp);
|
|
||||||
if (0 == conf) {
|
|
||||||
return handle_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* locate the [server] table */
|
/* Locate the [server] table. */
|
||||||
if (0 == (server = toml_table_in(conf, "server"))) {
|
if (0 == (server = toml_table_in(conf, "server"))) {
|
||||||
return handle_error();
|
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
|
||||||
|
toml_raw_t 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
|
A normal *make* suffices. Alternately, you can also simply include the
|
||||||
`toml.c` and `toml.h` files in your project.
|
`toml.c` and `toml.h` files in your project.
|
||||||
|
|
||||||
# Testing
|
## Testing
|
||||||
|
|
||||||
To test against the standard test set provided by BurntSushi/toml-test:
|
To test against the standard test set provided by BurntSushi/toml-test:
|
||||||
|
|
||||||
```
|
```sh
|
||||||
% make
|
% make
|
||||||
% cd test1
|
% cd test1
|
||||||
% bash build.sh # do this once
|
% bash build.sh # do this once
|
||||||
% bash run.sh # this will run the test suite
|
% bash run.sh # this will run the test suite
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
To test against the standard test set provided by iarna/toml:
|
To test against the standard test set provided by iarna/toml:
|
||||||
|
|
||||||
```
|
```sh
|
||||||
% make
|
% make
|
||||||
% cd test2
|
% cd test2
|
||||||
% bash build.sh # do this once
|
% bash build.sh # do this once
|
||||||
% bash run.sh # this will run the test suite
|
% bash run.sh # this will run the test suite
|
||||||
```
|
```
|
||||||
|
|
17
toml.c
17
toml.c
|
@ -1741,8 +1741,7 @@ const char* toml_key_in(const toml_table_t* tab, int keyidx)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toml_raw_t toml_raw_in(const toml_table_t* tab, const char* key)
|
||||||
const char* toml_raw_in(const toml_table_t* tab, const char* key)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < tab->nkval; 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;
|
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')
|
if (arr->kind != 'v')
|
||||||
return 0;
|
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;
|
if (! src_) return -1;
|
||||||
|
|
||||||
|
@ -1942,7 +1941,7 @@ int toml_rtots(const char* src_, toml_timestamp_t* ret)
|
||||||
|
|
||||||
|
|
||||||
/* Raw to boolean */
|
/* Raw to boolean */
|
||||||
int toml_rtob(const char* src, int* ret_)
|
int toml_rtob(toml_raw_t src, int* ret_)
|
||||||
{
|
{
|
||||||
if (!src) return -1;
|
if (!src) return -1;
|
||||||
int dummy;
|
int dummy;
|
||||||
|
@ -1961,7 +1960,7 @@ int toml_rtob(const char* src, int* ret_)
|
||||||
|
|
||||||
|
|
||||||
/* Raw to integer */
|
/* 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;
|
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;
|
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;
|
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];
|
char buf[100];
|
||||||
return toml_rtod_ex(src, ret_, buf, sizeof(buf));
|
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;
|
int multiline = 0;
|
||||||
const char* sp;
|
const char* sp;
|
||||||
|
|
21
toml.h
21
toml.h
|
@ -39,6 +39,9 @@
|
||||||
typedef struct toml_table_t toml_table_t;
|
typedef struct toml_table_t toml_table_t;
|
||||||
typedef struct toml_array_t toml_array_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.
|
/* Parse a file. Return a table on success, or 0 otherwise.
|
||||||
* Caller must toml_free(the-return-value) after use.
|
* 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);
|
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. */
|
/* 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,
|
TOML_EXTERN toml_array_t* toml_array_in(const toml_table_t* tab,
|
||||||
const char* key);
|
const char* key);
|
||||||
TOML_EXTERN toml_table_t* toml_table_in(const toml_table_t* tab,
|
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);
|
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. */
|
/* 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_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);
|
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.
|
/* Raw to String. Caller must call free(ret) after use.
|
||||||
* Return 0 on success, -1 otherwise.
|
* 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. */
|
/* 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. */
|
/* 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. */
|
/* 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 */
|
/* 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
|
/* Timestamp types. The year, month, day, hour, minute, second, z
|
||||||
* fields may be NULL if they are not relevant. e.g. In a DATE
|
* 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. */
|
/* 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 */
|
/* misc */
|
||||||
TOML_EXTERN int toml_utf8_to_ucs(const char* orig, int len, int64_t* ret);
|
TOML_EXTERN int toml_utf8_to_ucs(const char* orig, int len, int64_t* ret);
|
||||||
|
|
Loading…
Reference in a new issue