mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-12-16 03:08:52 +08:00
Compare commits
76 Commits
add-error-
...
key-format
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da98b6558d | ||
|
|
c433577120 | ||
|
|
a39300f9d9 | ||
|
|
2193c5c201 | ||
|
|
e2bbf550a0 | ||
|
|
1809484542 | ||
|
|
0571dd74ca | ||
|
|
19199ac82c | ||
|
|
572781971f | ||
|
|
0072e740d5 | ||
|
|
4dd83fe778 | ||
|
|
fe19e7ee0a | ||
|
|
f33ca743fb | ||
|
|
754c1ef879 | ||
|
|
911abe939e | ||
|
|
100d05822a | ||
|
|
feda8356a3 | ||
|
|
88aaefd747 | ||
|
|
4d0ad7335b | ||
|
|
96460a15d4 | ||
|
|
a50895cdff | ||
|
|
886801d00a | ||
|
|
f3a1586a44 | ||
|
|
098569a96d | ||
|
|
43f5a74bf0 | ||
|
|
6085c53ea2 | ||
|
|
496782b42e | ||
|
|
f7deb1e89e | ||
|
|
ce42e78e3c | ||
|
|
b853860a8f | ||
|
|
eba1aa2fde | ||
|
|
8434a6b18b | ||
|
|
eefca6e080 | ||
|
|
5e05b75473 | ||
|
|
d9449747f3 | ||
|
|
00e0ce12e7 | ||
|
|
92c2af024c | ||
|
|
c9574b8ce6 | ||
|
|
b68f1fd57f | ||
|
|
d99f260c1a | ||
|
|
c0a8b60a5d | ||
|
|
93503e9c59 | ||
|
|
cae5f34fb1 | ||
|
|
a69877005d | ||
|
|
452f1702c2 | ||
|
|
0f0f9cf3c1 | ||
|
|
49b373d4f5 | ||
|
|
acd6ed9a1e | ||
|
|
654ec0e013 | ||
|
|
9fd24aa23b | ||
|
|
d8d325741c | ||
|
|
f86d04f64d | ||
|
|
b78a37c826 | ||
|
|
29fbb6b695 | ||
|
|
31810136d1 | ||
|
|
a77516a2d0 | ||
|
|
826e6414a0 | ||
|
|
143437d309 | ||
|
|
5ac47b8983 | ||
|
|
34a2091a4d | ||
|
|
2e108e7010 | ||
|
|
43c9c95de8 | ||
|
|
9b41f4ab00 | ||
|
|
ed1604ca58 | ||
|
|
2c1269b82a | ||
|
|
ab94fbb2de | ||
|
|
7ba94b37ab | ||
|
|
b2ea268d69 | ||
|
|
2912407d33 | ||
|
|
b63668c0dc | ||
|
|
d72493a2fc | ||
|
|
58ddb8f589 | ||
|
|
9e194ea8b6 | ||
|
|
be7d7257c9 | ||
|
|
0eb9a90abf | ||
|
|
0cc0ef959b |
17
.github/workflows/main.yml
vendored
17
.github/workflows/main.yml
vendored
@@ -11,6 +11,9 @@ jobs:
|
||||
standard: ['11', '14', '17', '20']
|
||||
precompile: ['ON', 'OFF']
|
||||
steps:
|
||||
- name: Get number of CPU cores
|
||||
uses: SimenB/github-actions-cpu-cores@v2
|
||||
id: cpu-cores
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
@@ -25,7 +28,7 @@ jobs:
|
||||
cmake -B build/ -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DTOML11_BUILD_TESTS=ON -DTOML11_PRECOMPILE=${{ matrix.precompile }}
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --build build/
|
||||
cmake --build build/ -j${{ steps.cpu-cores.outputs.count }}
|
||||
- name: Test
|
||||
run: |
|
||||
ctest --output-on-failure --test-dir build/
|
||||
@@ -56,7 +59,7 @@ jobs:
|
||||
cmake -B build/ -DCMAKE_CXX_COMPILER=clang++-${{ matrix.compiler }} -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DTOML11_BUILD_TESTS=ON -DTOML11_PRECOMPILE=${{ matrix.precompile }}
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --build build/
|
||||
cmake --build build/ -j${{ steps.cpu-cores.outputs.count }}
|
||||
- name: Test
|
||||
run: |
|
||||
ctest --output-on-failure --test-dir build/
|
||||
@@ -86,7 +89,7 @@ jobs:
|
||||
cmake -B build/ -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DTOML11_BUILD_TESTS=ON -DTOML11_PRECOMPILE=${{ matrix.precompile }}
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --build build/
|
||||
cmake --build build/ -j${{ steps.cpu-cores.outputs.count }}
|
||||
- name: Test
|
||||
run: |
|
||||
ctest --output-on-failure --test-dir build/
|
||||
@@ -118,7 +121,7 @@ jobs:
|
||||
cmake -B build/ -DCMAKE_CXX_COMPILER=clang++-${{ matrix.compiler }} -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DTOML11_BUILD_TESTS=ON -DTOML11_PRECOMPILE=${{ matrix.precompile }}
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --build build/
|
||||
cmake --build build/ -j${{ steps.cpu-cores.outputs.count }}
|
||||
- name: Test
|
||||
run: |
|
||||
ctest --output-on-failure --test-dir build/
|
||||
@@ -139,7 +142,7 @@ jobs:
|
||||
cmake -B build/ -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DTOML11_BUILD_TESTS=ON -DTOML11_PRECOMPILE=${{ matrix.precompile }}
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --build build/
|
||||
cmake --build build/ -j${{ steps.cpu-cores.outputs.count }}
|
||||
- name: Test
|
||||
run: |
|
||||
ctest --output-on-failure --test-dir build/
|
||||
@@ -160,7 +163,7 @@ jobs:
|
||||
cmake -B build/ -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DTOML11_BUILD_TESTS=ON -DTOML11_PRECOMPILE=${{ matrix.precompile }}
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --build build/
|
||||
cmake --build build/ -j${{ steps.cpu-cores.outputs.count }}
|
||||
- name: Test
|
||||
run: |
|
||||
ctest --output-on-failure --test-dir build/
|
||||
@@ -184,7 +187,7 @@ jobs:
|
||||
cmake -B build/ -G "NMake Makefiles" -DTOML11_BUILD_TESTS=ON -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DTOML11_PRECOMPILE=${{ matrix.precompile }}
|
||||
- name: Build
|
||||
run: |
|
||||
cmake --build ./build --config "${{ matrix.config }}"
|
||||
cmake --build ./build --config "${{ matrix.config }}" -j${{ steps.cpu-cores.outputs.count }}
|
||||
- name: Test
|
||||
run: |
|
||||
ctest --build-config "${{ matrix.config }}" --test-dir build/ --output-on-failure
|
||||
|
||||
@@ -14,11 +14,13 @@ string(REGEX REPLACE "#define TOML11_VERSION_PATCH ([0-9]+)" "\\1" TOML11_VERSIO
|
||||
|
||||
project(toml11 LANGUAGES CXX VERSION "${TOML11_VERSION_MAJOR}.${TOML11_VERSION_MINOR}.${TOML11_VERSION_PATCH}")
|
||||
|
||||
include(CMakeDependentOption)
|
||||
include(CTest)
|
||||
include(CTest) # to use ${BUILD_TESTING}
|
||||
|
||||
option(TOML11_PRECOMPILE "precompile toml11 library" OFF)
|
||||
|
||||
include(CMakeDependentOption)
|
||||
cmake_policy(PUSH)
|
||||
cmake_policy(SET CMP0127 OLD) # syntax of condition changed in 3.22
|
||||
cmake_dependent_option(TOML11_INSTALL "install toml11 library" ON
|
||||
"${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}" OFF)
|
||||
cmake_dependent_option(TOML11_BUILD_EXAMPLES "build toml11 examples" OFF
|
||||
@@ -27,6 +29,8 @@ cmake_dependent_option(TOML11_BUILD_TESTS "build toml11 unit tests" OFF
|
||||
"${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}; ${BUILD_TESTING}" OFF)
|
||||
cmake_dependent_option(TOML11_BUILD_TOML_TESTS "build toml11 toml-test encoder & decoder" OFF
|
||||
"${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}" OFF)
|
||||
cmake_policy(POP)
|
||||
|
||||
cmake_dependent_option(TOML11_TEST_WITH_ASAN "build toml11 unit tests with asan" OFF
|
||||
"${TOML11_BUILD_TESTS}" OFF)
|
||||
cmake_dependent_option(TOML11_TEST_WITH_UBSAN "build toml11 unit tests with ubsan" OFF
|
||||
@@ -36,8 +40,22 @@ if(${TOML11_TEST_WITH_ASAN} AND ${TOML11_TEST_WITH_UBSAN})
|
||||
message(FATAL_ERROR "trying to build tests with BOTH asan and ubsan")
|
||||
endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(CheckCXXCompilerFlag)
|
||||
check_cxx_compiler_flag("-Wall" TOML11_COMPILER_SUPPORTS_WALL)
|
||||
check_cxx_compiler_flag("-Wextra" TOML11_COMPILER_SUPPORTS_WEXTRA)
|
||||
check_cxx_compiler_flag("-Wpedantic" TOML11_COMPILER_SUPPORTS_WPEDANTIC)
|
||||
check_cxx_compiler_flag("-Werror" TOML11_COMPILER_SUPPORTS_WERROR)
|
||||
check_cxx_compiler_flag("-Wsign-conversion" TOML11_COMPILER_SUPPORTS_WSIGN_CONVERSION)
|
||||
check_cxx_compiler_flag("-Wconversion" TOML11_COMPILER_SUPPORTS_WCONVERSION)
|
||||
check_cxx_compiler_flag("-Wduplicated-cond" TOML11_COMPILER_SUPPORTS_WDUPLICATED_COND)
|
||||
check_cxx_compiler_flag("-Wduplicated-branches" TOML11_COMPILER_SUPPORTS_WDUPLICATED_BRANCHES)
|
||||
check_cxx_compiler_flag("-Wlogical-op" TOML11_COMPILER_SUPPORTS_WLOGICAL_OP)
|
||||
check_cxx_compiler_flag("-Wdouble-promotion" TOML11_COMPILER_SUPPORTS_WDOUBLE_PROMOTION)
|
||||
check_cxx_compiler_flag("-Wrange-loop-analysis" TOML11_COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS)
|
||||
check_cxx_compiler_flag("-Wundef" TOML11_COMPILER_SUPPORTS_WUNDEF)
|
||||
check_cxx_compiler_flag("-Wshadow" TOML11_COMPILER_SUPPORTS_WSHADOW)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
set(TOML11_INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/toml11)
|
||||
set(TOML11_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
set(TOML11_CONFIG_DIR ${CMAKE_CURRENT_BINARY_DIR}/cmake)
|
||||
|
||||
191
README.md
191
README.md
@@ -100,6 +100,36 @@ Copy `single_include/toml.hpp` to your preferred location and add it to your inc
|
||||
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.
|
||||
|
||||
### CMake `FetchContent`
|
||||
|
||||
Using `FetchContent`, you can automatically download it.
|
||||
|
||||
```cmake
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
toml11
|
||||
GIT_REPOSITORY https://github.com/ToruNiina/toml11.git
|
||||
GIT_TAG v4.1.0
|
||||
)
|
||||
FetchContent_MakeAvailable(toml11)
|
||||
|
||||
add_executable(main main.cpp)
|
||||
target_link_libraries(main PRIVATE toml11::toml11)
|
||||
```
|
||||
|
||||
### CMake Package Manager (CPM)
|
||||
|
||||
After [adding cpm to your project](https://github.com/cpm-cmake/CPM.cmake?tab=readme-ov-file#adding-cpm), you can use toml11 by doing:
|
||||
|
||||
```cmake
|
||||
include(cmake/CPM.cmake)
|
||||
|
||||
CPMAddPackage("gh:ToruNiina/toml11@4.1.0")
|
||||
|
||||
add_executable(main main.cpp)
|
||||
target_link_libraries(main PUBLIC toml11::toml11)
|
||||
```
|
||||
|
||||
### Install Using CMake
|
||||
|
||||
You can install toml11 using CMake with the following steps:
|
||||
@@ -175,8 +205,30 @@ 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`.
|
||||
When parsing string literals, you can use the `""_toml` literal.
|
||||
|
||||
```cpp
|
||||
using namespace toml::literals::toml_literals;
|
||||
const toml::value lit = "a = 42"_toml;
|
||||
```
|
||||
|
||||
`toml::parse`, `parse_str` and `_toml` literal throw a `toml::syntax_error` exception in case of a syntax error.
|
||||
|
||||
The error message obtained with `what()` will look like this:
|
||||
|
||||
```
|
||||
[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
|
||||
```
|
||||
|
||||
Error messages can also be colorized by calling `toml::color::enable()`.
|
||||
|
||||
By using `toml::try_parse`, you can receive a `toml::result<toml::value, std::vector<toml::error_info>>` without throwing exceptions.
|
||||
|
||||
```cpp
|
||||
const auto input = toml::try_parse("input.toml");
|
||||
@@ -227,6 +279,40 @@ const toml::value input = toml::parse("input.toml");
|
||||
std::cout << toml::find<int>(input, "a") << std::endl;
|
||||
```
|
||||
|
||||
If type conversion or value lookup fails, a `toml::type_error` is thrown. The error message will look like this:
|
||||
|
||||
```
|
||||
[error] toml::value::as_string(): bad_cast to string
|
||||
--> input.toml
|
||||
|
|
||||
1 | a = 123_456
|
||||
| ^^^^^^^-- the actual type is integer
|
||||
```
|
||||
|
||||
You can access nested tables or arrays of tables in the same way.
|
||||
|
||||
```cpp
|
||||
// [a]
|
||||
// b = [
|
||||
// {c = 42},
|
||||
// {c = 54}
|
||||
// ]
|
||||
const toml::value input = toml::parse("input.toml");
|
||||
std::cout << toml::find<int>(input, "a", "b", 1, "c") << std::endl;
|
||||
```
|
||||
|
||||
Most STL containers and those with similar interfaces can be converted.
|
||||
|
||||
```cpp
|
||||
// array = [3,1,4,1,5]
|
||||
const toml::value input = toml::parse("input.toml");
|
||||
|
||||
const auto a1 = toml::find<std::vector<int>>(input, "array");
|
||||
const auto a2 = toml::find<std::array<int, 5>>(input, "array");
|
||||
const auto a3 = toml::find<std::deque<int>>(input, "array");
|
||||
const auto a4 = toml::find<boost::container::small_vector<int, 8>>(input, "array");
|
||||
```
|
||||
|
||||
You can perform advanced type conversions on complex TOML values.
|
||||
|
||||
```toml
|
||||
@@ -245,6 +331,36 @@ const auto mixed = toml::find<
|
||||
>(input, "mixed_array") << std::endl;
|
||||
```
|
||||
|
||||
User-defined types can also be converted by using macros or defining some specific functions.
|
||||
|
||||
```cpp
|
||||
namespace extlib
|
||||
{
|
||||
struct foo
|
||||
{
|
||||
int a;
|
||||
std::string b;
|
||||
};
|
||||
} // extlib
|
||||
TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(extlib::foo, a, b)
|
||||
|
||||
// ...
|
||||
|
||||
const auto input = R"(
|
||||
[foo]
|
||||
a = 42
|
||||
b = "bar"
|
||||
)"_toml;
|
||||
const extlib::foo f = toml::find<extlib::foo>(input, "foo");
|
||||
```
|
||||
|
||||
Using `toml::find_or`, you can get a default value in case of failure.
|
||||
|
||||
```cpp
|
||||
const toml::value input = toml::parse("input.toml");
|
||||
std::cout << toml::find_or(input, "a", 6*9) << std::endl;
|
||||
```
|
||||
|
||||
For more details, please refer to the [documentation](https://toruniina.github.io/toml11/docs/features/value/).
|
||||
|
||||
### comments
|
||||
@@ -331,19 +447,72 @@ std::cout << toml::format(input) << std::endl;
|
||||
```cpp
|
||||
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;
|
||||
output.at("a").as_integer_fmt().spacer = 4; // position of `_`
|
||||
|
||||
std::cout << toml::format(input) << std::endl;
|
||||
// a = 0xdead_beef
|
||||
```
|
||||
|
||||
You can also specify the formatting for tables and arrays.
|
||||
|
||||
```cpp
|
||||
toml::value output(toml::table{
|
||||
{"array-of-tables", toml::array{}},
|
||||
{"subtable", toml::table{}},
|
||||
});
|
||||
|
||||
auto& aot = output.at("array-of-tables");
|
||||
aot.as_array_fmt().fmt = toml::array_format::multiline; // one element per line
|
||||
aot.as_array_fmt().body_indent = 4;
|
||||
aot.as_array_fmt().closing_indent = 2;
|
||||
|
||||
toml::value v1(toml::table{ {"a", 42}, {"b", 3.14} });
|
||||
v1.as_table_fmt().fmt = toml::table_format::oneline;
|
||||
aot.push_back(std::move(v1));
|
||||
|
||||
toml::value v2(toml::table{ {"a", 42}, {"b", 3.14} });
|
||||
v2.as_table_fmt().fmt = toml::table_format::oneline;
|
||||
aot.push_back(std::move(v2));
|
||||
|
||||
output.at("subtable").as_table_fmt().fmt = toml::table_format::dotted;
|
||||
output.at("subtable")["a"] = 42;
|
||||
output.at("subtable")["b"] = 3.14;
|
||||
|
||||
std::cout << toml::format(output) << std::endl;
|
||||
// subtable.b = 3.14
|
||||
// subtable.a = 42
|
||||
// array-of-tables = [
|
||||
// {b = 3.14, a = 42},
|
||||
// {b = 3.14, a = 42},
|
||||
// ]
|
||||
```
|
||||
|
||||
These settings are read during parsing and will be maintained as long as the value type does not change when modified.
|
||||
|
||||
For details on possible formatting specifications, please refer to the [documentation](https://toruniina.github.io/toml11/docs/features/serialize/).
|
||||
|
||||
### configuring types
|
||||
### Configuring Types
|
||||
|
||||
[The examples directory](https://github.com/ToruNiina/toml11/tree/main/examples) provides usage examples, such as using
|
||||
arbitrary-precision integers, normalizing Unicode, and integrating with an external reflection library.
|
||||
Many types held by `toml::value`, such as `integer_type` and `array_type`, can be modified by changing the `type_config` type.
|
||||
|
||||
Please refer to these examples for implementation guidance in such scenarios.
|
||||
Refer to the [`examples` directory](https://github.com/ToruNiina/toml11/tree/main/examples) for complex use cases such as using multi-precision integers, changing containers, and normalizing Unicode.
|
||||
|
||||
Use these examples as references for implementing such configurations.
|
||||
|
||||
## Examples
|
||||
|
||||
The [`examples`](https://github.com/ToruNiina/toml11/tree/main/examples) directory provides various implementation examples in addition to type configurations.
|
||||
|
||||
- [boost_container](https://github.com/ToruNiina/toml11/tree/main/examples/boost_container)
|
||||
- This example shows how to use `boost::container` containers for `array_type` and `table_type`.
|
||||
- [boost_multiprecision](https://github.com/ToruNiina/toml11/tree/main/examples/boost_multiprecision)
|
||||
- This example demonstrates the use of `boost::multiprecision` multi-precision numeric types for `integer_type` and `floating_type`.
|
||||
- [parse_file](https://github.com/ToruNiina/toml11/tree/main/examples/parse_file)
|
||||
- This example includes type conversion implementations, covering slightly more complex cases. The corresponding TOML file is included.
|
||||
- [reflect](https://github.com/ToruNiina/toml11/tree/main/examples/reflect)
|
||||
- This example shows self-type conversion using boost-ext/reflect for user-defined types.
|
||||
- [unicode](https://github.com/ToruNiina/toml11/tree/main/examples/unicode)
|
||||
- This example demonstrates normalizing Unicode strings when searching for keys using uni-algo.
|
||||
|
||||
## Changes from v3
|
||||
|
||||
@@ -467,6 +636,14 @@ I appreciate the help of the contributors who introduced the great feature to th
|
||||
- Add fuzzing test based on ClusterFuzzLite
|
||||
- Esonhugh Skyworship (@Esonhugh)
|
||||
- Fix function signature of `strerror_r` on macos
|
||||
- Alberto (@0X1A)
|
||||
- Fix issues with CMake package configuration when used with vcpkg
|
||||
- Egor Pugin (@egorpugin)
|
||||
- Fix incorrect operator<<() argument type that gives build error
|
||||
- Andreas Keller (@andreaskeller96)
|
||||
- Fix not checking for \r\n when parsing line comments
|
||||
- 萧迩珀 (@CDK6182CHR)
|
||||
- Support template into_toml members
|
||||
|
||||
## Licensing terms
|
||||
|
||||
|
||||
196
README_ja.md
196
README_ja.md
@@ -97,6 +97,36 @@ toml11を使うには複数の方法があります。
|
||||
git submoduleなどでサブディレクトリにすれば、`toml11/include`にインクルードパスを通すか、
|
||||
`add_subdirectory(toml11)` とすることで使用できます。
|
||||
|
||||
### CMake `FetchContent`
|
||||
|
||||
CMakeの `FetchContent`を使用することで、`build`ディレクトリに自動でダウンロードすることができます。
|
||||
|
||||
```cmake
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
toml11
|
||||
GIT_REPOSITORY https://github.com/ToruNiina/toml11.git
|
||||
GIT_TAG v4.0.3
|
||||
)
|
||||
FetchContent_MakeAvailable(toml11)
|
||||
|
||||
add_executable(main main.cpp)
|
||||
target_link_libraries(main PRIVATE toml11::toml11)
|
||||
```
|
||||
|
||||
### CMake Package Manager (CPM)
|
||||
|
||||
[CMake package manager](https://github.com/cpm-cmake/CPM.cmake)を導入すると、以下のようにして使用することができます。
|
||||
|
||||
```cmake
|
||||
include(cmake/CPM.cmake)
|
||||
|
||||
CPMAddPackage("gh:ToruNiina/toml11@4.1.0")
|
||||
|
||||
add_executable(main main.cpp)
|
||||
target_link_libraries(main PUBLIC toml11::toml11)
|
||||
```
|
||||
|
||||
### Install using CMake
|
||||
|
||||
以下の手順で、CMakeを使ってインストールすることができます。
|
||||
@@ -139,7 +169,7 @@ $ cmake -B ./build/ -DTOML11_BUILD_EXAMPLES=ON
|
||||
$ cmake --build ./build/
|
||||
```
|
||||
|
||||
### Building example
|
||||
### Building Tests
|
||||
|
||||
`-DTOML11_BUILD_TESTS=ON`とすることで、ユニットテストをコンパイルできます。
|
||||
|
||||
@@ -174,8 +204,30 @@ const toml::value input = toml::parse("input.toml");
|
||||
const toml::value input = toml::parse_str("a = 42");
|
||||
```
|
||||
|
||||
`toml::parse`は文法エラーの際に `toml::syntax_error` 例外を投げます。
|
||||
これを避けるには、 `toml::result` を返す `toml::try_parse` を使います。
|
||||
文字列リテラルをパースする際は、`""_toml`リテラルを使うことができます。
|
||||
|
||||
```cpp
|
||||
using namespace toml::literals::toml_literals;
|
||||
const toml::value lit = "a = 42"_toml;
|
||||
```
|
||||
|
||||
`toml::parse`や`parse_str`は文法エラーの際に `toml::syntax_error` 例外を投げます。
|
||||
|
||||
`what()`で得られるエラーメッセージは以下のようになります。
|
||||
|
||||
```
|
||||
[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
|
||||
```
|
||||
|
||||
エラーメッセージには`toml::color::enable()`を呼ぶことで色を付けることも可能です。
|
||||
|
||||
`toml::try_parse`を使うことで、例外を投げずに `toml::result<toml::value, std::vector<toml::error_info>>` を受け取ることができます。
|
||||
|
||||
```cpp
|
||||
const auto input = toml::try_parse("input.toml");
|
||||
@@ -219,11 +271,46 @@ if(input.contains("a") && input.at("a").is_integer())
|
||||
}
|
||||
```
|
||||
|
||||
`toml::find` を使うことで、型変換と検索が同時に行えます。
|
||||
`toml::find` を使うことで、型変換と検索を同時に行うことができます。
|
||||
|
||||
```cpp
|
||||
const toml::value input = toml::parse("input.toml");
|
||||
std::cout << toml::find<int>(input, "a") << std::endl;
|
||||
std::cout << toml::find<std::string>(input, "a") << std::endl;
|
||||
```
|
||||
|
||||
型変換や値の検索に失敗した場合は、`toml::type_error`が送出されます。
|
||||
その場合のエラーメッセージは以下のようになります。
|
||||
|
||||
```
|
||||
[error] toml::value::as_string(): bad_cast to string
|
||||
--> input.toml
|
||||
|
|
||||
1 | a = 123_456
|
||||
| ^^^^^^^-- the actual type is integer
|
||||
```
|
||||
|
||||
ネストされたテーブルやテーブルの配列にも同じ方法でアクセスできます。
|
||||
|
||||
```cpp
|
||||
// [a]
|
||||
// b = [
|
||||
// {c = 42},
|
||||
// {c = 54}
|
||||
// ]
|
||||
const toml::value input = toml::parse("input.toml");
|
||||
std::cout << toml::find<int>(input, "a", "b", 1, "c") << std::endl;
|
||||
```
|
||||
|
||||
ほとんどのSTLコンテナや、同様のインターフェースを持つコンテナへ変換が可能です。
|
||||
|
||||
```cpp
|
||||
// array = [3,1,4,1,5]
|
||||
const toml::value input = toml::parse("input.toml");
|
||||
|
||||
const auto a1 = toml::find<std::vector<int> >(input, "array") << std::endl;
|
||||
const auto a2 = toml::find<std::array<int, 5>>(input, "array") << std::endl;
|
||||
const auto a3 = toml::find<std::deque<int> >(input, "array") << std::endl;
|
||||
const auto a4 = toml::find<boost::container::small_vector<int, 8>>(input, "array") << std::endl;
|
||||
```
|
||||
|
||||
また、複雑なTOML値に対して、高度な型変換を行うことができます。
|
||||
@@ -244,6 +331,36 @@ const auto mixed = toml::find<
|
||||
>(input, "mixed_array") << std::endl;
|
||||
```
|
||||
|
||||
マクロの使用または特定の関数を定義することで、ユーザー定義型にも変換が可能です。
|
||||
|
||||
```cpp
|
||||
namespace extlib
|
||||
{
|
||||
struct foo
|
||||
{
|
||||
int a;
|
||||
std::string b;
|
||||
};
|
||||
} // extlib
|
||||
TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(extlib::foo, a, b)
|
||||
|
||||
// ...
|
||||
|
||||
const auto input = R"(
|
||||
[foo]
|
||||
a = 42
|
||||
b = "bar"
|
||||
)"_toml;
|
||||
const extlib::foo f = toml::find<extlib::foo>(input, "foo");
|
||||
```
|
||||
|
||||
`toml::find_or`を使うことで、失敗時にデフォルト値を得ることができます。
|
||||
|
||||
```cpp
|
||||
const toml::value input = toml::parse("input.toml");
|
||||
std::cout << toml::find_or(input, "a", 6*9) << std::endl;
|
||||
```
|
||||
|
||||
詳細については[ドキュメント](https://toruniina.github.io/toml11/ja/docs/features/value/)を参照してください。
|
||||
|
||||
### comments
|
||||
@@ -332,18 +449,73 @@ 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;
|
||||
std::cout << toml::format(output) << std::endl;
|
||||
// a = 0xdead_beef
|
||||
```
|
||||
|
||||
テーブルや配列のフォーマットも指定が可能です。
|
||||
|
||||
```cpp
|
||||
toml::value output(toml::table{
|
||||
{"array-of-tables", toml::array{}},
|
||||
{"subtable", toml::table{}},
|
||||
});
|
||||
|
||||
auto& aot = output.at("array-of-tables");
|
||||
aot.as_array_fmt().fmt = toml::array_format::multiline;
|
||||
aot.as_array_fmt().body_indent = 4;
|
||||
aot.as_array_fmt().closing_indent = 2;
|
||||
|
||||
toml::value v1(toml::table{ {"a", 42}, {"b", 3.14} });
|
||||
v1.as_table_fmt().fmt = toml::table_format::oneline;
|
||||
aot.push_back(std::move(v1));
|
||||
|
||||
toml::value v2(toml::table{ {"a", 42}, {"b", 3.14} });
|
||||
v2.as_table_fmt().fmt = toml::table_format::oneline;
|
||||
aot.push_back(std::move(v2));
|
||||
|
||||
output.at("subtable").as_table_fmt().fmt = toml::table_format::dotted;
|
||||
output.at("subtable")["a"] = 42;
|
||||
output.at("subtable")["b"] = 3.14;
|
||||
|
||||
std::cout << toml::format(output) << std::endl;
|
||||
// subtable.b = 3.14
|
||||
// subtable.a = 42
|
||||
// array-of-tables = [
|
||||
// {b = 3.14, a = 42},
|
||||
// {b = 2.71, a = 54},
|
||||
// ]
|
||||
```
|
||||
|
||||
これらの設定はパース時に読み取られ、値を変更した際も型が変わらない限り維持されます。
|
||||
|
||||
どのような指定が可能かなどの詳細は[ドキュメント](https://toruniina.github.io/toml11/ja/docs/features/serialize/)を参照してください。
|
||||
|
||||
### configuring types
|
||||
|
||||
[`examples`ディレクトリ](https://github.com/ToruNiina/toml11/tree/main/examples)には、多倍長整数を使用する場合やユニコードを正規化する場合、
|
||||
外部のリフレクションライブラリと連携する場合などの複雑な使用例を用意しています。
|
||||
`toml::value`が持つ型の多く、`integer_type`や`array_type`などは`type_config`型を変更することで変更可能です。
|
||||
|
||||
[`examples`ディレクトリ](https://github.com/ToruNiina/toml11/tree/main/examples)には、
|
||||
多倍長整数を使用する場合やコンテナを変更する場合、ユニコードを正規化する場合などの複雑な使用例を用意しています。
|
||||
|
||||
そのような状況での実装例として参照してください。
|
||||
|
||||
## Examples
|
||||
|
||||
[`examples`ディレクトリ](https://github.com/ToruNiina/toml11/tree/main/examples)では、
|
||||
型の設定の他にも実装例を紹介しています。
|
||||
|
||||
- [boost_container](https://github.com/ToruNiina/toml11/tree/main/examples/boost_container)
|
||||
- `array_type`や`table_type`に`boost::container`のコンテナを使う例です。
|
||||
- [boost_multiprecision](https://github.com/ToruNiina/toml11/tree/main/examples/boost_multiprecision)
|
||||
- `integer_type`や`floating_type`に`boost::multiprecision`の多倍長数値型を使う例です。
|
||||
- [parse_file](https://github.com/ToruNiina/toml11/tree/main/examples/parse_file)
|
||||
- 少し複雑な場合も含めた、型変換の実装例です。対応するTOMLファイルが同梱されています。
|
||||
- [reflect](https://github.com/ToruNiina/toml11/tree/main/examples/reflect)
|
||||
- boost-ext/reflectを用いたユーザー定義型との自型変換の例です。
|
||||
- [unicode](https://github.com/ToruNiina/toml11/tree/main/examples/unicode)
|
||||
- uni-algoを用いて、キーを検索する際にユニコード文字列を正規化する例です。
|
||||
|
||||
## Changes from v3
|
||||
|
||||
toml11 v3からは複数の破壊的変更が追加されています。
|
||||
@@ -466,6 +638,14 @@ toml11 v3からは複数の破壊的変更が追加されています。
|
||||
- Add fuzzing test based on ClusterFuzzLite
|
||||
- Esonhugh Skyworship (@Esonhugh)
|
||||
- Fix function signature of `strerror_r` on macos
|
||||
- Alberto (@0X1A)
|
||||
- Fix issues with CMake package configuration when used with vcpkg
|
||||
- Egor Pugin (@egorpugin)
|
||||
- Fix incorrect operator<<() argument type that gives build error
|
||||
- Andreas Keller (@andreaskeller96)
|
||||
- Fix not checking for \r\n when parsing line comments
|
||||
- 萧迩珀 (@CDK6182CHR)
|
||||
- Support template into_toml members
|
||||
|
||||
## Licensing terms
|
||||
|
||||
|
||||
@@ -4,8 +4,10 @@ environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
generator: Visual Studio 16 2019
|
||||
systemver: 10.0.18362.0
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
||||
generator: Visual Studio 17 2022
|
||||
systemver: 10.0.22621.0
|
||||
|
||||
configuration:
|
||||
- Release
|
||||
@@ -19,7 +21,7 @@ install:
|
||||
|
||||
build_script:
|
||||
- cd C:\toml11
|
||||
- cmake -B build -G"%generator%" -A x64 -DCMAKE_CXX_STANDARD=11 -DTOML11_BUILD_TESTS=ON -DTOML11_PRECOMPILE=ON
|
||||
- cmake -B build -G"%generator%" -DCMAKE_SYSTEM_VERSION="%systemver%" -A x64 -DCMAKE_CXX_STANDARD=11 -DTOML11_BUILD_TESTS=ON -DTOML11_PRECOMPILE=ON
|
||||
- cmake --build build --config "%configuration%"
|
||||
|
||||
test_script:
|
||||
|
||||
@@ -7,19 +7,19 @@ type = "docs"
|
||||
|
||||
日本語版は[こちら](/toml11/ja/)
|
||||
|
||||
## [Installation]({{< relref "/installation" >}})
|
||||
## [Installation](docs/installation)
|
||||
|
||||
This section describes how to build and install toml11.
|
||||
|
||||
## [Features]({{< relref "/features" >}})
|
||||
## [Features](docs/features)
|
||||
|
||||
This section describes how to use toml11's features with examples.
|
||||
|
||||
## [Reference]({{< relref "/reference" >}})
|
||||
## [Reference](docs/reference)
|
||||
|
||||
This section details toml11 functions and classes.
|
||||
|
||||
## [ChangeLog]({{< relref "/changelog" >}})
|
||||
## [ChangeLog](docs/changelog)
|
||||
|
||||
This section describes changes from release to release.
|
||||
|
||||
|
||||
@@ -6,12 +6,60 @@ weight = 4
|
||||
|
||||
# Change Log
|
||||
|
||||
# v4.1.0
|
||||
|
||||
## Added
|
||||
|
||||
- support `std::get<std::u8string>`
|
||||
- support `toml::value(std::u8string)`
|
||||
- support `string_type = std::u8string`
|
||||
- support `operator<<(std::ostream&, toml::value)`
|
||||
- add `bool uppercase` to `toml::integer_format`
|
||||
- support `template into_toml()` (by 萧迩珀)
|
||||
|
||||
## Fixed
|
||||
|
||||
- Fix not checking for `\r\n` when parsing line comments (by Andreas Keller)
|
||||
|
||||
## Changed
|
||||
|
||||
- speedup CI tests by multicore build
|
||||
|
||||
# v4.0.3
|
||||
|
||||
## Fixed
|
||||
|
||||
- remove default template argument from forward declaration in `toml_fwd.hpp`
|
||||
- enable to call `toml::make_error_info` with multiple `toml::value`s
|
||||
- enable to copy/move `toml::result` having `std::reference_wrapper`
|
||||
- fix document generation error with the latest version of hugo
|
||||
- fix several tiny errors that causes warning
|
||||
- fix CMake compatibility warning
|
||||
|
||||
## Changed
|
||||
|
||||
add `-Werror` / `/WX` to build script
|
||||
set MSVC warning level to `/W4`
|
||||
add explanation of features to README
|
||||
|
||||
# v4.0.2
|
||||
|
||||
## Fixed
|
||||
|
||||
- check return value of fread in `parse(FILE*)`
|
||||
- version macro defined in `toml11/version.hpp`
|
||||
- update docs about compilation
|
||||
- update docs about file open mode
|
||||
|
||||
## Changed
|
||||
- use version macros defined in `toml11/version.hpp` as the project version in `CMakeLists.txt`
|
||||
|
||||
# v4.0.1
|
||||
|
||||
## Fixed
|
||||
|
||||
- Resolved naming conflict of `sematic_version::{major, minor}` with macros defined in `<sys/sysmacro.h>`
|
||||
- Fixed the definition of `operator<<` in `discard_comments`
|
||||
- Fixed the definition of `operator<<` in `discard_comments` (by Egor Pugin)
|
||||
- Fixed the issue where the first blank line was not output in `format_location`
|
||||
- Fixed the issue where error messages pointing to `source_location` referring to lines containing only newline characters were displayed in two lines
|
||||
- Corrected links in the README
|
||||
|
||||
@@ -60,10 +60,11 @@ Specifies the radix of an `integer`.
|
||||
```cpp
|
||||
struct integer_format_info
|
||||
{
|
||||
integer_format fmt = integer_format::dec;
|
||||
std::size_t width = 0; // minimal width (may exceed)
|
||||
std::size_t spacer = 0; // position of `_` (if 0, no spacer)
|
||||
std::string suffix = ""; // _suffix (library extension)
|
||||
integer_format fmt = integer_format::dec;
|
||||
bool uppercase = true; // use uppercase letters
|
||||
std::size_t width = 0; // minimal width (may exceed)
|
||||
std::size_t spacer = 0; // position of `_` (if 0, no spacer)
|
||||
std::string suffix = ""; // _suffix (library extension)
|
||||
};
|
||||
|
||||
bool operator==(const integer_format_info&, const integer_format_info&) noexcept;
|
||||
@@ -76,6 +77,10 @@ bool operator!=(const integer_format_info&, const integer_format_info&) noexcept
|
||||
|
||||
Specifies the radix.
|
||||
|
||||
### `bool uppercase`
|
||||
|
||||
Uses uppercase letters when formatted as a hexadecimal integer.
|
||||
|
||||
### `std::size_t width`
|
||||
|
||||
Specifies the minimum width. The formatted value may exceed this width.
|
||||
|
||||
@@ -7,19 +7,19 @@ type = "docs"
|
||||
|
||||
English version is [here](../en/)
|
||||
|
||||
## [Installation]({{< relref "/installation" >}})
|
||||
## [Installation](docs/installation)
|
||||
|
||||
toml11のインストール方法について説明します。
|
||||
|
||||
## [Features]({{< relref "/features" >}})
|
||||
## [Features](docs/features)
|
||||
|
||||
toml11の機能と使い方を例に沿って説明します。
|
||||
|
||||
## [Reference]({{< relref "/reference" >}})
|
||||
## [Reference](docs/reference)
|
||||
|
||||
toml11が持つ関数・クラスの詳細を説明します。
|
||||
|
||||
## [ChangeLog]({{< relref "/changelog" >}})
|
||||
## [ChangeLog](docs/changelog)
|
||||
|
||||
v3系から、そしてリリースごとの変化を説明します。
|
||||
|
||||
|
||||
@@ -6,12 +6,61 @@ weight = 4
|
||||
|
||||
# Change Log
|
||||
|
||||
# v4.1.0
|
||||
|
||||
## Added
|
||||
|
||||
- `std::get<std::u8string>`をサポート
|
||||
- `toml::value(std::u8string)`をサポート
|
||||
- `string_type = std::u8string`をサポート
|
||||
- `operator<<(std::ostream&, toml::value)`をサポート
|
||||
- `toml::integer_format`に、16進数表示で大文字を使うことを指定する`bool uppercase`を追加
|
||||
- `template`を使って実装された `into_toml()` をサポート (by 萧迩珀)
|
||||
|
||||
## Fixed
|
||||
|
||||
- Windowsで`\r\n`が改行に使われた際、出力時に`\r`が重複する問題を修正 (by Andreas Keller)
|
||||
|
||||
## Changed
|
||||
|
||||
- CIで複数コアを使うことでビルドを高速化
|
||||
|
||||
# v4.0.3
|
||||
|
||||
## Fixed
|
||||
|
||||
- `toml_fwd.hpp`を使用した際にデフォルト引数が重複する問題を修正
|
||||
- `toml::value`を複数渡した際に`toml::make_error_info`が使えない問題を修正
|
||||
- `std::reference_wrapper`を持つ`toml::result`をコピー・ムーブする際の問題を修正
|
||||
- hugoの最新版でドキュメントがビルドできない問題を修正
|
||||
- コンパイラによる軽微な警告を多数修正
|
||||
- CMakeの互換性に関する警告を抑制
|
||||
|
||||
## Changed
|
||||
|
||||
- CIビルドで`-Werror`, `/WX`を追加
|
||||
- CIビルドでMSVCのwarningレベルを`/W3`から`/W4`に変更
|
||||
- READMEでより多くの機能を紹介するよう更新
|
||||
|
||||
# v4.0.2
|
||||
|
||||
## Fixed
|
||||
|
||||
- `parse(FILE*)` 内の `fread` の結果をチェック
|
||||
- `toml11/version.hpp`のマクロを修正
|
||||
- コンパイルオプションに関するドキュメントの更新
|
||||
- ファイルオープンモードに関するドキュメントの更新
|
||||
|
||||
## Changed
|
||||
|
||||
- `CMakeLists.txt`内のバージョン番号を`version.hpp`から取得するように変更
|
||||
|
||||
# v4.0.1
|
||||
|
||||
## Fixed
|
||||
|
||||
- `sematic_version::{major, minor}` と `<sys/sysmacro.h>` 内で定義されるマクロの衝突を解消
|
||||
- `discard_comments` の `operator<<` の定義を修正
|
||||
- `discard_comments` の `operator<<` の定義を修正 (by Egor Pugin)
|
||||
- `format_location`を使用した際に最初の空行が出ない問題を解決
|
||||
- 改行文字のみを含む行を指す`source_location`でエラーメッセージを生成した際に、同じ行が二回表示される問題を解決
|
||||
- `README.md`内のリンクを修正
|
||||
|
||||
@@ -60,10 +60,11 @@ std::string to_string(const integer_format);
|
||||
```cpp
|
||||
struct integer_format_info
|
||||
{
|
||||
integer_format fmt = integer_format::dec;
|
||||
std::size_t width = 0; // minimal width (may exceed)
|
||||
std::size_t spacer = 0; // position of `_` (if 0, no spacer)
|
||||
std::string suffix = ""; // _suffix (library extension)
|
||||
integer_format fmt = integer_format::dec;
|
||||
bool uppercase = true; // use uppercase letters
|
||||
std::size_t width = 0; // minimal width (may exceed)
|
||||
std::size_t spacer = 0; // position of `_` (if 0, no spacer)
|
||||
std::string suffix = ""; // _suffix (library extension)
|
||||
};
|
||||
|
||||
bool operator==(const integer_format_info&, const integer_format_info&) noexcept;
|
||||
@@ -76,6 +77,10 @@ bool operator!=(const integer_format_info&, const integer_format_info&) noexcept
|
||||
|
||||
基数を指定します。
|
||||
|
||||
### `bool uppercase`
|
||||
|
||||
16進数表記で大文字を使用します。
|
||||
|
||||
### `std::size_t width`
|
||||
|
||||
最小の幅を指定します。値によってはこの幅を超えることがあります。
|
||||
|
||||
@@ -2,4 +2,5 @@ add_subdirectory(boost_container)
|
||||
add_subdirectory(boost_multiprecision)
|
||||
add_subdirectory(parse_file)
|
||||
add_subdirectory(reflect)
|
||||
add_subdirectory(u8string)
|
||||
add_subdirectory(unicode)
|
||||
|
||||
1
examples/u8string/.gitignore
vendored
Normal file
1
examples/u8string/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
u8string
|
||||
5
examples/u8string/CMakeLists.txt
Normal file
5
examples/u8string/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
add_executable(u8string u8string.cpp)
|
||||
target_link_libraries(u8string PRIVATE toml11::toml11)
|
||||
target_compile_features(u8string PRIVATE cxx_std_20)
|
||||
set_target_properties(u8string PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
23
examples/u8string/spec_example.toml
Normal file
23
examples/u8string/spec_example.toml
Normal file
@@ -0,0 +1,23 @@
|
||||
# This is a TOML document
|
||||
|
||||
title = "TOML Example"
|
||||
|
||||
[owner]
|
||||
name = "Tom Preston-Werner"
|
||||
dob = 1979-05-27T07:32:00-08:00
|
||||
|
||||
[database]
|
||||
enabled = true
|
||||
ports = [ 8000, 8001, 8002 ]
|
||||
data = [ ["delta", "phi"], [3.14] ]
|
||||
temp_targets = { cpu = 79.5, case = 72.0 }
|
||||
|
||||
[servers]
|
||||
|
||||
[servers.alpha]
|
||||
ip = "10.0.0.1"
|
||||
role = "frontend"
|
||||
|
||||
[servers.beta]
|
||||
ip = "10.0.0.2"
|
||||
role = "backend"
|
||||
120
examples/u8string/u8string.cpp
Normal file
120
examples/u8string/u8string.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
#include <toml.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
struct u8config
|
||||
{
|
||||
using comment_type = toml::preserve_comments;
|
||||
|
||||
using boolean_type = bool;
|
||||
using integer_type = std::int64_t;
|
||||
using floating_type = double;
|
||||
using string_type = std::u8string; // XXX
|
||||
|
||||
template<typename T>
|
||||
using array_type = std::vector<T>;
|
||||
template<typename K, typename T>
|
||||
using table_type = std::unordered_map<K, T>;
|
||||
|
||||
static toml::result<integer_type, toml::error_info>
|
||||
parse_int(const std::string& str, const toml::source_location src, const std::uint8_t base)
|
||||
{
|
||||
return toml::read_int<integer_type>(str, src, base);
|
||||
}
|
||||
static toml::result<floating_type, toml::error_info>
|
||||
parse_float(const std::string& str, const toml::source_location src, const bool is_hex)
|
||||
{
|
||||
return toml::read_float<floating_type>(str, src, is_hex);
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
const auto root = toml::parse<u8config>("spec_example.toml");
|
||||
|
||||
// using member functions
|
||||
{
|
||||
assert(root.at(u8"title").as_string() == u8"TOML Example");
|
||||
|
||||
assert(root.at(u8"owner").at(u8"name").as_string() == u8"Tom Preston-Werner");
|
||||
|
||||
const auto dob = root.at(u8"owner").at(u8"dob" ).as_offset_datetime();
|
||||
assert(dob.date .year == 1979);
|
||||
assert(dob.date .month == static_cast<int>(toml::month_t::May));
|
||||
assert(dob.date .day == 27);
|
||||
assert(dob.time .hour == 7);
|
||||
assert(dob.time .minute == 32);
|
||||
assert(dob.time .second == 0);
|
||||
assert(dob.offset.hour == -8);
|
||||
assert(dob.offset.minute == 0);
|
||||
|
||||
assert(root.at(u8"database").at(u8"enabled").as_boolean());
|
||||
assert(root.at(u8"database").at(u8"ports").at(0).as_integer() == 8000);
|
||||
assert(root.at(u8"database").at(u8"ports").at(1).as_integer() == 8001);
|
||||
assert(root.at(u8"database").at(u8"ports").at(2).as_integer() == 8002);
|
||||
assert(root.at(u8"database").at(u8"data").at(0).at(0).as_string() == u8"delta");
|
||||
assert(root.at(u8"database").at(u8"data").at(0).at(1).as_string() == u8"phi");
|
||||
assert(root.at(u8"database").at(u8"data").at(1).at(0).as_floating() == 3.14);
|
||||
assert(root.at(u8"database").at(u8"temp_targets").at(u8"cpu" ).as_floating() == 79.5);
|
||||
assert(root.at(u8"database").at(u8"temp_targets").at(u8"case").as_floating() == 72.0);
|
||||
|
||||
assert(root.at(u8"servers").at(u8"alpha").at(u8"ip" ).as_string() == u8"10.0.0.1");
|
||||
assert(root.at(u8"servers").at(u8"alpha").at(u8"role").as_string() == u8"frontend");
|
||||
assert(root.at(u8"servers").at(u8"beta" ).at(u8"ip" ).as_string() == u8"10.0.0.2");
|
||||
assert(root.at(u8"servers").at(u8"beta" ).at(u8"role").as_string() == u8"backend");
|
||||
}
|
||||
|
||||
// using toml::find
|
||||
{
|
||||
// you can get as std::string from u8string, using toml::get/find
|
||||
assert(toml::find<std::string>(root, u8"title") == "TOML Example");
|
||||
|
||||
assert(toml::find<std::string>(root, u8"owner", u8"name") == "Tom Preston-Werner");
|
||||
|
||||
const auto dob = toml::find<toml::offset_datetime>(root, u8"owner", u8"dob");
|
||||
assert(dob.date .year == 1979);
|
||||
assert(dob.date .month == static_cast<int>(toml::month_t::May));
|
||||
assert(dob.date .day == 27);
|
||||
assert(dob.time .hour == 7);
|
||||
assert(dob.time .minute == 32);
|
||||
assert(dob.time .second == 0);
|
||||
assert(dob.offset.hour == -8);
|
||||
assert(dob.offset.minute == 0);
|
||||
|
||||
assert(toml::find<bool>(root, u8"database", u8"enabled"));
|
||||
|
||||
const auto ports = toml::find<std::vector<int>>(root, u8"database", u8"ports");
|
||||
assert(ports.at(0) == 8000);
|
||||
assert(ports.at(1) == 8001);
|
||||
assert(ports.at(2) == 8002);
|
||||
|
||||
const auto data = toml::find<std::pair<std::vector<std::string>, std::vector<double>>>(root, u8"database", u8"data");
|
||||
assert(data.first.at(0) == "delta");
|
||||
assert(data.first.at(1) == "phi");
|
||||
assert(data.second.at(0) == 3.14);
|
||||
|
||||
const auto temp_targets = toml::find<std::map<std::string, double>>(root, u8"database", u8"temp_targets");
|
||||
assert(temp_targets.at("cpu" ) == 79.5);
|
||||
assert(temp_targets.at("case") == 72.0);
|
||||
|
||||
const auto servers = toml::find<std::map<std::string, std::map<std::string, std::string>>>(root, u8"servers");
|
||||
assert(servers.at("alpha").at("ip" ) == "10.0.0.1");
|
||||
assert(servers.at("alpha").at("role") == "frontend");
|
||||
assert(servers.at("beta" ).at("ip" ) == "10.0.0.2");
|
||||
assert(servers.at("beta" ).at("role") == "backend" );
|
||||
}
|
||||
|
||||
const std::u8string out = toml::format(root);
|
||||
|
||||
std::string printable;
|
||||
std::transform(out.begin(), out.end(), std::back_inserter(printable),
|
||||
[](const char8_t c) {return static_cast<char>(c);});
|
||||
std::cout << printable << std::endl;
|
||||
|
||||
std::cout << "ok." << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -498,7 +498,7 @@ struct source_location
|
||||
static source_location current() { return source_location{}; }
|
||||
};
|
||||
|
||||
inline std::string to_string(const source_location& loc)
|
||||
inline std::string to_string(const source_location&)
|
||||
{
|
||||
return std::string("");
|
||||
}
|
||||
|
||||
@@ -57,9 +57,10 @@ std::string to_string(const integer_format);
|
||||
struct integer_format_info
|
||||
{
|
||||
integer_format fmt = integer_format::dec;
|
||||
std::size_t width = 0; // minimal width (may exceed)
|
||||
std::size_t spacer = 0; // position of `_` (if 0, no spacer)
|
||||
std::string suffix = ""; // _suffix (library extension)
|
||||
bool uppercase = true; // hex with uppercase
|
||||
std::size_t width = 0; // minimal width (may exceed)
|
||||
std::size_t spacer = 0; // position of `_` (if 0, no spacer)
|
||||
std::string suffix = ""; // _suffix (library extension)
|
||||
};
|
||||
|
||||
bool operator==(const integer_format_info&, const integer_format_info&) noexcept;
|
||||
@@ -213,6 +214,29 @@ struct table_format_info
|
||||
bool operator==(const table_format_info&, const table_format_info&) noexcept;
|
||||
bool operator!=(const table_format_info&, const table_format_info&) noexcept;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// key
|
||||
|
||||
enum class key_format : std::uint8_t
|
||||
{
|
||||
bare = 0,
|
||||
quoted = 1, // ""
|
||||
quoted_literal = 2 // ''
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const key_format f);
|
||||
std::string to_string(const key_format);
|
||||
|
||||
struct key_format_info
|
||||
{
|
||||
key_format fmt = key_format::bare;
|
||||
std::int32_t spaces_before_equal = 1;
|
||||
std::int32_t spaces_after_equal = 1;
|
||||
};
|
||||
|
||||
bool operator==(const key_format_info&, const key_format_info&) noexcept;
|
||||
bool operator!=(const key_format_info&, const key_format_info&) noexcept;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wrapper
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "../location.hpp"
|
||||
#include "../types.hpp"
|
||||
#include "../value.hpp"
|
||||
#include "../version.hpp" // IWYU pragma: keep for TOML11_HAS_CHAR8_T
|
||||
|
||||
namespace toml
|
||||
{
|
||||
@@ -21,12 +21,6 @@ inline namespace toml_literals
|
||||
|
||||
::toml::value operator"" _toml(const char* str, std::size_t len);
|
||||
|
||||
#if defined(__cpp_char8_t)
|
||||
# if __cpp_char8_t >= 201811L
|
||||
# define TOML11_HAS_CHAR8_T 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(TOML11_HAS_CHAR8_T)
|
||||
// value of u8"" literal has been changed from char to char8_t and char8_t is
|
||||
// NOT compatible to char
|
||||
|
||||
@@ -109,16 +109,29 @@ get(const basic_value<TC>& v)
|
||||
return static_cast<T>(v.as_floating());
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// std::string with different char/trait/allocator
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<cxx::conjunction<
|
||||
detail::is_not_toml_type<T, basic_value<TC>>,
|
||||
detail::is_1byte_std_basic_string<T>
|
||||
>::value, T>
|
||||
get(const basic_value<TC>& v)
|
||||
{
|
||||
return detail::string_conv<cxx::remove_cvref_t<T>>(v.as_string());
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// std::string_view
|
||||
|
||||
#if defined(TOML11_HAS_STRING_VIEW)
|
||||
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<std::is_same<T, std::string_view>::value, std::string_view>
|
||||
cxx::enable_if_t<detail::is_string_view_of<T, typename basic_value<TC>::string_type>::value, T>
|
||||
get(const basic_value<TC>& v)
|
||||
{
|
||||
return std::string_view(v.as_string());
|
||||
return T(v.as_string());
|
||||
}
|
||||
|
||||
#endif // string_view
|
||||
@@ -175,6 +188,10 @@ cxx::enable_if_t<cxx::conjunction<
|
||||
detail::is_container<T>, // T is a container
|
||||
detail::has_push_back_method<T>, // .push_back() works
|
||||
detail::is_not_toml_type<T, basic_value<TC>>, // but not toml::array
|
||||
cxx::negation<detail::is_std_basic_string<T>>, // but not std::basic_string<CharT>
|
||||
#if defined(TOML11_HAS_STRING_VIEW)
|
||||
cxx::negation<detail::is_std_basic_string_view<T>>, // but not std::basic_string_view<CharT>
|
||||
#endif
|
||||
cxx::negation<detail::has_from_toml_method<T, TC>>, // no T.from_toml()
|
||||
cxx::negation<detail::has_specialized_from<T>>, // no toml::from<T>
|
||||
cxx::negation<std::is_constructible<T, const basic_value<TC>&>>
|
||||
@@ -201,16 +218,33 @@ template<typename T, typename TC>
|
||||
cxx::enable_if_t<detail::is_std_tuple<T>::value, T>
|
||||
get(const basic_value<TC>&);
|
||||
|
||||
// map-like
|
||||
// std::map<key, value> (key is convertible from toml::value::key_type)
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<cxx::conjunction<
|
||||
detail::is_map<T>, // T is map
|
||||
detail::is_not_toml_type<T, basic_value<TC>>, // but not toml::table
|
||||
std::is_convertible<typename basic_value<TC>::key_type,
|
||||
typename T::key_type>, // keys are convertible
|
||||
cxx::negation<detail::has_from_toml_method<T, TC>>, // no T.from_toml()
|
||||
cxx::negation<detail::has_specialized_from<T>>, // no toml::from<T>
|
||||
cxx::negation<std::is_constructible<T, const basic_value<TC>&>>
|
||||
>::value, T>
|
||||
get(const basic_value<TC>&);
|
||||
get(const basic_value<TC>& v);
|
||||
|
||||
// std::map<key, value> (key is not convertible from toml::value::key_type, but
|
||||
// is a std::basic_string)
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<cxx::conjunction<
|
||||
detail::is_map<T>, // T is map
|
||||
detail::is_not_toml_type<T, basic_value<TC>>, // but not toml::table
|
||||
cxx::negation<std::is_convertible<typename basic_value<TC>::key_type,
|
||||
typename T::key_type>>, // keys are NOT convertible
|
||||
detail::is_1byte_std_basic_string<typename T::key_type>, // is std::basic_string
|
||||
cxx::negation<detail::has_from_toml_method<T, TC>>, // no T.from_toml()
|
||||
cxx::negation<detail::has_specialized_from<T>>, // no toml::from<T>
|
||||
cxx::negation<std::is_constructible<T, const basic_value<TC>&>>
|
||||
>::value, T>
|
||||
get(const basic_value<TC>& v);
|
||||
|
||||
// toml::from<T>::from_toml(v)
|
||||
template<typename T, typename TC>
|
||||
@@ -245,6 +279,10 @@ cxx::enable_if_t<cxx::conjunction<
|
||||
detail::is_container<T>, // T is a container
|
||||
detail::has_push_back_method<T>, // .push_back() works
|
||||
detail::is_not_toml_type<T, basic_value<TC>>, // but not toml::array
|
||||
cxx::negation<detail::is_std_basic_string<T>>, // but not std::basic_string<CharT>
|
||||
#if defined(TOML11_HAS_STRING_VIEW)
|
||||
cxx::negation<detail::is_std_basic_string_view<T>>, // but not std::basic_string_view<CharT>
|
||||
#endif
|
||||
cxx::negation<detail::has_from_toml_method<T, TC>>, // no T.from_toml()
|
||||
cxx::negation<detail::has_specialized_from<T>>, // no toml::from<T>
|
||||
cxx::negation<std::is_constructible<T, const basic_value<TC>&>>
|
||||
@@ -363,10 +401,13 @@ get(const basic_value<TC>& v)
|
||||
// ============================================================================
|
||||
// map-like types; most likely STL map, like std::map or std::unordered_map.
|
||||
|
||||
// key is convertible from toml::value::key_type
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<cxx::conjunction<
|
||||
detail::is_map<T>, // T is map
|
||||
detail::is_not_toml_type<T, basic_value<TC>>, // but not toml::table
|
||||
std::is_convertible<typename basic_value<TC>::key_type,
|
||||
typename T::key_type>, // keys are convertible
|
||||
cxx::negation<detail::has_from_toml_method<T, TC>>, // no T.from_toml()
|
||||
cxx::negation<detail::has_specialized_from<T>>, // no toml::from<T>
|
||||
cxx::negation<std::is_constructible<T, const basic_value<TC>&>>
|
||||
@@ -388,6 +429,31 @@ get(const basic_value<TC>& v)
|
||||
return m;
|
||||
}
|
||||
|
||||
// key is NOT convertible from toml::value::key_type but std::basic_string
|
||||
template<typename T, typename TC>
|
||||
cxx::enable_if_t<cxx::conjunction<
|
||||
detail::is_map<T>, // T is map
|
||||
detail::is_not_toml_type<T, basic_value<TC>>, // but not toml::table
|
||||
cxx::negation<std::is_convertible<typename basic_value<TC>::key_type,
|
||||
typename T::key_type>>, // keys are NOT convertible
|
||||
detail::is_1byte_std_basic_string<typename T::key_type>, // is std::basic_string
|
||||
cxx::negation<detail::has_from_toml_method<T, TC>>, // no T.from_toml()
|
||||
cxx::negation<detail::has_specialized_from<T>>, // no toml::from<T>
|
||||
cxx::negation<std::is_constructible<T, const basic_value<TC>&>>
|
||||
>::value, T>
|
||||
get(const basic_value<TC>& v)
|
||||
{
|
||||
using key_type = typename T::key_type;
|
||||
using mapped_type = typename T::mapped_type;
|
||||
|
||||
T m;
|
||||
for(const auto& kv : v.as_table())
|
||||
{
|
||||
m.emplace(detail::string_conv<key_type>(kv.first), get<mapped_type>(kv.second));
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// user-defined, but convertible types.
|
||||
|
||||
|
||||
@@ -66,10 +66,11 @@ TOML11_INLINE std::string to_string(const integer_format c)
|
||||
|
||||
TOML11_INLINE bool operator==(const integer_format_info& lhs, const integer_format_info& rhs) noexcept
|
||||
{
|
||||
return lhs.fmt == rhs.fmt &&
|
||||
lhs.width == rhs.width &&
|
||||
lhs.spacer == rhs.spacer &&
|
||||
lhs.suffix == rhs.suffix ;
|
||||
return lhs.fmt == rhs.fmt &&
|
||||
lhs.uppercase == rhs.uppercase &&
|
||||
lhs.width == rhs.width &&
|
||||
lhs.spacer == rhs.spacer &&
|
||||
lhs.suffix == rhs.suffix ;
|
||||
}
|
||||
TOML11_INLINE bool operator!=(const integer_format_info& lhs, const integer_format_info& rhs) noexcept
|
||||
{
|
||||
@@ -292,5 +293,41 @@ TOML11_INLINE bool operator!=(const table_format_info& lhs, const table_format_i
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// key
|
||||
|
||||
TOML11_INLINE std::ostream& operator<<(std::ostream& os, const key_format f)
|
||||
{
|
||||
switch(f)
|
||||
{
|
||||
case key_format::bare : {os << "bare" ; break;}
|
||||
case key_format::quoted : {os << "quoted" ; break;}
|
||||
case key_format::quoted_literal : {os << "quoted_literal"; break;}
|
||||
default:
|
||||
{
|
||||
os << "unknown key_format: " << static_cast<std::uint8_t>(f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return os;
|
||||
}
|
||||
TOML11_INLINE std::string to_string(const key_format c)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << c;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
TOML11_INLINE bool operator==(const key_format_info& lhs, const key_format_info& rhs) noexcept
|
||||
{
|
||||
return lhs.fmt == rhs.fmt &&
|
||||
lhs.spaces_before_equal == rhs.spaces_before_equal &&
|
||||
lhs.spaces_after_equal == rhs.spaces_after_equal ;
|
||||
}
|
||||
TOML11_INLINE bool operator!=(const key_format_info& lhs, const key_format_info& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
} // namespace toml
|
||||
#endif // TOML11_FORMAT_IMPL_HPP
|
||||
|
||||
@@ -552,6 +552,7 @@ TOML11_INLINE either string(const spec& s)
|
||||
TOML11_INLINE non_ascii_key_char::non_ascii_key_char(const spec& s) noexcept
|
||||
{
|
||||
assert(s.v1_1_0_allow_non_english_in_bare_keys);
|
||||
(void)s; // for NDEBUG
|
||||
}
|
||||
|
||||
TOML11_INLINE std::uint32_t non_ascii_key_char::read_utf8(location& loc) const
|
||||
|
||||
@@ -172,7 +172,7 @@ parse_boolean(location& loc, const context<TC>& ctx)
|
||||
// no format info for boolean
|
||||
boolean_format_info fmt;
|
||||
|
||||
return ok(basic_value<TC>(val, std::move(fmt), {}, std::move(reg)));
|
||||
return ok(basic_value<TC>(val, std::move(fmt), {}, {}, std::move(reg)));
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
@@ -221,7 +221,7 @@ parse_bin_integer(location& loc, const context<TC>& ctx)
|
||||
const auto val = TC::parse_int(str, source_location(region(loc)), 2);
|
||||
if(val.is_ok())
|
||||
{
|
||||
return ok(basic_value<TC>(val.as_ok(), std::move(fmt), {}, std::move(reg)));
|
||||
return ok(basic_value<TC>(val.as_ok(), std::move(fmt), {}, {}, std::move(reg)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -273,7 +273,7 @@ parse_oct_integer(location& loc, const context<TC>& ctx)
|
||||
const auto val = TC::parse_int(str, source_location(region(loc)), 8);
|
||||
if(val.is_ok())
|
||||
{
|
||||
return ok(basic_value<TC>(val.as_ok(), std::move(fmt), {}, std::move(reg)));
|
||||
return ok(basic_value<TC>(val.as_ok(), std::move(fmt), {}, {}, std::move(reg)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -292,7 +292,7 @@ parse_hex_integer(location& loc, const context<TC>& ctx)
|
||||
if( ! reg.is_ok())
|
||||
{
|
||||
return err(make_syntax_error("toml::parse_hex_integer: "
|
||||
"invalid integer: hex_int must be like: 0xC0FFEE, 0xDEAD_BEEF",
|
||||
"invalid integer: hex_int must be like: 0xC0FFEE, 0xdead_beef",
|
||||
syntax::hex_int(spec), loc));
|
||||
}
|
||||
|
||||
@@ -320,10 +320,18 @@ parse_hex_integer(location& loc, const context<TC>& ctx)
|
||||
// 0x0000_0000 becomes empty.
|
||||
if(str.empty()) { str = "0"; }
|
||||
|
||||
// prefix zero and _ is removed. check if it uses upper/lower case.
|
||||
// if both upper and lower case letters are found, set upper=true.
|
||||
const auto lower_not_found = std::find_if(str.begin(), str.end(),
|
||||
[](const char c) { return std::islower(static_cast<int>(c)) != 0; }) == str.end();
|
||||
const auto upper_found = std::find_if(str.begin(), str.end(),
|
||||
[](const char c) { return std::isupper(static_cast<int>(c)) != 0; }) != str.end();
|
||||
fmt.uppercase = lower_not_found || upper_found;
|
||||
|
||||
const auto val = TC::parse_int(str, source_location(region(loc)), 16);
|
||||
if(val.is_ok())
|
||||
{
|
||||
return ok(basic_value<TC>(val.as_ok(), std::move(fmt), {}, std::move(reg)));
|
||||
return ok(basic_value<TC>(val.as_ok(), std::move(fmt), {}, {}, std::move(reg)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -394,7 +402,7 @@ parse_dec_integer(location& loc, const context<TC>& ctx)
|
||||
fmt.suffix = sfx;
|
||||
}
|
||||
|
||||
return ok(basic_value<TC>(val.as_ok(), std::move(fmt), {}, std::move(reg)));
|
||||
return ok(basic_value<TC>(val.as_ok(), std::move(fmt), {}, {}, std::move(reg)));
|
||||
}
|
||||
|
||||
template<typename TC>
|
||||
@@ -659,7 +667,7 @@ parse_floating(location& loc, const context<TC>& ctx)
|
||||
fmt.suffix = sfx;
|
||||
}
|
||||
|
||||
return ok(basic_value<TC>(val, std::move(fmt), {}, std::move(reg)));
|
||||
return ok(basic_value<TC>(val, std::move(fmt), {}, {}, std::move(reg)));
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
@@ -777,7 +785,7 @@ parse_local_date(location& loc, const context<TC>& ctx)
|
||||
auto fmt = std::move(std::get<1>(val_fmt_reg.unwrap()));
|
||||
auto reg = std::move(std::get<2>(val_fmt_reg.unwrap()));
|
||||
|
||||
return ok(basic_value<TC>(std::move(val), std::move(fmt), {}, std::move(reg)));
|
||||
return ok(basic_value<TC>(std::move(val), std::move(fmt), {}, {}, std::move(reg)));
|
||||
}
|
||||
|
||||
// all the offset_datetime, local_datetime, local_time parses date part.
|
||||
@@ -946,7 +954,7 @@ parse_local_time(location& loc, const context<TC>& ctx)
|
||||
auto fmt = std::move(std::get<1>(val_fmt_reg.unwrap()));
|
||||
auto reg = std::move(std::get<2>(val_fmt_reg.unwrap()));
|
||||
|
||||
return ok(basic_value<TC>(std::move(val), std::move(fmt), {}, std::move(reg)));
|
||||
return ok(basic_value<TC>(std::move(val), std::move(fmt), {}, {}, std::move(reg)));
|
||||
}
|
||||
|
||||
template<typename TC>
|
||||
@@ -1005,7 +1013,7 @@ parse_local_datetime(location& loc, const context<TC>& ctx)
|
||||
local_datetime val(std::get<0>(date_fmt_reg.unwrap()),
|
||||
std::get<0>(time_fmt_reg.unwrap()));
|
||||
|
||||
return ok(basic_value<TC>(val, std::move(fmt), {}, std::move(reg)));
|
||||
return ok(basic_value<TC>(val, std::move(fmt), {}, {}, std::move(reg)));
|
||||
}
|
||||
|
||||
template<typename TC>
|
||||
@@ -1132,7 +1140,7 @@ parse_offset_datetime(location& loc, const context<TC>& ctx)
|
||||
std::get<0>(time_fmt_reg.unwrap())),
|
||||
offset);
|
||||
|
||||
return ok(basic_value<TC>(val, std::move(fmt), {}, std::move(reg)));
|
||||
return ok(basic_value<TC>(val, std::move(fmt), {}, {}, std::move(reg)));
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
@@ -1393,7 +1401,7 @@ parse_ml_basic_string(location& loc, const context<TC>& ctx)
|
||||
}
|
||||
|
||||
return ok(basic_value<TC>(
|
||||
std::move(val), std::move(fmt), {}, std::move(reg)
|
||||
std::move(val), std::move(fmt), {}, {}, std::move(reg)
|
||||
));
|
||||
}
|
||||
|
||||
@@ -1473,7 +1481,7 @@ parse_basic_string(location& loc, const context<TC>& ctx)
|
||||
auto val = std::move(val_res.unwrap().first );
|
||||
auto reg = std::move(val_res.unwrap().second);
|
||||
|
||||
return ok(basic_value<TC>(std::move(val), std::move(fmt), {}, std::move(reg)));
|
||||
return ok(basic_value<TC>(std::move(val), std::move(fmt), {}, {}, std::move(reg)));
|
||||
}
|
||||
|
||||
template<typename TC>
|
||||
@@ -1520,7 +1528,7 @@ parse_ml_literal_string(location& loc, const context<TC>& ctx)
|
||||
string_type val(str.begin(), str.end());
|
||||
|
||||
return ok(basic_value<TC>(
|
||||
std::move(val), std::move(fmt), {}, std::move(reg)
|
||||
std::move(val), std::move(fmt), {}, {}, std::move(reg)
|
||||
));
|
||||
}
|
||||
|
||||
@@ -1573,7 +1581,7 @@ parse_literal_string(location& loc, const context<TC>& ctx)
|
||||
auto reg = std::move(val_res.unwrap().second);
|
||||
|
||||
return ok(basic_value<TC>(
|
||||
std::move(val), std::move(fmt), {}, std::move(reg)
|
||||
std::move(val), std::move(fmt), {}, {}, std::move(reg)
|
||||
));
|
||||
}
|
||||
|
||||
@@ -1693,21 +1701,7 @@ parse_simple_key(location& loc, const context<TC>& ctx)
|
||||
|
||||
if(const auto bare = syntax::unquoted_key(spec).scan(loc))
|
||||
{
|
||||
const auto reg = bare.as_string();
|
||||
// here we cannot use `if constexpr` because it is C++11.
|
||||
if(std::is_same<key_type, std::string>::value)
|
||||
{
|
||||
return ok(reg);
|
||||
}
|
||||
else
|
||||
{
|
||||
key_type k;
|
||||
for(const auto c : reg)
|
||||
{
|
||||
k += typename key_type::value_type(c);
|
||||
}
|
||||
return ok(k);
|
||||
}
|
||||
return ok(string_conv<key_type>(bare.as_string()));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1799,6 +1793,9 @@ parse_key_value_pair(location& loc, context<TC>& ctx)
|
||||
// loc = first;
|
||||
return err(v_res.unwrap_err());
|
||||
}
|
||||
|
||||
// set key reg/fmt
|
||||
|
||||
return ok(std::make_pair(std::move(key_res.unwrap()), std::move(v_res.unwrap())));
|
||||
}
|
||||
|
||||
@@ -1855,7 +1852,14 @@ skip_multiline_spacer(location& loc, context<TC>& ctx, const bool newline_found
|
||||
{
|
||||
spacer.newline_found = true;
|
||||
auto comment = comm.as_string();
|
||||
if( ! comment.empty() && comment.back() == '\n') {comment.pop_back();}
|
||||
if( ! comment.empty() && comment.back() == '\n')
|
||||
{
|
||||
comment.pop_back();
|
||||
if (!comment.empty() && comment.back() == '\r')
|
||||
{
|
||||
comment.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
spacer.comments.push_back(std::move(comment));
|
||||
spacer.indent_type = indent_char::none;
|
||||
@@ -2048,7 +2052,7 @@ parse_array(location& loc, context<TC>& ctx)
|
||||
}
|
||||
|
||||
return ok(basic_value<TC>(
|
||||
std::move(val), std::move(fmt), {}, region(first, loc)
|
||||
std::move(val), std::move(fmt), {}, {}, region(first, loc)
|
||||
));
|
||||
}
|
||||
|
||||
@@ -2205,7 +2209,7 @@ insert_value(const inserting_value_kind kind,
|
||||
fmt.fmt = table_format::implicit;
|
||||
}
|
||||
current_table.emplace(key, value_type(
|
||||
table_type{}, fmt, std::vector<std::string>{}, key_reg));
|
||||
table_type{}, fmt, std::vector<std::string>{}, {}, key_reg));
|
||||
|
||||
assert(current_table.at(key).is_table());
|
||||
current_table_ptr = std::addressof(current_table.at(key).as_table());
|
||||
@@ -2352,7 +2356,8 @@ insert_value(const inserting_value_kind kind,
|
||||
|
||||
current_table.emplace(key, value_type(
|
||||
array_type{ std::move(val) }, std::move(fmt),
|
||||
std::vector<std::string>{}, std::move(key_reg)
|
||||
std::vector<std::string>{}, key_format_info{},
|
||||
key_reg, key_reg
|
||||
));
|
||||
|
||||
assert( ! current_table.at(key).as_array().empty());
|
||||
@@ -2603,7 +2608,7 @@ parse_inline_table(location& loc, context<TC>& ctx)
|
||||
}
|
||||
|
||||
basic_value<TC> retval(
|
||||
std::move(table), std::move(fmt), {}, region(first, loc));
|
||||
std::move(table), std::move(fmt), {}, {}, region(first, loc));
|
||||
|
||||
return ok(std::move(retval));
|
||||
}
|
||||
@@ -3170,10 +3175,10 @@ parse_file(location& loc, context<TC>& ctx)
|
||||
|
||||
if(loc.eof())
|
||||
{
|
||||
return ok(value_type(table_type(), table_format_info{}, {}, region(loc)));
|
||||
return ok(value_type(table_type(), table_format_info{}, {}, {}, region(loc)));
|
||||
}
|
||||
|
||||
value_type root(table_type(), table_format_info{}, {}, region(loc));
|
||||
value_type root(table_type(), table_format_info{}, {}, {}, region(loc));
|
||||
root.as_table_fmt().fmt = table_format::multiline;
|
||||
root.as_table_fmt().indent_type = indent_char::none;
|
||||
|
||||
@@ -3278,7 +3283,7 @@ parse_file(location& loc, context<TC>& ctx)
|
||||
table_format_info fmt;
|
||||
fmt.fmt = table_format::multiline;
|
||||
fmt.indent_type = indent_char::none;
|
||||
auto tab = value_type(table_type{}, std::move(fmt), std::move(com), reg);
|
||||
auto tab = value_type(table_type{}, std::move(fmt), std::move(com), {}, reg);
|
||||
|
||||
auto inserted = insert_value(inserting_value_kind::array_table,
|
||||
std::addressof(root.as_table()),
|
||||
@@ -3365,7 +3370,7 @@ parse_file(location& loc, context<TC>& ctx)
|
||||
table_format_info fmt;
|
||||
fmt.fmt = table_format::multiline;
|
||||
fmt.indent_type = indent_char::none;
|
||||
auto tab = value_type(table_type{}, std::move(fmt), std::move(com), reg);
|
||||
auto tab = value_type(table_type{}, std::move(fmt), std::move(com), {}, reg);
|
||||
|
||||
auto inserted = insert_value(inserting_value_kind::std_table,
|
||||
std::addressof(root.as_table()),
|
||||
@@ -3440,7 +3445,7 @@ parse_impl(std::vector<location::char_type> cs, std::string fname, const spec& s
|
||||
{
|
||||
auto src = std::make_shared<std::vector<location::char_type>>(std::move(cs));
|
||||
location loc(std::move(src), std::move(fname));
|
||||
return ok(value_type(table_type(), table_format_info{}, std::vector<std::string>{}, region(loc)));
|
||||
return ok(value_type(table_type(), table_format_info{}, std::vector<std::string>{}, {}, region(loc)));
|
||||
}
|
||||
|
||||
// to simplify parser, add newline at the end if there is no LF.
|
||||
@@ -3525,7 +3530,7 @@ try_parse(std::istream& is, std::string fname = "unknown file", spec s = spec::d
|
||||
// read whole file as a sequence of char
|
||||
assert(fsize >= 0);
|
||||
std::vector<detail::location::char_type> letters(static_cast<std::size_t>(fsize), '\0');
|
||||
is.read(reinterpret_cast<char*>(letters.data()), fsize);
|
||||
is.read(reinterpret_cast<char*>(letters.data()), static_cast<std::streamsize>(fsize));
|
||||
|
||||
return detail::parse_impl<TC>(std::move(letters), std::move(fname), std::move(s));
|
||||
}
|
||||
|
||||
@@ -244,13 +244,13 @@ struct result
|
||||
{
|
||||
if(other.is_ok())
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(other.as_ok());
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(other.succ_);
|
||||
assert(tmp == std::addressof(this->succ_));
|
||||
(void)tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(other.as_err());
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(other.fail_);
|
||||
assert(tmp == std::addressof(this->fail_));
|
||||
(void)tmp;
|
||||
}
|
||||
@@ -259,13 +259,13 @@ struct result
|
||||
{
|
||||
if(other.is_ok())
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(std::move(other.as_ok()));
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(std::move(other.succ_));
|
||||
assert(tmp == std::addressof(this->succ_));
|
||||
(void)tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(std::move(other.as_err()));
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(std::move(other.fail_));
|
||||
assert(tmp == std::addressof(this->fail_));
|
||||
(void)tmp;
|
||||
}
|
||||
@@ -276,13 +276,13 @@ struct result
|
||||
this->cleanup();
|
||||
if(other.is_ok())
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(other.as_ok());
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(other.succ_);
|
||||
assert(tmp == std::addressof(this->succ_));
|
||||
(void)tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(other.as_err());
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(other.fail_);
|
||||
assert(tmp == std::addressof(this->fail_));
|
||||
(void)tmp;
|
||||
}
|
||||
@@ -294,13 +294,13 @@ struct result
|
||||
this->cleanup();
|
||||
if(other.is_ok())
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(std::move(other.as_ok()));
|
||||
auto tmp = ::new(std::addressof(this->succ_)) success_type(std::move(other.succ_));
|
||||
assert(tmp == std::addressof(this->succ_));
|
||||
(void)tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(std::move(other.as_err()));
|
||||
auto tmp = ::new(std::addressof(this->fail_)) failure_type(std::move(other.fail_));
|
||||
assert(tmp == std::addressof(this->fail_));
|
||||
(void)tmp;
|
||||
}
|
||||
|
||||
@@ -59,13 +59,15 @@ class serializer
|
||||
using array_type = typename value_type::array_type ;
|
||||
using table_type = typename value_type::table_type ;
|
||||
|
||||
using char_type = typename string_type::value_type;
|
||||
|
||||
public:
|
||||
|
||||
explicit serializer(const spec& sp)
|
||||
: spec_(sp), force_inline_(false), current_indent_(0)
|
||||
{}
|
||||
|
||||
std::string operator()(const std::vector<key_type>& ks, const value_type& v)
|
||||
string_type operator()(const std::vector<key_type>& ks, const value_type& v)
|
||||
{
|
||||
for(const auto& k : ks)
|
||||
{
|
||||
@@ -74,13 +76,13 @@ class serializer
|
||||
return (*this)(v);
|
||||
}
|
||||
|
||||
std::string operator()(const key_type& k, const value_type& v)
|
||||
string_type operator()(const key_type& k, const value_type& v)
|
||||
{
|
||||
this->keys_.push_back(k);
|
||||
return (*this)(v);
|
||||
}
|
||||
|
||||
std::string operator()(const value_type& v)
|
||||
string_type operator()(const value_type& v)
|
||||
{
|
||||
switch(v.type())
|
||||
{
|
||||
@@ -98,14 +100,14 @@ class serializer
|
||||
}
|
||||
case value_t::table :
|
||||
{
|
||||
std::string retval;
|
||||
string_type retval;
|
||||
if(this->keys_.empty()) // it might be the root table. emit comments here.
|
||||
{
|
||||
retval += format_comments(v.comments(), v.as_table_fmt().indent_type);
|
||||
}
|
||||
if( ! retval.empty()) // we have comment.
|
||||
{
|
||||
retval += '\n';
|
||||
retval += char_type('\n');
|
||||
}
|
||||
|
||||
retval += (*this)(v.as_table(), v.as_table_fmt(), v.comments(), v.location());
|
||||
@@ -115,7 +117,7 @@ class serializer
|
||||
{
|
||||
if(this->spec_.ext_null_value)
|
||||
{
|
||||
return "null";
|
||||
return string_conv<string_type>("null");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -131,12 +133,19 @@ class serializer
|
||||
|
||||
private:
|
||||
|
||||
std::string operator()(const boolean_type& b, const boolean_format_info&, const source_location&) // {{{
|
||||
string_type operator()(const boolean_type& b, const boolean_format_info&, const source_location&) // {{{
|
||||
{
|
||||
if(b) { return std::string("true"); } else { return std::string("false"); }
|
||||
if(b)
|
||||
{
|
||||
return string_conv<string_type>("true");
|
||||
}
|
||||
else
|
||||
{
|
||||
return string_conv<string_type>("false");
|
||||
}
|
||||
} // }}}
|
||||
|
||||
std::string operator()(const integer_type i, const integer_format_info& fmt, const source_location& loc) // {{{
|
||||
string_type operator()(const integer_type i, const integer_format_info& fmt, const source_location& loc) // {{{
|
||||
{
|
||||
std::ostringstream oss;
|
||||
this->set_locale(oss);
|
||||
@@ -180,7 +189,6 @@ class serializer
|
||||
retval += '_';
|
||||
retval += fmt.suffix;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -193,13 +201,27 @@ class serializer
|
||||
{
|
||||
case integer_format::hex:
|
||||
{
|
||||
oss << std::setw(static_cast<int>(fmt.width)) << std::setfill('0') << std::hex << i;
|
||||
return std::string("0x") + insert_spacer(oss.str());
|
||||
oss << std::noshowbase
|
||||
<< std::setw(static_cast<int>(fmt.width))
|
||||
<< std::setfill('0')
|
||||
<< std::hex;
|
||||
if(fmt.uppercase)
|
||||
{
|
||||
oss << std::uppercase;
|
||||
}
|
||||
else
|
||||
{
|
||||
oss << std::nouppercase;
|
||||
}
|
||||
oss << i;
|
||||
retval = std::string("0x") + insert_spacer(oss.str());
|
||||
break;
|
||||
}
|
||||
case integer_format::oct:
|
||||
{
|
||||
oss << std::setw(static_cast<int>(fmt.width)) << std::setfill('0') << std::oct << i;
|
||||
return std::string("0o") + insert_spacer(oss.str());
|
||||
retval = std::string("0o") + insert_spacer(oss.str());
|
||||
break;
|
||||
}
|
||||
case integer_format::bin:
|
||||
{
|
||||
@@ -228,7 +250,8 @@ class serializer
|
||||
{
|
||||
oss << *iter;
|
||||
}
|
||||
return std::string("0b") + oss.str();
|
||||
retval = std::string("0b") + oss.str();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
@@ -238,9 +261,10 @@ class serializer
|
||||
}
|
||||
}
|
||||
}
|
||||
return string_conv<string_type>(retval);
|
||||
} // }}}
|
||||
|
||||
std::string operator()(const floating_type f, const floating_format_info& fmt, const source_location&) // {{{
|
||||
string_type operator()(const floating_type f, const floating_format_info& fmt, const source_location&) // {{{
|
||||
{
|
||||
using std::isnan;
|
||||
using std::isinf;
|
||||
@@ -261,7 +285,7 @@ class serializer
|
||||
oss << '_';
|
||||
oss << fmt.suffix;
|
||||
}
|
||||
return oss.str();
|
||||
return string_conv<string_type>(oss.str());
|
||||
}
|
||||
|
||||
if(isinf(f))
|
||||
@@ -276,7 +300,7 @@ class serializer
|
||||
oss << '_';
|
||||
oss << fmt.suffix;
|
||||
}
|
||||
return oss.str();
|
||||
return string_conv<string_type>(oss.str());
|
||||
}
|
||||
|
||||
switch(fmt.fmt)
|
||||
@@ -301,7 +325,7 @@ class serializer
|
||||
s += '_';
|
||||
s += fmt.suffix;
|
||||
}
|
||||
return s;
|
||||
return string_conv<string_type>(s);
|
||||
}
|
||||
case floating_format::fixed:
|
||||
{
|
||||
@@ -314,7 +338,7 @@ class serializer
|
||||
{
|
||||
oss << '_' << fmt.suffix;
|
||||
}
|
||||
return oss.str();
|
||||
return string_conv<string_type>(oss.str());
|
||||
}
|
||||
case floating_format::scientific:
|
||||
{
|
||||
@@ -327,7 +351,7 @@ class serializer
|
||||
{
|
||||
oss << '_' << fmt.suffix;
|
||||
}
|
||||
return oss.str();
|
||||
return string_conv<string_type>(oss.str());
|
||||
}
|
||||
case floating_format::hex:
|
||||
{
|
||||
@@ -335,14 +359,14 @@ class serializer
|
||||
{
|
||||
oss << std::hexfloat << f;
|
||||
// suffix is only for decimal numbers.
|
||||
return oss.str();
|
||||
return string_conv<string_type>(oss.str());
|
||||
}
|
||||
else // no hex allowed. output with max precision.
|
||||
{
|
||||
oss << std::setprecision(std::numeric_limits<floating_type>::max_digits10)
|
||||
<< std::scientific << f;
|
||||
// suffix is only for decimal numbers.
|
||||
return oss.str();
|
||||
return string_conv<string_type>(oss.str());
|
||||
}
|
||||
}
|
||||
default:
|
||||
@@ -351,58 +375,58 @@ class serializer
|
||||
{
|
||||
oss << '_' << fmt.suffix;
|
||||
}
|
||||
return oss.str();
|
||||
return string_conv<string_type>(oss.str());
|
||||
}
|
||||
}
|
||||
} // }}}
|
||||
|
||||
std::string operator()(string_type s, const string_format_info& fmt, const source_location& loc) // {{{
|
||||
string_type operator()(string_type s, const string_format_info& fmt, const source_location& loc) // {{{
|
||||
{
|
||||
std::string retval;
|
||||
string_type retval;
|
||||
switch(fmt.fmt)
|
||||
{
|
||||
case string_format::basic:
|
||||
{
|
||||
retval += '"';
|
||||
retval += char_type('"');
|
||||
retval += this->escape_basic_string(s);
|
||||
retval += '"';
|
||||
retval += char_type('"');
|
||||
return retval;
|
||||
}
|
||||
case string_format::literal:
|
||||
{
|
||||
if(std::find(s.begin(), s.end(), '\n') != s.end())
|
||||
if(std::find(s.begin(), s.end(), char_type('\n')) != s.end())
|
||||
{
|
||||
throw serialization_error(format_error("toml::serializer: "
|
||||
"(non-multiline) literal string cannot have a newline",
|
||||
loc, "here"), loc);
|
||||
}
|
||||
retval += '\'';
|
||||
retval += char_type('\'');
|
||||
retval += s;
|
||||
retval += '\'';
|
||||
retval += char_type('\'');
|
||||
return retval;
|
||||
}
|
||||
case string_format::multiline_basic:
|
||||
{
|
||||
retval += "\"\"\"";
|
||||
retval += string_conv<string_type>("\"\"\"");
|
||||
if(fmt.start_with_newline)
|
||||
{
|
||||
retval += '\n';
|
||||
retval += char_type('\n');
|
||||
}
|
||||
|
||||
retval += this->escape_ml_basic_string(s);
|
||||
|
||||
retval += "\"\"\"";
|
||||
retval += string_conv<string_type>("\"\"\"");
|
||||
return retval;
|
||||
}
|
||||
case string_format::multiline_literal:
|
||||
{
|
||||
retval += "'''";
|
||||
retval += string_conv<string_type>("'''");
|
||||
if(fmt.start_with_newline)
|
||||
{
|
||||
retval += '\n';
|
||||
retval += char_type('\n');
|
||||
}
|
||||
retval += s;
|
||||
retval += "'''";
|
||||
retval += string_conv<string_type>("'''");
|
||||
return retval;
|
||||
}
|
||||
default:
|
||||
@@ -414,19 +438,19 @@ class serializer
|
||||
}
|
||||
} // }}}
|
||||
|
||||
std::string operator()(const local_date_type& d, const local_date_format_info&, const source_location&) // {{{
|
||||
string_type operator()(const local_date_type& d, const local_date_format_info&, const source_location&) // {{{
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << d;
|
||||
return oss.str();
|
||||
return string_conv<string_type>(oss.str());
|
||||
} // }}}
|
||||
|
||||
std::string operator()(const local_time_type& t, const local_time_format_info& fmt, const source_location&) // {{{
|
||||
string_type operator()(const local_time_type& t, const local_time_format_info& fmt, const source_location&) // {{{
|
||||
{
|
||||
return this->format_local_time(t, fmt.has_seconds, fmt.subsecond_precision);
|
||||
} // }}}
|
||||
|
||||
std::string operator()(const local_datetime_type& dt, const local_datetime_format_info& fmt, const source_location&) // {{{
|
||||
string_type operator()(const local_datetime_type& dt, const local_datetime_format_info& fmt, const source_location&) // {{{
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << dt.date;
|
||||
@@ -437,11 +461,11 @@ class serializer
|
||||
case datetime_delimiter_kind::space: { oss << ' '; break; }
|
||||
default: { oss << 'T'; break; }
|
||||
}
|
||||
oss << this->format_local_time(dt.time, fmt.has_seconds, fmt.subsecond_precision);
|
||||
return oss.str();
|
||||
return string_conv<string_type>(oss.str()) +
|
||||
this->format_local_time(dt.time, fmt.has_seconds, fmt.subsecond_precision);
|
||||
} // }}}
|
||||
|
||||
std::string operator()(const offset_datetime_type& odt, const offset_datetime_format_info& fmt, const source_location&) // {{{
|
||||
string_type operator()(const offset_datetime_type& odt, const offset_datetime_format_info& fmt, const source_location&) // {{{
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << odt.date;
|
||||
@@ -452,12 +476,12 @@ class serializer
|
||||
case datetime_delimiter_kind::space: { oss << ' '; break; }
|
||||
default: { oss << 'T'; break; }
|
||||
}
|
||||
oss << this->format_local_time(odt.time, fmt.has_seconds, fmt.subsecond_precision);
|
||||
oss << string_conv<std::string>(this->format_local_time(odt.time, fmt.has_seconds, fmt.subsecond_precision));
|
||||
oss << odt.offset;
|
||||
return oss.str();
|
||||
return string_conv<string_type>(oss.str());
|
||||
} // }}}
|
||||
|
||||
std::string operator()(const array_type& a, const array_format_info& fmt, const comment_type& com, const source_location& loc) // {{{
|
||||
string_type operator()(const array_type& a, const array_format_info& fmt, const comment_type& com, const source_location& loc) // {{{
|
||||
{
|
||||
array_format f = fmt.fmt;
|
||||
if(fmt.fmt == array_format::default_format)
|
||||
@@ -546,7 +570,7 @@ class serializer
|
||||
throw serialization_error("array of table must have its key. "
|
||||
"use format(key, v)", loc);
|
||||
}
|
||||
std::string retval;
|
||||
string_type retval;
|
||||
for(const auto& e : a)
|
||||
{
|
||||
assert(e.is_table());
|
||||
@@ -556,9 +580,9 @@ class serializer
|
||||
retval += this->format_indent(e.as_table_fmt().indent_type);
|
||||
this->current_indent_ -= e.as_table_fmt().name_indent;
|
||||
|
||||
retval += "[[";
|
||||
retval += string_conv<string_type>("[[");
|
||||
retval += this->format_keys(this->keys_).value();
|
||||
retval += "]]\n";
|
||||
retval += string_conv<string_type>("]]\n");
|
||||
|
||||
retval += this->format_ml_table(e.as_table(), e.as_table_fmt());
|
||||
}
|
||||
@@ -567,20 +591,20 @@ class serializer
|
||||
else if(f == array_format::oneline)
|
||||
{
|
||||
// ignore comments. we cannot emit comments
|
||||
std::string retval;
|
||||
retval += "[";
|
||||
string_type retval;
|
||||
retval += char_type('[');
|
||||
for(const auto& e : a)
|
||||
{
|
||||
this->force_inline_ = true;
|
||||
retval += (*this)(e);
|
||||
retval += ", ";
|
||||
retval += string_conv<string_type>(", ");
|
||||
}
|
||||
if( ! a.empty())
|
||||
{
|
||||
retval.pop_back(); // ` `
|
||||
retval.pop_back(); // `,`
|
||||
}
|
||||
retval += "]";
|
||||
retval += char_type(']');
|
||||
this->force_inline_ = false;
|
||||
return retval;
|
||||
}
|
||||
@@ -588,32 +612,32 @@ class serializer
|
||||
{
|
||||
assert(f == array_format::multiline);
|
||||
|
||||
std::string retval;
|
||||
retval += "[\n";
|
||||
string_type retval;
|
||||
retval += string_conv<string_type>("[\n");
|
||||
|
||||
for(const auto& e : a)
|
||||
{
|
||||
this->current_indent_ += fmt.body_indent;
|
||||
retval += format_comments(e.comments(), fmt.indent_type);
|
||||
retval += format_indent(fmt.indent_type);
|
||||
retval += this->format_comments(e.comments(), fmt.indent_type);
|
||||
retval += this->format_indent(fmt.indent_type);
|
||||
this->current_indent_ -= fmt.body_indent;
|
||||
|
||||
this->force_inline_ = true;
|
||||
retval += (*this)(e);
|
||||
retval += ",\n";
|
||||
retval += string_conv<string_type>(",\n");
|
||||
}
|
||||
this->force_inline_ = false;
|
||||
|
||||
this->current_indent_ += fmt.closing_indent;
|
||||
retval += format_indent(fmt.indent_type);
|
||||
retval += this->format_indent(fmt.indent_type);
|
||||
this->current_indent_ -= fmt.closing_indent;
|
||||
|
||||
retval += "]";
|
||||
retval += char_type(']');
|
||||
return retval;
|
||||
}
|
||||
} // }}}
|
||||
|
||||
std::string operator()(const table_type& t, const table_format_info& fmt, const comment_type& com, const source_location& loc) // {{{
|
||||
string_type operator()(const table_type& t, const table_format_info& fmt, const comment_type& com, const source_location& loc) // {{{
|
||||
{
|
||||
if(this->force_inline_)
|
||||
{
|
||||
@@ -630,17 +654,17 @@ class serializer
|
||||
{
|
||||
if(fmt.fmt == table_format::multiline)
|
||||
{
|
||||
std::string retval;
|
||||
string_type retval;
|
||||
// comment is emitted inside format_ml_table
|
||||
if(auto k = this->format_keys(this->keys_))
|
||||
{
|
||||
this->current_indent_ += fmt.name_indent;
|
||||
retval += format_comments(com, fmt.indent_type);
|
||||
retval += format_indent(fmt.indent_type);
|
||||
retval += this->format_comments(com, fmt.indent_type);
|
||||
retval += this->format_indent(fmt.indent_type);
|
||||
this->current_indent_ -= fmt.name_indent;
|
||||
retval += '[';
|
||||
retval += char_type('[');
|
||||
retval += k.value();
|
||||
retval += "]\n";
|
||||
retval += string_conv<string_type>("]\n");
|
||||
}
|
||||
// otherwise, its the root.
|
||||
|
||||
@@ -657,7 +681,7 @@ class serializer
|
||||
}
|
||||
else if(fmt.fmt == table_format::dotted)
|
||||
{
|
||||
std::vector<std::string> keys;
|
||||
std::vector<string_type> keys;
|
||||
if(this->keys_.empty())
|
||||
{
|
||||
throw serialization_error(format_error("toml::serializer: "
|
||||
@@ -674,7 +698,7 @@ class serializer
|
||||
{
|
||||
assert(fmt.fmt == table_format::implicit);
|
||||
|
||||
std::string retval;
|
||||
string_type retval;
|
||||
for(const auto& kv : t)
|
||||
{
|
||||
const auto& k = kv.first;
|
||||
@@ -722,46 +746,48 @@ class serializer
|
||||
|
||||
private:
|
||||
|
||||
std::string escape_basic_string(const std::string& s) const // {{{
|
||||
string_type escape_basic_string(const string_type& s) const // {{{
|
||||
{
|
||||
std::string retval;
|
||||
for(const char c : s)
|
||||
string_type retval;
|
||||
for(const char_type c : s)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case '\\': {retval += "\\\\"; break;}
|
||||
case '\"': {retval += "\\\""; break;}
|
||||
case '\b': {retval += "\\b"; break;}
|
||||
case '\t': {retval += "\\t"; break;}
|
||||
case '\f': {retval += "\\f"; break;}
|
||||
case '\n': {retval += "\\n"; break;}
|
||||
case '\r': {retval += "\\r"; break;}
|
||||
case char_type('\\'): {retval += string_conv<string_type>("\\\\"); break;}
|
||||
case char_type('\"'): {retval += string_conv<string_type>("\\\""); break;}
|
||||
case char_type('\b'): {retval += string_conv<string_type>("\\b" ); break;}
|
||||
case char_type('\t'): {retval += string_conv<string_type>("\\t" ); break;}
|
||||
case char_type('\f'): {retval += string_conv<string_type>("\\f" ); break;}
|
||||
case char_type('\n'): {retval += string_conv<string_type>("\\n" ); break;}
|
||||
case char_type('\r'): {retval += string_conv<string_type>("\\r" ); break;}
|
||||
default :
|
||||
{
|
||||
if(c == 0x1B && spec_.v1_1_0_add_escape_sequence_e)
|
||||
if(c == char_type(0x1B) && spec_.v1_1_0_add_escape_sequence_e)
|
||||
{
|
||||
retval += "\\e";
|
||||
retval += string_conv<string_type>("\\e");
|
||||
}
|
||||
else if((0x00 <= c && c <= 0x08) || (0x0A <= c && c <= 0x1F) || c == 0x7F)
|
||||
else if((char_type(0x00) <= c && c <= char_type(0x08)) ||
|
||||
(char_type(0x0A) <= c && c <= char_type(0x1F)) ||
|
||||
c == char_type(0x7F))
|
||||
{
|
||||
if(spec_.v1_1_0_add_escape_sequence_x)
|
||||
{
|
||||
retval += "\\x";
|
||||
retval += string_conv<string_type>("\\x");
|
||||
}
|
||||
else
|
||||
{
|
||||
retval += "\\u00";
|
||||
retval += string_conv<string_type>("\\u00");
|
||||
}
|
||||
const auto c1 = c / 16;
|
||||
const auto c2 = c % 16;
|
||||
retval += static_cast<char>('0' + c1);
|
||||
retval += static_cast<char_type>('0' + c1);
|
||||
if(c2 < 10)
|
||||
{
|
||||
retval += static_cast<char>('0' + c2);
|
||||
retval += static_cast<char_type>('0' + c2);
|
||||
}
|
||||
else // 10 <= c2
|
||||
{
|
||||
retval += static_cast<char>('A' + (c2 - 10));
|
||||
retval += static_cast<char_type>('A' + (c2 - 10));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -774,45 +800,47 @@ class serializer
|
||||
return retval;
|
||||
} // }}}
|
||||
|
||||
std::string escape_ml_basic_string(const std::string& s) // {{{
|
||||
string_type escape_ml_basic_string(const string_type& s) // {{{
|
||||
{
|
||||
std::string retval;
|
||||
for(const char c : s)
|
||||
string_type retval;
|
||||
for(const char_type c : s)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case '\\': {retval += "\\\\"; break;}
|
||||
case '\b': {retval += "\\b"; break;}
|
||||
case '\t': {retval += "\\t"; break;}
|
||||
case '\f': {retval += "\\f"; break;}
|
||||
case '\n': {retval += "\n"; break;}
|
||||
case '\r': {retval += "\\r"; break;}
|
||||
case char_type('\\'): {retval += string_conv<string_type>("\\\\"); break;}
|
||||
case char_type('\b'): {retval += string_conv<string_type>("\\b" ); break;}
|
||||
case char_type('\t'): {retval += string_conv<string_type>("\\t" ); break;}
|
||||
case char_type('\f'): {retval += string_conv<string_type>("\\f" ); break;}
|
||||
case char_type('\n'): {retval += string_conv<string_type>("\n" ); break;}
|
||||
case char_type('\r'): {retval += string_conv<string_type>("\\r" ); break;}
|
||||
default :
|
||||
{
|
||||
if(c == 0x1B && spec_.v1_1_0_add_escape_sequence_e)
|
||||
if(c == char_type(0x1B) && spec_.v1_1_0_add_escape_sequence_e)
|
||||
{
|
||||
retval += "\\e";
|
||||
retval += string_conv<string_type>("\\e");
|
||||
}
|
||||
else if((0x00 <= c && c <= 0x08) || (0x0A <= c && c <= 0x1F) || c == 0x7F)
|
||||
else if((char_type(0x00) <= c && c <= char_type(0x08)) ||
|
||||
(char_type(0x0A) <= c && c <= char_type(0x1F)) ||
|
||||
c == char_type(0x7F))
|
||||
{
|
||||
if(spec_.v1_1_0_add_escape_sequence_x)
|
||||
{
|
||||
retval += "\\x";
|
||||
retval += string_conv<string_type>("\\x");
|
||||
}
|
||||
else
|
||||
{
|
||||
retval += "\\u00";
|
||||
retval += string_conv<string_type>("\\u00");
|
||||
}
|
||||
const auto c1 = c / 16;
|
||||
const auto c2 = c % 16;
|
||||
retval += static_cast<char>('0' + c1);
|
||||
retval += static_cast<char_type>('0' + c1);
|
||||
if(c2 < 10)
|
||||
{
|
||||
retval += static_cast<char>('0' + c2);
|
||||
retval += static_cast<char_type>('0' + c2);
|
||||
}
|
||||
else // 10 <= c2
|
||||
{
|
||||
retval += static_cast<char>('A' + (c2 - 10));
|
||||
retval += static_cast<char_type>('A' + (c2 - 10));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -833,16 +861,16 @@ class serializer
|
||||
// str5 = """Here are three quotation marks: ""\"."""
|
||||
// str6 = """Here are fifteen quotation marks: ""\"""\"""\"""\"""\"."""
|
||||
// ```
|
||||
auto found_3_quotes = retval.find("\"\"\"");
|
||||
while(found_3_quotes != std::string::npos)
|
||||
auto found_3_quotes = retval.find(string_conv<string_type>("\"\"\""));
|
||||
while(found_3_quotes != string_type::npos)
|
||||
{
|
||||
retval.replace(found_3_quotes, 3, "\"\"\\\"");
|
||||
found_3_quotes = retval.find("\"\"\"");
|
||||
retval.replace(found_3_quotes, 3, string_conv<string_type>("\"\"\\\""));
|
||||
found_3_quotes = retval.find(string_conv<string_type>("\"\"\""));
|
||||
}
|
||||
return retval;
|
||||
} // }}}
|
||||
|
||||
std::string format_local_time(const local_time_type& t, const bool has_seconds, const std::size_t subsec_prec) // {{{
|
||||
string_type format_local_time(const local_time_type& t, const bool has_seconds, const std::size_t subsec_prec) // {{{
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << std::setfill('0') << std::setw(2) << static_cast<int>(t.hour);
|
||||
@@ -862,10 +890,10 @@ class serializer
|
||||
oss << '.' << subsec_str.substr(0, subsec_prec);
|
||||
}
|
||||
}
|
||||
return oss.str();
|
||||
return string_conv<string_type>(oss.str());
|
||||
} // }}}
|
||||
|
||||
std::string format_ml_table(const table_type& t, const table_format_info& fmt) // {{{
|
||||
string_type format_ml_table(const table_type& t, const table_format_info& fmt) // {{{
|
||||
{
|
||||
const auto format_later = [](const value_type& v) -> bool {
|
||||
|
||||
@@ -881,7 +909,7 @@ class serializer
|
||||
return is_ml_table || is_ml_array_table;
|
||||
};
|
||||
|
||||
std::string retval;
|
||||
string_type retval;
|
||||
this->current_indent_ += fmt.body_indent;
|
||||
for(const auto& kv : t)
|
||||
{
|
||||
@@ -902,9 +930,9 @@ class serializer
|
||||
else
|
||||
{
|
||||
retval += format_key(key);
|
||||
retval += " = ";
|
||||
retval += string_conv<string_type>(" = ");
|
||||
retval += (*this)(val);
|
||||
retval += "\n";
|
||||
retval += char_type('\n');
|
||||
}
|
||||
this->keys_.pop_back();
|
||||
}
|
||||
@@ -912,7 +940,7 @@ class serializer
|
||||
|
||||
if( ! retval.empty())
|
||||
{
|
||||
retval += "\n"; // for readability, add empty line between tables
|
||||
retval += char_type('\n'); // for readability, add empty line between tables
|
||||
}
|
||||
for(const auto& kv : t)
|
||||
{
|
||||
@@ -929,33 +957,33 @@ class serializer
|
||||
return retval;
|
||||
} // }}}
|
||||
|
||||
std::string format_inline_table(const table_type& t, const table_format_info&) // {{{
|
||||
string_type format_inline_table(const table_type& t, const table_format_info&) // {{{
|
||||
{
|
||||
// comments are ignored because we cannot write without newline
|
||||
std::string retval;
|
||||
retval += '{';
|
||||
string_type retval;
|
||||
retval += char_type('{');
|
||||
for(const auto& kv : t)
|
||||
{
|
||||
this->force_inline_ = true;
|
||||
retval += this->format_key(kv.first);
|
||||
retval += " = ";
|
||||
retval += string_conv<string_type>(" = ");
|
||||
retval += (*this)(kv.second);
|
||||
retval += ", ";
|
||||
retval += string_conv<string_type>(", ");
|
||||
}
|
||||
if( ! t.empty())
|
||||
{
|
||||
retval.pop_back(); // ' '
|
||||
retval.pop_back(); // ','
|
||||
}
|
||||
retval += '}';
|
||||
retval += char_type('}');
|
||||
this->force_inline_ = false;
|
||||
return retval;
|
||||
} // }}}
|
||||
|
||||
std::string format_ml_inline_table(const table_type& t, const table_format_info& fmt) // {{{
|
||||
string_type format_ml_inline_table(const table_type& t, const table_format_info& fmt) // {{{
|
||||
{
|
||||
std::string retval;
|
||||
retval += "{\n";
|
||||
string_type retval;
|
||||
retval += string_conv<string_type>("{\n");
|
||||
this->current_indent_ += fmt.body_indent;
|
||||
for(const auto& kv : t)
|
||||
{
|
||||
@@ -963,12 +991,12 @@ class serializer
|
||||
retval += format_comments(kv.second.comments(), fmt.indent_type);
|
||||
retval += format_indent(fmt.indent_type);
|
||||
retval += kv.first;
|
||||
retval += " = ";
|
||||
retval += string_conv<string_type>(" = ");
|
||||
|
||||
this->force_inline_ = true;
|
||||
retval += (*this)(kv.second);
|
||||
|
||||
retval += ",\n";
|
||||
retval += string_conv<string_type>(",\n");
|
||||
}
|
||||
if( ! t.empty())
|
||||
{
|
||||
@@ -982,12 +1010,12 @@ class serializer
|
||||
retval += format_indent(fmt.indent_type);
|
||||
this->current_indent_ -= fmt.closing_indent;
|
||||
|
||||
retval += '}';
|
||||
retval += char_type('}');
|
||||
return retval;
|
||||
} // }}}
|
||||
|
||||
std::string format_dotted_table(const table_type& t, const table_format_info& fmt, // {{{
|
||||
const source_location&, std::vector<std::string>& keys)
|
||||
string_type format_dotted_table(const table_type& t, const table_format_info& fmt, // {{{
|
||||
const source_location&, std::vector<string_type>& keys)
|
||||
{
|
||||
// lets say we have: `{"a": {"b": {"c": {"d": "foo", "e": "bar"} } }`
|
||||
// and `a` and `b` are `dotted`.
|
||||
@@ -1003,7 +1031,7 @@ class serializer
|
||||
// a.b.c.e = "bar"
|
||||
// ```
|
||||
|
||||
std::string retval;
|
||||
string_type retval;
|
||||
|
||||
for(const auto& kv : t)
|
||||
{
|
||||
@@ -1024,10 +1052,10 @@ class serializer
|
||||
retval += format_comments(val.comments(), fmt.indent_type);
|
||||
retval += format_indent(fmt.indent_type);
|
||||
retval += format_keys(keys).value();
|
||||
retval += " = ";
|
||||
retval += string_conv<string_type>(" = ");
|
||||
this->force_inline_ = true; // sub-table must be inlined
|
||||
retval += (*this)(val);
|
||||
retval += '\n';
|
||||
retval += char_type('\n');
|
||||
this->force_inline_ = false;
|
||||
}
|
||||
keys.pop_back();
|
||||
@@ -1035,15 +1063,15 @@ class serializer
|
||||
return retval;
|
||||
} // }}}
|
||||
|
||||
std::string format_key(const key_type& key) // {{{
|
||||
string_type format_key(const key_type& key) // {{{
|
||||
{
|
||||
if(key.empty())
|
||||
{
|
||||
return std::string("\"\"");
|
||||
return string_conv<string_type>("\"\"");
|
||||
}
|
||||
|
||||
// check the key can be a bare (unquoted) key
|
||||
auto loc = detail::make_temporary_location(key);
|
||||
auto loc = detail::make_temporary_location(string_conv<std::string>(key));
|
||||
auto reg = detail::syntax::unquoted_key(this->spec_).scan(loc);
|
||||
if(reg.is_ok() && loc.eof())
|
||||
{
|
||||
@@ -1051,41 +1079,43 @@ class serializer
|
||||
}
|
||||
|
||||
//if it includes special characters, then format it in a "quoted" key.
|
||||
std::string formatted("\"");
|
||||
for(const char c : key)
|
||||
string_type formatted = string_conv<string_type>("\"");
|
||||
for(const char_type c : key)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case '\\': {formatted += "\\\\"; break;}
|
||||
case '\"': {formatted += "\\\""; break;}
|
||||
case '\b': {formatted += "\\b"; break;}
|
||||
case '\t': {formatted += "\\t"; break;}
|
||||
case '\f': {formatted += "\\f"; break;}
|
||||
case '\n': {formatted += "\\n"; break;}
|
||||
case '\r': {formatted += "\\r"; break;}
|
||||
case char_type('\\'): {formatted += string_conv<string_type>("\\\\"); break;}
|
||||
case char_type('\"'): {formatted += string_conv<string_type>("\\\""); break;}
|
||||
case char_type('\b'): {formatted += string_conv<string_type>("\\b" ); break;}
|
||||
case char_type('\t'): {formatted += string_conv<string_type>("\\t" ); break;}
|
||||
case char_type('\f'): {formatted += string_conv<string_type>("\\f" ); break;}
|
||||
case char_type('\n'): {formatted += string_conv<string_type>("\\n" ); break;}
|
||||
case char_type('\r'): {formatted += string_conv<string_type>("\\r" ); break;}
|
||||
default :
|
||||
{
|
||||
// ASCII ctrl char
|
||||
if((0x00 <= c && c <= 0x08) || (0x0A <= c && c <= 0x1F) || c == 0x7F)
|
||||
if( (char_type(0x00) <= c && c <= char_type(0x08)) ||
|
||||
(char_type(0x0A) <= c && c <= char_type(0x1F)) ||
|
||||
c == char_type(0x7F))
|
||||
{
|
||||
if(spec_.v1_1_0_add_escape_sequence_x)
|
||||
{
|
||||
formatted += "\\x";
|
||||
formatted += string_conv<string_type>("\\x");
|
||||
}
|
||||
else
|
||||
{
|
||||
formatted += "\\u00";
|
||||
formatted += string_conv<string_type>("\\u00");
|
||||
}
|
||||
const auto c1 = c / 16;
|
||||
const auto c2 = c % 16;
|
||||
formatted += static_cast<char>('0' + c1);
|
||||
formatted += static_cast<char_type>('0' + c1);
|
||||
if(c2 < 10)
|
||||
{
|
||||
formatted += static_cast<char>('0' + c2);
|
||||
formatted += static_cast<char_type>('0' + c2);
|
||||
}
|
||||
else // 10 <= c2
|
||||
{
|
||||
formatted += static_cast<char>('A' + (c2 - 10));
|
||||
formatted += static_cast<char_type>('A' + (c2 - 10));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1096,58 +1126,58 @@ class serializer
|
||||
}
|
||||
}
|
||||
}
|
||||
formatted += "\"";
|
||||
formatted += string_conv<string_type>("\"");
|
||||
return formatted;
|
||||
} // }}}
|
||||
cxx::optional<std::string> format_keys(const std::vector<key_type>& keys) // {{{
|
||||
cxx::optional<string_type> format_keys(const std::vector<key_type>& keys) // {{{
|
||||
{
|
||||
if(keys.empty())
|
||||
{
|
||||
return cxx::make_nullopt();
|
||||
}
|
||||
|
||||
std::string formatted;
|
||||
string_type formatted;
|
||||
for(const auto& ky : keys)
|
||||
{
|
||||
formatted += format_key(ky);
|
||||
formatted += '.';
|
||||
formatted += char_type('.');
|
||||
}
|
||||
formatted.pop_back(); // remove the last dot '.'
|
||||
return formatted;
|
||||
} // }}}
|
||||
|
||||
std::string format_comments(const discard_comments&, const indent_char) const // {{{
|
||||
string_type format_comments(const discard_comments&, const indent_char) const // {{{
|
||||
{
|
||||
return "";
|
||||
return string_conv<string_type>("");
|
||||
} // }}}
|
||||
std::string format_comments(const preserve_comments& comments, const indent_char indent_type) const // {{{
|
||||
string_type format_comments(const preserve_comments& comments, const indent_char indent_type) const // {{{
|
||||
{
|
||||
std::string retval;
|
||||
string_type retval;
|
||||
for(const auto& c : comments)
|
||||
{
|
||||
if(c.empty()) {continue;}
|
||||
retval += format_indent(indent_type);
|
||||
if(c.front() != '#') {retval += '#';}
|
||||
retval += c;
|
||||
if(c.back() != '\n') {retval += '\n';}
|
||||
if(c.front() != '#') {retval += char_type('#');}
|
||||
retval += string_conv<string_type>(c);
|
||||
if(c.back() != '\n') {retval += char_type('\n');}
|
||||
}
|
||||
return retval;
|
||||
} // }}}
|
||||
|
||||
std::string format_indent(const indent_char indent_type) const // {{{
|
||||
string_type format_indent(const indent_char indent_type) const // {{{
|
||||
{
|
||||
const auto indent = static_cast<std::size_t>((std::max)(0, this->current_indent_));
|
||||
if(indent_type == indent_char::space)
|
||||
{
|
||||
return detail::make_string(indent, ' ');
|
||||
return string_conv<string_type>(make_string(indent, ' '));
|
||||
}
|
||||
else if(indent_type == indent_char::tab)
|
||||
{
|
||||
return detail::make_string(indent, '\t');
|
||||
return string_conv<string_type>(make_string(indent, '\t'));
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
return string_type{};
|
||||
}
|
||||
} // }}}
|
||||
|
||||
@@ -1166,29 +1196,38 @@ class serializer
|
||||
} // detail
|
||||
|
||||
template<typename TC>
|
||||
std::string format(const basic_value<TC>& v,
|
||||
const spec s = spec::default_version())
|
||||
typename basic_value<TC>::string_type
|
||||
format(const basic_value<TC>& v, const spec s = spec::default_version())
|
||||
{
|
||||
detail::serializer<TC> ser(s);
|
||||
return ser(v);
|
||||
}
|
||||
template<typename TC>
|
||||
std::string format(const typename basic_value<TC>::key_type& k,
|
||||
const basic_value<TC>& v,
|
||||
const spec s = spec::default_version())
|
||||
typename basic_value<TC>::string_type
|
||||
format(const typename basic_value<TC>::key_type& k,
|
||||
const basic_value<TC>& v,
|
||||
const spec s = spec::default_version())
|
||||
{
|
||||
detail::serializer<TC> ser(s);
|
||||
return ser(k, v);
|
||||
}
|
||||
template<typename TC>
|
||||
std::string format(const std::vector<typename basic_value<TC>::key_type>& ks,
|
||||
const basic_value<TC>& v,
|
||||
const spec s = spec::default_version())
|
||||
typename basic_value<TC>::string_type
|
||||
format(const std::vector<typename basic_value<TC>::key_type>& ks,
|
||||
const basic_value<TC>& v,
|
||||
const spec s = spec::default_version())
|
||||
{
|
||||
detail::serializer<TC> ser(s);
|
||||
return ser(ks, v);
|
||||
}
|
||||
|
||||
template<typename TC>
|
||||
std::ostream& operator<<(std::ostream& os, const basic_value<TC>& v)
|
||||
{
|
||||
os << format(v);
|
||||
return os;
|
||||
}
|
||||
|
||||
} // toml
|
||||
|
||||
#if defined(TOML11_COMPILE_SOURCES)
|
||||
@@ -1197,25 +1236,25 @@ namespace toml
|
||||
struct type_config;
|
||||
struct ordered_type_config;
|
||||
|
||||
extern template std::string
|
||||
extern template typename basic_value<type_config>::string_type
|
||||
format<type_config>(const basic_value<type_config>&, const spec);
|
||||
|
||||
extern template std::string
|
||||
extern template typename basic_value<type_config>::string_type
|
||||
format<type_config>(const typename basic_value<type_config>::key_type& k,
|
||||
const basic_value<type_config>& v, const spec);
|
||||
|
||||
extern template std::string
|
||||
extern template typename basic_value<type_config>::string_type
|
||||
format<type_config>(const std::vector<typename basic_value<type_config>::key_type>& ks,
|
||||
const basic_value<type_config>& v, const spec s);
|
||||
|
||||
extern template std::string
|
||||
extern template typename basic_value<type_config>::string_type
|
||||
format<ordered_type_config>(const basic_value<ordered_type_config>&, const spec);
|
||||
|
||||
extern template std::string
|
||||
extern template typename basic_value<type_config>::string_type
|
||||
format<ordered_type_config>(const typename basic_value<ordered_type_config>::key_type& k,
|
||||
const basic_value<ordered_type_config>& v, const spec);
|
||||
|
||||
extern template std::string
|
||||
extern template typename basic_value<type_config>::string_type
|
||||
format<ordered_type_config>(const std::vector<typename basic_value<ordered_type_config>::key_type>& ks,
|
||||
const basic_value<ordered_type_config>& v, const spec s);
|
||||
|
||||
|
||||
@@ -83,6 +83,14 @@ struct has_into_toml_method_impl
|
||||
static std::false_type check(...);
|
||||
};
|
||||
|
||||
struct has_template_into_toml_method_impl
|
||||
{
|
||||
template<typename T, typename TypeConfig>
|
||||
static std::true_type check(decltype(std::declval<T>().template into_toml<TypeConfig>())*);
|
||||
template<typename T, typename TypeConfig>
|
||||
static std::false_type check(...);
|
||||
};
|
||||
|
||||
struct has_specialized_from_impl
|
||||
{
|
||||
template<typename T>
|
||||
@@ -126,6 +134,9 @@ struct has_from_toml_method: decltype(has_from_toml_method_impl::check<T, TC>(nu
|
||||
template<typename T>
|
||||
struct has_into_toml_method: decltype(has_into_toml_method_impl::check<T>(nullptr)){};
|
||||
|
||||
template<typename T, typename TypeConfig>
|
||||
struct has_template_into_toml_method: decltype(has_template_into_toml_method_impl::check<T, TypeConfig>(nullptr)){};
|
||||
|
||||
template<typename T>
|
||||
struct has_specialized_from: decltype(has_specialized_from_impl::check<T>(nullptr)){};
|
||||
template<typename T>
|
||||
@@ -162,6 +173,32 @@ struct is_std_forward_list_impl<std::forward_list<T>> : std::true_type{};
|
||||
template<typename T>
|
||||
using is_std_forward_list = is_std_forward_list_impl<cxx::remove_cvref_t<T>>;
|
||||
|
||||
template<typename T> struct is_std_basic_string_impl : std::false_type{};
|
||||
template<typename C, typename T, typename A>
|
||||
struct is_std_basic_string_impl<std::basic_string<C, T, A>> : std::true_type{};
|
||||
template<typename T>
|
||||
using is_std_basic_string = is_std_basic_string_impl<cxx::remove_cvref_t<T>>;
|
||||
|
||||
template<typename T> struct is_1byte_std_basic_string_impl : std::false_type{};
|
||||
template<typename C, typename T, typename A>
|
||||
struct is_1byte_std_basic_string_impl<std::basic_string<C, T, A>>
|
||||
: std::integral_constant<bool, sizeof(C) == sizeof(char)> {};
|
||||
template<typename T>
|
||||
using is_1byte_std_basic_string = is_std_basic_string_impl<cxx::remove_cvref_t<T>>;
|
||||
|
||||
#if defined(TOML11_HAS_STRING_VIEW)
|
||||
template<typename T> struct is_std_basic_string_view_impl : std::false_type{};
|
||||
template<typename C, typename T>
|
||||
struct is_std_basic_string_view_impl<std::basic_string_view<C, T>> : std::true_type{};
|
||||
template<typename T>
|
||||
using is_std_basic_string_view = is_std_basic_string_view_impl<cxx::remove_cvref_t<T>>;
|
||||
|
||||
template<typename V, typename S>
|
||||
struct is_string_view_of : std::false_type {};
|
||||
template<typename C, typename T>
|
||||
struct is_string_view_of<std::basic_string_view<C, T>, std::basic_string<C, T>> : std::true_type {};
|
||||
#endif
|
||||
|
||||
template<typename T> struct is_chrono_duration_impl: std::false_type{};
|
||||
template<typename Rep, typename Period>
|
||||
struct is_chrono_duration_impl<std::chrono::duration<Rep, Period>>: std::true_type{};
|
||||
|
||||
@@ -99,6 +99,72 @@ inline std::string make_string(std::size_t len, char c)
|
||||
return std::string(len, c);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template<typename Char, typename Traits, typename Alloc,
|
||||
typename Char2, typename Traits2, typename Alloc2>
|
||||
struct string_conv_impl
|
||||
{
|
||||
static_assert(sizeof(Char) == sizeof(char), "");
|
||||
static_assert(sizeof(Char2) == sizeof(char), "");
|
||||
|
||||
static std::basic_string<Char, Traits, Alloc> invoke(std::basic_string<Char2, Traits2, Alloc2> s)
|
||||
{
|
||||
std::basic_string<Char, Traits, Alloc> retval;
|
||||
std::transform(s.begin(), s.end(), std::back_inserter(retval),
|
||||
[](const Char2 c) {return static_cast<Char>(c);});
|
||||
return retval;
|
||||
}
|
||||
template<std::size_t N>
|
||||
static std::basic_string<Char, Traits, Alloc> invoke(const Char2 (&s)[N])
|
||||
{
|
||||
std::basic_string<Char, Traits, Alloc> retval;
|
||||
// "string literal" has null-char at the end. to skip it, we use prev.
|
||||
std::transform(std::begin(s), std::prev(std::end(s)), std::back_inserter(retval),
|
||||
[](const Char2 c) {return static_cast<Char>(c);});
|
||||
return retval;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Char, typename Traits, typename Alloc>
|
||||
struct string_conv_impl<Char, Traits, Alloc, Char, Traits, Alloc>
|
||||
{
|
||||
static_assert(sizeof(Char) == sizeof(char), "");
|
||||
|
||||
static std::basic_string<Char, Traits, Alloc> invoke(std::basic_string<Char, Traits, Alloc> s)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
template<std::size_t N>
|
||||
static std::basic_string<Char, Traits, Alloc> invoke(const Char (&s)[N])
|
||||
{
|
||||
return std::basic_string<Char, Traits, Alloc>(s);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename S, typename Char2, typename Traits2, typename Alloc2>
|
||||
cxx::enable_if_t<is_std_basic_string<S>::value, S>
|
||||
string_conv(std::basic_string<Char2, Traits2, Alloc2> s)
|
||||
{
|
||||
using C = typename S::value_type;
|
||||
using T = typename S::traits_type;
|
||||
using A = typename S::allocator_type;
|
||||
return string_conv_impl<C, T, A, Char2, Traits2, Alloc2>::invoke(std::move(s));
|
||||
}
|
||||
template<typename S, std::size_t N>
|
||||
cxx::enable_if_t<is_std_basic_string<S>::value, S>
|
||||
string_conv(const char (&s)[N])
|
||||
{
|
||||
using C = typename S::value_type;
|
||||
using T = typename S::traits_type;
|
||||
using A = typename S::allocator_type;
|
||||
using C2 = char;
|
||||
using T2 = std::char_traits<C2>;
|
||||
using A2 = std::allocator<C2>;
|
||||
|
||||
return string_conv_impl<C, T, A, C2, T2, A2>::template invoke<N>(s);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace toml
|
||||
#endif // TOML11_UTILITY_HPP
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,8 +2,8 @@
|
||||
#define TOML11_VERSION_HPP
|
||||
|
||||
#define TOML11_VERSION_MAJOR 4
|
||||
#define TOML11_VERSION_MINOR 0
|
||||
#define TOML11_VERSION_PATCH 2
|
||||
#define TOML11_VERSION_MINOR 1
|
||||
#define TOML11_VERSION_PATCH 0
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error "__cplusplus is not defined"
|
||||
@@ -57,6 +57,11 @@
|
||||
#define TOML11_CXX20_VALUE 202002L
|
||||
#endif//TOML11_CXX20_VALUE
|
||||
|
||||
#if defined(__cpp_char8_t)
|
||||
# if __cpp_char8_t >= 201811L
|
||||
# define TOML11_HAS_CHAR8_T 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if TOML11_CPLUSPLUS_STANDARD_VERSION >= TOML11_CXX17_VALUE
|
||||
# if __has_include(<string_view>)
|
||||
|
||||
@@ -40,6 +40,7 @@ enum class string_format : std::uint8_t;
|
||||
enum class datetime_delimiter_kind : std::uint8_t;
|
||||
enum class array_format : std::uint8_t;
|
||||
enum class table_format : std::uint8_t;
|
||||
enum class key_format : std::uint8_t;
|
||||
|
||||
struct boolean_format_info;
|
||||
struct integer_format_info;
|
||||
@@ -51,6 +52,7 @@ struct local_date_format_info;
|
||||
struct local_time_format_info;
|
||||
struct array_format_info;
|
||||
struct table_format_info;
|
||||
struct key_format_info;
|
||||
|
||||
template<typename Key, typename Val, typename Cmp, typename Allocator>
|
||||
class ordered_map;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -99,6 +99,7 @@ if(TOML11_PRECOMPILE)
|
||||
# required options to use toml11 with MSVC
|
||||
if(MSVC)
|
||||
target_compile_options(toml11 PUBLIC "/utf-8")
|
||||
target_compile_options(toml11 PRIVATE "/W4" "/WX")
|
||||
if(MSVC_VERSION LESS 1910)
|
||||
message(STATUS "MSVC < 1910. DEFINE_CONVERSION_NON_INTRUSIVE is disabled")
|
||||
target_compile_definitions(toml11 PUBLIC -DTOML11_WITHOUT_DEFINE_NON_INTRUSIVE)
|
||||
@@ -107,6 +108,22 @@ if(TOML11_PRECOMPILE)
|
||||
else() # MSVC 2019
|
||||
target_compile_options(toml11 PUBLIC "/Zc:preprocessor")
|
||||
endif()
|
||||
else()
|
||||
target_compile_options(toml11 PRIVATE
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WALL}>: -Wall >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WEXTRA}>: -Wextra >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WPEDANTIC}>: -Wpedantic >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WERROR}>: -Werror >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WSIGN_CONVERSION}>: -Wsign-conversion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WCONVERSION}>: -Wconversion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDUPLICATED_COND}>: -Wduplicated-cond >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDUPLICATED_BRANCHES}>: -Wduplicated-branches>
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WLOGICAL_OP}>: -Wlogical-op >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDOUBLE_PROMOTION}>: -Wdouble-promotion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS}>: -Wrange-loop-analysis>
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WUNDEF}>: -Wundef >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WSHADOW}>: -Wshadow >
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
add_library(toml11 INTERFACE)
|
||||
|
||||
@@ -10,25 +10,25 @@ namespace toml
|
||||
struct type_config;
|
||||
struct ordered_type_config;
|
||||
|
||||
template std::string
|
||||
template typename basic_value<type_config>::string_type
|
||||
format<type_config>(const basic_value<type_config>&, const spec);
|
||||
|
||||
template std::string
|
||||
template typename basic_value<type_config>::string_type
|
||||
format<type_config>(const typename basic_value<type_config>::key_type& k,
|
||||
const basic_value<type_config>& v, const spec);
|
||||
|
||||
template std::string
|
||||
template typename basic_value<type_config>::string_type
|
||||
format<type_config>(const std::vector<typename basic_value<type_config>::key_type>& ks,
|
||||
const basic_value<type_config>& v, const spec s);
|
||||
|
||||
template std::string
|
||||
template typename basic_value<type_config>::string_type
|
||||
format<ordered_type_config>(const basic_value<ordered_type_config>&, const spec);
|
||||
|
||||
template std::string
|
||||
template typename basic_value<type_config>::string_type
|
||||
format<ordered_type_config>(const typename basic_value<ordered_type_config>::key_type& k,
|
||||
const basic_value<ordered_type_config>& v, const spec);
|
||||
|
||||
template std::string
|
||||
template typename basic_value<type_config>::string_type
|
||||
format<ordered_type_config>(const std::vector<typename basic_value<ordered_type_config>::key_type>& ks,
|
||||
const basic_value<ordered_type_config>& v, const spec s);
|
||||
|
||||
|
||||
@@ -41,23 +41,6 @@ set(TOML11_TEST_NAMES
|
||||
test_visit
|
||||
)
|
||||
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
check_cxx_compiler_flag("-Wall" COMPILER_SUPPORTS_WALL)
|
||||
check_cxx_compiler_flag("-Wextra" COMPILER_SUPPORTS_WEXTRA)
|
||||
check_cxx_compiler_flag("-Wpedantic" COMPILER_SUPPORTS_WPEDANTIC)
|
||||
check_cxx_compiler_flag("-Werror" COMPILER_SUPPORTS_WERROR)
|
||||
|
||||
check_cxx_compiler_flag("-Wsign-conversion" COMPILER_SUPPORTS_WSIGN_CONVERSION)
|
||||
check_cxx_compiler_flag("-Wconversion" COMPILER_SUPPORTS_WCONVERSION)
|
||||
check_cxx_compiler_flag("-Wduplicated-cond" COMPILER_SUPPORTS_WDUPLICATED_COND)
|
||||
check_cxx_compiler_flag("-Wduplicated-branches" COMPILER_SUPPORTS_WDUPLICATED_BRANCHES)
|
||||
check_cxx_compiler_flag("-Wlogical-op" COMPILER_SUPPORTS_WLOGICAL_OP)
|
||||
check_cxx_compiler_flag("-Wdouble-promotion" COMPILER_SUPPORTS_WDOUBLE_PROMOTION)
|
||||
check_cxx_compiler_flag("-Wrange-loop-analysis" COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS)
|
||||
check_cxx_compiler_flag("-Wundef" COMPILER_SUPPORTS_WUNDEF)
|
||||
check_cxx_compiler_flag("-Wshadow" COMPILER_SUPPORTS_WSHADOW)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
add_library(toml11_test_utility STATIC utility.cpp)
|
||||
target_include_directories(toml11_test_utility
|
||||
@@ -72,27 +55,28 @@ if(BUILD_TESTING)
|
||||
)
|
||||
target_link_libraries(${TEST_NAME} PUBLIC toml11 toml11_test_utility)
|
||||
if(MSVC)
|
||||
target_compile_options(${TEST_NAME} PRIVATE /W3)
|
||||
target_compile_options(${TEST_NAME} PRIVATE /W4 /WX)
|
||||
else()
|
||||
target_compile_options(${TEST_NAME} PRIVATE
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WALL}>: -Wall >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WEXTRA}>: -Wextra >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WPEDANTIC}>: -Wpedantic >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WSIGN_CONVERSION}>: -Wsign-conversion >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WCONVERSION}>: -Wconversion >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WDUPLICATED_COND}>: -Wduplicated-cond >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WDUPLICATED_BRANCHES}>: -Wduplicated-branches>
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WLOGICAL_OP}>: -Wlogical-op >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WDOUBLE_PROMOTION}>: -Wdouble-promotion >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS}>: -Wrange-loop-analysis>
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WUNDEF}>: -Wundef >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WSHADOW}>: -Wshadow >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WALL}>: -Wall >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WEXTRA}>: -Wextra >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WPEDANTIC}>: -Wpedantic >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WERROR}>: -Werror >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WSIGN_CONVERSION}>: -Wsign-conversion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WCONVERSION}>: -Wconversion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDUPLICATED_COND}>: -Wduplicated-cond >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDUPLICATED_BRANCHES}>: -Wduplicated-branches>
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WLOGICAL_OP}>: -Wlogical-op >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDOUBLE_PROMOTION}>: -Wdouble-promotion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS}>: -Wrange-loop-analysis>
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WUNDEF}>: -Wundef >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WSHADOW}>: -Wshadow >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
)
|
||||
target_link_options(${TEST_NAME} PRIVATE
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
)
|
||||
endif()
|
||||
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME})
|
||||
@@ -111,27 +95,27 @@ if(TOML11_BUILD_TOML_TESTS)
|
||||
)
|
||||
target_link_libraries(toml11_decoder PRIVATE toml11)
|
||||
if(MSVC)
|
||||
target_compile_options(${TEST_NAME} PRIVATE /W3)
|
||||
target_compile_options(${TEST_NAME} PRIVATE /W4 /WX)
|
||||
else()
|
||||
target_compile_options(toml11_decoder PRIVATE
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WALL}>: -Wall >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WEXTRA}>: -Wextra >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WPEDANTIC}>: -Wpedantic >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WSIGN_CONVERSION}>: -Wsign-conversion >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WCONVERSION}>: -Wconversion >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WDUPLICATED_COND}>: -Wduplicated-cond >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WDUPLICATED_BRANCHES}>: -Wduplicated-branches>
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WLOGICAL_OP}>: -Wlogical-op >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WDOUBLE_PROMOTION}>: -Wdouble-promotion >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS}>: -Wrange-loop-analysis>
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WUNDEF}>: -Wundef >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WSHADOW}>: -Wshadow >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WALL}>: -Wall >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WEXTRA}>: -Wextra >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WPEDANTIC}>: -Wpedantic >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WSIGN_CONVERSION}>: -Wsign-conversion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WCONVERSION}>: -Wconversion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDUPLICATED_COND}>: -Wduplicated-cond >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDUPLICATED_BRANCHES}>: -Wduplicated-branches>
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WLOGICAL_OP}>: -Wlogical-op >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDOUBLE_PROMOTION}>: -Wdouble-promotion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS}>: -Wrange-loop-analysis>
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WUNDEF}>: -Wundef >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WSHADOW}>: -Wshadow >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
)
|
||||
target_link_options(toml11_decoder PRIVATE
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -143,7 +127,7 @@ if(TOML11_BUILD_TOML_TESTS)
|
||||
target_compile_definitions(toml11_decoder_v1_1_0 PRIVATE -DTOML11_TO_JSON_USE_V1_1_0)
|
||||
target_link_libraries(toml11_decoder_v1_1_0 PRIVATE toml11)
|
||||
if(MSVC)
|
||||
target_compile_options(${TEST_NAME} PRIVATE /W3)
|
||||
target_compile_options(${TEST_NAME} PRIVATE /W4 /WX)
|
||||
else()
|
||||
target_compile_options(toml11_decoder_v1_1_0 PRIVATE
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WALL}>: -Wall >
|
||||
@@ -174,27 +158,27 @@ if(TOML11_BUILD_TOML_TESTS)
|
||||
)
|
||||
target_link_libraries(toml11_encoder PRIVATE toml11)
|
||||
if(MSVC)
|
||||
target_compile_options(${TEST_NAME} PRIVATE /W3)
|
||||
target_compile_options(${TEST_NAME} PRIVATE /W4 /WX)
|
||||
else()
|
||||
target_compile_options(toml11_encoder PRIVATE
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WALL}>: -Wall >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WEXTRA}>: -Wextra >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WPEDANTIC}>: -Wpedantic >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WSIGN_CONVERSION}>: -Wsign-conversion >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WCONVERSION}>: -Wconversion >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WDUPLICATED_COND}>: -Wduplicated-cond >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WDUPLICATED_BRANCHES}>: -Wduplicated-branches>
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WLOGICAL_OP}>: -Wlogical-op >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WDOUBLE_PROMOTION}>: -Wdouble-promotion >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS}>: -Wrange-loop-analysis>
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WUNDEF}>: -Wundef >
|
||||
$<$<BOOL:${COMPILER_SUPPORTS_WSHADOW}>: -Wshadow >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WALL}>: -Wall >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WEXTRA}>: -Wextra >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WPEDANTIC}>: -Wpedantic >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WSIGN_CONVERSION}>: -Wsign-conversion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WCONVERSION}>: -Wconversion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDUPLICATED_COND}>: -Wduplicated-cond >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDUPLICATED_BRANCHES}>: -Wduplicated-branches>
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WLOGICAL_OP}>: -Wlogical-op >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WDOUBLE_PROMOTION}>: -Wdouble-promotion >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS}>: -Wrange-loop-analysis>
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WUNDEF}>: -Wundef >
|
||||
$<$<BOOL:${TOML11_COMPILER_SUPPORTS_WSHADOW}>: -Wshadow >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
)
|
||||
target_link_options(toml11_encoder PRIVATE
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_ASAN}>: -fsanitize=address >
|
||||
$<$<BOOL:${TOML11_TEST_WITH_UBSAN}>: -fsanitize=undefined >
|
||||
)
|
||||
endif()
|
||||
endif(TOML11_BUILD_TOML_TESTS)
|
||||
|
||||
@@ -627,14 +627,29 @@ TEST_CASE("testing toml::find string conversion")
|
||||
toml::find<std::string>(v, "key") += "bar";
|
||||
CHECK_EQ("foobar", toml::find<std::string>(v, "key"));
|
||||
}
|
||||
}
|
||||
|
||||
#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
|
||||
#if defined(TOML11_HAS_CHAR8_T)
|
||||
TEST_CASE("testing toml::find<string-like>")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
{
|
||||
value_type v = toml::table{{"key", "foo"}};
|
||||
CHECK_EQ("foo", toml::find<std::string_view>(v, "key"));
|
||||
CHECK_EQ(u8"foo", toml::find<std::u8string>(v, "key"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
|
||||
TEST_CASE("testing toml::get<string_view>")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
{
|
||||
value_type v("foo");
|
||||
CHECK_EQ("foo", toml::get<std::string_view>(v));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("testing toml::find array conversion")
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <toml11/parser.hpp>
|
||||
#include <toml11/serializer.hpp>
|
||||
#include <toml11/types.hpp>
|
||||
#include <toml11/literal.hpp>
|
||||
|
||||
TEST_CASE("testing decimal")
|
||||
{
|
||||
@@ -25,19 +26,40 @@ TEST_CASE("testing decimal")
|
||||
|
||||
TEST_CASE("testing hex")
|
||||
{
|
||||
const auto hex_fmt = [](std::size_t w, std::size_t s) {
|
||||
const auto hex_fmt = [](bool u, std::size_t w, std::size_t s) {
|
||||
toml::integer_format_info fmt;
|
||||
fmt.fmt = toml::integer_format::hex;
|
||||
fmt.uppercase = u;
|
||||
fmt.width = w;
|
||||
fmt.spacer = s;
|
||||
return fmt;
|
||||
};
|
||||
|
||||
CHECK_EQ("0xdeadbeef", toml::format(toml::value(0xDEADBEEF, hex_fmt(8, 0))));
|
||||
CHECK_EQ("0xdead_beef", toml::format(toml::value(0xDEADBEEF, hex_fmt(8, 4))));
|
||||
CHECK_EQ("0xff", toml::format(toml::value(0xFF, hex_fmt(2, 0))));
|
||||
CHECK_EQ("0x00ff", toml::format(toml::value(0xFF, hex_fmt(4, 0))));
|
||||
CHECK_EQ("0x0000ff", toml::format(toml::value(0xFF, hex_fmt(6, 0))));
|
||||
CHECK_EQ("0xdeadbeef", toml::format(toml::value(0xDEADBEEF, hex_fmt(false, 8, 0))));
|
||||
CHECK_EQ("0xdead_beef", toml::format(toml::value(0xDEADBEEF, hex_fmt(false, 8, 4))));
|
||||
CHECK_EQ("0xff", toml::format(toml::value(0xFF, hex_fmt(false, 2, 0))));
|
||||
CHECK_EQ("0x00ff", toml::format(toml::value(0xFF, hex_fmt(false, 4, 0))));
|
||||
CHECK_EQ("0x0000ff", toml::format(toml::value(0xFF, hex_fmt(false, 6, 0))));
|
||||
|
||||
CHECK_EQ("0xDEADBEEF", toml::format(toml::value(0xDEADBEEF, hex_fmt(true, 8, 0))));
|
||||
CHECK_EQ("0xDEAD_BEEF", toml::format(toml::value(0xDEADBEEF, hex_fmt(true, 8, 4))));
|
||||
CHECK_EQ("0xFF", toml::format(toml::value(0xFF, hex_fmt(true, 2, 0))));
|
||||
CHECK_EQ("0x00FF", toml::format(toml::value(0xFF, hex_fmt(true, 4, 0))));
|
||||
CHECK_EQ("0x0000FF", toml::format(toml::value(0xFF, hex_fmt(true, 6, 0))));
|
||||
|
||||
using namespace toml::literals::toml_literals;
|
||||
|
||||
CHECK_EQ("0xdeadbeef", toml::format("0xdeadbeef"_toml ));
|
||||
CHECK_EQ("0xdead_beef", toml::format("0xdead_beef"_toml));
|
||||
CHECK_EQ("0xff", toml::format("0xff"_toml ));
|
||||
CHECK_EQ("0x00ff", toml::format("0x00ff"_toml ));
|
||||
CHECK_EQ("0x0000ff", toml::format("0x0000ff"_toml ));
|
||||
|
||||
CHECK_EQ("0xDEADBEEF", toml::format("0xDEADBEEF"_toml ));
|
||||
CHECK_EQ("0xDEAD_BEEF", toml::format("0xDEAD_BEEF"_toml));
|
||||
CHECK_EQ("0xFF", toml::format("0xFF"_toml ));
|
||||
CHECK_EQ("0x00FF", toml::format("0x00FF"_toml ));
|
||||
CHECK_EQ("0x0000FF", toml::format("0x0000FF"_toml ));
|
||||
}
|
||||
|
||||
TEST_CASE("testing oct")
|
||||
|
||||
@@ -240,8 +240,19 @@ TEST_CASE("testing toml::get<floating-like>")
|
||||
}
|
||||
}
|
||||
|
||||
#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
|
||||
#if defined(TOML11_HAS_CHAR8_T)
|
||||
TEST_CASE("testing toml::get<string-like>")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
{
|
||||
value_type v("foo");
|
||||
CHECK_EQ(u8"foo", toml::get<std::u8string>(v));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
|
||||
TEST_CASE("testing toml::get<string_view>")
|
||||
{
|
||||
using value_type = toml::value;
|
||||
{
|
||||
|
||||
@@ -34,23 +34,29 @@ TEST_CASE("testing decimal_value")
|
||||
TEST_CASE("testing hex_value")
|
||||
{
|
||||
toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
|
||||
const auto hex_fmt = [](std::size_t w, std::size_t s) {
|
||||
const auto hex_fmt = [](bool u, std::size_t w, std::size_t s) {
|
||||
toml::integer_format_info fmt;
|
||||
fmt.fmt = toml::integer_format::hex;
|
||||
fmt.uppercase = u;
|
||||
fmt.width = w;
|
||||
fmt.spacer = s;
|
||||
return fmt;
|
||||
};
|
||||
|
||||
toml11_test_parse_success<toml::value_t::integer>("0xDEADBEEF", 0xDEADBEEF, comments(), hex_fmt(8, 0), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0xdeadbeef", 0xDEADBEEF, comments(), hex_fmt(8, 0), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0xDEADbeef", 0xDEADBEEF, comments(), hex_fmt(8, 0), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0xDEAD_BEEF", 0xDEADBEEF, comments(), hex_fmt(8, 4), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0xdead_beef", 0xDEADBEEF, comments(), hex_fmt(8, 4), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0xdead_BEEF", 0xDEADBEEF, comments(), hex_fmt(8, 4), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0xFF", 0xFF, comments(), hex_fmt(2, 0), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0x00FF", 0xFF, comments(), hex_fmt(4, 0), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0x0000FF", 0xFF, comments(), hex_fmt(6, 0), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0xDEADBEEF", 0xDEADBEEF, comments(), hex_fmt(true, 8, 0), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0xdeadbeef", 0xDEADBEEF, comments(), hex_fmt(false, 8, 0), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0xDEADbeef", 0xDEADBEEF, comments(), hex_fmt(true, 8, 0), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0xDEAD_BEEF", 0xDEADBEEF, comments(), hex_fmt(true, 8, 4), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0xdead_beef", 0xDEADBEEF, comments(), hex_fmt(false, 8, 4), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0xdead_BEEF", 0xDEADBEEF, comments(), hex_fmt(true, 8, 4), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0xFF", 0xFF, comments(), hex_fmt(true, 2, 0), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0x00FF", 0xFF, comments(), hex_fmt(true, 4, 0), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0x0000FF", 0xFF, comments(), hex_fmt(true, 6, 0), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0xff", 0xFF, comments(), hex_fmt(false, 2, 0), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0x00ff", 0xFF, comments(), hex_fmt(false, 4, 0), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0x0000ff", 0xFF, comments(), hex_fmt(false, 6, 0), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0x00", 0, comments(), hex_fmt(true, 2, 0), ctx);
|
||||
toml11_test_parse_success<toml::value_t::integer>("0x12345", 0x12345, comments(), hex_fmt(true, 5, 0), ctx);
|
||||
}
|
||||
|
||||
TEST_CASE("testing oct_value")
|
||||
|
||||
@@ -49,6 +49,25 @@ struct foobar
|
||||
int a;
|
||||
std::string b;
|
||||
};
|
||||
|
||||
struct corge
|
||||
{
|
||||
int a;
|
||||
std::string b;
|
||||
|
||||
void from_toml(const toml::value& v)
|
||||
{
|
||||
this->a = toml::find<int>(v, "a");
|
||||
this->b = toml::find<std::string>(v, "b");
|
||||
return ;
|
||||
}
|
||||
|
||||
template <typename TC>
|
||||
toml::basic_value<TC> into_toml() const
|
||||
{
|
||||
return toml::basic_value<TC>(typename toml::basic_value<TC>::table_type{{"a", this->a}, {"b", this->b}});
|
||||
}
|
||||
};
|
||||
} // extlib
|
||||
|
||||
namespace toml
|
||||
@@ -215,6 +234,19 @@ TEST_CASE("test_conversion_by_member_methods")
|
||||
CHECK(v == v2);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
const toml::value v(toml::table{{"a", 42}, {"b", "baz"}});
|
||||
|
||||
const auto corge = toml::get<extlib::corge>(v);
|
||||
CHECK_EQ(corge.a, 42);
|
||||
CHECK_EQ(corge.b, "baz");
|
||||
|
||||
const toml::value v2(corge);
|
||||
|
||||
CHECK_EQ(v, v2);
|
||||
}
|
||||
|
||||
{
|
||||
const toml::ordered_value v(toml::ordered_table{{"a", 42}, {"b", "baz"}});
|
||||
|
||||
|
||||
@@ -587,6 +587,105 @@ TEST_CASE("testing constructor (string_view)")
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TOML11_HAS_CHAR8_T
|
||||
TEST_CASE("testing constructor (u8string)")
|
||||
{
|
||||
toml::string_format_info fmt;
|
||||
fmt.fmt = toml::string_format::basic;
|
||||
|
||||
const std::string eq("hoge");
|
||||
const std::string ne("fuga");
|
||||
|
||||
const std::u8string ref(u8"hoge");
|
||||
|
||||
{
|
||||
toml::value x(ref);
|
||||
test_is_type(x, toml::value_t::string);
|
||||
test_as_type_throws(x, toml::value_t::string);
|
||||
test_as_type_fmt_throws(x, toml::value_t::string);
|
||||
|
||||
test_as_type<toml::value_t::string>(x, "hoge", "fuga");
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
{
|
||||
toml::value x_with_comments(ref, std::vector<std::string>{"foo", "bar"});
|
||||
|
||||
test_is_type (x_with_comments, toml::value_t::string);
|
||||
test_as_type_throws (x_with_comments, toml::value_t::string);
|
||||
test_as_type_fmt_throws(x_with_comments, toml::value_t::string);
|
||||
|
||||
test_as_type<toml::value_t::string>(x_with_comments, eq, ne);
|
||||
|
||||
CHECK_EQ(x_with_comments.comments().size(), 2);
|
||||
CHECK_EQ(x_with_comments.comments().at(0), "foo");
|
||||
CHECK_EQ(x_with_comments.comments().at(1), "bar");
|
||||
|
||||
CHECK_EQ(x_with_comments.location().is_ok(), false);
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
{
|
||||
toml::value x_with_format(eq, fmt);
|
||||
|
||||
test_is_type (x_with_format, toml::value_t::string);
|
||||
test_as_type_throws (x_with_format, toml::value_t::string);
|
||||
test_as_type_fmt_throws(x_with_format, toml::value_t::string);
|
||||
|
||||
test_as_type <toml::value_t::string>(x_with_format, eq, ne);
|
||||
test_as_type_fmt<toml::value_t::string>(x_with_format, fmt);
|
||||
|
||||
CHECK_EQ(x_with_format.comments().size(), 0);
|
||||
CHECK_EQ(x_with_format.location().is_ok(), false);
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
{
|
||||
toml::value x_with_com_fmt(ref, fmt,
|
||||
std::vector<std::string>{"foo", "bar"});
|
||||
|
||||
test_is_type (x_with_com_fmt, toml::value_t::string);
|
||||
test_as_type_throws (x_with_com_fmt, toml::value_t::string);
|
||||
test_as_type_fmt_throws(x_with_com_fmt, toml::value_t::string);
|
||||
|
||||
test_as_type <toml::value_t::string>(x_with_com_fmt, eq, ne);
|
||||
test_as_type_fmt<toml::value_t::string>(x_with_com_fmt, fmt);
|
||||
|
||||
CHECK_EQ(x_with_com_fmt.comments().size(), 2);
|
||||
CHECK_EQ(x_with_com_fmt.comments().at(0), "foo");
|
||||
CHECK_EQ(x_with_com_fmt.comments().at(1), "bar");
|
||||
|
||||
CHECK_EQ(x_with_com_fmt.location().is_ok(), false);
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
{
|
||||
toml::value x_assign(ne, fmt);
|
||||
x_assign = ref;
|
||||
|
||||
test_is_type (x_assign, toml::value_t::string);
|
||||
test_as_type_throws (x_assign, toml::value_t::string);
|
||||
test_as_type_fmt_throws(x_assign, toml::value_t::string);
|
||||
|
||||
test_as_type <toml::value_t::string>(x_assign, eq, ne);
|
||||
test_as_type_fmt<toml::value_t::string>(x_assign, fmt);
|
||||
|
||||
CHECK_EQ(x_assign.comments().size(), 0);
|
||||
CHECK_EQ(x_assign.location().is_ok(), false);
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
{
|
||||
toml::value x_assign_different_type(true);
|
||||
x_assign_different_type = ref;
|
||||
|
||||
test_is_type (x_assign_different_type, toml::value_t::string);
|
||||
test_as_type_throws (x_assign_different_type, toml::value_t::string);
|
||||
test_as_type_fmt_throws(x_assign_different_type, toml::value_t::string);
|
||||
|
||||
test_as_type<toml::value_t::string>(x_assign_different_type, eq, ne);
|
||||
|
||||
CHECK_EQ(x_assign_different_type.comments().size(), 0);
|
||||
CHECK_EQ(x_assign_different_type.location().is_ok(), false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("testing constructor (local_date)")
|
||||
{
|
||||
toml::local_date_format_info fmt;
|
||||
|
||||
@@ -29,10 +29,11 @@ namespace toml
|
||||
std::ostream& operator<<(std::ostream& os, const integer_format_info& fmt)
|
||||
{
|
||||
os << "integer_format_info{";
|
||||
os << "fmt = " << fmt.fmt << ", ";
|
||||
os << "width = " << fmt.width << ", ";
|
||||
os << "spacer = " << fmt.spacer << ", ";
|
||||
os << "suffix = \"" << fmt.suffix << "\"}";
|
||||
os << "fmt = " << fmt.fmt << ", ";
|
||||
os << "uppercase = " << fmt.uppercase << ", ";
|
||||
os << "width = " << fmt.width << ", ";
|
||||
os << "spacer = " << fmt.spacer << ", ";
|
||||
os << "suffix = \"" << fmt.suffix << "\"}";
|
||||
return os;
|
||||
}
|
||||
std::ostream& operator<<(std::ostream& os, const floating_format_info& fmt)
|
||||
|
||||
@@ -86,13 +86,6 @@ void toml11_test_parse_failure(F fn, std::string in, toml::detail::context<TC> c
|
||||
|
||||
namespace toml
|
||||
{
|
||||
template<typename TC>
|
||||
std::ostream& operator<<(std::ostream& os, const toml::basic_value<TC>& v)
|
||||
{
|
||||
os << toml::format(v);
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const integer_format_info&);
|
||||
std::ostream& operator<<(std::ostream& os, const floating_format_info&);
|
||||
std::ostream& operator<<(std::ostream& os, const string_format_info&);
|
||||
|
||||
Reference in New Issue
Block a user