Init.
This commit is contained in:
parent
75aa7b2d5a
commit
09de99f7a8
12 changed files with 2376 additions and 0 deletions
28
Makefile
Normal file
28
Makefile
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
CC = gcc
|
||||||
|
CFILES = toml.c
|
||||||
|
|
||||||
|
CFLAGS = -std=c99 -Wall -Wextra
|
||||||
|
CFLAGS += -O2 -DNDEBUG
|
||||||
|
#CFLAGS += -O0 -g
|
||||||
|
|
||||||
|
EXEC = toml_json
|
||||||
|
|
||||||
|
LIB = libtoml.a
|
||||||
|
|
||||||
|
all: $(LIB) $(EXEC)
|
||||||
|
|
||||||
|
|
||||||
|
libtoml.a: toml.o
|
||||||
|
ar -rcs $@ $^
|
||||||
|
|
||||||
|
toml_json: toml_json.c $(LIB)
|
||||||
|
|
||||||
|
prefix ?= /usr/local
|
||||||
|
|
||||||
|
install: all
|
||||||
|
install -d ${prefix}/include ${prefix}/lib
|
||||||
|
install toml.h ${prefix}/include
|
||||||
|
install libtoml.a ${prefix}/lib
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o $(EXEC) $(LIB)
|
101
README.md
Normal file
101
README.md
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
# tomlc99
|
||||||
|
TOML in c99; v0.4.0 compliant.
|
||||||
|
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
Please see the `toml.h` file for details. What follows is a simple example that
|
||||||
|
parses this config file:
|
||||||
|
|
||||||
|
```
|
||||||
|
[server]
|
||||||
|
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.
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
FILE* fp;
|
||||||
|
toml_table_t* conf;
|
||||||
|
toml_table_t* server;
|
||||||
|
const char* raw;
|
||||||
|
char* host;
|
||||||
|
int64_t port;
|
||||||
|
char errbuf[200];
|
||||||
|
|
||||||
|
/* open file and parse */
|
||||||
|
if (0 == (fp = fopen(FNAME, "r"))) {
|
||||||
|
perror("fopen");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
conf = toml_parse_file(fp, errbuf, sizeof(errbuf));
|
||||||
|
fclose(fp);
|
||||||
|
if (0 == conf) {
|
||||||
|
fprintf(stderr, "ERROR: %s\n", errbuf);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* locate the [server] table */
|
||||||
|
if (0 == (server = toml_table_in(conf, "server"))) {
|
||||||
|
fprintf(stderr, "ERROR: missing [server]\n");
|
||||||
|
toml_free(conf);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* extract host config value */
|
||||||
|
if (0 == (raw = toml_raw_in(server, "host"))) {
|
||||||
|
fprintf(stderr, "ERROR: missing 'host' in [server]\n");
|
||||||
|
toml_free(conf);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (toml_rtos(raw, &host)) {
|
||||||
|
fprintf(stderr, "ERROR: bad value in 'host'\n");
|
||||||
|
toml_free(conf);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* extract port config value */
|
||||||
|
if (0 == (raw = toml_raw_in(server, "port"))) {
|
||||||
|
fprintf(stderr, "ERROR: missing 'port' in [server]\n");
|
||||||
|
free(host);
|
||||||
|
toml_free(conf);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (toml_rtoi(raw, &port)) {
|
||||||
|
fprintf(stderr, "ERROR: bad value in 'port'\n");
|
||||||
|
free(host);
|
||||||
|
toml_free(conf);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* done with conf */
|
||||||
|
toml_free(conf);
|
||||||
|
|
||||||
|
/* use host and port */
|
||||||
|
do_work(host, port);
|
||||||
|
|
||||||
|
/* clean up */
|
||||||
|
free(host);
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
# Building
|
||||||
|
|
||||||
|
A normal *make* suffices. Alternately, you can also simply include the
|
||||||
|
`toml.c` and `toml.h` files in your project.
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
|
||||||
|
To test against the standard test set provided by BurntSushi/toml-test:
|
||||||
|
|
||||||
|
```
|
||||||
|
% make
|
||||||
|
% cd test
|
||||||
|
% bash build.sh # do this once
|
||||||
|
% bash run.sh # this will run the test suite
|
||||||
|
```
|
||||||
|
|
||||||
|
|
3
test/.gitignore
vendored
Normal file
3
test/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
/goworkspace
|
||||||
|
/toml-test
|
||||||
|
/toml-test-decoder
|
9
test/build.sh
Normal file
9
test/build.sh
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
mkdir -p $DIR/goworkspace
|
||||||
|
export GOPATH=$DIR/goworkspace # if it isn't already set
|
||||||
|
go get github.com/BurntSushi/toml-test # install test suite
|
||||||
|
go get github.com/BurntSushi/toml/cmd/toml-test-decoder # e.g., install my parser
|
||||||
|
cp $GOPATH/bin/* .
|
||||||
|
|
1
test/extra/array_of_tables.toml
Normal file
1
test/extra/array_of_tables.toml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
x = [ {'a'= 1}, {'a'= 2} ]
|
1
test/extra/inline_array.toml
Normal file
1
test/extra/inline_array.toml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
x = [1,2,3]
|
1
test/extra/inline_table.toml
Normal file
1
test/extra/inline_table.toml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
x = {'a'= 1, 'b'= 2 }
|
4
test/run.sh
Normal file
4
test/run.sh
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
export GOPATH=$DIR/goworkspace # if it isn't already set
|
||||||
|
# $GOPATH/bin/toml-test $GOPATH/bin/toml-test-decoder # e.g., run tests on my parser
|
||||||
|
$GOPATH/bin/toml-test ../toml_json
|
108
toml.h
Normal file
108
toml.h
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2017 CK Tan
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef TOML_H
|
||||||
|
#define TOML_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define TOML_EXTERN extern "C"
|
||||||
|
#else
|
||||||
|
#define TOML_EXTERN extern
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct toml_table_t toml_table_t;
|
||||||
|
typedef struct toml_array_t toml_array_t;
|
||||||
|
|
||||||
|
/* Parse a file. Return a table on success, or 0 otherwise.
|
||||||
|
* Caller must toml_free(the-return-value) after use.
|
||||||
|
*/
|
||||||
|
TOML_EXTERN toml_table_t* toml_parse_file(FILE* fp,
|
||||||
|
char* errbuf,
|
||||||
|
int errbufsz);
|
||||||
|
|
||||||
|
/* Parse a string containing the full config.
|
||||||
|
* Return a table on success, or 0 otherwise.
|
||||||
|
* Caller must toml_free(the-return-value) after use.
|
||||||
|
*/
|
||||||
|
TOML_EXTERN toml_table_t* toml_parse(char* conf, /* NUL terminated, please. */
|
||||||
|
char* errbuf,
|
||||||
|
int errbufsz);
|
||||||
|
|
||||||
|
/* Free the table returned by toml_parse() or toml_parse_file(). */
|
||||||
|
TOML_EXTERN void toml_free(toml_table_t* tab);
|
||||||
|
|
||||||
|
/* Retrieve the key in table at keyidx. Return 0 if out of range. */
|
||||||
|
TOML_EXTERN const char* toml_key_in(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(toml_table_t* tab, const char* key);
|
||||||
|
TOML_EXTERN toml_array_t* toml_array_in(toml_table_t* tab, const char* key);
|
||||||
|
TOML_EXTERN toml_table_t* toml_table_in(toml_table_t* tab, const char* key);
|
||||||
|
|
||||||
|
/* Return the array kind: 't'able, 'a'rray, 'v'alue */
|
||||||
|
TOML_EXTERN char toml_array_kind(toml_array_t* arr);
|
||||||
|
|
||||||
|
/* Deref array by index. Return the element at idx or 0 if out of range. */
|
||||||
|
TOML_EXTERN const char* toml_raw_at(toml_array_t* arr, int idx);
|
||||||
|
TOML_EXTERN toml_array_t* toml_array_at(toml_array_t* arr, int idx);
|
||||||
|
TOML_EXTERN toml_table_t* toml_table_at(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);
|
||||||
|
|
||||||
|
/* Raw to Boolean. Return 0 on success, -1 otherwise. */
|
||||||
|
TOML_EXTERN int toml_rtob(const char* s, int* ret);
|
||||||
|
|
||||||
|
/* Raw to Integer. Return 0 on success, -1 otherwise. */
|
||||||
|
TOML_EXTERN int toml_rtoi(const char* s, int64_t* ret);
|
||||||
|
|
||||||
|
/* Raw to Double. Return 0 on success, -1 otherwise. */
|
||||||
|
TOML_EXTERN int toml_rtod(const char* s, double* ret);
|
||||||
|
|
||||||
|
/* Timestamp types. The year, month, day, hour, minute, second, z
|
||||||
|
* fields may be NULL if they are not relevant.
|
||||||
|
*/
|
||||||
|
typedef struct toml_timestamp_t toml_timestamp_t;
|
||||||
|
struct toml_timestamp_t {
|
||||||
|
struct { /* internal. do not use. */
|
||||||
|
int year, month, day;
|
||||||
|
int hour, minute, second;
|
||||||
|
char z[10];
|
||||||
|
} __buffer;
|
||||||
|
int *year, *month, *day;
|
||||||
|
int *hour, *minute, *second;
|
||||||
|
char* z;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Raw to Timestamp. Return 0 on success, -1 otherwise. */
|
||||||
|
TOML_EXTERN int toml_rtots(const char* s, toml_timestamp_t* ret);
|
||||||
|
|
||||||
|
/* 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]);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* TOML_H */
|
165
toml_cat.c
Normal file
165
toml_cat.c
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
#ifdef NDEBUG
|
||||||
|
#under NDEBUG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "toml.h"
|
||||||
|
|
||||||
|
typedef struct node_t node_t;
|
||||||
|
struct node_t {
|
||||||
|
const char* key;
|
||||||
|
toml_table_t* tab;
|
||||||
|
};
|
||||||
|
|
||||||
|
node_t stack[20];
|
||||||
|
int stacktop = 0;
|
||||||
|
|
||||||
|
|
||||||
|
static void print_table_title(const char* arrname)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
printf("%s", arrname ? "[[" : "[");
|
||||||
|
for (i = 1; i < stacktop; i++) {
|
||||||
|
printf("%s", stack[i].key);
|
||||||
|
if (i + 1 < stacktop)
|
||||||
|
printf(".");
|
||||||
|
}
|
||||||
|
if (arrname)
|
||||||
|
printf(".%s]]\n", arrname);
|
||||||
|
else
|
||||||
|
printf("]\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void print_array_of_tables(toml_array_t* arr, const char* key);
|
||||||
|
static void print_array(toml_array_t* arr);
|
||||||
|
|
||||||
|
|
||||||
|
static void print_table(toml_table_t* curtab)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const char* key;
|
||||||
|
const char* raw;
|
||||||
|
toml_array_t* arr;
|
||||||
|
toml_table_t* tab;
|
||||||
|
|
||||||
|
|
||||||
|
for (i = 0; 0 != (key = toml_key_in(curtab, i)); i++) {
|
||||||
|
if (0 != (raw = toml_raw_in(curtab, key))) {
|
||||||
|
printf("%s = %s\n", key, raw);
|
||||||
|
} else if (0 != (arr = toml_array_in(curtab, key))) {
|
||||||
|
if (toml_array_typ(arr) == 't') {
|
||||||
|
print_array_of_tables(arr, key);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("%s = [\n", key);
|
||||||
|
print_array(arr);
|
||||||
|
printf(" ]\n");
|
||||||
|
}
|
||||||
|
} else if (0 != (tab = toml_table_in(curtab, key))) {
|
||||||
|
stack[stacktop].key = key;
|
||||||
|
stack[stacktop].tab = tab;
|
||||||
|
stacktop++;
|
||||||
|
print_table_title(0);
|
||||||
|
print_table(tab);
|
||||||
|
stacktop--;
|
||||||
|
} else {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_array_of_tables(toml_array_t* arr, const char* key)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
toml_table_t* tab;
|
||||||
|
printf("\n");
|
||||||
|
for (i = 0; 0 != (tab = toml_table_at(arr, i)); i++) {
|
||||||
|
print_table_title(key);
|
||||||
|
print_table(tab);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void print_array(toml_array_t* curarr)
|
||||||
|
{
|
||||||
|
toml_array_t* arr;
|
||||||
|
const char* raw;
|
||||||
|
toml_table_t* tab;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
switch (toml_array_typ(curarr)) {
|
||||||
|
|
||||||
|
case 'v':
|
||||||
|
for (i = 0; 0 != (raw = toml_raw_at(curarr, i)); i++) {
|
||||||
|
printf(" %d: %s,\n", i, raw);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'a':
|
||||||
|
for (i = 0; 0 != (arr = toml_array_at(curarr, i)); i++) {
|
||||||
|
printf(" %d: \n", i);
|
||||||
|
print_array(arr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 't':
|
||||||
|
for (i = 0; 0 != (tab = toml_table_at(curarr, i)); i++) {
|
||||||
|
print_table(tab);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void cat(FILE* fp)
|
||||||
|
{
|
||||||
|
char errbuf[200];
|
||||||
|
|
||||||
|
toml_table_t* tab = toml_parse_file(fp, errbuf, sizeof(errbuf));
|
||||||
|
if (!tab) {
|
||||||
|
fprintf(stderr, "ERROR: %s\n", errbuf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack[stacktop].tab = tab;
|
||||||
|
stack[stacktop].key = "";
|
||||||
|
stacktop++;
|
||||||
|
print_table(tab);
|
||||||
|
stacktop--;
|
||||||
|
|
||||||
|
toml_free(tab);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, const char* argv[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if (argc == 1) {
|
||||||
|
cat(stdin);
|
||||||
|
} else {
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
|
||||||
|
FILE* fp = fopen(argv[i], "r");
|
||||||
|
if (!fp) {
|
||||||
|
fprintf(stderr, "ERROR: cannot open %s: %s\n",
|
||||||
|
argv[i], strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
cat(fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
183
toml_json.c
Normal file
183
toml_json.c
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
#ifdef NDEBUG
|
||||||
|
#undef NDEBUG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include "toml.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void print_escape_string(const char* s)
|
||||||
|
{
|
||||||
|
for ( ; *s; s++) {
|
||||||
|
int ch = *s;
|
||||||
|
switch (ch) {
|
||||||
|
case '\b': printf("\\b"); break;
|
||||||
|
case '\t': printf("\\t"); break;
|
||||||
|
case '\n': printf("\\n"); break;
|
||||||
|
case '\f': printf("\\f"); break;
|
||||||
|
case '\r': printf("\\r"); break;
|
||||||
|
case '"': printf("\\\""); break;
|
||||||
|
case '\\': printf("\\\\"); break;
|
||||||
|
default: printf("%c", ch); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_raw(const char* s)
|
||||||
|
{
|
||||||
|
char* sval;
|
||||||
|
int64_t ival;
|
||||||
|
int bval;
|
||||||
|
double dval;
|
||||||
|
toml_timestamp_t ts;
|
||||||
|
|
||||||
|
if (0 == toml_rtos(s, &sval)) {
|
||||||
|
printf("{\"type\":\"string\",\"value\":\"");
|
||||||
|
print_escape_string(sval);
|
||||||
|
printf("\"}");
|
||||||
|
free(sval);
|
||||||
|
} else if (0 == toml_rtoi(s, &ival)) {
|
||||||
|
printf("{\"type\":\"integer\",\"value\":\"%" PRId64 "\"}", ival);
|
||||||
|
} else if (0 == toml_rtob(s, &bval)) {
|
||||||
|
printf("{\"type\":\"bool\",\"value\":\"%s\"}", bval ? "true" : "false");
|
||||||
|
} else if (0 == toml_rtod(s, &dval)) {
|
||||||
|
printf("{\"type\":\"float\",\"value\":\"%s\"}", s);
|
||||||
|
} else if (0 == toml_rtots(s, &ts)) {
|
||||||
|
if (ts.year && ts.hour) {
|
||||||
|
printf("{\"type\":\"datetime\",\"value\":\"%04d-%02d-%02dT%02d:%02d:%02d%s\"}",
|
||||||
|
*ts.year, *ts.month, *ts.day, *ts.hour, *ts.minute, *ts.second,
|
||||||
|
(ts.z ? ts.z : ""));
|
||||||
|
} else if (ts.year) {
|
||||||
|
printf("{\"type\":\"date\",\"value\":\"%04d-%02d-%02d\"}",
|
||||||
|
*ts.year, *ts.month, *ts.day);
|
||||||
|
} else if (ts.hour) {
|
||||||
|
printf("{\"type\":\"time\",\"value\":\"%02d:%02d:%02d\"}",
|
||||||
|
*ts.hour, *ts.minute, *ts.second);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "unknown type\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void print_array(toml_array_t* arr);
|
||||||
|
static void print_table(toml_table_t* curtab)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const char* key;
|
||||||
|
const char* raw;
|
||||||
|
toml_array_t* arr;
|
||||||
|
toml_table_t* tab;
|
||||||
|
|
||||||
|
|
||||||
|
printf("{");
|
||||||
|
for (i = 0; 0 != (key = toml_key_in(curtab, i)); i++) {
|
||||||
|
|
||||||
|
printf("%s\"%s\":", i > 0 ? "," : "", key);
|
||||||
|
|
||||||
|
if (0 != (raw = toml_raw_in(curtab, key))) {
|
||||||
|
print_raw(raw);
|
||||||
|
} else if (0 != (arr = toml_array_in(curtab, key))) {
|
||||||
|
print_array(arr);
|
||||||
|
} else if (0 != (tab = toml_table_in(curtab, key))) {
|
||||||
|
print_table(tab);
|
||||||
|
} else {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_table_array(toml_array_t* curarr)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
toml_table_t* tab;
|
||||||
|
|
||||||
|
printf("[");
|
||||||
|
for (i = 0; 0 != (tab = toml_table_at(curarr, i)); i++) {
|
||||||
|
printf("%s", i > 0 ? "," : "");
|
||||||
|
print_table(tab);
|
||||||
|
}
|
||||||
|
printf("]");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_array(toml_array_t* curarr)
|
||||||
|
{
|
||||||
|
toml_array_t* arr;
|
||||||
|
const char* raw;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (toml_array_kind(curarr) == 't') {
|
||||||
|
print_table_array(curarr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("{\"type\":\"array\",\"value\":[");
|
||||||
|
switch (toml_array_kind(curarr)) {
|
||||||
|
|
||||||
|
case 'v':
|
||||||
|
for (i = 0; 0 != (raw = toml_raw_at(curarr, i)); i++) {
|
||||||
|
printf("%s", i > 0 ? "," : "");
|
||||||
|
print_raw(raw);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'a':
|
||||||
|
for (i = 0; 0 != (arr = toml_array_at(curarr, i)); i++) {
|
||||||
|
printf("%s", i > 0 ? "," : "");
|
||||||
|
print_array(arr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf("]}");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void cat(FILE* fp)
|
||||||
|
{
|
||||||
|
char errbuf[200];
|
||||||
|
|
||||||
|
toml_table_t* tab = toml_parse_file(fp, errbuf, sizeof(errbuf));
|
||||||
|
if (!tab) {
|
||||||
|
fprintf(stderr, "ERROR: %s\n", errbuf);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
print_table(tab);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
toml_free(tab);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, const char* argv[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if (argc == 1) {
|
||||||
|
cat(stdin);
|
||||||
|
} else {
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
|
||||||
|
FILE* fp = fopen(argv[i], "r");
|
||||||
|
if (!fp) {
|
||||||
|
fprintf(stderr, "ERROR: cannot open %s: %s\n",
|
||||||
|
argv[i], strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
cat(fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue