A header only C++11 library for parsing TOML

Overview

tinytoml

A header only C++11 library for parsing TOML.

Build Status

This parser is based on TOML v0.4.0. This library is distributed under simplified BSD License.

Introduction

tinytoml is a tiny TOML parser for C++11 with following properties:

  • header file only
  • C++11 library friendly (array is std::vector, table is std::map, time is std::chrono::system_clock::time_point).
  • no external dependencies (note: we're using cmake for testing, but it's not required to use this library).

We'd like to keep this library as handy as possible.

Prerequisite

  • C++11 compiler
  • C++11 libraries.

I've only checked this library works with recent clang++ (3.5) and g++ (4.7). I didn't check this with cl.exe. Acutally I'm using this library on my Linux app and Mac app. However, I haven't written Windows app yet.

How to use

Copy include/toml/toml.h into your project, and include it from your source. That's all.

Example code

// Parse foo.toml. If foo.toml is valid, pr.valid() should be true.
// If not valid, pr.errorReason will contain the parser error reason.
std::ifstream ifs("foo.toml");
toml::ParseResult pr = toml::parse(ifs);

if (!pr.valid()) {
    cout << pr.errorReason << endl;
    return;
}

// Note for users from older version:
// Since toml::Parser has a state, I don't recommend to use it directly any more.
// So, I've moved toml::Parser to toml::internal::Parser.
// Using toml::parse() is recommended.

// pr.value is the parsed value.
const toml::Value& v = pr.value;

// You can find a value by find().
// If found, non-null pointer will be returned.
// You can check the type of value with is().
// You can get the inner value by as().
const toml::Value* x = v.find("foo.bar.baz");
if (x && x->is<std::string>()) {
    cout << x->as<string>() << endl;
} else if (x && x->is<int>()) {
    cout << x->as<int>() << endl;
}

// Note: the inner value of integer value is actually int64_t,
// however, you can use 'int' for convenience.
toml::Value* z = ...;
int x = z->as<int>();
int64_t y = z->as<int64_t>();
// toml::Array is actually std::vector<toml::Value>.
// So, you can use range based for, etc.
const toml::Array& ar = z->as<toml::Array>();
for (const toml::Value& v : ar) {
    ...
}

// For convenience way, you can use get() when you're sure that the value exists
// and you know the value type.
// If type error occurred, std::runtime_error is raised.
toml::Value v = ...;
cout << v.get<string>("foo.bar") << endl;

// For array type, you can also use get<std::vector<int>>() etc.
// Note that a fresh vector<int> is allocated.
std::vector<int> vs = v.get<std::vector<int>>();

// If you need to check value existence or type, you should use find().

How to test

The directory 'src' contains a few tests. We're using google testing framework, and cmake.

$ mkdir -p out/Debug; cd out/Debug
$ cmake ../../src
$ make
$ make test

'src' also contains a small example for how to use this.

Comments
  • Expand testsuite with builder/writer tests that enumerate success documents.

    Expand testsuite with builder/writer tests that enumerate success documents.

    This branch contains two new test executables that test builder/writer interfaces (which, are somewhat lacking..)

    Commit 60efde0 fixes proper escaping of keys when outputting the value to ostream.

    The builder test (BuilderTest.build_parse_datetime_01) is currently failing. I'm simply assuming this is due to a parser bug (which I have yet to look into. Priorities..)

    I'm in the process of implementing better write support (more formatting options, as well as per Value). I'm positive this will resolve #11 as well.

    Please review and consider merging.

    opened by veeg 12
  • Optional indentation + move semantics

    Optional indentation + move semantics

    Add the ability to format output with indentation if required.

    Example usage: value.write(&os, toml::Value::INDENT_ENABLED);

    Also added move semantics for a small performance increase.

    opened by sir-earl 7
  • Error by building an Qt based project

    Error by building an Qt based project

    Hey! I want to use TinyTOML in my Qt project, I've added the line QMAKE_CXXFLAGS += -std=c++11 to set the flags for C++11.

    Now when I start building I get the following error:

    In file included from src/core/project.cpp:29:0:
    src/core/../../externals/tinytoml/toml.h: In static member function 'static bool toml::Parser::parseTime(const string&, toml::Value*)':
    src/core/../../externals/tinytoml/toml.h:829:58: error: 'timegm' was not declared in this scope
         *v = std::chrono::system_clock::from_time_t(timegm(&t));
                                                              ^
    mingw32-make[1]: *** [debug/project.o] Error 1
    Makefile.Debug:143: recipe for target 'debug/project.o' failed
    mingw32-make[1]: Leaving directory 'C:/arden'
    mingw32-make: *** [debug] Error 2
    makefile:34: recipe for target 'debug' failed
    [Finished in 2.5s]
    

    How can I fix this?

    ~ Jan

    opened by ghost 7
  • Comparison operator

    Comparison operator

    Hello, I am wondering if it would be possible to add support for comparing toml::Value using the equality operators? toml::Value has some type information to cast and do the comparison. It would also be nice to have .compare_as<T,T>() for comparisons.

    opened by RobertBColton 6
  • gmtime_r fails with MinGW GCC version 4.8.0

    gmtime_r fails with MinGW GCC version 4.8.0

    With a simple int main() and g++ -std=c++11 main.cpp -o tinytomltest.exe that only includes the tinytoml header, I get the following:

    toml.h: In member function 'void toml::Value::write(std::ostream*, const string&, int) const':
    toml.h:1298:25: error: 'gmtime_r' was not declared in this scope
             gmtime_r(&tt, &t);
                             ^
    

    This was tested with an older version of MinGW that is shipped with the ENIGMA game engine. gcc -v gives:

    gcc version 4.8.2 (GCC)
    

    I tried with Visual Studio 2015 and created an empty Console Application, which worked just fine using the MSVC 2015 compiler.

    So it loos like the entire issue is with MinGW. I guess tinytoml wants to use gmtime_r because this represents universal time. https://linux.die.net/man/3/gmtime_r

    I know with this version of MinGW that I tested, localtime does in fact work. I know because it's used in ENIGMA's engine to implement GameMaker's date and time functions. https://github.com/enigma-dev/enigma-dev/blob/master/ENIGMAsystem/SHELL/Universal_System/Extensions/DateTime/date_time.cpp#L46

    But that won't work with tinytoml because localtime would format the dates and times in the users local timezone making them be incorrect when read back from the toml file if read on a computer with a different timezone.

    I read on another GitHub post that some things changed with POSIX in newer MinGW releases. I still could not solve the tinytoml issue by defining _POSIX_C_SOURCE 200809L even though I know it's irrelevant for my MinGW version.

    The full source of what won't compile with MinGW gcc version 4.8.0:

    #define _POSIX_C_SOURCE 200809L
    #include <time.h>
    
    #include "tinytoml.h"
    
    int main() {
    
    	return 0;
    }
    

    One work around I have found that makes this build with this MinGW is adding the following to tinytoml.h:

    #if defined(_WIN32)
    // gmtime_r can be defined by mingw
    #ifndef gmtime_r
    static struct tm* gmtime_r(const time_t* t, struct tm* r)
    {
      // gmtime is threadsafe in windows because it uses TLS
      struct tm *theTm = gmtime(t);
      if (theTm) {
        *r = *theTm;
        return r;
      } else {
        return 0;
      }
    }
    #endif // gmtime_r
    #else
    extern struct tm* gmtime_r(const time_t* t, struct tm* r);
    #endif
    

    This patch was taken from here: http://redmine.webtoolkit.eu/boards/2/topics/7316

    With this patch I can build the following with the MinGW GCC version 4.8.0, though it was hard to figure out how to use time types in tinytoml.h:

    #include "tinytoml.h"
    
    #include <fstream>
    
    int main() {
    	std::ofstream ofs("C:/Users/Owner/Desktop/tinytomltest.toml");
    	toml::Table root;
    
    	toml::Table sceneValue = toml::Table();
    	sceneValue["name"] = "Scene0";
    	time_t rawtime;
    	localtime(&rawtime);
    	sceneValue["created"] = std::chrono::system_clock::from_time_t(rawtime);
    
    	root["scene"] = sceneValue;
    
    	ofs << root;
    	ofs.close();
    	return 0;
    }
    

    And this is the output:

    
    [scene]
    created = 1970-03-16T07:53:44Z
    name = "Scene0"
    

    Perhaps this could be added to the examples in the README.md since it just prints the current date and time to make it clearer how to use dates and times?

    opened by RobertBColton 5
  • Time type suggestions

    Time type suggestions

    In the Qt Framework the DateTime, Date, and Time objects main conversion type is std::time_t. This conversion requires a rather long call:

    return QVariant(QDateTime::fromTime_t(std::chrono::system_clock::to_time_t(value.as<std::time_t>())));
    

    Is it possible that toml::Value could also provide .asstd::time_t() for time types? Is it possible that toml::Value could also distinguish between Date, Time, and DateTime? It would be useful in our Qt application which has separate QDateEdit, QTimeEdit, and QDateTime edit so as to not have to create the third control when either Date or Time is not needed.

    opened by RobertBColton 5
  • support compilation with exception disabled

    support compilation with exception disabled

    Given failwith is the only function incompatible when -fno-exceptions is specified, I think it would be great to provide a version where exceptions are disabled. The compilation condition can be guarded by a macro guard.

    opened by hongxuchen 3
  • Remove return statements after failwith()

    Remove return statements after failwith()

    All the compilers I've run tinytoml against (GCC 5, Clang 3.9, VS 2015) correctly understand that failwith() doesn't return, and warn about these returns being unreachable with certain warning flags.

    opened by mrkline 3
  • Inline internal::type_name<> templates.

    Inline internal::type_name<> templates.

    This template and its specializations can be instantiated in each object file. In such a case, we cannot link multiple object files which use toml.h. Without inline, it depends on compilers and its optimization settings whether this templates are in-line expanded.

    To help compilers to expand it and to avoid link conflicts, this CL adds inline attributes to the template.

    opened by peria 3
  • Make tinytoml compilable with Visual C++ compiler.

    Make tinytoml compilable with Visual C++ compiler.

    Make tinytoml library compilable with Visual C++ compiler 2015. What I did in this PR are

    • Make some functions to replace with GNU extensions.
    • Put some preprocessor directives to replace compiler specific attributes.
    • Update CMakeLists.txt to handle compiler options correctly.
    • Disable tests with multi-byte characters. Visual C++ cannot handle UTF8 without BOM.

    With this PR, tinytoml can be compiled in DOS prompt.

    C:\tinytoml>mkdir out
    C:\tinytoml>cd out
    C:\tinytoml\out>cmake ..\src -G"Visual Studio 14 2015 Win64"
    C:\tinytoml\out>cmake --build .
    
    opened by peria 3
  • Fix compiler warnings

    Fix compiler warnings

    Hello! In using this library clang produced several warnings which I've addressed. Of note, it looks like in several places the bool Token constructor was being called when likely the string one was desired. The rest of the changes I don't think fix any correctness issues, and mostly were to make clang happy.

    If you're interested in reproducing my compiler warning output, I was building with -Werror -Wall -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded -Wno-weak-vtables -Wno-global-constructors -Wno-exit-time-destructors -Wno-gnu-zero-variadic-macro-arguments -Wno-unused-member-function -Wno-switch-enum -Wno-covered-switch-default

    opened by mjkoo 3
  • ABRT on __cxxabiv1

    ABRT on __cxxabiv1

    Here is the seed that cause the ABRT when parse it use parseFile. you can use your parse_file.cc to reproduce the ABRT.

    I think it occured at void toml::failwith<char const toml::Value::ensureValue

    case1445.zip

    opened by liweiii 0
  • stack-overflow at

    stack-overflow at "parseFile"

    Hi,

    I have found a bug when I fuzzing . When I enter an input file to a program use toml.h with parseFile, it cause a stack-overflow at parseFile function. I think there maybe too much loop or other bug cause this . my stack size is 8192kbs.

    I know that we can avoid it by ulimit -s , but I think parse a toml file about 32k that cause 8M stack overflow maybe not a good way. If I make a file follow some pattern , the file may be minimized and smaller than 10k.

    Here is the backtrace:

    #0 __asan_memset ()
        at /src/llvm-project/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:26
    #1  std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__zero() () at /usr/local/bin/../include/c++/v1/string:1563
    #2  std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string() () at /usr/local/bin/../include/c++/v1/string:1812
    #3  toml::internal::Token::Token(toml::internal::TokenType) () at ./include/toml/toml.h:272
    #4  toml::internal::Lexer::nextToken(bool) () at ./include/toml/toml.h:1022
    #5  toml::internal::Lexer::nextValueToken() () at ./include/toml/toml.h:967
    #6  toml::internal::Parser::nextValue() () at ./include/toml/toml.h:347
    #7  toml::internal::Parser::consumeForValue(toml::internal::TokenType) ()
        at ./include/toml/toml.h:1740
    

    (and maybe 20000 times repeat below two lines)

    toml::internal::Parser::parseArray(toml::Value*) () at ./include/toml/toml.h:1978
    toml::internal::Parser::parseValue(toml::Value*) () at ./include/toml/toml.h:1919
    

    and this below:

    toml::internal::Parser::parseKeyValue(toml::Value*) () at ./include/toml/toml.h:1883
    toml::internal::Parser::parse() () at ./include/toml/toml.h:1790
    toml::parse(std::__1::basic_istream<char, std::__1::char_traits<char> >&) ()
        at ./include/toml/toml.h:385
    toml::parseFile(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) () at ./include/toml/toml.h:401
    LLVMFuzzerTestOneInput () at /src/parse_file.cc:16
    fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) ()
    RunOneTest () at /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:323
    fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) ()
    main () at /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20
    

    the testcase I use is like parse_file.cc in your project. you can just compile use your code and input my file to the parse_file. stack size is 8192kbs. And you will get a segment fault caused by stack overflow. I have upload the file causes this. crashcase.zip

    opened by liweiii 1
  • Macro for adding custom types to Value::as<T>()

    Macro for adding custom types to Value::as()

    It would be nice to be able to support our own custom types to the TOML parser through templates, so that we could simply write value.as<My_t>() for any My_t that we want . Based on my reading of the source, it's already possible without touching the source by adding new template specialization for a few types. I made a macro in my project to do this; I haven't tested it yet, but would you be interested in a pull request to add this type of functionality?

    I'd also like to provide an automatic way to deserialize a custom type, but I'm not sure how to do that yet; it might require source modification.

    Edit: forgot to mention, I also used this in my project to provide parsers for all the different integer and float types, because the project currently only accepts int64_t and double. Would you be interested in that as well?

    opened by heyx3 0
  • Make

    Make "typeToString()" public?

    It would be nice if my own code could access "typeToString()", for example when generating error messages in my own parsing code (e.x. Expected a 'string', but got 'table'). Is there a reason it was left private?

    opened by heyx3 2
  • Can't compile with nvcc 9.0.176 or 10.0.130

    Can't compile with nvcc 9.0.176 or 10.0.130

    I'm trying to compile a simple CUDA file using tinytoml:

    // test_toml.cu
    
    #include <iostream>
    
    #include "toml.h"
    
    int main ()
    {
      std::cerr << "TOML in .cu file!" << std::endl;
      return 0;
    }
    

    using

    nvcc --std=c++11 test_toml.cu -o test_toml
    

    I get a compiler error like the following:

    toml.h: In member function ‘toml::Value toml::internal::Parser::parse()’:
    toml.h:1775:24: error: cannot convert ‘toml::Value (*)(toml::Table (*)()) {aka toml::Value (*)(std::map<std::__cxx11::basic_string<char>, toml::Value> (*)())}’ to ‘toml::Value*’ in initialization
         Value* currentValue = &root;
                            ^~~~
    toml.h:1782:41: error: no matching function for call to ‘toml::internal::Parser::parseGroupKey(toml::Value (*)(toml::Table (*)()))’
                 currentValue = parseGroupKey(&root);
                                             ^
    toml.h:356:15: note: candidate: toml::Value* toml::internal::Parser::parseGroupKey(toml::Value*)
         Value* parseGroupKey(Value* root);
                   ^~~~~~~~~~~~~
    toml.h:356:15: note:   no known conversion for argument 1 from ‘toml::Value (*)(toml::Table (*)()) {aka toml::Value (*)(std::map<std::__cxx11::basic_string<char>, toml::Value> (*)())}’ to ‘toml::Value*’
    toml.h: In member function ‘bool toml::internal::Parser::parseInlineTable(toml::Value*)’:
    toml.h:2033:7: error: request for member ‘has’ in ‘toml::internal::t’, which is of non-class type ‘toml::Value(toml::Table (*)()) {aka toml::Value(std::map<std::__cxx11::basic_string<char>, toml::Value> (*)())}’
             if (t.has(key)) {
           ^ ~
    toml.h:2038:3: error: request for member ‘set’ in ‘toml::internal::t’, which is of non-class type ‘toml::Value(toml::Table (*)()) {aka toml::Value(std::map<std::__cxx11::basic_string<char>, toml::Value> (*)())}’
             t.set(key, v);
       ^
    [dshaff@farnarkle1 sandbox]$ nvcc --std=c++11 test_toml.cu -o test_toml
    toml.h: In member function ‘toml::Value toml::internal::Parser::parse()’:
    toml.h:1775:24: error: cannot convert ‘toml::Value (*)(toml::Table (*)()) {aka toml::Value (*)(std::map<std::__cxx11::basic_string<char>, toml::Value> (*)())}’ to ‘toml::Value*’ in initialization
         Value* currentValue = &root;
                            ^~~~
    toml.h:1782:41: error: no matching function for call to ‘toml::internal::Parser::parseGroupKey(toml::Value (*)(toml::Table (*)()))’
                 currentValue = parseGroupKey(&root);
                                             ^
    toml.h:356:15: note: candidate: toml::Value* toml::internal::Parser::parseGroupKey(toml::Value*)
         Value* parseGroupKey(Value* root);
                   ^~~~~~~~~~~~~
    toml.h:356:15: note:   no known conversion for argument 1 from ‘toml::Value (*)(toml::Table (*)()) {aka toml::Value (*)(std::map<std::__cxx11::basic_string<char>, toml::Value> (*)())}’ to ‘toml::Value*’
    toml.h: In member function ‘bool toml::internal::Parser::parseInlineTable(toml::Value*)’:
    toml.h:2033:7: error: request for member ‘has’ in ‘toml::internal::t’, which is of non-class type ‘toml::Value(toml::Table (*)()) {aka toml::Value(std::map<std::__cxx11::basic_string<char>, toml::Value> (*)())}’
             if (t.has(key)) {
           ^ ~
    toml.h:2038:3: error: request for member ‘set’ in ‘toml::internal::t’, which is of non-class type ‘toml::Value(toml::Table (*)()) {aka toml::Value(std::map<std::__cxx11::basic_string<char>, toml::Value> (*)())}’
             t.set(key, v);
       ^
    
    opened by dean-shaff 1
Releases(v0.4)
Owner
mayah
puyopuyo AI and more
mayah
Header-only TOML config file parser and serializer for C++17 (and later!).

toml++ homepage ✨ This README is fine, but the toml++ homepage is better. ✨ Library features Header-only Supports the latest TOML release (v1.0.0), pl

Mark Gillard 970 Jan 9, 2023
A C++11 or library for parsing and serializing JSON to and from a DOM container in memory.

Branch master develop Azure Docs Drone Matrix Fuzzing --- Appveyor codecov.io Boost.JSON Overview Boost.JSON is a portable C++ library which provides

Boost.org 333 Dec 29, 2022
Header-only C++11 library to encode/decode base64, base64url, base32, base32hex and hex (a.k.a. base16) as specified in RFC 4648, plus Crockford's base32. MIT licensed with consistent, flexible API.

cppcodec Header-only C++11 library to encode/decode base64, base64url, base32, base32hex and hex (a.k.a. base16) as specified in RFC 4648, plus Crockf

Topology 491 Dec 28, 2022
Zmeya is a header-only C++11 binary serialization library designed for games and performance-critical applications

Zmeya Zmeya is a header-only C++11 binary serialization library designed for games and performance-critical applications. Zmeya is not even a serializ

Sergey Makeev 99 Dec 24, 2022
Header-only library for automatic (de)serialization of C++ types to/from JSON.

fuser 1-file header-only library for automatic (de)serialization of C++ types to/from JSON. how it works The library has a predefined set of (de)seria

null 51 Dec 17, 2022
libcluon is a small and efficient, single-file and header-only library written in modern C++ to power microservices.

libcluon Linux & OSX Build (TravisCI) Win64 Build (AppVeyor) Test Coverage Coverity Analysis CII Best Practices libcluon is a small single-file, heade

Christian Berger 81 Nov 30, 2022
Parsing gigabytes of JSON per second

simdjson : Parsing gigabytes of JSON per second JSON is everywhere on the Internet. Servers spend a *lot* of time parsing it. We need a fresh approach

null 16.3k Jan 2, 2023
Use to copy a file from an NTFS partitioned volume by reading the raw volume and parsing the NTFS structures.

ntfsDump Use to copy a file from an NTFS partitioned volume by reading the raw volume and parsing the NTFS structures. Similar to https://github.com/P

null 102 Dec 30, 2022
Your binary serialization library

Bitsery Header only C++ binary serialization library. It is designed around the networking requirements for real-time data delivery, especially for ga

Mindaugas Vinkelis 771 Jan 2, 2023
Cap'n Proto serialization/RPC system - core tools and C++ library

Cap'n Proto is an insanely fast data interchange format and capability-based RPC system. Think JSON, except binary. Or think Protocol Buffers, except

Cap'n Proto 9.5k Jan 1, 2023
A C++11 library for serialization

cereal - A C++11 library for serialization cereal is a header-only C++11 serialization library. cereal takes arbitrary data types and reversibly turns

iLab @ USC 3.4k Jan 3, 2023
FlatBuffers: Memory Efficient Serialization Library

FlatBuffers FlatBuffers is a cross platform serialization library architected for maximum memory efficiency. It allows you to directly access serializ

Google 19.7k Jan 9, 2023
FlatBuffers Compiler and Library in C for C

OS-X & Ubuntu: Windows: The JSON parser may change the interface for parsing union vectors in a future release which requires code generation to match

null 550 Dec 25, 2022
Simple C++ 20 Serialization Library that works out of the box with aggregate types!

BinaryLove3 Simple C++ 20 Serialization Library that works out of the box with aggregate types! Requirements BinaryLove3 is a c++20 only library.

RedSkittleFox 14 Sep 2, 2022
A C++ library for interacting with JSON.

JsonCpp JSON is a lightweight data-interchange format. It can represent numbers, strings, ordered sequences of values, and collections of name/value p

null 6.9k Jan 4, 2023
CppSerdes is a serialization/deserialization library designed with embedded systems in mind

A C++ serialization/deserialization library designed with embedded systems in mind

Darren V Levine 79 Nov 5, 2022
Morse code decoding library

ggmorse Morse code decoding library ggmorse2.mp4 ggmorse0.mp4 ggmorse1.mp4 Try it out You can easily test the library using the free GGMorse applicati

Georgi Gerganov 106 Dec 23, 2022
C++17 library for all your binary de-/serialization needs

blobify blobify is a header-only C++17 library to handle binary de-/serialization in your project. Given a user-defined C++ struct, blobify can encode

Tony Wasserka 247 Dec 8, 2022
C++ BSON Library

This is a standalone BSON ("binary JSON") library for C++. (See bsonspec.org for more information on the BSON format.) The library is at this time a b

Dwight Merriman 57 Dec 16, 2022