fixed issue #51
This commit is contained in:
parent
1cfa8e42c4
commit
715fa54d45
55 changed files with 747 additions and 366 deletions
1
stdex/.gitignore
vendored
Normal file
1
stdex/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/*.out
|
15
stdex/RUN.sh
Normal file
15
stdex/RUN.sh
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
rm -f *.out
|
||||||
|
for i in *.toml; do
|
||||||
|
echo -n $i
|
||||||
|
../toml_cat $i >& $i.out
|
||||||
|
if [ -f $i.res ]; then
|
||||||
|
if $(diff $i.out $i.res >& /dev/null); then
|
||||||
|
echo " [OK]"
|
||||||
|
else
|
||||||
|
echo " [FAILED]"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " [??]"
|
||||||
|
fi
|
||||||
|
|
||||||
|
done
|
3
stdex/comment.toml
Normal file
3
stdex/comment.toml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# This is a full-line comment
|
||||||
|
key = "value" # This is a comment at the end of a line
|
||||||
|
another = "# This is not a comment"
|
4
stdex/comment.toml.res
Normal file
4
stdex/comment.toml.res
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
key = "value",
|
||||||
|
another = "# This is not a comment",
|
||||||
|
}
|
4
stdex/keys00.toml
Normal file
4
stdex/keys00.toml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
key = "value"
|
||||||
|
bare_key = "value"
|
||||||
|
bare-key = "value"
|
||||||
|
1234 = "value"
|
6
stdex/keys00.toml.res
Normal file
6
stdex/keys00.toml.res
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
key = "value",
|
||||||
|
bare_key = "value",
|
||||||
|
bare-key = "value",
|
||||||
|
1234 = "value",
|
||||||
|
}
|
5
stdex/keys01.toml
Normal file
5
stdex/keys01.toml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
"127.0.0.1" = "value"
|
||||||
|
"character encoding" = "value"
|
||||||
|
"ʎǝʞ" = "value"
|
||||||
|
'key2' = "value"
|
||||||
|
'quoted "value"' = "value"
|
7
stdex/keys01.toml.res
Normal file
7
stdex/keys01.toml.res
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
127.0.0.1 = "value",
|
||||||
|
character encoding = "value",
|
||||||
|
ʎǝʞ = "value",
|
||||||
|
key2 = "value",
|
||||||
|
quoted "value" = "value",
|
||||||
|
}
|
1
stdex/keys02.toml
Normal file
1
stdex/keys02.toml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
= "no key name" # INVALID
|
1
stdex/keys02.toml.res
Normal file
1
stdex/keys02.toml.res
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ERROR: line 1: syntax error
|
1
stdex/keys03.toml
Normal file
1
stdex/keys03.toml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
"" = "blank" # VALID but discouraged
|
3
stdex/keys03.toml.res
Normal file
3
stdex/keys03.toml.res
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
= "blank",
|
||||||
|
}
|
4
stdex/keys04.toml
Normal file
4
stdex/keys04.toml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
name = "Orange"
|
||||||
|
physical.color = "orange"
|
||||||
|
physical.shape = "round"
|
||||||
|
site."google.com" = true
|
10
stdex/keys04.toml.res
Normal file
10
stdex/keys04.toml.res
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
name = "Orange",
|
||||||
|
physical = {
|
||||||
|
color = "orange",
|
||||||
|
shape = "round",
|
||||||
|
},
|
||||||
|
site = {
|
||||||
|
google.com = true,
|
||||||
|
},
|
||||||
|
}
|
3
stdex/keys05.toml
Normal file
3
stdex/keys05.toml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
fruit.name = "banana" # this is best practice
|
||||||
|
fruit. color = "yellow" # same as fruit.color
|
||||||
|
fruit . flavor = "banana" # same as fruit.flavor
|
7
stdex/keys05.toml.res
Normal file
7
stdex/keys05.toml.res
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
fruit = {
|
||||||
|
name = "banana",
|
||||||
|
color = "yellow",
|
||||||
|
flavor = "banana",
|
||||||
|
},
|
||||||
|
}
|
3
stdex/keys06.toml
Normal file
3
stdex/keys06.toml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# DO NOT DO THIS
|
||||||
|
name = "Tom"
|
||||||
|
name = "Pradyun"
|
1
stdex/keys06.toml.res
Normal file
1
stdex/keys06.toml.res
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ERROR: line 3: key exists
|
3
stdex/keys07.toml
Normal file
3
stdex/keys07.toml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# THIS WILL NOT WORK
|
||||||
|
spelling = "favorite"
|
||||||
|
"spelling" = "favourite"
|
1
stdex/keys07.toml.res
Normal file
1
stdex/keys07.toml.res
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ERROR: line 3: key exists
|
5
stdex/keys08.toml
Normal file
5
stdex/keys08.toml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# This makes the key "fruit" into a table.
|
||||||
|
fruit.apple.smooth = true
|
||||||
|
|
||||||
|
# So then you can add to the table "fruit" like so:
|
||||||
|
fruit.orange = 2
|
8
stdex/keys08.toml.res
Normal file
8
stdex/keys08.toml.res
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
fruit = {
|
||||||
|
orange = 2,
|
||||||
|
apple = {
|
||||||
|
smooth = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
8
stdex/keys09.toml
Normal file
8
stdex/keys09.toml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# THE FOLLOWING IS INVALID
|
||||||
|
|
||||||
|
# This defines the value of fruit.apple to be an integer.
|
||||||
|
fruit.apple = 1
|
||||||
|
|
||||||
|
# But then this treats fruit.apple like it's a table.
|
||||||
|
# You can't turn an integer into a table.
|
||||||
|
fruit.apple.smooth = true
|
1
stdex/keys09.toml.res
Normal file
1
stdex/keys09.toml.res
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ERROR: line 8: key exists
|
10
stdex/keys10.toml
Normal file
10
stdex/keys10.toml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# VALID BUT DISCOURAGED
|
||||||
|
|
||||||
|
apple.type = "fruit"
|
||||||
|
orange.type = "fruit"
|
||||||
|
|
||||||
|
apple.skin = "thin"
|
||||||
|
orange.skin = "thick"
|
||||||
|
|
||||||
|
apple.color = "red"
|
||||||
|
orange.color = "orange"
|
12
stdex/keys10.toml.res
Normal file
12
stdex/keys10.toml.res
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
apple = {
|
||||||
|
type = "fruit",
|
||||||
|
skin = "thin",
|
||||||
|
color = "red",
|
||||||
|
},
|
||||||
|
orange = {
|
||||||
|
type = "fruit",
|
||||||
|
skin = "thick",
|
||||||
|
color = "orange",
|
||||||
|
},
|
||||||
|
}
|
9
stdex/keys11.toml
Normal file
9
stdex/keys11.toml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# RECOMMENDED
|
||||||
|
|
||||||
|
apple.type = "fruit"
|
||||||
|
apple.skin = "thin"
|
||||||
|
apple.color = "red"
|
||||||
|
|
||||||
|
orange.type = "fruit"
|
||||||
|
orange.skin = "thick"
|
||||||
|
orange.color = "orange"
|
12
stdex/keys11.toml.res
Normal file
12
stdex/keys11.toml.res
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
apple = {
|
||||||
|
type = "fruit",
|
||||||
|
skin = "thin",
|
||||||
|
color = "red",
|
||||||
|
},
|
||||||
|
orange = {
|
||||||
|
type = "fruit",
|
||||||
|
skin = "thick",
|
||||||
|
color = "orange",
|
||||||
|
},
|
||||||
|
}
|
1
stdex/keys12.toml
Normal file
1
stdex/keys12.toml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
3.14159 = "pi"
|
5
stdex/keys12.toml.res
Normal file
5
stdex/keys12.toml.res
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
3 = {
|
||||||
|
14159 = "pi",
|
||||||
|
},
|
||||||
|
}
|
1
stdex/kvpair0.toml
Normal file
1
stdex/kvpair0.toml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
key = "value"
|
3
stdex/kvpair0.toml.res
Normal file
3
stdex/kvpair0.toml.res
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
key = "value",
|
||||||
|
}
|
1
stdex/kvpair1.toml
Normal file
1
stdex/kvpair1.toml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
key = # INVALID
|
1
stdex/kvpair1.toml.res
Normal file
1
stdex/kvpair1.toml.res
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ERROR: line 1: syntax error
|
1
stdex/kvpair2.toml
Normal file
1
stdex/kvpair2.toml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
first = "Tom" last = "Preston-Werner" # INVALID
|
1
stdex/kvpair2.toml.res
Normal file
1
stdex/kvpair2.toml.res
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ERROR: line 1: extra chars after value
|
1
stdex/string0.toml
Normal file
1
stdex/string0.toml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
str = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."
|
3
stdex/string0.toml.res
Normal file
3
stdex/string0.toml.res
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
str = "I'm a string. \"You can quote me\". Name\tJos\0xc3\0xa9\nLocation\tSF.",
|
||||||
|
}
|
9
stdex/string1.toml
Normal file
9
stdex/string1.toml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
str1 = """
|
||||||
|
Roses are red
|
||||||
|
Violets are blue"""
|
||||||
|
|
||||||
|
# On a Unix system, the above multi-line string will most likely be the same as:
|
||||||
|
str2 = "Roses are red\nViolets are blue"
|
||||||
|
|
||||||
|
# On a Windows system, it will most likely be equivalent to:
|
||||||
|
str3 = "Roses are red\r\nViolets are blue"
|
5
stdex/string1.toml.res
Normal file
5
stdex/string1.toml.res
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
str1 = "Roses are red\nViolets are blue",
|
||||||
|
str2 = "Roses are red\nViolets are blue",
|
||||||
|
str3 = "Roses are red\r\nViolets are blue",
|
||||||
|
}
|
15
stdex/string3.toml
Normal file
15
stdex/string3.toml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# The following strings are byte-for-byte equivalent:
|
||||||
|
str1 = "The quick brown fox jumps over the lazy dog."
|
||||||
|
|
||||||
|
str2 = """
|
||||||
|
The quick brown \
|
||||||
|
|
||||||
|
|
||||||
|
fox jumps over \
|
||||||
|
the lazy dog."""
|
||||||
|
|
||||||
|
str3 = """\
|
||||||
|
The quick brown \
|
||||||
|
fox jumps over \
|
||||||
|
the lazy dog.\
|
||||||
|
"""
|
5
stdex/string3.toml.res
Normal file
5
stdex/string3.toml.res
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
str1 = "The quick brown fox jumps over the lazy dog.",
|
||||||
|
str2 = "The quick brown fox jumps over the lazy dog.",
|
||||||
|
str3 = "The quick brown fox jumps over the lazy dog.",
|
||||||
|
}
|
7
stdex/string4.toml
Normal file
7
stdex/string4.toml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
str4 = """Here are two quotation marks: "". Simple enough."""
|
||||||
|
# str5 = """Here are three quotation marks: """.""" # INVALID
|
||||||
|
str5 = """Here are three quotation marks: ""\"."""
|
||||||
|
str6 = """Here are fifteen quotation marks: ""\"""\"""\"""\"""\"."""
|
||||||
|
|
||||||
|
# "This," she said, "is just a pointless statement."
|
||||||
|
str7 = """"This," she said, "is just a pointless statement.""""
|
6
stdex/string4.toml.res
Normal file
6
stdex/string4.toml.res
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
str4 = "Here are two quotation marks: \"\". Simple enough.",
|
||||||
|
str5 = "Here are three quotation marks: \"\"\".",
|
||||||
|
str6 = "Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".",
|
||||||
|
str7 = "\"This,\" she said, \"is just a pointless statement.\"",
|
||||||
|
}
|
5
stdex/string5.toml
Normal file
5
stdex/string5.toml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# What you see is what you get.
|
||||||
|
winpath = 'C:\Users\nodejs\templates'
|
||||||
|
winpath2 = '\\ServerX\admin$\system32\'
|
||||||
|
quoted = 'Tom "Dubs" Preston-Werner'
|
||||||
|
regex = '<\i\c*\s*>'
|
6
stdex/string5.toml.res
Normal file
6
stdex/string5.toml.res
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
winpath = "C:\\Users\\nodejs\\templates",
|
||||||
|
winpath2 = "\\\\ServerX\\admin$\\system32\\",
|
||||||
|
quoted = "Tom \"Dubs\" Preston-Werner",
|
||||||
|
regex = "<\\i\\c*\\s*>",
|
||||||
|
}
|
7
stdex/string6.toml
Normal file
7
stdex/string6.toml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
regex2 = '''I [dw]on't need \d{2} apples'''
|
||||||
|
lines = '''
|
||||||
|
The first newline is
|
||||||
|
trimmed in raw strings.
|
||||||
|
All other whitespace
|
||||||
|
is preserved.
|
||||||
|
'''
|
4
stdex/string6.toml.res
Normal file
4
stdex/string6.toml.res
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
regex2 = "I [dw]on't need \\d{2} apples",
|
||||||
|
lines = "The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n",
|
||||||
|
}
|
4
stdex/string7.toml
Normal file
4
stdex/string7.toml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
quot15 = '''Here are fifteen quotation marks: """""""""""""""'''
|
||||||
|
|
||||||
|
# 'That,' she said, 'is still pointless.'
|
||||||
|
str = ''''That,' she said, 'is still pointless.''''
|
4
stdex/string7.toml.res
Normal file
4
stdex/string7.toml.res
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
quot15 = "Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\"",
|
||||||
|
str = "'That,' she said, 'is still pointless.'",
|
||||||
|
}
|
3
stdex/string8.toml
Normal file
3
stdex/string8.toml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# apos15 = '''Here are fifteen apostrophes: '''''''''''''''''' # INVALID
|
||||||
|
apos15 = "Here are fifteen apostrophes: '''''''''''''''"
|
||||||
|
|
1
stdex/string8.toml.res
Normal file
1
stdex/string8.toml.res
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ERROR: line 2: triple-s-quote inside string lit
|
34
toml.h
34
toml.h
|
@ -1,19 +1,19 @@
|
||||||
/*
|
/*
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2017 - 2019 CK Tan
|
Copyright (c) 2017 - 2019 CK Tan
|
||||||
https://github.com/cktan/tomlc99
|
https://github.com/cktan/tomlc99
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all
|
||||||
copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
@ -41,14 +41,14 @@ typedef struct toml_table_t toml_table_t;
|
||||||
typedef struct toml_array_t toml_array_t;
|
typedef struct toml_array_t toml_array_t;
|
||||||
typedef struct toml_datum_t toml_datum_t;
|
typedef struct toml_datum_t toml_datum_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.
|
||||||
*/
|
*/
|
||||||
TOML_EXTERN toml_table_t* toml_parse_file(FILE* fp,
|
TOML_EXTERN toml_table_t* toml_parse_file(FILE* fp,
|
||||||
char* errbuf,
|
char* errbuf,
|
||||||
int errbufsz);
|
int errbufsz);
|
||||||
|
|
||||||
/* Parse a string containing the full config.
|
/* Parse a string containing the full config.
|
||||||
* Return a table on success, or 0 otherwise.
|
* 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.
|
||||||
*/
|
*/
|
||||||
|
@ -56,14 +56,14 @@ TOML_EXTERN toml_table_t* toml_parse(char* conf, /* NUL terminated, please. */
|
||||||
char* errbuf,
|
char* errbuf,
|
||||||
int errbufsz);
|
int errbufsz);
|
||||||
|
|
||||||
/* Free the table returned by toml_parse() or toml_parse_file(). Once
|
/* Free the table returned by toml_parse() or toml_parse_file(). Once
|
||||||
* this function is called, any handles accessed through this tab
|
* this function is called, any handles accessed through this tab
|
||||||
* directly or indirectly are no longer valid.
|
* directly or indirectly are no longer valid.
|
||||||
*/
|
*/
|
||||||
TOML_EXTERN void toml_free(toml_table_t* tab);
|
TOML_EXTERN void toml_free(toml_table_t* tab);
|
||||||
|
|
||||||
|
|
||||||
/* 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
|
||||||
* type, the hour, minute, second and z fields will be NULLs.
|
* type, the hour, minute, second and z fields will be NULLs.
|
||||||
*/
|
*/
|
||||||
|
@ -80,7 +80,7 @@ struct toml_timestamp_t {
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
/*-----------------------------------------------------------------
|
||||||
* Enhanced access methods
|
* Enhanced access methods
|
||||||
*/
|
*/
|
||||||
struct toml_datum_t {
|
struct toml_datum_t {
|
||||||
int ok;
|
int ok;
|
||||||
|
@ -122,13 +122,13 @@ TOML_EXTERN toml_table_t* toml_table_in(const toml_table_t* tab,
|
||||||
const char* key);
|
const char* key);
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
/*-----------------------------------------------------------------
|
||||||
* lesser used
|
* lesser used
|
||||||
*/
|
*/
|
||||||
/* Return the array kind: 't'able, 'a'rray, 'v'alue */
|
/* Return the array kind: 't'able, 'a'rray, 'v'alue, 'm'ixed */
|
||||||
TOML_EXTERN char toml_array_kind(const toml_array_t* arr);
|
TOML_EXTERN char toml_array_kind(const toml_array_t* arr);
|
||||||
|
|
||||||
/* For array kind 'v'alue, return the type of values
|
/* For array kind 'v'alue, return the type of values
|
||||||
i:int, d:double, b:bool, s:string, t:time, D:date, T:timestamp
|
i:int, d:double, b:bool, s:string, t:time, D:date, T:timestamp, 'm'ixed
|
||||||
0 if unknown
|
0 if unknown
|
||||||
*/
|
*/
|
||||||
TOML_EXTERN char toml_array_type(const toml_array_t* arr);
|
TOML_EXTERN char toml_array_type(const toml_array_t* arr);
|
||||||
|
@ -149,7 +149,7 @@ 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);
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
/*--------------------------------------------------------------
|
||||||
* 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);
|
||||||
TOML_EXTERN int toml_ucs_to_utf8(int64_t code, char buf[6]);
|
TOML_EXTERN int toml_ucs_to_utf8(int64_t code, char buf[6]);
|
||||||
|
@ -158,7 +158,7 @@ TOML_EXTERN void toml_set_memutil(void* (*xxmalloc)(size_t),
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------
|
/*--------------------------------------------------------------
|
||||||
* deprecated
|
* deprecated
|
||||||
*/
|
*/
|
||||||
/* A raw value, must be processed by toml_rto* before using. */
|
/* A raw value, must be processed by toml_rto* before using. */
|
||||||
typedef const char* toml_raw_t;
|
typedef const char* toml_raw_t;
|
||||||
|
|
321
toml_cat.c
321
toml_cat.c
|
@ -1,26 +1,26 @@
|
||||||
/*
|
/*
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2017 CK Tan
|
Copyright (c) 2017 CK Tan
|
||||||
https://github.com/cktan/tomlc99
|
https://github.com/cktan/tomlc99
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all
|
||||||
copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
|
@ -33,6 +33,8 @@ SOFTWARE.
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include "toml.h"
|
#include "toml.h"
|
||||||
|
|
||||||
typedef struct node_t node_t;
|
typedef struct node_t node_t;
|
||||||
|
@ -43,128 +45,229 @@ struct node_t {
|
||||||
|
|
||||||
node_t stack[20];
|
node_t stack[20];
|
||||||
int stacktop = 0;
|
int stacktop = 0;
|
||||||
|
int indent = 0;
|
||||||
|
|
||||||
|
static void prindent()
|
||||||
static void print_table_title(const char* arrname)
|
|
||||||
{
|
{
|
||||||
int i;
|
for (int i = 0; i < indent; i++) printf(" ");
|
||||||
printf("%s", arrname ? "[[" : "[");
|
}
|
||||||
for (i = 1; i < stacktop; i++) {
|
|
||||||
printf("%s", stack[i].key);
|
|
||||||
if (i + 1 < stacktop)
|
static void print_string(const char* s)
|
||||||
printf(".");
|
{
|
||||||
}
|
int ok = 1;
|
||||||
if (arrname)
|
for (const char* p = s; *p && ok; p++) {
|
||||||
printf(".%s]]\n", arrname);
|
int ch = *p;
|
||||||
else
|
ok = isprint(ch) && ch != '"' && ch != '\\';
|
||||||
printf("]\n");
|
}
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
printf("\"%s\"", s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = strlen(s);
|
||||||
|
|
||||||
|
printf("\"");
|
||||||
|
for ( ; len; len--, s++) {
|
||||||
|
int ch = *s;
|
||||||
|
if (isprint(ch) && ch != '"' && ch != '\\') {
|
||||||
|
putchar(ch);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ch) {
|
||||||
|
case 0x8: printf("\\b"); continue;
|
||||||
|
case 0x9: printf("\\t"); continue;
|
||||||
|
case 0xa: printf("\\n"); continue;
|
||||||
|
case 0xc: printf("\\f"); continue;
|
||||||
|
case 0xd: printf("\\r"); continue;
|
||||||
|
case '"': printf("\\\""); continue;
|
||||||
|
case '\\': printf("\\\\"); continue;
|
||||||
|
default: printf("\\0x%02x", ch & 0xff); continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void print_array_of_tables(toml_array_t* arr, const char* key);
|
|
||||||
static void print_array(toml_array_t* arr);
|
static void print_array(toml_array_t* arr);
|
||||||
|
|
||||||
|
|
||||||
static void print_table(toml_table_t* curtab)
|
static void print_table(toml_table_t* curtab)
|
||||||
{
|
{
|
||||||
|
toml_datum_t d;
|
||||||
int i;
|
int i;
|
||||||
const char* key;
|
const char* key;
|
||||||
const char* raw;
|
|
||||||
toml_array_t* arr;
|
toml_array_t* arr;
|
||||||
toml_table_t* tab;
|
toml_table_t* tab;
|
||||||
|
|
||||||
|
|
||||||
for (i = 0; 0 != (key = toml_key_in(curtab, i)); i++) {
|
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_kind(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)
|
if (0 != (arr = toml_array_in(curtab, key))) {
|
||||||
{
|
prindent();
|
||||||
int i;
|
printf("%s = [\n", key);
|
||||||
toml_table_t* tab;
|
indent++;
|
||||||
printf("\n");
|
print_array(arr);
|
||||||
for (i = 0; 0 != (tab = toml_table_at(arr, i)); i++) {
|
indent--;
|
||||||
print_table_title(key);
|
prindent();
|
||||||
print_table(tab);
|
printf("],\n");
|
||||||
printf("\n");
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != (tab = toml_table_in(curtab, key))) {
|
||||||
|
stack[stacktop].key = key;
|
||||||
|
stack[stacktop].tab = tab;
|
||||||
|
stacktop++;
|
||||||
|
prindent();
|
||||||
|
printf("%s = {\n", key);
|
||||||
|
indent++;
|
||||||
|
print_table(tab);
|
||||||
|
indent--;
|
||||||
|
prindent();
|
||||||
|
printf("},\n");
|
||||||
|
stacktop--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = toml_string_in(curtab, key);
|
||||||
|
if (d.ok) {
|
||||||
|
prindent();
|
||||||
|
printf("%s = ", key);
|
||||||
|
print_string(d.u.s);
|
||||||
|
printf(",\n");
|
||||||
|
free(d.u.s);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = toml_bool_in(curtab, key);
|
||||||
|
if (d.ok) {
|
||||||
|
prindent();
|
||||||
|
printf("%s = %s,\n", key, d.u.b ? "true" : "false");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = toml_int_in(curtab, key);
|
||||||
|
if (d.ok) {
|
||||||
|
prindent();
|
||||||
|
printf("%s = %" PRId64 ",\n", key, d.u.i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = toml_double_in(curtab, key);
|
||||||
|
if (d.ok) {
|
||||||
|
prindent();
|
||||||
|
printf("%s = %g,\n", key, d.u.d);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = toml_timestamp_in(curtab, key);
|
||||||
|
if (d.ok) {
|
||||||
|
prindent();
|
||||||
|
printf(" %s = %s,\n", key, toml_raw_in(curtab, key));
|
||||||
|
free(d.u.ts);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void print_array(toml_array_t* curarr)
|
static void print_array(toml_array_t* curarr)
|
||||||
{
|
{
|
||||||
|
toml_datum_t d;
|
||||||
toml_array_t* arr;
|
toml_array_t* arr;
|
||||||
const char* raw;
|
|
||||||
toml_table_t* tab;
|
toml_table_t* tab;
|
||||||
int i;
|
const int n = toml_array_nelem(curarr);
|
||||||
|
|
||||||
switch (toml_array_kind(curarr)) {
|
for (int i = 0; i < n; i++) {
|
||||||
|
|
||||||
case 'v':
|
if (0 != (arr = toml_array_at(curarr, i))) {
|
||||||
for (i = 0; 0 != (raw = toml_raw_at(curarr, i)); i++) {
|
prindent();
|
||||||
printf(" %d: %s,\n", i, raw);
|
printf("[\n");
|
||||||
|
indent++;
|
||||||
|
print_array(arr);
|
||||||
|
indent--;
|
||||||
|
prindent();
|
||||||
|
printf("],\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != (tab = toml_table_at(curarr, i))) {
|
||||||
|
prindent();
|
||||||
|
printf("{\n");
|
||||||
|
indent++;
|
||||||
|
print_table(tab);
|
||||||
|
indent--;
|
||||||
|
prindent();
|
||||||
|
printf("},\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = toml_string_at(curarr, i);
|
||||||
|
if (d.ok) {
|
||||||
|
prindent();
|
||||||
|
print_string(d.u.s);
|
||||||
|
printf(",\n");
|
||||||
|
free(d.u.s);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = toml_bool_at(curarr, i);
|
||||||
|
if (d.ok) {
|
||||||
|
prindent();
|
||||||
|
printf("%s,\n", d.u.b ? "true" : "false");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = toml_int_at(curarr, i);
|
||||||
|
if (d.ok) {
|
||||||
|
prindent();
|
||||||
|
printf("%" PRId64 ",\n", d.u.i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = toml_double_at(curarr, i);
|
||||||
|
if (d.ok) {
|
||||||
|
prindent();
|
||||||
|
printf("%g,\n", d.u.d);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = toml_timestamp_at(curarr, i);
|
||||||
|
if (d.ok) {
|
||||||
|
prindent();
|
||||||
|
printf("%s,\n", toml_raw_at(curarr, i));
|
||||||
|
free(d.u.ts);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
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;
|
|
||||||
|
|
||||||
case '\0':
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void cat(FILE* fp)
|
static void cat(FILE* fp)
|
||||||
{
|
{
|
||||||
char errbuf[200];
|
char errbuf[200];
|
||||||
|
|
||||||
toml_table_t* tab = toml_parse_file(fp, errbuf, sizeof(errbuf));
|
toml_table_t* tab = toml_parse_file(fp, errbuf, sizeof(errbuf));
|
||||||
if (!tab) {
|
if (!tab) {
|
||||||
fprintf(stderr, "ERROR: %s\n", errbuf);
|
fprintf(stderr, "ERROR: %s\n", errbuf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
stack[stacktop].tab = tab;
|
stack[stacktop].tab = tab;
|
||||||
stack[stacktop].key = "";
|
stack[stacktop].key = "";
|
||||||
stacktop++;
|
stacktop++;
|
||||||
|
printf("{\n");
|
||||||
|
indent++;
|
||||||
print_table(tab);
|
print_table(tab);
|
||||||
|
indent--;
|
||||||
|
printf("}\n");
|
||||||
stacktop--;
|
stacktop--;
|
||||||
|
|
||||||
toml_free(tab);
|
toml_free(tab);
|
||||||
|
@ -175,19 +278,19 @@ int main(int argc, const char* argv[])
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
cat(stdin);
|
cat(stdin);
|
||||||
} else {
|
} else {
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
|
|
||||||
FILE* fp = fopen(argv[i], "r");
|
FILE* fp = fopen(argv[i], "r");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
fprintf(stderr, "ERROR: cannot open %s: %s\n",
|
fprintf(stderr, "ERROR: cannot open %s: %s\n",
|
||||||
argv[i], strerror(errno));
|
argv[i], strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
cat(fp);
|
cat(fp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue