diff options
| author | kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> | 2021-04-15 23:19:01 -0700 |
|---|---|---|
| committer | kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> | 2021-04-15 23:19:01 -0700 |
| commit | 42253150e43fa4289130d4b53729e618908a251e (patch) | |
| tree | 2523976f18503837a72dc2fadfba3304d774fab5 /libraries | |
| parent | 8b926d29d7aef9c7bbcb25ec9bfbf0ad314a8d72 (diff) | |
| download | PrismLauncher-42253150e43fa4289130d4b53729e618908a251e.tar.gz PrismLauncher-42253150e43fa4289130d4b53729e618908a251e.tar.bz2 PrismLauncher-42253150e43fa4289130d4b53729e618908a251e.zip | |
add toml11 as dependency
Diffstat (limited to 'libraries')
27 files changed, 12370 insertions, 0 deletions
diff --git a/libraries/README.md b/libraries/README.md index cdc72004..76ee8c46 100644 --- a/libraries/README.md +++ b/libraries/README.md @@ -158,3 +158,10 @@ A Google Analytics library for Qt. BSD licensed, derived from [qt-google-analytics](https://github.com/HSAnet/qt-google-analytics). Modifications include better handling of IP anonymization (can be enabled) and general improvements of the API (application handles persistence and ID generation instead of the library). + +## toml11 +A C++11 TOML language parser. Used by Forge 1.14+ to store mod metadata. + +See [github repo](https://github.com/ToruNiina/toml11). + +Licenced under the MIT licence. diff --git a/libraries/toml11/CMakeLists.txt b/libraries/toml11/CMakeLists.txt new file mode 100644 index 00000000..556ec150 --- /dev/null +++ b/libraries/toml11/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.1) +project(toml11) + +add_library(toml11 INTERFACE) +target_include_directories(toml11 INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include") diff --git a/libraries/toml11/LICENSE b/libraries/toml11/LICENSE new file mode 100644 index 00000000..f55c511d --- /dev/null +++ b/libraries/toml11/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017 Toru Niina + +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. diff --git a/libraries/toml11/README.md b/libraries/toml11/README.md new file mode 100644 index 00000000..d5bc1c81 --- /dev/null +++ b/libraries/toml11/README.md @@ -0,0 +1,1918 @@ +toml11 +====== + +[](https://github.com/ToruNiina/toml11/actions) +[](https://travis-ci.org/ToruNiina/toml11) +[](https://ci.appveyor.com/project/ToruNiina/toml11/branch/master) +[](https://circleci.com/gh/ToruNiina/toml11/tree/master) +[](https://github.com/ToruNiina/toml11/releases) +[](LICENSE) +[](https://doi.org/10.5281/zenodo.1209136) + +toml11 is a C++11 (or later) header-only toml parser/encoder depending only on C++ standard library. + +- It is compatible to the latest version of [TOML v1.0.0](https://toml.io/en/v1.0.0). +- It is one of the most TOML standard compliant libraries, tested with [the language agnostic test suite for TOML parsers by BurntSushi](https://github.com/BurntSushi/toml-test). +- It shows highly informative error messages. You can see the error messages about invalid files at [CircleCI](https://circleci.com/gh/ToruNiina/toml11). +- It has configurable container. You can use any random-access containers and key-value maps as backend containers. +- It optionally preserves comments without any overhead. +- It has configurable serializer that supports comments, inline tables, literal strings and multiline strings. +- It supports user-defined type conversion from/into toml values. +- It correctly handles UTF-8 sequences, with or without BOM, both on posix and Windows. + +## Example + +```cpp +#include <toml.hpp> +#include <iostream> + +int main() +{ + // ```toml + // title = "an example toml file" + // nums = [3, 1, 4, 1, 5] + // ``` + auto data = toml::parse("example.toml"); + + // find a value with the specified type from a table + std::string title = toml::find<std::string>(data, "title"); + + // convert the whole array into any container automatically + std::vector<int> nums = toml::find<std::vector<int>>(data, "nums"); + + // access with STL-like manner + if(not data.contains("foo")) + { + data["foo"] = "bar"; + } + + // pass a fallback + std::string name = toml::find_or<std::string>(data, "name", "not found"); + + // width-dependent formatting + std::cout << std::setw(80) << data << std::endl; + + return 0; +} +``` + +## Table of Contents + +- [Integration](#integration) +- [Decoding a toml file](#decoding-a-toml-file) + - [In the case of syntax error](#in-the-case-of-syntax-error) + - [Invalid UTF-8 Codepoints](#invalid-utf-8-codepoints) +- [Finding a toml value](#finding-a-toml-value) + - [Finding a value in a table](#finding-a-value-in-a-table) + - [In case of error](#in-case-of-error) + - [Dotted keys](#dotted-keys) +- [Casting a toml value](#casting-a-toml-value) +- [Checking value type](#checking-value-type) +- [More about conversion](#more-about-conversion) + - [Converting an array](#converting-an-array) + - [Converting a table](#converting-a-table) + - [Getting an array of tables](#getting-an-array-of-tables) + - [Cost of conversion](#cost-of-conversion) + - [Converting datetime and its variants](#converting-datetime-and-its-variants) +- [Getting with a fallback](#getting-with-a-fallback) +- [Expecting conversion](#expecting-conversion) +- [Visiting a toml::value](#visiting-a-tomlvalue) +- [Constructing a toml::value](#constructing-a-tomlvalue) +- [Preserving Comments](#preserving-comments) +- [Customizing containers](#customizing-containers) +- [TOML literal](#toml-literal) +- [Conversion between toml value and arbitrary types](#conversion-between-toml-value-and-arbitrary-types) +- [Formatting user-defined error messages](#formatting-user-defined-error-messages) +- [Obtaining location information](#obtaining-location-information) +- [Exceptions](#exceptions) +- [Colorize Error Messages](#colorize-error-messages) +- [Serializing TOML data](#serializing-toml-data) +- [Underlying types](#underlying-types) +- [Unreleased TOML features](#unreleased-toml-features) +- [Breaking Changes from v2](#breaking-changes-from-v2) +- [Running Tests](#running-tests) +- [Contributors](#contributors) +- [Licensing Terms](#licensing-terms) + +## Integration + +Just include the file after adding it to the include path. + +```cpp +#include <toml.hpp> // that's all! now you can use it. +#include <iostream> + +int main() +{ + const auto data = toml::parse("example.toml"); + const auto title = toml::find<std::string>(data, "title"); + std::cout << "the title is " << title << std::endl; + return 0; +} +``` + +The convenient way is to add this repository as a git-submodule or to install +it in your system by CMake. + +Note for MSVC: We recommend to set `/Zc:__cplusplus` to detect C++ version correctly. + +## Decoding a toml file + +To parse a toml file, the only thing you have to do is +to pass a filename to the `toml::parse` function. + +```cpp +const std::string fname("sample.toml"); +const toml::value data = toml::parse(fname); +``` + +As required by the TOML specification, the top-level value is always a table. +You can find a value inside it, cast it into a table explicitly, and insert it as a value into other `toml::value`. + +If it encounters an error while opening a file, it will throw `std::runtime_error`. + +You can also pass a `std::istream` to the `toml::parse` function. +To show a filename in an error message, however, it is recommended to pass the +filename with the stream. + +```cpp +std::ifstream ifs("sample.toml", std::ios_base::binary); +assert(ifs.good()); +const auto data = toml::parse(ifs, /*optional -> */ "sample.toml"); +``` + +**Note**: When you are **on Windows, open a file in binary mode**. +If a file is opened in text-mode, CRLF ("\r\n") will automatically be +converted to LF ("\n") and this causes inconsistency between file size +and the contents that would be read. This causes weird error. + +### In the case of syntax error + +If there is a syntax error in a toml file, `toml::parse` will throw +`toml::syntax_error` that inherits `std::exception`. + +toml11 has clean and informative error messages inspired by Rust and +it looks like the following. + +```console +terminate called after throwing an instance of 'toml::syntax_error' + what(): [error] toml::parse_table: invalid line format # error description + --> example.toml # file name + 3 | a = 42 = true # line num and content + | ^------ expected newline, but got '='. # error reason +``` + +If you (mistakenly) duplicate tables and got an error, it is helpful to see +where they are. toml11 shows both at the same time like the following. + +```console +terminate called after throwing an instance of 'toml::syntax_error' + what(): [error] toml::insert_value: table ("table") already exists. + --> duplicate-table.toml + 1 | [table] + | ~~~~~~~ table already exists here + ... + 3 | [table] + | ~~~~~~~ table defined twice +``` + +When toml11 encounters a malformed value, it tries to detect what type it is. +Then it shows hints to fix the format. An error message while reading one of +the malformed files in [the language agnostic test suite](https://github.com/BurntSushi/toml-test). +is shown below. + +```console +what(): [error] bad time: should be HH:MM:SS.subsec + --> ./datetime-malformed-no-secs.toml + 1 | no-secs = 1987-07-05T17:45Z + | ^------- HH:MM:SS.subsec + | +Hint: pass: 1979-05-27T07:32:00, 1979-05-27 07:32:00.999999 +Hint: fail: 1979-05-27T7:32:00, 1979-05-27 17:32 +``` + +You can find other examples in a job named `output_result` on +[CircleCI](https://circleci.com/gh/ToruNiina/toml11). + +Since the error message generation is generally a difficult task, the current +status is not ideal. If you encounter a weird error message, please let us know +and contribute to improve the quality! + +### Invalid UTF-8 codepoints + +It throws `syntax_error` if a value of an escape sequence +representing unicode character is not a valid UTF-8 codepoint. + +```console + what(): [error] toml::read_utf8_codepoint: input codepoint is too large. + --> utf8.toml + 1 | exceeds_unicode = "\U0011FFFF example" + | ^--------- should be in [0x00..0x10FFFF] +``` + +## Finding a toml value + +After parsing successfully, you can obtain the values from the result of +`toml::parse` using `toml::find` function. + +```toml +# sample.toml +answer = 42 +pi = 3.14 +numbers = [1,2,3] +time = 1979-05-27T07:32:00Z +``` + +``` cpp +const auto data = toml::parse("sample.toml"); +const auto answer = toml::find<std::int64_t >(data, "answer"); +const auto pi = toml::find<double >(data, "pi"); +const auto numbers = toml::find<std::vector<int>>(data, "numbers"); +const auto timepoint = toml::find<std::chrono::system_clock::time_point>(data, "time"); +``` + +By default, `toml::find` returns a `toml::value`. + +```cpp +const toml::value& answer = toml::find(data, "answer"); +``` + +When you pass an exact TOML type that does not require type conversion, +`toml::find` returns a reference without copying the value. + +```cpp +const auto data = toml::parse("sample.toml"); +const auto& answer = toml::find<toml::integer>(data, "answer"); +``` + +If the specified type requires conversion, you can't take a reference to the value. +See also [underlying types](#underlying-types). + +**NOTE**: For some technical reason, automatic conversion between `integer` and +`floating` is not supported. If you want to get a floating value even if a value +has integer value, you need to convert it manually after obtaining a value, +like the followings. + +```cpp +const auto vx = toml::find(data, "x"); +double x = vx.is_floating() ? vx.as_floating(std::nothrow) : + static_cast<double>(vx.as_integer()); // it throws if vx is neither + // floating nor integer. +``` + +### Finding a value in a table + +There are several way to get a value defined in a table. +First, you can get a table as a normal value and find a value from the table. + +```toml +[fruit] +name = "apple" +[fruit.physical] +color = "red" +shape = "round" +``` + +``` cpp +const auto data = toml::parse("fruit.toml"); +const auto& fruit = toml::find(data, "fruit"); +const auto name = toml::find<std::string>(fruit, "name"); + +const auto& physical = toml::find(fruit, "physical"); +const auto color = toml::find<std::string>(physical, "color"); +const auto shape = toml::find<std::string>(physical, "shape"); +``` + +Here, variable `fruit` is a `toml::value` and can be used as the first argument +of `toml::find`. + +Second, you can pass as many arguments as the number of subtables to `toml::find`. + +```cpp +const auto data = toml::parse("fruit.toml"); +const auto color = toml::find<std::string>(data, "fruit", "physical", "color"); +const auto shape = toml::find<std::string>(data, "fruit", "physical", "shape"); +``` + +### Finding a value in an array + +You can find n-th value in an array by `toml::find`. + +```toml +values = ["foo", "bar", "baz"] +``` + +``` cpp +const auto data = toml::parse("sample.toml"); +const auto values = toml::find(data, "values"); +const auto bar = toml::find<std::string>(values, 1); +``` + +`toml::find` can also search array recursively. + +```cpp +const auto data = toml::parse("fruit.toml"); +const auto bar = toml::find<std::string>(data, "values", 1); +``` + +Before calling `toml::find`, you can check if a value corresponding to a key +exists. You can use both `bool toml::value::contains(const key&) const` and +`std::size_t toml::value::count(const key&) const`. Those behaves like the +`std::map::contains` and `std::map::count`. + +```cpp +const auto data = toml::parse("fruit.toml"); +if(data.contains("fruit") && data.at("fruit").count("physical") != 0) +{ + // ... +} +``` + +### In case of error + +If the value does not exist, `toml::find` throws `std::out_of_range` with the +location of the table. + +```console +terminate called after throwing an instance of 'std::out_of_range' + what(): [error] key "answer" not found + --> example.toml + 6 | [tab] + | ~~~~~ in this table +``` + +---- + +If the specified type differs from the actual value contained, it throws +`toml::type_error` that inherits `std::exception`. + +Similar to the case of syntax error, toml11 also displays clean error messages. +The error message when you choose `int` to get `string` value would be like this. + +```console +terminate called after throwing an instance of 'toml::type_error' + what(): [error] toml::value bad_cast to integer + --> example.toml + 3 | title = "TOML Example" + | ~~~~~~~~~~~~~~ the actual type is string +``` + +**NOTE**: In order to show this kind of error message, all the toml values have +a pointer to represent its range in a file. The entire contents of a file is +shared by `toml::value`s and remains on the heap memory. It is recommended to +destruct all the `toml::value` classes after configuring your application +if you have a large TOML file compared to the memory resource. + +### Dotted keys + +TOML v0.5.0 has a new feature named "dotted keys". +You can chain keys to represent the structure of the data. + +```toml +physical.color = "orange" +physical.shape = "round" +``` + +This is equivalent to the following. + +```toml +[physical] +color = "orange" +shape = "round" +``` + +You can get both of the above tables with the same c++ code. + +```cpp +const auto physical = toml::find(data, "physical"); +const auto color = toml::find<std::string>(physical, "color"); +``` + +The following code does not work for the above toml file. + +```cpp +// XXX this does not work! +const auto color = toml::find<std::string>(data, "physical.color"); +``` + +The above code works with the following toml file. + +```toml +"physical.color" = "orange" +# equivalent to {"physical.color": "orange"}, +# NOT {"physical": {"color": "orange"}}. +``` + + +## Casting a toml value + +### `toml::get` + +`toml::parse` returns `toml::value`. `toml::value` is a union type that can +contain one of the following types. + +- `toml::boolean` (`bool`) +- `toml::integer` (`std::int64_t`) +- `toml::floating` (`double`) +- `toml::string` (a type convertible to std::string) +- `toml::local_date` +- `toml::local_time` +- `toml::local_datetime` +- `toml::offset_datetime` +- `toml::array` (by default, `std::vector<toml::value>`) + - It depends. See [customizing containers](#customizing-containers) for detail. +- `toml::table` (by default, `std::unordered_map<toml::key, toml::value>`) + - It depends. See [customizing containers](#customizing-containers) for detail. + +To get a value inside, you can use `toml::get<T>()`. The usage is the same as +`toml::find<T>` (actually, `toml::find` internally uses `toml::get` after casting +a value to `toml::table`). + +``` cpp +const toml::value data = toml::parse("sample.toml"); +const toml::value answer_ = toml::get<toml::table >(data).at("answer"); +const std::int64_t answer = toml::get<std::int64_t>(answer_); +``` + +When you pass an exact TOML type that does not require type conversion, +`toml::get` returns a reference through which you can modify the content +(if the `toml::value` is `const`, it returns `const` reference). + +```cpp +toml::value data = toml::parse("sample.toml"); +toml::value answer_ = toml::get<toml::table >(data).at("answer"); +toml::integer& answer = toml::get<toml::integer>(answer_); +answer = 6 * 9; // write to data.answer. now `answer_` contains 54. +``` + +If the specified type requires conversion, you can't take a reference to the value. +See also [underlying types](#underlying-types). + +It also throws a `toml::type_error` if the type differs. + +### `as_xxx` + +You can also use a member function to cast a value. + +```cpp +const std::int64_t answer = data.as_table().at("answer").as_integer(); +``` + +It also throws a `toml::type_error` if the type differs. If you are sure that +the value `v` contains a value of the specified type, you can suppress checking +by passing `std::nothrow`. + +```cpp +const auto& answer = data.as_table().at("answer"); +if(answer.is_integer() && answer.as_integer(std::nothrow) == 42) +{ + std::cout << "value is 42" << std::endl; +} +``` + +If `std::nothrow` is passed, the functions are marked as noexcept. + +By casting a `toml::value` into an array or a table, you can iterate over the +elements. + +```cpp +const auto data = toml::parse("example.toml"); +std::cout << "keys in the top-level table are the following: \n"; +for(const auto& [k, v] : data.as_table()) +{ + std::cout << k << '\n'; +} + +const auto& fruits = toml::find(data, "fruits"); +for(const auto& v : fruits.as_array()) +{ + std::cout << toml::find<std::string>(v, "name") << '\n'; +} +``` + +The full list of the functions is below. + +```cpp +namespace toml { +class value { + // ... + const boolean& as_boolean() const&; + const integer& as_integer() const&; + const floating& as_floating() const&; + const string& as_string() const&; + const offset_datetime& as_offset_datetime() const&; + const local_datetime& as_local_datetime() const&; + const local_date& as_local_date() const&; + const local_time& as_local_time() const&; + const array& as_array() const&; + const table& as_table() const&; + // -------------------------------------------------------- + // non-const version + boolean& as_boolean() &; + // ditto... + // -------------------------------------------------------- + // rvalue version + boolean&& as_boolean() &&; + // ditto... + + // -------------------------------------------------------- + // noexcept versions ... + const boolean& as_boolean(const std::nothrow_t&) const& noexcept; + boolean& as_boolean(const std::nothrow_t&) & noexcept; + boolean&& as_boolean(const std::nothrow_t&) && noexcept; + // ditto... +}; +} // toml +``` + +### `at()` + +You can access to the element of a table and an array by `toml::basic_value::at`. + +```cpp +const toml::value v{1,2,3,4,5}; +std::cout << v.at(2).as_integer() << std::endl; // 3 + +const toml::value v{{"foo", 42}, {"bar", 3.14}}; +std::cout << v.at("foo").as_integer() << std::endl; // 42 +``` + +If an invalid key (integer for a table, string for an array), it throws +`toml::type_error` for the conversion. If the provided key is out-of-range, +it throws `std::out_of_range`. + +Note that, although `std::string` has `at()` member function, `toml::value::at` +throws if the contained type is a string. Because `std::string` does not +contain `toml::value`. + +### `operator[]` + +You can also access to the element of a table and an array by +`toml::basic_value::operator[]`. + +```cpp +const toml::value v{1,2,3,4,5}; +std::cout << v[2].as_integer() << std::endl; // 3 + +const toml::value v{{"foo", 42}, {"bar", 3.14}}; +std::cout << v["foo"].as_integer() << std::endl; // 42 +``` + +When you access to a `toml::value` that is not initialized yet via +`operator[](const std::string&)`, the `toml::value` will be a table, +just like the `std::map`. + +```cpp +toml::value v; // not initialized as a table. +v["foo"] = 42; // OK. `v` will be a table. +``` + +Contrary, if you access to a `toml::value` that contains an array via `operator[]`, +it does not check anything. It converts `toml::value` without type check and then +access to the n-th element without boundary check, just like the `std::vector::operator[]`. + +```cpp +toml::value v; // not initialized as an array +v[2] = 42; // error! UB +``` + +Please make sure that the `toml::value` has an array inside when you access to +its element via `operator[]`. + +## Checking value type + +You can check the type of a value by `is_xxx` function. + +```cpp +const toml::value v = /* ... */; +if(v.is_integer()) +{ + std::cout << "value is an integer" << std::endl; +} +``` + +The complete list of the functions is below. + +```cpp +namespace toml { +class value { + // ... + bool is_boolean() const noexcept; + bool is_integer() const noexcept; + bool is_floating() const noexcept; + bool is_string() const noexcept; + bool is_offset_datetime() const noexcept; + bool is_local_datetime() const noexcept; + bool is_local_date() const noexcept; + bool is_local_time() const noexcept; + bool is_array() const noexcept; + bool is_table() const noexcept; + bool is_uninitialized() const noexcept; + // ... +}; +} // toml +``` + +Also, you can get `enum class value_t` from `toml::value::type()`. + +```cpp +switch(data.at("something").type()) +{ + case toml::value_t::integer: /*do some stuff*/ ; break; + case toml::value_t::floating: /*do some stuff*/ ; break; + case toml::value_t::string : /*do some stuff*/ ; break; + default : throw std::runtime_error( + "unexpected type : " + toml::stringize(data.at("something").type())); +} +``` + +The complete list of the `enum`s can be found in the section +[underlying types](#underlying-types). + +The `enum`s can be used as a parameter of `toml::value::is` function like the following. + +```cpp +toml::value v = /* ... */; +if(v.is(toml::value_t::boolean)) // ... +``` + +## More about conversion + +Since `toml::find` internally uses `toml::get`, all the following examples work +with both `toml::get` and `toml::find`. + +### Converting an array + +You can get any kind of `container` class from a `toml::array` +except for `map`-like classes. + +``` cpp +// # sample.toml +// numbers = [1,2,3] + +const auto numbers = toml::find(data, "numbers"); + +const auto vc = toml::get<std::vector<int> >(numbers); +const auto ls = toml::get<std::list<int> >(numbers); +const auto dq = toml::get<std::deque<int> >(numbers); +const auto ar = toml::get<std::array<int, 3>>(numbers); +// if the size of data.at("numbers") is larger than that of std::array, +// it will throw toml::type_error because std::array is not resizable. +``` + +Surprisingly, you can convert `toml::array` into `std::pair` and `std::tuple`. + +```cpp +// numbers = [1,2,3] +const auto tp = toml::get<std::tuple<short, int, unsigned int>>(numbers); +``` + +This functionality is helpful when you have a toml file like the following. + +```toml +array_of_arrays = [[1, 2, 3], ["foo", "bar", "baz"]] # toml allows this +``` + +What is the corresponding C++ type? +Obviously, it is a `std::pair` of `std::vector`s. + +```cpp +const auto array_of_arrays = toml::find(data, "array_of_arrays"); +const auto aofa = toml::get< + std::pair<std::vector<int>, std::vector<std::string>> + >(array_of_arrays); +``` + +If you don't know the type of the elements, you can use `toml::array`, +which is a `std::vector` of `toml::value`, instead. + +```cpp +const auto a_of_a = toml::get<toml::array>(array_of_arrays); +const auto first = toml::get<std::vector<int>>(a_of_a.at(0)); +``` + +You can change the implementation of `toml::array` with `std::deque` or some +other array-like container. See [Customizing containers](#customizing-containers) +for detail. + +### Converting a table + +When all the values of the table have the same type, toml11 allows you to +convert a `toml::table` to a `map` that contains the convertible type. + +```toml +[tab] +key1 = "foo" # all the values are +key2 = "bar" # toml String +``` + +```cpp +const auto data = toml::parse("sample.toml"); +const auto tab = toml::find<std::map<std::string, std::string>>(data, "tab"); +std::cout << tab["key1"] << std::endl; // foo +std::cout << tab["key2"] << std::endl; // bar +``` + +But since `toml::table` is just an alias of `std::unordered_map<toml::key, toml::value>`, +normally you don't need to convert it because it has all the functionalities that +`std::unordered_map` has (e.g. `operator[]`, `count`, and `find`). In most cases +`toml::table` is sufficient. + +```cpp +toml::table tab = toml::get<toml::table>(data); +if(data.count("title") != 0) +{ + data["title"] = std::string("TOML example"); +} +``` + +You can change the implementation of `toml::table` with `std::map` or some +other map-like container. See [Customizing containers](#customizing-containers) +for detail. + +### Getting an array of tables + +An array of tables is just an array of tables. +You can get it in completely the same way as the other arrays and tables. + +```toml +# sample.toml +array_of_inline_tables = [{key = "value1"}, {key = "value2"}, {key = "value3"}] + +[[array_of_tables]] +key = "value4" +[[array_of_tables]] +key = "value5" +[[array_of_tables]] +key = "value6" +``` + +```cpp +const auto data = toml::parse("sample.toml" |
