mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-12-16 03:08:52 +08:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a344668fa2 | ||
|
|
25aa97a435 | ||
|
|
af70d3dfed | ||
|
|
8b5cfb4105 | ||
|
|
4e0624aa60 | ||
|
|
3ac2c065eb | ||
|
|
470f81dc94 | ||
|
|
93a9f2711c | ||
|
|
761e576991 | ||
|
|
e6e84714c5 | ||
|
|
1efc99e11c | ||
|
|
92aa42a58e | ||
|
|
b1c9df8998 | ||
|
|
9633e5fe5a | ||
|
|
2164fd39f7 | ||
|
|
c22a3fd227 | ||
|
|
57c6652360 | ||
|
|
defde33544 | ||
|
|
46ed051740 | ||
|
|
2963d9a25b | ||
|
|
531f335417 | ||
|
|
f29f42277e | ||
|
|
b03cde566a | ||
|
|
57d4e196a3 | ||
|
|
deb3ab6617 | ||
|
|
bf992e8f94 | ||
|
|
7c07f4382c | ||
|
|
125f608fa5 | ||
|
|
4d0ed847f9 | ||
|
|
79594709fe | ||
|
|
55a738c11f | ||
|
|
eebe1f87e6 | ||
|
|
95c3b5f538 | ||
|
|
e2790c9e7b | ||
|
|
9b52dc0131 | ||
|
|
5212992f05 | ||
|
|
fcd6e47500 |
@@ -12,7 +12,7 @@ jobs:
|
||||
command: |
|
||||
g++ --version
|
||||
cd tests/
|
||||
g++ -std=c++11 -O2 -Wall -Wextra -Werror -DTOML11_COLORIZE_ERROR_MESSAGE -I../ check_toml_test.cpp -o check_toml_test
|
||||
g++ -std=c++11 -O2 -Wall -Wextra -Werror -DTOML11_DISALLOW_HETEROGENEOUS_ARRAYS -I../ check_toml_test.cpp -o check_toml_test
|
||||
go get github.com/BurntSushi/toml-test
|
||||
$GOPATH/bin/toml-test ./check_toml_test
|
||||
test_serialization:
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
command: |
|
||||
g++ --version
|
||||
cd tests/
|
||||
g++ -std=c++11 -O2 -Wall -Wextra -Wpedantic -Werror -DTOML11_COLORIZE_ERROR_MESSAGE -I../ check_serialization.cpp -o check_serialization
|
||||
g++ -std=c++11 -O2 -Wall -Wextra -Wpedantic -Werror -DTOML11_DISALLOW_HETEROGENEOUS_ARRAYS -I../ check_serialization.cpp -o check_serialization
|
||||
git clone https://github.com/BurntSushi/toml-test.git
|
||||
cp check_serialization toml-test/tests/valid
|
||||
cd toml-test/tests/valid
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
command: |
|
||||
g++ --version
|
||||
cd tests/
|
||||
g++ -std=c++11 -O2 -Wall -Wextra -Wpedantic -Werror -DTOML11_COLORIZE_ERROR_MESSAGE -I../ check.cpp -o check
|
||||
g++ -std=c++11 -O2 -Wall -Wextra -Wpedantic -Werror -DTOML11_DISALLOW_HETEROGENEOUS_ARRAYS -I../ check.cpp -o check
|
||||
git clone https://github.com/BurntSushi/toml-test.git
|
||||
cp check toml-test/tests/invalid
|
||||
cp check toml-test/tests/valid
|
||||
|
||||
105
.github/workflows/main.yml
vendored
Normal file
105
.github/workflows/main.yml
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
name: build
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build-linux-gcc:
|
||||
runs-on: Ubuntu-18.04
|
||||
strategy:
|
||||
matrix:
|
||||
# g++-4.8 and 4.9 are tested on Travis.CI.
|
||||
compiler: ['g++-9', 'g++-8', 'g++-7', 'g++-6', 'g++-5']
|
||||
standard: ['11', '14', '17']
|
||||
exclude:
|
||||
- {compiler: 'g++-5', standard: '17'}
|
||||
- {compiler: 'g++-6', standard: '17'}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Install
|
||||
run: |
|
||||
sudo apt-add-repository ppa:mhier/libboost-latest
|
||||
sudo apt-get update
|
||||
sudo apt-get install boost1.70
|
||||
if [[ "${{ matrix.compiler }}" == "g++-6" || "${{ matrix.compiler }}" == "g++-5" ]] ; then
|
||||
sudo apt-add-repository ppa:ubuntu-toolchain-r/test
|
||||
sudo apt-get update
|
||||
sudo apt-get install ${{ matrix.compiler }}
|
||||
fi
|
||||
- name: Configure
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake .. -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} -DCMAKE_CXX_STANDARD=${{ matrix.standard }}
|
||||
- name: Build
|
||||
run: |
|
||||
cd build && cmake --build .
|
||||
- name: Test
|
||||
run: |
|
||||
cd build && ctest --output-on-failure
|
||||
build-linux-clang:
|
||||
runs-on: Ubuntu-18.04
|
||||
strategy:
|
||||
matrix:
|
||||
compiler: ['10', '9', '8', '7', '6.0', '5.0', '4.0', '3.9']
|
||||
standard: ['11', '14', '17']
|
||||
exclude:
|
||||
- {compiler: '3.9', standard: '17'}
|
||||
- {compiler: '4.0', standard: '17'}
|
||||
- {compiler: '5.0', standard: '17'}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Install
|
||||
run: |
|
||||
sudo apt-add-repository ppa:mhier/libboost-latest
|
||||
sudo apt-get update
|
||||
sudo apt-get install boost1.70
|
||||
if [[ "${{ matrix.compiler }}" != "6" && "${{ matrix.compiler }}" != "8" && "${{ matrix.compiler }}" != "9" ]] ; then
|
||||
sudo apt-add-repository ppa:ubuntu-toolchain-r/test
|
||||
sudo apt-get update
|
||||
sudo apt-get install clang-${{ matrix.compiler }}
|
||||
fi
|
||||
- name: Configure
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake .. -DCMAKE_CXX_COMPILER=clang++-${{ matrix.compiler }} -DCMAKE_CXX_STANDARD=${{ matrix.standard }}
|
||||
- name: Build
|
||||
run: |
|
||||
cd build && cmake --build .
|
||||
- name: Test
|
||||
run: |
|
||||
cd build && ctest --output-on-failure
|
||||
build-windows-msvc:
|
||||
runs-on: windows-2019
|
||||
strategy:
|
||||
matrix:
|
||||
standard: ['11', '14', '17']
|
||||
config: ['Release', 'Debug']
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
- name: Configure
|
||||
shell: cmd
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ../ -G "NMake Makefiles" -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DBoost_ADDITIONAL_VERSIONS=1.72.0 -DBoost_USE_MULTITHREADED=ON -DBoost_ARCHITECTURE=-x64 -DBoost_NO_BOOST_CMAKE=ON -DBOOST_ROOT=%BOOST_ROOT_1_72_0%
|
||||
- name: Build
|
||||
working-directory: ./build
|
||||
run: |
|
||||
cmake --build . --config "${{ matrix.config }}"
|
||||
- name: Test
|
||||
working-directory: ./build
|
||||
run: |
|
||||
file --mime-encoding tests/toml/tests/example.toml
|
||||
file --mime-encoding tests/toml/tests/fruit.toml
|
||||
file --mime-encoding tests/toml/tests/hard_example.toml
|
||||
file --mime-encoding tests/toml/tests/hard_example_unicode.toml
|
||||
ctest --build-config "${{ matrix.config }}" --output-on-failure
|
||||
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
enable_testing()
|
||||
|
||||
project(toml11 VERSION 3.3.1)
|
||||
project(toml11 VERSION 3.5.0)
|
||||
|
||||
option(toml11_BUILD_TEST "Build toml tests" ON)
|
||||
option(toml11_TEST_WITH_ASAN "use LLVM address sanitizer" OFF)
|
||||
|
||||
66
README.md
66
README.md
@@ -1,6 +1,7 @@
|
||||
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)
|
||||
@@ -10,8 +11,7 @@ toml11
|
||||
|
||||
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 v0.5.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md).
|
||||
- It optionally supports the [unreleased features](#unreleased-toml-features) in the master branch of toml-lang/toml.
|
||||
- It is compatible to the latest version of [TOML v1.0.0-rc.1](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v1.0.0-rc.1.md).
|
||||
- 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.
|
||||
@@ -120,6 +120,9 @@ 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.
|
||||
@@ -267,11 +270,11 @@ 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, "apple");
|
||||
const auto name = toml::find<std::string>(fruit, "name");
|
||||
|
||||
const auto& physical = toml::find(fruit, "physical");
|
||||
const auto color = toml::find<std::string>(fruit, "color");
|
||||
const auto shape = toml::find<std::string>(fruit, "shape");
|
||||
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
|
||||
@@ -463,6 +466,24 @@ if(answer.is_integer() && answer.as_integer(std::nothrow) == 42)
|
||||
|
||||
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
|
||||
@@ -1652,13 +1673,8 @@ not capable of representing a Local Time independent from a specific day.
|
||||
|
||||
## Unreleased TOML features
|
||||
|
||||
There are some unreleased features in toml-lang/toml:master.
|
||||
Currently, the following features are available after defining
|
||||
`TOML11_USE_UNRELEASED_TOML_FEATURES` macro flag.
|
||||
|
||||
To use those features, `#define` `TOML11_USE_UNRELEASED_TOML_FEATURES` before
|
||||
including `toml.hpp` or pass `-DTOML11_USE_UNRELEASED_TOML_FEATURES` to your
|
||||
compiler.
|
||||
Since TOML v1.0.0-rc.1 has been released, those features are now activated by
|
||||
default. We no longer need to define `TOML11_USE_UNRELEASED_FEATURES`.
|
||||
|
||||
- Leading zeroes in exponent parts of floats are permitted.
|
||||
- e.g. `1.0e+01`, `5e+05`
|
||||
@@ -1668,10 +1684,10 @@ compiler.
|
||||
- Allow heterogeneous arrays
|
||||
- [toml-lang/toml/PR/676](https://github.com/toml-lang/toml/pull/676)
|
||||
|
||||
### Note about heterogeneous arrays
|
||||
## Note about heterogeneous arrays
|
||||
|
||||
Although `toml::parse` allows heterogeneous arrays, constructor of `toml::value`
|
||||
does not.
|
||||
does not. Here the reason is explained.
|
||||
|
||||
```cpp
|
||||
// this won't be compiled
|
||||
@@ -1680,8 +1696,10 @@ toml::value v{
|
||||
}
|
||||
```
|
||||
|
||||
There is a workaround for this issue. By explicitly converting values into
|
||||
There is a workaround for this. By explicitly converting values into
|
||||
`toml::value`, you can initialize `toml::value` with a heterogeneous array.
|
||||
Also, you can first initialize a `toml::value` with an array and then
|
||||
`push_back` into it.
|
||||
|
||||
```cpp
|
||||
// OK!
|
||||
@@ -1689,6 +1707,17 @@ toml::value v{
|
||||
toml::value("foo"), toml::value(3.14), toml::value(42),
|
||||
toml::value{1,2,3,4,5}, toml::value{{"key", "value"}}
|
||||
}
|
||||
|
||||
// OK!
|
||||
toml::value v(toml::array{});
|
||||
v.push_back("foo");
|
||||
v.push_back(3.14);
|
||||
|
||||
// OK!
|
||||
toml::array a;
|
||||
a.push_back("foo");
|
||||
a.push_back(3.14);
|
||||
toml::value v(std::move(a));
|
||||
```
|
||||
|
||||
The reason why the first example is not allowed is the following.
|
||||
@@ -1717,15 +1746,14 @@ This means that the above C++ code makes constructor's overload resolution
|
||||
ambiguous. So a constructor that allows both "table as an initializer-list" and
|
||||
"heterogeneous array as an initializer-list" cannot be implemented.
|
||||
|
||||
Thus, although it is painful, you need to explicitly cast values into
|
||||
`toml::value` when you initialize heterogeneous array in C++ code.
|
||||
Thus, although it is painful, we need to explicitly cast values into
|
||||
`toml::value` when you initialize heterogeneous array in a C++ code.
|
||||
|
||||
```cpp
|
||||
// You need to do this when you want to initialize hetero array.
|
||||
toml::value v{
|
||||
toml::value("foo"), toml::value(3.14), toml::value(42),
|
||||
toml::value{1,2,3,4,5}, toml::value{{"key", "value"}}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Breaking Changes from v2
|
||||
|
||||
@@ -183,3 +183,9 @@ add_executable(test_multiple_translation_unit
|
||||
test_multiple_translation_unit_1.cpp
|
||||
test_multiple_translation_unit_2.cpp)
|
||||
target_link_libraries(test_multiple_translation_unit toml11::toml11)
|
||||
|
||||
if(WIN32)
|
||||
add_executable(test_windows test_windows.cpp)
|
||||
target_link_libraries(test_windows toml11::toml11)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -80,13 +80,13 @@ BOOST_AUTO_TEST_CASE(test_detect_conflicting_value)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_detect_inhomogeneous_array)
|
||||
{
|
||||
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||
BOOST_TEST_MESSAGE("heterogeneous array will be allowed in the next release");
|
||||
#else
|
||||
#ifdef TOML11_DISALLOW_HETEROGENEOUS_ARRAYS
|
||||
std::istringstream stream(std::string(
|
||||
"a = [1, 1.0]\n"
|
||||
));
|
||||
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
|
||||
#else
|
||||
BOOST_TEST_MESSAGE("After v1.0.0-rc.1, heterogeneous arrays are allowed");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -47,8 +47,6 @@ struct qux
|
||||
|
||||
struct foobar
|
||||
{
|
||||
foobar() = default; // later we use std::vector<foobar>, default ctor is required.
|
||||
|
||||
// via constructor
|
||||
explicit foobar(const toml::value& v)
|
||||
: a(toml::find<int>(v, "a")), b(toml::find<std::string>(v, "b"))
|
||||
@@ -137,8 +135,6 @@ struct qux
|
||||
|
||||
struct foobar
|
||||
{
|
||||
foobar() = default; // later we use std::vector<foobar>, default ctor is required.
|
||||
|
||||
template<typename C, template<typename ...> class M, template<typename ...> class A>
|
||||
explicit foobar(const toml::basic_value<C, M, A>& v)
|
||||
: a(toml::find<int>(v, "a")), b(toml::find<std::string>(v, "b"))
|
||||
@@ -488,5 +484,64 @@ BOOST_AUTO_TEST_CASE(test_recursive_conversion)
|
||||
BOOST_TEST(foobars.at(2).b == "quux");
|
||||
BOOST_TEST(foobars.at(3).b == "foobar");
|
||||
}
|
||||
|
||||
// via constructor
|
||||
{
|
||||
const toml::value v{
|
||||
{"0", toml::table{{"a", 42}, {"b", "baz"}}},
|
||||
{"1", toml::table{{"a", 43}, {"b", "qux"}}},
|
||||
{"2", toml::table{{"a", 44}, {"b", "quux"}}},
|
||||
{"3", toml::table{{"a", 45}, {"b", "foobar"}}}
|
||||
};
|
||||
|
||||
{
|
||||
const auto foobars = toml::get<std::map<std::string, extlib::foobar>>(v);
|
||||
BOOST_TEST(foobars.size() == 4ul);
|
||||
BOOST_TEST(foobars.at("0").a == 42);
|
||||
BOOST_TEST(foobars.at("1").a == 43);
|
||||
BOOST_TEST(foobars.at("2").a == 44);
|
||||
BOOST_TEST(foobars.at("3").a == 45);
|
||||
|
||||
BOOST_TEST(foobars.at("0").b == "baz");
|
||||
BOOST_TEST(foobars.at("1").b == "qux");
|
||||
BOOST_TEST(foobars.at("2").b == "quux");
|
||||
BOOST_TEST(foobars.at("3").b == "foobar");
|
||||
}
|
||||
{
|
||||
const auto foobars = toml::get<std::map<std::string, extlib2::foobar>>(v);
|
||||
BOOST_TEST(foobars.size() == 4ul);
|
||||
BOOST_TEST(foobars.at("0").a == 42);
|
||||
BOOST_TEST(foobars.at("1").a == 43);
|
||||
BOOST_TEST(foobars.at("2").a == 44);
|
||||
BOOST_TEST(foobars.at("3").a == 45);
|
||||
|
||||
BOOST_TEST(foobars.at("0").b == "baz");
|
||||
BOOST_TEST(foobars.at("1").b == "qux");
|
||||
BOOST_TEST(foobars.at("2").b == "quux");
|
||||
BOOST_TEST(foobars.at("3").b == "foobar");
|
||||
}
|
||||
}
|
||||
{
|
||||
const toml::basic_value<toml::discard_comments, std::map, std::deque>
|
||||
v{
|
||||
{"0", toml::table{{"a", 42}, {"b", "baz"}}},
|
||||
{"1", toml::table{{"a", 43}, {"b", "qux"}}},
|
||||
{"2", toml::table{{"a", 44}, {"b", "quux"}}},
|
||||
{"3", toml::table{{"a", 45}, {"b", "foobar"}}}
|
||||
};
|
||||
|
||||
const auto foobars = toml::get<std::map<std::string, extlib::foobar>>(v);
|
||||
BOOST_TEST(foobars.size() == 4ul);
|
||||
BOOST_TEST(foobars.at("0").a == 42);
|
||||
BOOST_TEST(foobars.at("1").a == 43);
|
||||
BOOST_TEST(foobars.at("2").a == 44);
|
||||
BOOST_TEST(foobars.at("3").a == 45);
|
||||
|
||||
BOOST_TEST(foobars.at("0").b == "baz");
|
||||
BOOST_TEST(foobars.at("1").b == "qux");
|
||||
BOOST_TEST(foobars.at("2").b == "quux");
|
||||
BOOST_TEST(foobars.at("3").b == "foobar");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ BOOST_AUTO_TEST_CASE(test_example)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_example_stream)
|
||||
{
|
||||
std::ifstream ifs("toml/tests/example.toml");
|
||||
std::ifstream ifs("toml/tests/example.toml", std::ios::binary);
|
||||
const auto data = toml::parse(ifs);
|
||||
|
||||
BOOST_TEST(toml::find<std::string>(data, "title") == "TOML Example");
|
||||
|
||||
@@ -9,27 +9,24 @@
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_resize)
|
||||
BOOST_AUTO_TEST_CASE(test_try_reserve)
|
||||
{
|
||||
{
|
||||
typedef std::vector<int> resizable_type;
|
||||
typedef std::array<int,1> non_resizable_type;
|
||||
BOOST_TEST(toml::detail::has_resize_method<resizable_type>::value);
|
||||
BOOST_TEST(!toml::detail::has_resize_method<non_resizable_type>::value);
|
||||
// since BOOST_TEST is a macro, it cannot handle commas correctly.
|
||||
// When toml::detail::has_reserve_method<std::array<int, 1>>::value
|
||||
// is passed to a macro, C preprocessor considers
|
||||
// toml::detail::has_reserve_method<std::array<int as the first argument
|
||||
// and 1>>::value as the second argument. We need an alias to avoid
|
||||
// this problem.
|
||||
using reservable_type = std::vector<int> ;
|
||||
using nonreservable_type = std::array<int, 1>;
|
||||
BOOST_TEST( toml::detail::has_reserve_method<reservable_type >::value);
|
||||
BOOST_TEST(!toml::detail::has_reserve_method<nonreservable_type>::value);
|
||||
}
|
||||
{
|
||||
std::vector<int> v;
|
||||
toml::resize(v, 10);
|
||||
BOOST_TEST(v.size() == 10u);
|
||||
}
|
||||
{
|
||||
std::array<int, 15> a;
|
||||
toml::resize(a, 10);
|
||||
BOOST_TEST(a.size() == 15u);
|
||||
}
|
||||
{
|
||||
std::array<int, 15> a;
|
||||
BOOST_CHECK_THROW(toml::resize(a, 20), std::invalid_argument);
|
||||
toml::try_reserve(v, 100);
|
||||
BOOST_TEST(v.capacity() == 100u);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
12
tests/test_windows.cpp
Normal file
12
tests/test_windows.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#include <windows.h>
|
||||
#include <toml.hpp>
|
||||
#include <iostream>
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace toml::literals::toml_literals;
|
||||
const auto data = u8R"(windows = "defines min and max as a macro")"_toml;
|
||||
|
||||
std::cout << toml::find<std::string>(data, "windows") << std::endl;
|
||||
return 0;
|
||||
}
|
||||
4
toml.hpp
4
toml.hpp
@@ -33,6 +33,10 @@
|
||||
# error "toml11 requires C++11 or later."
|
||||
#endif
|
||||
|
||||
#define TOML11_VERSION_MAJOR 3
|
||||
#define TOML11_VERSION_MINOR 5
|
||||
#define TOML11_VERSION_PATCH 0
|
||||
|
||||
#include "toml/parser.hpp"
|
||||
#include "toml/literal.hpp"
|
||||
#include "toml/serializer.hpp"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef TOML11_COLOR_HPP
|
||||
#define TOML11_COLOR_HPP
|
||||
#include <ostream>
|
||||
#include <cstdint>
|
||||
#include <ostream>
|
||||
|
||||
#ifdef TOML11_COLORIZE_ERROR_MESSAGE
|
||||
#define TOML11_ERROR_MESSAGE_COLORIZED true
|
||||
|
||||
@@ -2,18 +2,20 @@
|
||||
// Distributed under the MIT License.
|
||||
#ifndef TOML11_COMBINATOR_HPP
|
||||
#define TOML11_COMBINATOR_HPP
|
||||
#include "traits.hpp"
|
||||
#include "result.hpp"
|
||||
#include "utility.hpp"
|
||||
#include "region.hpp"
|
||||
#include <type_traits>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <array>
|
||||
#include <iomanip>
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
|
||||
#include <array>
|
||||
#include <iomanip>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
#include "region.hpp"
|
||||
#include "result.hpp"
|
||||
#include "traits.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
// they scans characters and returns region if it matches to the condition.
|
||||
// when they fail, it does not change the location.
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
// Distributed under the MIT License.
|
||||
#ifndef TOML11_COMMENTS_HPP
|
||||
#define TOML11_COMMENTS_HPP
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <iterator>
|
||||
#include <initializer_list>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
// This file provides mainly two classes, `preserve_comments` and `discard_comments`.
|
||||
// Those two are a container that have the same interface as `std::vector<std::string>`
|
||||
|
||||
@@ -2,15 +2,16 @@
|
||||
// Distributed under the MIT License.
|
||||
#ifndef TOML11_DATETIME_HPP
|
||||
#define TOML11_DATETIME_HPP
|
||||
#include <chrono>
|
||||
#include <tuple>
|
||||
#include <array>
|
||||
#include <ostream>
|
||||
#include <iomanip>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <ostream>
|
||||
#include <tuple>
|
||||
|
||||
namespace toml
|
||||
{
|
||||
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
// Distributed under the MIT License.
|
||||
#ifndef TOML11_EXCEPTION_HPP
|
||||
#define TOML11_EXCEPTION_HPP
|
||||
#include "source_location.hpp"
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include "source_location.hpp"
|
||||
|
||||
namespace toml
|
||||
{
|
||||
|
||||
|
||||
60
toml/get.hpp
60
toml/get.hpp
@@ -2,10 +2,11 @@
|
||||
// Distributed under the MIT License.
|
||||
#ifndef TOML11_GET_HPP
|
||||
#define TOML11_GET_HPP
|
||||
#include <algorithm>
|
||||
|
||||
#include "from.hpp"
|
||||
#include "result.hpp"
|
||||
#include "value.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
namespace toml
|
||||
{
|
||||
@@ -198,23 +199,23 @@ get(const basic_value<C, M, V>& v)
|
||||
// ============================================================================
|
||||
// forward declaration to use this recursively. ignore this and go ahead.
|
||||
|
||||
// array-like type with resize(N) method
|
||||
// array-like type with push_back(value) method
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<detail::conjunction<
|
||||
detail::is_container<T>, // T is container
|
||||
detail::has_resize_method<T>, // T::resize(N) works
|
||||
detail::is_container<T>, // T is a container
|
||||
detail::has_push_back_method<T>, // T::push_back(value) works
|
||||
detail::negation< // but not toml::array
|
||||
detail::is_exact_toml_type<T, basic_value<C, M, V>>>
|
||||
>::value, T>
|
||||
get(const basic_value<C, M, V>&);
|
||||
|
||||
// array-like type with resize(N) method
|
||||
// array-like type without push_back(value) method
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<detail::conjunction<
|
||||
detail::is_container<T>, // T is container
|
||||
detail::negation<detail::has_resize_method<T>>, // no T::resize() exists
|
||||
detail::is_container<T>, // T is a container
|
||||
detail::negation<detail::has_push_back_method<T>>, // w/o push_back(...)
|
||||
detail::negation< // not toml::array
|
||||
detail::is_exact_toml_type<T, basic_value<C, M, V>>>
|
||||
>::value, T>
|
||||
@@ -274,31 +275,54 @@ get(const basic_value<C, M, V>&);
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<detail::conjunction<
|
||||
detail::is_container<T>, // T is container
|
||||
detail::has_resize_method<T>, // T::resize(N) works
|
||||
detail::is_container<T>, // T is a container
|
||||
detail::has_push_back_method<T>, // container.push_back(elem) works
|
||||
detail::negation< // but not toml::array
|
||||
detail::is_exact_toml_type<T, basic_value<C, M, V>>>
|
||||
>::value, T>
|
||||
get(const basic_value<C, M, V>& v)
|
||||
{
|
||||
using value_type = typename T::value_type;
|
||||
const auto& ar = v.as_array();
|
||||
const auto& ary = v.as_array();
|
||||
|
||||
T container;
|
||||
container.resize(ar.size());
|
||||
std::transform(ar.cbegin(), ar.cend(), container.begin(),
|
||||
[](const value& x){return ::toml::get<value_type>(x);});
|
||||
try_reserve(container, ary.size());
|
||||
|
||||
for(const auto& elem : ary)
|
||||
{
|
||||
container.push_back(get<value_type>(elem));
|
||||
}
|
||||
return container;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// array-like types; but does not have resize(); most likely std::array.
|
||||
// std::forward_list does not have push_back, insert, or emplace.
|
||||
// It has insert_after, emplace_after, push_front.
|
||||
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<detail::is_std_forward_list<T>::value, T>
|
||||
get(const basic_value<C, M, V>& v)
|
||||
{
|
||||
using value_type = typename T::value_type;
|
||||
T container;
|
||||
for(const auto& elem : v.as_array())
|
||||
{
|
||||
container.push_front(get<value_type>(elem));
|
||||
}
|
||||
container.reverse();
|
||||
return container;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// array-like types, without push_back(). most likely [std|boost]::array.
|
||||
|
||||
template<typename T, typename C,
|
||||
template<typename ...> class M, template<typename ...> class V>
|
||||
detail::enable_if_t<detail::conjunction<
|
||||
detail::is_container<T>, // T is container
|
||||
detail::negation<detail::has_resize_method<T>>, // no T::resize() exists
|
||||
detail::negation< // but not toml::array
|
||||
detail::is_container<T>, // T is a container
|
||||
detail::negation<detail::has_push_back_method<T>>, // w/o push_back
|
||||
detail::negation< // T is not toml::array
|
||||
detail::is_exact_toml_type<T, basic_value<C, M, V>>>
|
||||
>::value, T>
|
||||
get(const basic_value<C, M, V>& v)
|
||||
@@ -396,7 +420,7 @@ get(const basic_value<C, M, V>& v)
|
||||
T map;
|
||||
for(const auto& kv : v.as_table())
|
||||
{
|
||||
map[key_type(kv.first)] = ::toml::get<mapped_type>(kv.second);
|
||||
map.emplace(key_type(kv.first), get<mapped_type>(kv.second));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
// Distributed under the MIT License.
|
||||
#ifndef TOML11_LEXER_HPP
|
||||
#define TOML11_LEXER_HPP
|
||||
#include "combinator.hpp"
|
||||
#include <stdexcept>
|
||||
#include <istream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <fstream>
|
||||
|
||||
#include "combinator.hpp"
|
||||
|
||||
namespace toml
|
||||
{
|
||||
namespace detail
|
||||
@@ -69,15 +70,8 @@ using lex_zero_prefixable_int = sequence<lex_digit, repeat<either<lex_digit,
|
||||
|
||||
using lex_fractional_part = sequence<character<'.'>, lex_zero_prefixable_int>;
|
||||
|
||||
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||
// use toml-lang/toml HEAD
|
||||
using lex_exponent_part = sequence<either<character<'e'>, character<'E'>>,
|
||||
maybe<lex_sign>, lex_zero_prefixable_int>;
|
||||
#else
|
||||
// strictly TOML v0.5.0
|
||||
using lex_exponent_part = sequence<either<character<'e'>, character<'E'>>,
|
||||
lex_dec_int>;
|
||||
#endif
|
||||
|
||||
using lex_float = either<lex_special_float,
|
||||
sequence<lex_dec_int, either<lex_exponent_part,
|
||||
@@ -125,17 +119,11 @@ using lex_local_time = lex_partial_time;
|
||||
// ===========================================================================
|
||||
|
||||
using lex_quotation_mark = character<'"'>;
|
||||
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||
using lex_basic_unescaped = exclude<either<in_range<0x00, 0x08>, // 0x09 (tab)
|
||||
in_range<0x0a, 0x1F>, // is allowed
|
||||
character<0x22>, character<0x5C>,
|
||||
character<0x7F>>>;
|
||||
#else
|
||||
using lex_basic_unescaped = exclude<either<in_range<0x00, 0x1F>,
|
||||
character<0x22>, character<0x5C>,
|
||||
character<0x7F>>>;
|
||||
|
||||
#endif
|
||||
using lex_escape = character<'\\'>;
|
||||
using lex_escape_unicode_short = sequence<character<'u'>,
|
||||
repeat<lex_hex_dig, exactly<4>>>;
|
||||
@@ -183,12 +171,6 @@ using lex_basic_string = sequence<lex_quotation_mark,
|
||||
// In parse_ml_basic_string() function, the trailing `"`s will be attached to
|
||||
// the string body.
|
||||
//
|
||||
// Note: This feature is a "clarification". Therefore this change is considered
|
||||
// as a spec that has been defined since the time when the multi-line
|
||||
// basic string was introduced. Although it is a post-v0.5.0 changes,
|
||||
// this change will be activated regardless of the flag,
|
||||
// `TOML11_USE_UNRELEASED_TOML_FEATURES`.
|
||||
//
|
||||
using lex_ml_basic_string_delim = repeat<lex_quotation_mark, exactly<3>>;
|
||||
using lex_ml_basic_string_open = lex_ml_basic_string_delim;
|
||||
using lex_ml_basic_string_close = sequence<
|
||||
@@ -196,18 +178,11 @@ using lex_ml_basic_string_close = sequence<
|
||||
maybe<lex_quotation_mark>, maybe<lex_quotation_mark>
|
||||
>;
|
||||
|
||||
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||
using lex_ml_basic_unescaped = exclude<either<in_range<0x00, 0x08>, // 0x09
|
||||
in_range<0x0a, 0x1F>, // is tab
|
||||
character<0x5C>, // backslash
|
||||
character<0x7F>, // DEL
|
||||
lex_ml_basic_string_delim>>;
|
||||
#else // TOML v0.5.0
|
||||
using lex_ml_basic_unescaped = exclude<either<in_range<0x00,0x1F>,
|
||||
character<0x5C>,
|
||||
character<0x7F>,
|
||||
lex_ml_basic_string_delim>>;
|
||||
#endif
|
||||
|
||||
using lex_ml_basic_escaped_newline = sequence<
|
||||
lex_escape, maybe<lex_ws>, lex_newline,
|
||||
|
||||
@@ -2,15 +2,23 @@
|
||||
// Distributed under the MIT License.
|
||||
#ifndef TOML11_PARSER_HPP
|
||||
#define TOML11_PARSER_HPP
|
||||
#include "result.hpp"
|
||||
#include "region.hpp"
|
||||
#include "combinator.hpp"
|
||||
#include "lexer.hpp"
|
||||
#include "types.hpp"
|
||||
#include "value.hpp"
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
|
||||
#include "combinator.hpp"
|
||||
#include "lexer.hpp"
|
||||
#include "region.hpp"
|
||||
#include "result.hpp"
|
||||
#include "types.hpp"
|
||||
#include "value.hpp"
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
#if __has_include(<filesystem>)
|
||||
#define TOML11_HAS_STD_FILESYSTEM
|
||||
#include <filesystem>
|
||||
#endif // has_include(<string_view>)
|
||||
#endif // cplusplus >= C++17
|
||||
|
||||
namespace toml
|
||||
{
|
||||
@@ -733,7 +741,13 @@ parse_local_time(location<Container>& loc)
|
||||
case 0: break;
|
||||
default: break;
|
||||
}
|
||||
if(sf.size() >= 6)
|
||||
if(sf.size() >= 9)
|
||||
{
|
||||
time.millisecond = from_string<std::uint16_t>(sf.substr(0, 3), 0u);
|
||||
time.microsecond = from_string<std::uint16_t>(sf.substr(3, 3), 0u);
|
||||
time.nanosecond = from_string<std::uint16_t>(sf.substr(6, 3), 0u);
|
||||
}
|
||||
else if(sf.size() >= 6)
|
||||
{
|
||||
time.millisecond = from_string<std::uint16_t>(sf.substr(0, 3), 0u);
|
||||
time.microsecond = from_string<std::uint16_t>(sf.substr(3, 3), 0u);
|
||||
@@ -977,7 +991,12 @@ parse_array(location<Container>& loc)
|
||||
|
||||
if(auto val = parse_value<value_type>(loc))
|
||||
{
|
||||
#ifndef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||
// After TOML v1.0.0-rc.1, array becomes to be able to have values
|
||||
// with different types. So here we will omit this by default.
|
||||
//
|
||||
// But some of the test-suite checks if the parser accepts a hetero-
|
||||
// geneous arrays, so we keep this for a while.
|
||||
#ifdef TOML11_DISALLOW_HETEROGENEOUS_ARRAYS
|
||||
if(!retval.empty() && retval.front().type() != val.as_ok().type())
|
||||
{
|
||||
auto array_start_loc = loc;
|
||||
@@ -1389,9 +1408,6 @@ insert_nested_key(typename Value::table_type& root, const Value& v,
|
||||
// According to toml-lang/toml:36d3091b3 "Clarify that inline
|
||||
// tables are immutable", check if it adds key-value pair to an
|
||||
// inline table.
|
||||
// This is one of the unreleased (after-0.5.0) toml feature.
|
||||
// But this is marked as "Clarify", so TOML-lang intended that
|
||||
// inline tables are immutable in all version.
|
||||
{
|
||||
// here, if the value is a (multi-line) table, the region
|
||||
// should be something like `[table-name]`.
|
||||
@@ -2049,10 +2065,11 @@ parse(std::istream& is, const std::string& fname = "unknown file")
|
||||
std::vector<char> letters(static_cast<std::size_t>(fsize));
|
||||
is.read(letters.data(), fsize);
|
||||
|
||||
if(!letters.empty() && letters.back() == '\0')
|
||||
while(!letters.empty() && letters.back() == '\0')
|
||||
{
|
||||
letters.pop_back();
|
||||
}
|
||||
assert(letters.empty() || letters.back() != '\0');
|
||||
|
||||
detail::location<std::vector<char>>
|
||||
loc(std::move(fname), std::move(letters));
|
||||
@@ -2094,5 +2111,39 @@ basic_value<Comment, Table, Array> parse(const std::string& fname)
|
||||
return parse<Comment, Table, Array>(ifs, fname);
|
||||
}
|
||||
|
||||
#ifdef TOML11_HAS_STD_FILESYSTEM
|
||||
// This function just forwards `parse("filename.toml")` to std::string version
|
||||
// to avoid the ambiguity in overload resolution.
|
||||
//
|
||||
// Both std::string and std::filesystem::path are convertible from const char[].
|
||||
// Without this, both parse(std::string) and parse(std::filesystem::path)
|
||||
// matches to parse("filename.toml"). This breaks the existing code.
|
||||
//
|
||||
// This function exactly matches to the invokation with string literal.
|
||||
// So this function is preferred than others and the ambiguity disappears.
|
||||
template<typename Comment = ::toml::discard_comments,
|
||||
template<typename ...> class Table = std::unordered_map,
|
||||
template<typename ...> class Array = std::vector,
|
||||
std::size_t N>
|
||||
basic_value<Comment, Table, Array> parse(const char (&fname)[N])
|
||||
{
|
||||
return parse<Comment, Table, Array>(std::string(fname));
|
||||
}
|
||||
|
||||
template<typename Comment = ::toml::discard_comments,
|
||||
template<typename ...> class Table = std::unordered_map,
|
||||
template<typename ...> class Array = std::vector>
|
||||
basic_value<Comment, Table, Array> parse(const std::filesystem::path& fpath)
|
||||
{
|
||||
std::ifstream ifs(fpath, std::ios_base::binary);
|
||||
if(!ifs.good())
|
||||
{
|
||||
throw std::runtime_error("toml::parse: file open error -> " +
|
||||
fpath.string());
|
||||
}
|
||||
return parse<Comment, Table, Array>(ifs, fpath.string());
|
||||
}
|
||||
#endif // TOML11_HAS_STD_FILESYSTEM
|
||||
|
||||
} // toml
|
||||
#endif// TOML11_PARSER_HPP
|
||||
|
||||
@@ -498,7 +498,7 @@ inline std::string format_underline(const std::string& message,
|
||||
{
|
||||
// invalid
|
||||
// ~~~~~~~
|
||||
const auto underline_len = std::min(reg->size(), reg->line().size());
|
||||
const auto underline_len = (std::min)(reg->size(), reg->line().size());
|
||||
retval << color::bold << color::red
|
||||
<< make_string(underline_len, '~') << color::reset;
|
||||
}
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
// Distributed under the MIT License.
|
||||
#ifndef TOML11_SERIALIZER_HPP
|
||||
#define TOML11_SERIALIZER_HPP
|
||||
#include "value.hpp"
|
||||
#include "lexer.hpp"
|
||||
#include <limits>
|
||||
#include <cstdio>
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "lexer.hpp"
|
||||
#include "value.hpp"
|
||||
|
||||
namespace toml
|
||||
{
|
||||
|
||||
@@ -135,43 +137,8 @@ struct serializer
|
||||
{
|
||||
// the resulting value does not have any float specific part!
|
||||
token += ".0";
|
||||
return token;
|
||||
}
|
||||
if(!has_exponent)
|
||||
{
|
||||
return token; // there is no exponent part. just return it.
|
||||
}
|
||||
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
|
||||
// Although currently it is not released yet as a tagged version,
|
||||
// TOML will allow zero-prefix in an exponent part, such as `1.234e+01`.
|
||||
// ```toml
|
||||
// num1 = 1.234e+1 # OK in TOML v0.5.0
|
||||
// num2 = 1.234e+01 # error in TOML v0.5.0 but will be allowed soon
|
||||
// ```
|
||||
// To avoid `e+01`, the following `else` section removes the zero
|
||||
// prefixes in the exponent part.
|
||||
// If the feature is activated, it can be skipped.
|
||||
return token;
|
||||
#else
|
||||
// zero-prefix in an exponent is NOT allowed in TOML v0.5.0.
|
||||
// remove it if it exists.
|
||||
bool sign_exists = false;
|
||||
std::size_t zero_prefix = 0;
|
||||
for(auto iter = std::next(e), iend = token.cend(); iter != iend; ++iter)
|
||||
{
|
||||
if(*iter == '+' || *iter == '-'){sign_exists = true; continue;}
|
||||
if(*iter == '0'){zero_prefix += 1;}
|
||||
else {break;}
|
||||
}
|
||||
if(zero_prefix != 0)
|
||||
{
|
||||
const auto offset = std::distance(token.cbegin(), e) +
|
||||
(sign_exists ? 2 : 1);
|
||||
token.erase(static_cast<typename std::string::size_type>(offset),
|
||||
zero_prefix);
|
||||
}
|
||||
return token;
|
||||
#endif
|
||||
}
|
||||
std::string operator()(const string_type& s) const
|
||||
{
|
||||
@@ -590,7 +557,7 @@ struct serializer
|
||||
for(const auto& item : v)
|
||||
{
|
||||
if(is_first) {is_first = false;} else {token += ',';}
|
||||
token += visit(serializer(std::numeric_limits<std::size_t>::max(),
|
||||
token += visit(serializer((std::numeric_limits<std::size_t>::max)(),
|
||||
this->float_prec_, true), item);
|
||||
}
|
||||
token += ']';
|
||||
@@ -610,7 +577,7 @@ struct serializer
|
||||
if(is_first) {is_first = false;} else {token += ',';}
|
||||
token += format_key(kv.first);
|
||||
token += '=';
|
||||
token += visit(serializer(std::numeric_limits<std::size_t>::max(),
|
||||
token += visit(serializer((std::numeric_limits<std::size_t>::max)(),
|
||||
this->float_prec_, true), kv.second);
|
||||
}
|
||||
token += '}';
|
||||
@@ -732,7 +699,8 @@ format(const basic_value<C, M, V>& v, std::size_t w = 80u,
|
||||
oss << v.comments();
|
||||
oss << '\n'; // to split the file comment from the first element
|
||||
}
|
||||
oss << visit(serializer<value_type>(w, fprec, no_comment, false), v);
|
||||
const auto serialized = visit(serializer<value_type>(w, fprec, no_comment, false), v);
|
||||
oss << serialized;
|
||||
return oss.str();
|
||||
}
|
||||
return visit(serializer<value_type>(w, fprec, force_inline), v);
|
||||
@@ -788,7 +756,8 @@ operator<<(std::basic_ostream<charT, traits>& os, const basic_value<C, M, V>& v)
|
||||
os << '\n'; // to split the file comment from the first element
|
||||
}
|
||||
// the root object can't be an inline table. so pass `false`.
|
||||
os << visit(serializer<value_type>(w, fprec, false, no_comment), v);
|
||||
const auto serialized = visit(serializer<value_type>(w, fprec, no_comment, false), v);
|
||||
os << serialized;
|
||||
|
||||
// if v is a non-table value, and has only one comment, then
|
||||
// put a comment just after a value. in the following way.
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
// Distributed under the MIT License.
|
||||
#ifndef TOML11_SOURCE_LOCATION_HPP
|
||||
#define TOML11_SOURCE_LOCATION_HPP
|
||||
#include "region.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
#include "region.hpp"
|
||||
|
||||
namespace toml
|
||||
{
|
||||
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
// Distributed under the MIT License.
|
||||
#ifndef TOML11_STRING_HPP
|
||||
#define TOML11_STRING_HPP
|
||||
#include <cstdint>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
#if __has_include(<string_view>)
|
||||
#include <string_view>
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
// Distributed under the MIT License.
|
||||
#ifndef TOML11_TRAITS_HPP
|
||||
#define TOML11_TRAITS_HPP
|
||||
#include <chrono>
|
||||
#include <forward_list>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <chrono>
|
||||
#include <tuple>
|
||||
#include <string>
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
#if __has_include(<string_view>)
|
||||
#include <string_view>
|
||||
@@ -43,17 +45,23 @@ struct has_mapped_type_impl
|
||||
template<typename T> static std::true_type check(typename T::mapped_type*);
|
||||
template<typename T> static std::false_type check(...);
|
||||
};
|
||||
struct has_resize_method_impl
|
||||
struct has_reserve_method_impl
|
||||
{
|
||||
constexpr static std::size_t dummy=0;
|
||||
template<typename T> static std::true_type check(decltype(std::declval<T>().resize(dummy))*);
|
||||
template<typename T> static std::false_type check(...);
|
||||
template<typename T> static std::true_type check(
|
||||
decltype(std::declval<T>().reserve(std::declval<std::size_t>()))*);
|
||||
};
|
||||
struct has_push_back_method_impl
|
||||
{
|
||||
template<typename T> static std::false_type check(...);
|
||||
template<typename T> static std::true_type check(
|
||||
decltype(std::declval<T>().push_back(std::declval<typename T::value_type>()))*);
|
||||
};
|
||||
|
||||
struct is_comparable_impl
|
||||
{
|
||||
template<typename T> static std::true_type check(decltype(std::declval<T>() < std::declval<T>())*);
|
||||
template<typename T> static std::false_type check(...);
|
||||
template<typename T> static std::true_type check(
|
||||
decltype(std::declval<T>() < std::declval<T>())*);
|
||||
};
|
||||
|
||||
struct has_from_toml_method_impl
|
||||
@@ -91,7 +99,9 @@ struct has_key_type : decltype(has_key_type_impl::check<T>(nullptr)){};
|
||||
template<typename T>
|
||||
struct has_mapped_type : decltype(has_mapped_type_impl::check<T>(nullptr)){};
|
||||
template<typename T>
|
||||
struct has_resize_method : decltype(has_resize_method_impl::check<T>(nullptr)){};
|
||||
struct has_reserve_method : decltype(has_reserve_method_impl::check<T>(nullptr)){};
|
||||
template<typename T>
|
||||
struct has_push_back_method : decltype(has_push_back_method_impl::check<T>(nullptr)){};
|
||||
template<typename T>
|
||||
struct is_comparable : decltype(is_comparable_impl::check<T>(nullptr)){};
|
||||
|
||||
@@ -149,6 +159,10 @@ template<typename T> struct is_std_tuple : std::false_type{};
|
||||
template<typename ... Ts>
|
||||
struct is_std_tuple<std::tuple<Ts...>> : std::true_type{};
|
||||
|
||||
template<typename T> struct is_std_forward_list : std::false_type{};
|
||||
template<typename T>
|
||||
struct is_std_forward_list<std::forward_list<T>> : std::true_type{};
|
||||
|
||||
template<typename T> struct is_chrono_duration: std::false_type{};
|
||||
template<typename Rep, typename Period>
|
||||
struct is_chrono_duration<std::chrono::duration<Rep, Period>>: std::true_type{};
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
// Distributed under the MIT License.
|
||||
#ifndef TOML11_TYPES_HPP
|
||||
#define TOML11_TYPES_HPP
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "comments.hpp"
|
||||
#include "datetime.hpp"
|
||||
#include "string.hpp"
|
||||
#include "traits.hpp"
|
||||
#include "comments.hpp"
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace toml
|
||||
{
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
// Distributed under the MIT License.
|
||||
#ifndef TOML11_UTILITY_HPP
|
||||
#define TOML11_UTILITY_HPP
|
||||
#include "traits.hpp"
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
#include "traits.hpp"
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
# define TOML11_MARK_AS_DEPRECATED(msg) [[deprecated(msg)]]
|
||||
@@ -36,30 +37,25 @@ inline std::unique_ptr<T> make_unique(Ts&& ... args)
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
inline void resize_impl(T& container, std::size_t N, std::true_type)
|
||||
template<typename Container>
|
||||
void try_reserve_impl(Container& container, std::size_t N, std::true_type)
|
||||
{
|
||||
container.resize(N);
|
||||
return ;
|
||||
container.reserve(N);
|
||||
return;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void resize_impl(T& container, std::size_t N, std::false_type)
|
||||
template<typename Container>
|
||||
void try_reserve_impl(Container&, std::size_t, std::false_type) noexcept
|
||||
{
|
||||
if(container.size() >= N) {return;}
|
||||
|
||||
throw std::invalid_argument("not resizable type");
|
||||
return;
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
template<typename T>
|
||||
inline void resize(T& container, std::size_t N)
|
||||
template<typename Container>
|
||||
void try_reserve(Container& container, std::size_t N)
|
||||
{
|
||||
if(container.size() == N) {return;}
|
||||
|
||||
return detail::resize_impl(container, N, detail::has_resize_method<T>());
|
||||
if(N <= container.size()) {return;}
|
||||
detail::try_reserve_impl(container, N, detail::has_reserve_method<Container>{});
|
||||
return;
|
||||
}
|
||||
|
||||
namespace detail
|
||||
|
||||
@@ -2,17 +2,18 @@
|
||||
// Distributed under the MIT License.
|
||||
#ifndef TOML11_VALUE_HPP
|
||||
#define TOML11_VALUE_HPP
|
||||
#include "traits.hpp"
|
||||
#include "into.hpp"
|
||||
#include "utility.hpp"
|
||||
#include "exception.hpp"
|
||||
#include "storage.hpp"
|
||||
#include "region.hpp"
|
||||
#include "types.hpp"
|
||||
#include "source_location.hpp"
|
||||
#include "comments.hpp"
|
||||
#include <cassert>
|
||||
|
||||
#include "comments.hpp"
|
||||
#include "exception.hpp"
|
||||
#include "into.hpp"
|
||||
#include "region.hpp"
|
||||
#include "source_location.hpp"
|
||||
#include "storage.hpp"
|
||||
#include "traits.hpp"
|
||||
#include "types.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace toml
|
||||
{
|
||||
|
||||
|
||||
Reference in New Issue
Block a user