.github/workflows | ||
cmake | ||
docs | ||
examples | ||
include | ||
single_include | ||
src | ||
tests | ||
tools/expand | ||
.editorconfig | ||
.gitignore | ||
.gitmodules | ||
CMakeLists.txt | ||
LICENSE | ||
README_ja.md | ||
README.md |
toml11
toml11 is a feature-rich TOML language library for C++.
- It complies with the latest TOML language specification.
- It passes all the standard TOML language test cases.
- It supports new features merged into the upcoming TOML version (v1.1.0).
- It provides clear error messages, including the location of the error.
- It parses and retains comments, associating them with corresponding values.
- It maintains formatting information such as hex integers and considers these during serialization.
- It provides exception-less parse function.
- It supports complex type conversions from TOML values.
- It allows customization of the types stored in
toml::value
. - It provides some extensions not present in the TOML language standard.
Example
#include <toml.hpp>
#include <iostream>
// ```toml
// title = "an example toml file"
// nums = [3, 1, 4, 1, 5] # pi!
// ```
int main()
{
// select TOML version at runtime (optional)
auto data = toml::parse("example.toml", toml::spec::v(1,1,0));
// find a value with the specified type from a table
std::string title = toml::find<std::string>(data, "title");
// convert the whole array into STL-like container automatically
std::vector<int> nums = toml::find<std::vector<int>>(data, "nums");
// access with STL-like manner
if( ! data.contains("foo"))
{
data["foo"] = "bar";
}
if(data.at("nums").is_array())
{
data.push_back(9);
}
// check comments
assert(data.at("nums").comments().at(0) == "# pi!");
// pass a fallback
std::string name = toml::find_or<std::string>(data, "name", "not found");
// serialization considering format info
data.at("nums").as_array_fmt().fmt = toml::array_format::multiline;
data.at("nums").as_array_fmt().indent_type = toml::indent_char::space;
data.at("nums").as_array_fmt().body_indent = 2;
std::cout << toml::format(data) << std::endl;
return 0;
}
For more details, please refer to the documentation.
Table of Contents
Integration
There are several ways to use toml11.
Here is a brief overview of each method. For more details, please refer to the documentation.
Single Include File
Copy single_include/toml.hpp
to your preferred location and add it to your include path.
git submodule
By adding toml11 as a subdirectory using git submodule
(or any other way),
you can either add toml11/include
to your include path or use add_subdirectory(toml11)
in your CMake project.
Install Using CMake
You can install toml11 using CMake with the following steps:
$ git clone https://github.com/ToruNiina/toml11
$ cd toml11
$ git submodule update --init --recursive
$ cmake -B ./build/
$ cmake --build ./build/
$ cmake --install ./build/ --prefix /path/to/toml11
Precompile Library
By setting -DTOML11_PRECOMPILE=ON
, you can precompile some of the library functions.
In this case, the standard library features available will vary with the C++ version, and part of the interface will change.
Therefore, you need to specify CMAKE_CXX_STANDARD
.
$ cmake -B ./build/ -DTOML11_PRECOMPILE=ON -DCMAKE_CXX_STANDARD=11/14/17/20
$ cmake --build ./build/
Building Example
To compile the examples in the examples/
directory, set -DTOML11_BUILD_EXAMPLES=ON
.
$ cmake -B ./build/ -DTOML11_BUILD_EXAMPLES=ON
$ cmake --build ./build/
Building Tests
To compile unit tests, set -DTOML11_BUILD_TESTS=ON
.
Additionally, to compile the encoder and decoder for toml-test, set -DTOML11_BUILD_TOML_TESTS=ON
.
$ cmake -B ./build/ -DTOML11_BUILD_EXAMPLES=ON
$ cmake --build ./build/
Features
Here is a brief overview of the features provided by toml11.
For more details, please refer to the documentation.
Parsing a File
To parse a file, use toml::parse
.
The overall type of the file is always a table.
However, since toml::value
contains metadata such as comments and formatting information,
toml::parse
returns a toml::value
rather than a toml::table
.
const toml::value input = toml::parse("input.toml");
To parse a string directly, use toml::parse_str
.
const toml::value input = toml::parse_str("a = 42");
toml::parse
throws a toml::syntax_error
exception on syntax errors.
To avoid this, use toml::try_parse
, which returns a toml::result
.
const auto input = toml::try_parse("input.toml");
if(input.is_ok())
{
std::cout << input.unwrap().at("a").as_integer() << std::endl;
}
Additionally, toml11 allows easy and precise control over the version of the TOML language being used.
You can enable specific new features from TOML v1.1.0 while using TOML v1.0.0.
toml::spec s = toml::spec::v(1, 0, 0);
s.v1_1_0_allow_trailing_comma_in_inline_tables = true;
const toml::value input = toml::parse("input.toml");
Moreover, several language extensions not included in the TOML standard are available.
toml::spec s = toml::spec::v(1, 0, 0);
s.ext_hex_float = true; // this allows hexadecimal floating-point numbers
s.ext_null_value = true; // this allows `key = null` value
s.ext_num_suffix = true; // this allows numeric suffixes like `100_msec`
For more detail and reference of each feature, please refer to the documentation.
finding a value
toml::value
provides member functions for accessing values, such as at()
, is_xxx()
, and as_xxx()
.
const toml::value input = toml::parse("input.toml");
if(input.contains("a") && input.at("a").is_integer())
{
std::cout << input.at("a").as_integer() << std::endl;
}
By using toml::find
, you can perform type conversion and search simultaneously.
const toml::value input = toml::parse("input.toml");
std::cout << toml::find<int>(input, "a") << std::endl;
You can perform advanced type conversions on complex TOML values.
mixed_array = [
42,
3.14,
{a = "foo", b = "bar"}
]
const toml::value input = toml::parse("input.toml");
const auto mixed = toml::find<
std::tuple<int, double, std::map<std::string, std::string>>
>(input, "mixed_array") << std::endl;
For more details, please refer to the documentation.
comments
toml11 stores comments related to values within the value itself.
Comments related to a value include a series of comments written immediately before the value and any comments written after the value without a newline in between.
# This is a comment for a.
# This is also a comment for a.
a = 42 # This is also a comment for a.
# This is separated by a newline, so it is not a comment for b.
# This is a comment for b.
b = "foo"
These comments are stored in toml::value
with an interface similar to std::vector<std::string>
.
const toml::value input = toml::parse("input.toml");
std::cout << input.at("a").comments().size() << std::endl;
std::cout << input.at("a").comments().at(0) << std::endl;
For more details, please refer to the documentation.
error messages
One of the goals of toml11 is to provide clear and understandable error messages.
For parsing errors, you might see an error message like the following:
[error] bad integer: `_` must be surrounded by digits
--> internal string at line 64 in file main.cpp
|
1 | a = 123__456
| ^-- invalid underscore
Hint: valid : -42, 1_000, 1_2_3_4_5, 0xC0FFEE, 0b0010, 0o755
Hint: invalid: _42, 1__000, 0123
If you request a type different from the actual stored type, an error message like this will be displayed:
[error] toml::value::as_string(): bad_cast to string
--> input.toml
|
1 | a = 123_456
| ^^^^^^^-- the actual type is integer
Such error messages can also be produced for user-specific algorithm that is not related to TOML syntax.
const toml::value& a = input.at("a");
if(a.as_integer() < 0)
{
const toml::error_info err = toml::make_error_info(
"positive integer is required",
a, "but got negative value"
);
std::cerr << toml::format_error(err) << std::endl;
}
For more details, please refer to the documentation.
serialization
You can format a toml::value
into a std::string
using toml::format
.
const toml::value input = toml::parse("input.toml");
std::cout << toml::format(input) << std::endl;
toml::format
references the formatting information, allowing you to change the formatting method.
toml::value output(toml::table{ {"a", 0xDEADBEEF} });
output.at("a").as_integer_fmt().fmt = toml::integer_format::hex;
output.at("a").as_integer_fmt().spacer = 4;
std::cout << toml::format(input) << std::endl;
For details on possible formatting specifications, please refer to the documentation.
compilcated configurations
The examples directory provides complex usage examples, such as using arbitrary-precision integers, normalizing Unicode, and integrating with external reflection libraries.
Please refer to these examples for implementation guidance in such scenarios.
Changes from v3
toml11 v4 introduces several breaking changes.
Efforts have been made to minimize the need for changes for those using simple functionality. However, if you were utilizing advanced features, some adjustments may be necessary.
Nevertheless, we believe that the added or streamlined features will provide enhanced convenience in return.
Breaking Changes
- Changed branch from
master
tomain
. - Changed template arguments of
toml::basic_value
. - Removed
toml::string
and explicitly store formatting information of all the values. - Modified arguments of
toml::format
to accommodate formatting information. - Changed default arguments of
toml::parse
to taketoml::spec
for specifying TOML version information. - Updated the interface of
toml::source_location
to accommodate multiline regions. - Modified arguments of
toml::format_error
. - Renamed
toml::format_underline
totoml::format_location
. - Unified control method of
toml::color
totoml::color::enable/disable()
.
Added features
- Added
toml::parse_str
. - Added
toml::try_parse
. - Added support for parsing byte sequences.
- Added formatting information to
toml::value
. - Changed to saving comments in
toml::value
by default. - Added
single_include/toml.hpp
. - Enabled to use as a precompiled library.
Contributors
I appreciate the help of the contributors who introduced the great feature to this library.
- Guillaume Fraux (@Luthaf)
- Windows support and CI on Appvayor
- Intel Compiler support
- Quentin Khan (@xaxousis)
- Found & Fixed a bug around ODR
- Improved error messages for invalid keys to show the location where the parser fails
- Petr Beneš (@wbenny)
- Fixed warnings on MSVC
- Ivan Shynkarenka (@chronoxor)
- Fixed Visual Studio 2019 warnings
- Fix compilation error in
<filesystem>
with MinGW
- Khoi Dinh Trinh (@khoitd1997)
- Fixed warnings while type conversion
- @KerstinKeller
- Added installation script to CMake
- J.C. Moyer (@jcmoyer)
- Fixed an example code in the documentation
- Jt Freeman (@blockparty-sh)
- Fixed feature test macro around
localtime_s
- Suppress warnings in Debug mode
- Fixed feature test macro around
- OGAWA Kenichi (@kenichiice)
- Suppress warnings on intel compiler
- Fix include path in README
- Jordan Williams (@jwillikers)
- Fixed clang range-loop-analysis warnings
- Fixed feature test macro to suppress -Wundef
- Use cache variables in CMakeLists.txt
- Automate test set fetching, update and refactor CMakeLists.txt
- Scott McCaskill
- Parse 9 digits (nanoseconds) of fractional seconds in a
local_time
- Parse 9 digits (nanoseconds) of fractional seconds in a
- Shu Wang (@halfelf)
- fix "Finding a value in an array" example in README
- @maass-tv and @SeverinLeonhardt
- Fix MSVC warning C4866
- Mohammed Alyousef (@MoAlyousef)
- Made testing optional in CMake
- Alex Merry (@amerry)
- Add missing include files
- sneakypete81 (@sneakypete81)
- Fix typo in error message
- Oliver Kahrmann (@founderio)
- Fix missing filename in error message if parsed file is empty
- Karl Nilsson (@karl-nilsson)
- Fix many spelling errors
- ohdarling88 (@ohdarling)
- Fix a bug in a constructor of serializer
- estshorter (@estshorter)
- Fix MSVC warning C26478
- Philip Top (@phlptp)
- Improve checking standard library feature availability check
- Louis Marascio (@marascio)
- Fix free-nonheap-object warning
- Axel Huebl (@ax3l)
- Make installation optional if the library is embedded
- Ken Matsui (@ken-matsui)
- Support user-defined error message prefix
- Support dynamic color mode
- Giel van Schijndel (@muggenhor)
- Remove needless copy in
parse
function
- Remove needless copy in
- Lukáš Hrázký (@lukash)
- Add a
parse(FILE *)
interface and improve file-related error messages
- Add a
- spiderman idog (@spiderman-idog)
- Fix typo in README
- Jajauma's GitHub (@Jajauma)
- Avoid possible lexer truncation warnings
- Moritz Klammler (@ctcmkl)
- Many patches in (#200) including:
- Improve CMake scripts, build process, and test file handling
- Detect error when
discard_comments
is accessed - And more.
- Chris White (@cxw42)
- Fix address-sanitizer error when parsing literal strings having invalid UTF-8 characters
- Fix function name in error messages
- offa (@offa)
- Update checkout action to v3
- Update Required CMake version
- Cleanup old CI settings
- Sergey Vidyuk (@VestniK)
- Fix for case when vector iterator is raw pointer
- Kfir Gollan (@kfirgollan)
- Add installation example with checkinstall and cmake
- Martin Tournoij (@arp242)
- Escape control characters in keys
- @DavidKorczynski
- Add fuzzing test based on ClusterFuzzLite
- Esonhugh Skyworship (@Esonhugh)
- Fix function signature of
strerror_r
on macos
- Fix function signature of
Licensing terms
This product is licensed under the terms of the MIT License.
- Copyright (c) 2017-2024 Toru Niina
All rights reserved.