mirror of
https://github.com/ToruNiina/toml11.git
synced 2025-12-16 03:08:52 +08:00
Compare commits
50 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c037913b2c | ||
|
|
6a328fe890 | ||
|
|
7c18cbb1d9 | ||
|
|
ba7d49f452 | ||
|
|
b0784ce286 | ||
|
|
670186fac7 | ||
|
|
5005998709 | ||
|
|
84fb703e04 | ||
|
|
8c2560761b | ||
|
|
07ea5e52e2 | ||
|
|
d2b1e962c9 | ||
|
|
528031012d | ||
|
|
c205c762fe | ||
|
|
a32cd6cb61 | ||
|
|
38e113d2dc | ||
|
|
f15480ae4d | ||
|
|
00bec8ae45 | ||
|
|
d599edd1d4 | ||
|
|
a9534579c6 | ||
|
|
c8ff302c94 | ||
|
|
003bc16c1b | ||
|
|
9132abc5c4 | ||
|
|
99d565bcc4 | ||
|
|
5f38127692 | ||
|
|
3c3ebd88b4 | ||
|
|
08f7ea9c56 | ||
|
|
cde29399f4 | ||
|
|
eec429e31b | ||
|
|
79ddcaece6 | ||
|
|
8398b9a08b | ||
|
|
9c5abf0bfd | ||
|
|
4fa94d45b3 | ||
|
|
46e84a9cc2 | ||
|
|
4e6ae9a994 | ||
|
|
f23c003d2f | ||
|
|
4b719f0806 | ||
|
|
22ace027de | ||
|
|
bc219af5b5 | ||
|
|
68e8a31659 | ||
|
|
32a5341d09 | ||
|
|
ce68f6f4c2 | ||
|
|
e696aabd11 | ||
|
|
7fb93e2f54 | ||
|
|
19cc9a2edf | ||
|
|
72f5afb6af | ||
|
|
a8fa14d159 | ||
|
|
75999aa9ad | ||
|
|
259da54edb | ||
|
|
b461f363da | ||
|
|
d43139a471 |
24
.github/workflows/main.yml
vendored
24
.github/workflows/main.yml
vendored
@@ -9,10 +9,13 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
# g++-4.8 and 4.9 are tested on Travis.CI.
|
# g++-4.8 and 4.9 are tested on Travis.CI.
|
||||||
compiler: ['g++-9', 'g++-8', 'g++-7', 'g++-6', 'g++-5']
|
compiler: ['g++-9', 'g++-8', 'g++-7', 'g++-6', 'g++-5']
|
||||||
standard: ['11', '14', '17']
|
standard: ['11', '14', '17', '20']
|
||||||
exclude:
|
exclude:
|
||||||
- {compiler: 'g++-5', standard: '17'}
|
- {compiler: 'g++-5', standard: '17'}
|
||||||
- {compiler: 'g++-6', standard: '17'}
|
- {compiler: 'g++-6', standard: '17'}
|
||||||
|
- {compiler: 'g++-5', standard: '20'}
|
||||||
|
- {compiler: 'g++-6', standard: '20'}
|
||||||
|
- {compiler: 'g++-7', standard: '20'}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
@@ -31,7 +34,11 @@ jobs:
|
|||||||
- name: Configure
|
- name: Configure
|
||||||
run: |
|
run: |
|
||||||
mkdir build && cd build
|
mkdir build && cd build
|
||||||
cmake .. -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} -DCMAKE_CXX_STANDARD=${{ matrix.standard }}
|
if [[ "${{ matrix.compiler }}" == "g++-8" && ( "${{ matrix.standard }}" == "17" || "${{ matrix.standard }}" == "20" ) ]] ; then
|
||||||
|
cmake .. -Dtoml11_BUILD_TEST=ON -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DTOML11_REQUIRE_FILESYSTEM_LIBRARY=ON
|
||||||
|
else
|
||||||
|
cmake .. -Dtoml11_BUILD_TEST=ON -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} -DCMAKE_CXX_STANDARD=${{ matrix.standard }}
|
||||||
|
fi
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
cd build && cmake --build .
|
cd build && cmake --build .
|
||||||
@@ -43,11 +50,14 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
compiler: ['10', '9', '8', '7', '6.0', '5.0', '4.0', '3.9']
|
compiler: ['10', '9', '8', '7', '6.0', '5.0', '4.0', '3.9']
|
||||||
standard: ['11', '14', '17']
|
standard: ['11', '14', '17', '20']
|
||||||
exclude:
|
exclude:
|
||||||
- {compiler: '3.9', standard: '17'}
|
- {compiler: '3.9', standard: '17'}
|
||||||
- {compiler: '4.0', standard: '17'}
|
- {compiler: '4.0', standard: '17'}
|
||||||
- {compiler: '5.0', standard: '17'}
|
- {compiler: '5.0', standard: '17'}
|
||||||
|
- {compiler: '3.9', standard: '20'}
|
||||||
|
- {compiler: '4.0', standard: '20'}
|
||||||
|
- {compiler: '5.0', standard: '20'}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
@@ -66,7 +76,7 @@ jobs:
|
|||||||
- name: Configure
|
- name: Configure
|
||||||
run: |
|
run: |
|
||||||
mkdir build && cd build
|
mkdir build && cd build
|
||||||
cmake .. -DCMAKE_CXX_COMPILER=clang++-${{ matrix.compiler }} -DCMAKE_CXX_STANDARD=${{ matrix.standard }}
|
cmake .. -Dtoml11_BUILD_TEST=ON -DCMAKE_CXX_COMPILER=clang++-${{ matrix.compiler }} -DCMAKE_CXX_STANDARD=${{ matrix.standard }}
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
cd build && cmake --build .
|
cd build && cmake --build .
|
||||||
@@ -77,7 +87,7 @@ jobs:
|
|||||||
runs-on: windows-2019
|
runs-on: windows-2019
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
standard: ['11', '14', '17']
|
standard: ['11', '14', '17', '20']
|
||||||
config: ['Release', 'Debug']
|
config: ['Release', 'Debug']
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -88,9 +98,10 @@ jobs:
|
|||||||
- name: Configure
|
- name: Configure
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
|
file --mime-encoding tests/test_literals.cpp
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake ../ -G "NMake Makefiles" -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DBoost_ADDITIONAL_VERSIONS=1.72.0 -DBoost_USE_MULTITHREADED=ON -DBoost_ARCHITECTURE=-x64 -DBoost_NO_BOOST_CMAKE=ON -DBOOST_ROOT=%BOOST_ROOT_1_72_0%
|
cmake ../ -G "NMake Makefiles" -Dtoml11_BUILD_TEST=ON -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DBoost_ADDITIONAL_VERSIONS=1.72.0 -DBoost_USE_MULTITHREADED=ON -DBoost_ARCHITECTURE=-x64 -DBoost_NO_BOOST_CMAKE=ON -DBOOST_ROOT=%BOOST_ROOT_1_72_0%
|
||||||
- name: Build
|
- name: Build
|
||||||
working-directory: ./build
|
working-directory: ./build
|
||||||
run: |
|
run: |
|
||||||
@@ -98,6 +109,7 @@ jobs:
|
|||||||
- name: Test
|
- name: Test
|
||||||
working-directory: ./build
|
working-directory: ./build
|
||||||
run: |
|
run: |
|
||||||
|
./tests/test_literals --log_level=all
|
||||||
file --mime-encoding tests/toml/tests/example.toml
|
file --mime-encoding tests/toml/tests/example.toml
|
||||||
file --mime-encoding tests/toml/tests/fruit.toml
|
file --mime-encoding tests/toml/tests/fruit.toml
|
||||||
file --mime-encoding tests/toml/tests/hard_example.toml
|
file --mime-encoding tests/toml/tests/hard_example.toml
|
||||||
|
|||||||
16
.travis.yml
16
.travis.yml
@@ -101,7 +101,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
env: COMPILER="g++-8" CXX_STANDARD=17
|
env: COMPILER="g++-8" CXX_STANDARD=17 REQUIRE_FILESYSTEM_LIBRARY=ON
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -113,7 +113,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
env: COMPILER="g++-8" CXX_STANDARD=17 TOML_HEAD=ON
|
env: COMPILER="g++-8" CXX_STANDARD=17 TOML_HEAD=ON REQUIRE_FILESYSTEM_LIBRARY=ON
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -237,7 +237,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-8" CXX_STANDARD=17
|
env: COMPILER="clang++-8" CXX_STANDARD=17 REQUIRE_FILESYSTEM_LIBRARY=ON
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -251,7 +251,7 @@ matrix:
|
|||||||
- os: linux
|
- os: linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER="clang++-8" CXX_STANDARD=17 TOML_HEAD=ON
|
env: COMPILER="clang++-8" CXX_STANDARD=17 TOML_HEAD=ON REQUIRE_FILESYSTEM_LIBRARY=ON
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
@@ -321,11 +321,17 @@ script:
|
|||||||
export WITH_UBSAN="OFF"
|
export WITH_UBSAN="OFF"
|
||||||
fi
|
fi
|
||||||
- echo "WITH_UBSAN = ${WITH_UBSAN}"
|
- echo "WITH_UBSAN = ${WITH_UBSAN}"
|
||||||
|
- echo "REQUIRE_FILESYSTEM_LIBRARY = ${REQUIRE_FILESYSTEM_LIBRARY}"
|
||||||
|
- |
|
||||||
|
if [[ "${REQUIRE_FILESYSTEM_LIBRARY}" != "ON" ]]; then
|
||||||
|
export REQUIRE_FILESYSTEM_LIBRARY="OFF"
|
||||||
|
fi
|
||||||
|
- echo "REQUIRE_FILESYSTEM_LIBRARY = ${REQUIRE_FILESYSTEM_LIBRARY}"
|
||||||
- cmake --version
|
- cmake --version
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
- echo "COMPILER = ${COMPILER}"
|
- echo "COMPILER = ${COMPILER}"
|
||||||
- echo "CXX_STANDARD = ${CXX_STANDARD}"
|
- echo "CXX_STANDARD = ${CXX_STANDARD}"
|
||||||
- cmake -DCMAKE_CXX_COMPILER=$COMPILER -DCMAKE_CXX_STANDARD=$CXX_STANDARD -DTOML11_USE_UNRELEASED_TOML_FEATURES=${TOML_HEAD} -Dtoml11_TEST_WITH_ASAN=${WITH_ASAN} -Dtoml11_TEST_WITH_UBSAN=${WITH_UBSAN} ..
|
- cmake -DCMAKE_CXX_COMPILER=$COMPILER -DCMAKE_CXX_STANDARD=$CXX_STANDARD -DTOML11_REQUIRE_FILESYSTEM_LIBRARY=${REQUIRE_FILESYSTEM_LIBRARY} -Dtoml11_BUILD_TEST=ON -DTOML11_USE_UNRELEASED_TOML_FEATURES=${TOML_HEAD} -Dtoml11_TEST_WITH_ASAN=${WITH_ASAN} -Dtoml11_TEST_WITH_UBSAN=${WITH_UBSAN} ..
|
||||||
- make
|
- make
|
||||||
- ctest --output-on-failure
|
- ctest --output-on-failure
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ enable_testing()
|
|||||||
|
|
||||||
project(toml11 VERSION 3.5.0)
|
project(toml11 VERSION 3.5.0)
|
||||||
|
|
||||||
option(toml11_BUILD_TEST "Build toml tests" ON)
|
option(toml11_BUILD_TEST "Build toml tests" OFF)
|
||||||
option(toml11_TEST_WITH_ASAN "use LLVM address sanitizer" OFF)
|
option(toml11_TEST_WITH_ASAN "use LLVM address sanitizer" OFF)
|
||||||
option(toml11_TEST_WITH_UBSAN "use LLVM undefined behavior sanitizer" OFF)
|
option(toml11_TEST_WITH_UBSAN "use LLVM undefined behavior sanitizer" OFF)
|
||||||
|
|
||||||
@@ -37,6 +37,11 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
add_definitions("/Zc:__cplusplus") # define __cplusplus value correctly
|
||||||
|
add_definitions("/utf-8") # enable to use u8"" literal
|
||||||
|
endif()
|
||||||
|
|
||||||
# Set some common directories
|
# Set some common directories
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
set(toml11_install_cmake_dir ${CMAKE_INSTALL_LIBDIR}/cmake/toml11)
|
set(toml11_install_cmake_dir ${CMAKE_INSTALL_LIBDIR}/cmake/toml11)
|
||||||
|
|||||||
19
README.md
19
README.md
@@ -11,7 +11,7 @@ toml11
|
|||||||
|
|
||||||
toml11 is a C++11 (or later) header-only toml parser/encoder depending only on C++ standard library.
|
toml11 is a C++11 (or later) header-only toml parser/encoder depending only on C++ standard library.
|
||||||
|
|
||||||
- It is compatible to the latest version of [TOML v1.0.0-rc.1](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v1.0.0-rc.1.md).
|
- It is compatible to the latest version of [TOML v1.0.0-rc.2](https://toml.io/en/v1.0.0-rc.2).
|
||||||
- It is one of the most TOML standard compliant libraries, tested with [the language agnostic test suite for TOML parsers by BurntSushi](https://github.com/BurntSushi/toml-test).
|
- It is one of the most TOML standard compliant libraries, tested with [the language agnostic test suite for TOML parsers by BurntSushi](https://github.com/BurntSushi/toml-test).
|
||||||
- It shows highly informative error messages. You can see the error messages about invalid files at [CircleCI](https://circleci.com/gh/ToruNiina/toml11).
|
- It shows highly informative error messages. You can see the error messages about invalid files at [CircleCI](https://circleci.com/gh/ToruNiina/toml11).
|
||||||
- It has configurable container. You can use any random-access containers and key-value maps as backend containers.
|
- It has configurable container. You can use any random-access containers and key-value maps as backend containers.
|
||||||
@@ -95,7 +95,7 @@ int main()
|
|||||||
Just include the file after adding it to the include path.
|
Just include the file after adding it to the include path.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#include <toml11/toml.hpp> // that's all! now you can use it.
|
#include <toml.hpp> // that's all! now you can use it.
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
@@ -110,6 +110,8 @@ int main()
|
|||||||
The convenient way is to add this repository as a git-submodule or to install
|
The convenient way is to add this repository as a git-submodule or to install
|
||||||
it in your system by CMake.
|
it in your system by CMake.
|
||||||
|
|
||||||
|
Note for MSVC: We recommend to set `/Zc:__cplusplus` to detect C++ version correctly.
|
||||||
|
|
||||||
## Decoding a toml file
|
## Decoding a toml file
|
||||||
|
|
||||||
To parse a toml file, the only thing you have to do is
|
To parse a toml file, the only thing you have to do is
|
||||||
@@ -1798,7 +1800,7 @@ for automating test set fetching!).
|
|||||||
```sh
|
```sh
|
||||||
$ mkdir build
|
$ mkdir build
|
||||||
$ cd build
|
$ cd build
|
||||||
$ cmake ..
|
$ cmake .. -Dtoml11_BUILD_TEST=ON
|
||||||
$ make
|
$ make
|
||||||
$ make test
|
$ make test
|
||||||
```
|
```
|
||||||
@@ -1836,6 +1838,17 @@ I appreciate the help of the contributors who introduced the great feature to th
|
|||||||
- Fixed feature test macro to suppress -Wundef
|
- Fixed feature test macro to suppress -Wundef
|
||||||
- Use cache variables in CMakeLists.txt
|
- Use cache variables in CMakeLists.txt
|
||||||
- Automate test set fetching, update and refactor CMakeLists.txt
|
- Automate test set fetching, update and refactor CMakeLists.txt
|
||||||
|
- Scott McCaskill
|
||||||
|
- Parse 9 digits (nanoseconds) of fractional seconds in a `local_time`
|
||||||
|
- Shu Wang (@halfelf)
|
||||||
|
- fix "Finding a value in an array" example in README
|
||||||
|
- @maass-tv and @SeverinLeonhardt
|
||||||
|
- Fix MSVC warning C4866
|
||||||
|
- OGAWA KenIchi (@kenichiice)
|
||||||
|
- Fix include path in README
|
||||||
|
- Mohammed Alyousef (@MoAlyousef)
|
||||||
|
- Made testing optional in CMake
|
||||||
|
|
||||||
|
|
||||||
## Licensing terms
|
## Licensing terms
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ build_script:
|
|||||||
- cd C:\toml11
|
- cd C:\toml11
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
- cmake -G"%generator%" -DBOOST_ROOT=C:/Libraries/boost_1_69_0 ..
|
- cmake -G"%generator%" -DBOOST_ROOT=C:/Libraries/boost_1_69_0 -Dtoml11_BUILD_TEST=ON ..
|
||||||
- cmake --build . --config "%configuration%"
|
- cmake --build . --config "%configuration%"
|
||||||
- file --mime-encoding tests/toml/tests/hard_example_unicode.toml
|
- file --mime-encoding tests/toml/tests/hard_example_unicode.toml
|
||||||
|
|
||||||
|
|||||||
@@ -150,9 +150,46 @@ find_package(Boost COMPONENTS unit_test_framework REQUIRED)
|
|||||||
add_definitions(-DBOOST_TEST_DYN_LINK)
|
add_definitions(-DBOOST_TEST_DYN_LINK)
|
||||||
add_definitions(-DUNITTEST_FRAMEWORK_LIBRARY_EXIST)
|
add_definitions(-DUNITTEST_FRAMEWORK_LIBRARY_EXIST)
|
||||||
|
|
||||||
|
# check which standard library implementation is used. If libstdc++ is used,
|
||||||
|
# it will fail to compile. It compiles if libc++ is used.
|
||||||
|
include(CheckCXXSourceCompiles)
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
#include <cstddef>
|
||||||
|
#ifdef __GLIBCXX__
|
||||||
|
static_assert(false);
|
||||||
|
#endif
|
||||||
|
int main() {
|
||||||
|
return 0;
|
||||||
|
}" TOML11_WITH_LIBCXX_LIBRARY)
|
||||||
|
|
||||||
|
# LLVM 8 requires -lc++fs if compiled with libc++ to use <filesystem>.
|
||||||
|
# LLVM 9+ does not require any special library.
|
||||||
|
# GCC 8 requires -lstdc++fs. GCC 9+ does not require it.
|
||||||
|
#
|
||||||
|
# Yes, we can check the version of the compiler used in the current build
|
||||||
|
# directly in CMake. But, in most cases, clang build uses libstdc++ as the
|
||||||
|
# standard library implementation and it makes the condition complicated.
|
||||||
|
# In many environment, the default installed C++ compiler is GCC and libstdc++
|
||||||
|
# is installed along with it. In most build on such an environment, even if we
|
||||||
|
# chose clang as the C++ compiler, still libstdc++ is used. Checking default
|
||||||
|
# gcc version makes the condition complicated.
|
||||||
|
# The purpose of this file is to compile tests. We know the environment on which
|
||||||
|
# the tests run. We can set this option and, I think, it is easier and better.
|
||||||
|
option(TOML11_REQUIRE_FILESYSTEM_LIBRARY "need to link -lstdc++fs or -lc++fs" OFF)
|
||||||
|
|
||||||
foreach(TEST_NAME ${TEST_NAMES})
|
foreach(TEST_NAME ${TEST_NAMES})
|
||||||
add_executable(${TEST_NAME} ${TEST_NAME}.cpp)
|
add_executable(${TEST_NAME} ${TEST_NAME}.cpp)
|
||||||
target_link_libraries(${TEST_NAME} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} toml11::toml11)
|
target_link_libraries(${TEST_NAME} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} toml11::toml11)
|
||||||
|
|
||||||
|
# to compile tests with <filesystem>...
|
||||||
|
if(TOML11_REQUIRE_FILESYSTEM_LIBRARY)
|
||||||
|
if(TOML11_WITH_LIBCXX_LIBRARY)
|
||||||
|
target_link_libraries(${TEST_NAME} "c++fs")
|
||||||
|
else()
|
||||||
|
target_link_libraries(${TEST_NAME} "stdc++fs")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
target_include_directories(${TEST_NAME} PRIVATE ${Boost_INCLUDE_DIRS})
|
target_include_directories(${TEST_NAME} PRIVATE ${Boost_INCLUDE_DIRS})
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
@@ -178,6 +215,7 @@ foreach(TEST_NAME ${TEST_NAMES})
|
|||||||
endif()
|
endif()
|
||||||
endforeach(TEST_NAME)
|
endforeach(TEST_NAME)
|
||||||
|
|
||||||
|
|
||||||
# this test is to check it compiles. it will not run
|
# this test is to check it compiles. it will not run
|
||||||
add_executable(test_multiple_translation_unit
|
add_executable(test_multiple_translation_unit
|
||||||
test_multiple_translation_unit_1.cpp
|
test_multiple_translation_unit_1.cpp
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
BOOST_AUTO_TEST_CASE(test_comment_before)
|
BOOST_AUTO_TEST_CASE(test_comment_before)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
const std::string file = u8R"(
|
const std::string file = R"(
|
||||||
# comment for a.
|
# comment for a.
|
||||||
a = 42
|
a = 42
|
||||||
# comment for b.
|
# comment for b.
|
||||||
@@ -24,12 +24,12 @@ BOOST_AUTO_TEST_CASE(test_comment_before)
|
|||||||
const auto& b = toml::find(v, "b");
|
const auto& b = toml::find(v, "b");
|
||||||
|
|
||||||
BOOST_TEST(a.comments().size() == 1u);
|
BOOST_TEST(a.comments().size() == 1u);
|
||||||
BOOST_TEST(a.comments().front() == u8" comment for a.");
|
BOOST_TEST(a.comments().front() == " comment for a.");
|
||||||
BOOST_TEST(b.comments().size() == 1u);
|
BOOST_TEST(b.comments().size() == 1u);
|
||||||
BOOST_TEST(b.comments().front() == u8" comment for b.");
|
BOOST_TEST(b.comments().front() == " comment for b.");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const std::string file = u8R"(
|
const std::string file = R"(
|
||||||
# comment for a.
|
# comment for a.
|
||||||
# another comment for a.
|
# another comment for a.
|
||||||
a = 42
|
a = 42
|
||||||
@@ -45,18 +45,18 @@ BOOST_AUTO_TEST_CASE(test_comment_before)
|
|||||||
const auto& b = toml::find(v, "b");
|
const auto& b = toml::find(v, "b");
|
||||||
|
|
||||||
BOOST_TEST(a.comments().size() == 2u);
|
BOOST_TEST(a.comments().size() == 2u);
|
||||||
BOOST_TEST(a.comments().front() == u8" comment for a.");
|
BOOST_TEST(a.comments().front() == " comment for a.");
|
||||||
BOOST_TEST(a.comments().back() == u8" another comment for a.");
|
BOOST_TEST(a.comments().back() == " another comment for a.");
|
||||||
BOOST_TEST(b.comments().size() == 2u);
|
BOOST_TEST(b.comments().size() == 2u);
|
||||||
BOOST_TEST(b.comments().front() == u8" comment for b.");
|
BOOST_TEST(b.comments().front() == " comment for b.");
|
||||||
BOOST_TEST(b.comments().back() == u8" also comment for b.");
|
BOOST_TEST(b.comments().back() == " also comment for b.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_comment_inline)
|
BOOST_AUTO_TEST_CASE(test_comment_inline)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
const std::string file = u8R"(
|
const std::string file = R"(
|
||||||
a = 42 # comment for a.
|
a = 42 # comment for a.
|
||||||
b = "baz" # comment for b.
|
b = "baz" # comment for b.
|
||||||
)";
|
)";
|
||||||
@@ -68,12 +68,12 @@ BOOST_AUTO_TEST_CASE(test_comment_inline)
|
|||||||
const auto& b = toml::find(v, "b");
|
const auto& b = toml::find(v, "b");
|
||||||
|
|
||||||
BOOST_TEST(a.comments().size() == 1u);
|
BOOST_TEST(a.comments().size() == 1u);
|
||||||
BOOST_TEST(a.comments().front() == u8" comment for a.");
|
BOOST_TEST(a.comments().front() == " comment for a.");
|
||||||
BOOST_TEST(b.comments().size() == 1u);
|
BOOST_TEST(b.comments().size() == 1u);
|
||||||
BOOST_TEST(b.comments().front() == u8" comment for b.");
|
BOOST_TEST(b.comments().front() == " comment for b.");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const std::string file = u8R"(
|
const std::string file = R"(
|
||||||
a = [
|
a = [
|
||||||
42,
|
42,
|
||||||
] # comment for a.
|
] # comment for a.
|
||||||
@@ -90,18 +90,18 @@ BOOST_AUTO_TEST_CASE(test_comment_inline)
|
|||||||
const auto& b0 = b.as_array().at(0);
|
const auto& b0 = b.as_array().at(0);
|
||||||
|
|
||||||
BOOST_TEST(a.comments().size() == 1u);
|
BOOST_TEST(a.comments().size() == 1u);
|
||||||
BOOST_TEST(a.comments().front() == u8" comment for a.");
|
BOOST_TEST(a.comments().front() == " comment for a.");
|
||||||
BOOST_TEST(b.comments().size() == 1u);
|
BOOST_TEST(b.comments().size() == 1u);
|
||||||
BOOST_TEST(b.comments().front() == u8" this is a comment for b.");
|
BOOST_TEST(b.comments().front() == " this is a comment for b.");
|
||||||
BOOST_TEST(b0.comments().size() == 1u);
|
BOOST_TEST(b0.comments().size() == 1u);
|
||||||
BOOST_TEST(b0.comments().front() == u8" this is not a comment for b, but \"bar\"");
|
BOOST_TEST(b0.comments().front() == " this is not a comment for b, but \"bar\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_comment_both)
|
BOOST_AUTO_TEST_CASE(test_comment_both)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
const std::string file = u8R"(
|
const std::string file = R"(
|
||||||
# comment for a.
|
# comment for a.
|
||||||
a = 42 # inline comment for a.
|
a = 42 # inline comment for a.
|
||||||
# comment for b.
|
# comment for b.
|
||||||
@@ -122,25 +122,25 @@ BOOST_AUTO_TEST_CASE(test_comment_both)
|
|||||||
const auto& c0 = c.as_array().at(0);
|
const auto& c0 = c.as_array().at(0);
|
||||||
|
|
||||||
BOOST_TEST(a.comments().size() == 2u);
|
BOOST_TEST(a.comments().size() == 2u);
|
||||||
BOOST_TEST(a.comments().front() == u8" comment for a.");
|
BOOST_TEST(a.comments().front() == " comment for a.");
|
||||||
BOOST_TEST(a.comments().back() == u8" inline comment for a.");
|
BOOST_TEST(a.comments().back() == " inline comment for a.");
|
||||||
BOOST_TEST(b.comments().size() == 2u);
|
BOOST_TEST(b.comments().size() == 2u);
|
||||||
BOOST_TEST(b.comments().front() == u8" comment for b.");
|
BOOST_TEST(b.comments().front() == " comment for b.");
|
||||||
BOOST_TEST(b.comments().back() == u8" inline comment for b.");
|
BOOST_TEST(b.comments().back() == " inline comment for b.");
|
||||||
|
|
||||||
BOOST_TEST(c.comments().size() == 2u);
|
BOOST_TEST(c.comments().size() == 2u);
|
||||||
BOOST_TEST(c.comments().front() == u8" comment for c.");
|
BOOST_TEST(c.comments().front() == " comment for c.");
|
||||||
BOOST_TEST(c.comments().back() == u8" another comment for c.");
|
BOOST_TEST(c.comments().back() == " another comment for c.");
|
||||||
|
|
||||||
BOOST_TEST(c0.comments().size() == 2u);
|
BOOST_TEST(c0.comments().size() == 2u);
|
||||||
BOOST_TEST(c0.comments().front() == u8" comment for the first element.");
|
BOOST_TEST(c0.comments().front() == " comment for the first element.");
|
||||||
BOOST_TEST(c0.comments().back() == u8" this also.");
|
BOOST_TEST(c0.comments().back() == " this also.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_discard_comment)
|
BOOST_AUTO_TEST_CASE(test_discard_comment)
|
||||||
{
|
{
|
||||||
const std::string file = u8R"(
|
const std::string file = R"(
|
||||||
# comment for a.
|
# comment for a.
|
||||||
a = 42 # inline comment for a.
|
a = 42 # inline comment for a.
|
||||||
# comment for b.
|
# comment for b.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
do { \
|
do { \
|
||||||
const std::string token (tkn); \
|
const std::string token (tkn); \
|
||||||
const std::string expected(expct); \
|
const std::string expected(expct); \
|
||||||
toml::detail::location<std::string> loc("test", token); \
|
toml::detail::location loc("test", token); \
|
||||||
const auto result = lxr::invoke(loc); \
|
const auto result = lxr::invoke(loc); \
|
||||||
BOOST_TEST(result.is_ok()); \
|
BOOST_TEST(result.is_ok()); \
|
||||||
if(result.is_ok()){ \
|
if(result.is_ok()){ \
|
||||||
@@ -28,7 +28,7 @@ do { \
|
|||||||
#define TOML11_TEST_LEX_REJECT(lxr, tkn) \
|
#define TOML11_TEST_LEX_REJECT(lxr, tkn) \
|
||||||
do { \
|
do { \
|
||||||
const std::string token (tkn); \
|
const std::string token (tkn); \
|
||||||
toml::detail::location<std::string> loc("test", token); \
|
toml::detail::location loc("test", token); \
|
||||||
const auto result = lxr::invoke(loc); \
|
const auto result = lxr::invoke(loc); \
|
||||||
BOOST_TEST(result.is_err()); \
|
BOOST_TEST(result.is_err()); \
|
||||||
const bool loc_same = (loc.begin() == loc.iter()); \
|
const bool loc_same = (loc.begin() == loc.iter()); \
|
||||||
|
|||||||
@@ -18,12 +18,11 @@ BOOST_AUTO_TEST_CASE(test_quoted_key)
|
|||||||
{
|
{
|
||||||
TOML11_TEST_LEX_ACCEPT(lex_key, "\"127.0.0.1\"", "\"127.0.0.1\"");
|
TOML11_TEST_LEX_ACCEPT(lex_key, "\"127.0.0.1\"", "\"127.0.0.1\"");
|
||||||
TOML11_TEST_LEX_ACCEPT(lex_key, "\"character encoding\"", "\"character encoding\"");
|
TOML11_TEST_LEX_ACCEPT(lex_key, "\"character encoding\"", "\"character encoding\"");
|
||||||
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
|
||||||
|
// UTF-8 codepoint of characters that looks like "key" written upside down
|
||||||
TOML11_TEST_LEX_ACCEPT(lex_key, "\"\xCA\x8E\xC7\x9D\xCA\x9E\"",
|
TOML11_TEST_LEX_ACCEPT(lex_key, "\"\xCA\x8E\xC7\x9D\xCA\x9E\"",
|
||||||
"\"\xCA\x8E\xC7\x9D\xCA\x9E\"");
|
"\"\xCA\x8E\xC7\x9D\xCA\x9E\"");
|
||||||
#else
|
|
||||||
TOML11_TEST_LEX_ACCEPT(lex_key, u8"\"ʎǝʞ\"", u8"\"ʎǝʞ\"");
|
|
||||||
#endif
|
|
||||||
TOML11_TEST_LEX_ACCEPT(lex_key, "'key2'", "'key2'");
|
TOML11_TEST_LEX_ACCEPT(lex_key, "'key2'", "'key2'");
|
||||||
TOML11_TEST_LEX_ACCEPT(lex_key, "'quoted \"value\"'", "'quoted \"value\"'");
|
TOML11_TEST_LEX_ACCEPT(lex_key, "'quoted \"value\"'", "'quoted \"value\"'");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,15 +31,9 @@ BOOST_AUTO_TEST_CASE(test_basic_string)
|
|||||||
"\"192.168.1.1\"",
|
"\"192.168.1.1\"",
|
||||||
"\"192.168.1.1\"");
|
"\"192.168.1.1\"");
|
||||||
|
|
||||||
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
|
||||||
TOML11_TEST_LEX_ACCEPT(lex_string,
|
TOML11_TEST_LEX_ACCEPT(lex_string,
|
||||||
"\"\xE4\xB8\xAD\xE5\x9B\xBD\"",
|
"\"\xE4\xB8\xAD\xE5\x9B\xBD\"", // UTF-8 string (means "China" in
|
||||||
"\"\xE4\xB8\xAD\xE5\x9B\xBD\"");
|
"\"\xE4\xB8\xAD\xE5\x9B\xBD\""); // Chinese characters)
|
||||||
#else
|
|
||||||
TOML11_TEST_LEX_ACCEPT(lex_string,
|
|
||||||
u8"\"中国\"",
|
|
||||||
u8"\"中国\"");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
TOML11_TEST_LEX_ACCEPT(lex_string,
|
TOML11_TEST_LEX_ACCEPT(lex_string,
|
||||||
"\"You'll hate me after this - #\"",
|
"\"You'll hate me after this - #\"",
|
||||||
|
|||||||
@@ -12,6 +12,170 @@ BOOST_AUTO_TEST_CASE(test_file_as_literal)
|
|||||||
{
|
{
|
||||||
using namespace toml::literals::toml_literals;
|
using namespace toml::literals::toml_literals;
|
||||||
|
|
||||||
|
{
|
||||||
|
const toml::value r{{"a", 42}, {"b", "baz"}};
|
||||||
|
const toml::value v = R"(
|
||||||
|
a = 42
|
||||||
|
b = "baz"
|
||||||
|
)"_toml;
|
||||||
|
|
||||||
|
BOOST_TEST(r == v);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value r{
|
||||||
|
{"c", 3.14},
|
||||||
|
{"table", toml::table{{"a", 42}, {"b", "baz"}}}
|
||||||
|
};
|
||||||
|
const toml::value v = R"(
|
||||||
|
c = 3.14
|
||||||
|
[table]
|
||||||
|
a = 42
|
||||||
|
b = "baz"
|
||||||
|
)"_toml;
|
||||||
|
|
||||||
|
BOOST_TEST(r == v);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value r{
|
||||||
|
{"table", toml::table{{"a", 42}, {"b", "baz"}}}
|
||||||
|
};
|
||||||
|
const toml::value v = R"(
|
||||||
|
[table]
|
||||||
|
a = 42
|
||||||
|
b = "baz"
|
||||||
|
)"_toml;
|
||||||
|
|
||||||
|
BOOST_TEST(r == v);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value r{
|
||||||
|
{"array_of_tables", toml::array{toml::table{}}}
|
||||||
|
};
|
||||||
|
const toml::value v = R"(
|
||||||
|
[[array_of_tables]]
|
||||||
|
)"_toml;
|
||||||
|
|
||||||
|
BOOST_TEST(r == v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_value_as_literal)
|
||||||
|
{
|
||||||
|
using namespace toml::literals::toml_literals;
|
||||||
|
|
||||||
|
{
|
||||||
|
const toml::value v1 = "true"_toml;
|
||||||
|
const toml::value v2 = "false"_toml;
|
||||||
|
|
||||||
|
BOOST_TEST(v1.is_boolean());
|
||||||
|
BOOST_TEST(v2.is_boolean());
|
||||||
|
BOOST_TEST(toml::get<bool>(v1));
|
||||||
|
BOOST_TEST(!toml::get<bool>(v2));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v1 = "123_456"_toml;
|
||||||
|
const toml::value v2 = "0b0010"_toml;
|
||||||
|
const toml::value v3 = "0xDEADBEEF"_toml;
|
||||||
|
|
||||||
|
BOOST_TEST(v1.is_integer());
|
||||||
|
BOOST_TEST(v2.is_integer());
|
||||||
|
BOOST_TEST(v3.is_integer());
|
||||||
|
BOOST_TEST(toml::get<toml::integer>(v1) == 123456);
|
||||||
|
BOOST_TEST(toml::get<toml::integer>(v2) == 2);
|
||||||
|
BOOST_TEST(toml::get<toml::integer>(v3) == 0xDEADBEEF);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v1 = "3.1415"_toml;
|
||||||
|
const toml::value v2 = "6.02e+23"_toml;
|
||||||
|
|
||||||
|
BOOST_TEST(v1.is_floating());
|
||||||
|
BOOST_TEST(v2.is_floating());
|
||||||
|
BOOST_TEST(toml::get<double>(v1) == 3.1415, boost::test_tools::tolerance(0.00001));
|
||||||
|
BOOST_TEST(toml::get<double>(v2) == 6.02e23, boost::test_tools::tolerance(0.0001));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v1 = R"("foo")"_toml;
|
||||||
|
const toml::value v2 = R"('foo')"_toml;
|
||||||
|
const toml::value v3 = R"("""foo""")"_toml;
|
||||||
|
const toml::value v4 = R"('''foo''')"_toml;
|
||||||
|
|
||||||
|
BOOST_TEST(v1.is_string());
|
||||||
|
BOOST_TEST(v2.is_string());
|
||||||
|
BOOST_TEST(v3.is_string());
|
||||||
|
BOOST_TEST(v4.is_string());
|
||||||
|
BOOST_TEST(toml::get<std::string>(v1) == "foo");
|
||||||
|
BOOST_TEST(toml::get<std::string>(v2) == "foo");
|
||||||
|
BOOST_TEST(toml::get<std::string>(v3) == "foo");
|
||||||
|
BOOST_TEST(toml::get<std::string>(v4) == "foo");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const toml::value v1 = R"([1,2,3])"_toml;
|
||||||
|
BOOST_TEST(v1.is_array());
|
||||||
|
const bool result = (toml::get<std::vector<int>>(v1) == std::vector<int>{1,2,3});
|
||||||
|
BOOST_TEST(result);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v2 = R"([1,])"_toml;
|
||||||
|
BOOST_TEST(v2.is_array());
|
||||||
|
const bool result = (toml::get<std::vector<int>>(v2) == std::vector<int>{1});
|
||||||
|
BOOST_TEST(result);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v3 = R"([[1,]])"_toml;
|
||||||
|
BOOST_TEST(v3.is_array());
|
||||||
|
const bool result = (toml::get<std::vector<int>>(toml::get<toml::array>(v3).front()) == std::vector<int>{1});
|
||||||
|
BOOST_TEST(result);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v4 = R"([[1],])"_toml;
|
||||||
|
BOOST_TEST(v4.is_array());
|
||||||
|
const bool result = (toml::get<std::vector<int>>(toml::get<toml::array>(v4).front()) == std::vector<int>{1});
|
||||||
|
BOOST_TEST(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v1 = R"({a = 42})"_toml;
|
||||||
|
|
||||||
|
BOOST_TEST(v1.is_table());
|
||||||
|
const bool result = toml::get<std::map<std::string,int>>(v1) ==
|
||||||
|
std::map<std::string,int>{{"a", 42}};
|
||||||
|
BOOST_TEST(result);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v1 = "1979-05-27"_toml;
|
||||||
|
|
||||||
|
BOOST_TEST(v1.is_local_date());
|
||||||
|
BOOST_TEST(toml::get<toml::local_date>(v1) ==
|
||||||
|
toml::local_date(1979, toml::month_t::May, 27));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v1 = "12:00:00"_toml;
|
||||||
|
|
||||||
|
BOOST_TEST(v1.is_local_time());
|
||||||
|
const bool result = toml::get<std::chrono::hours>(v1) == std::chrono::hours(12);
|
||||||
|
BOOST_TEST(result);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v1 = "1979-05-27T07:32:00"_toml;
|
||||||
|
BOOST_TEST(v1.is_local_datetime());
|
||||||
|
BOOST_TEST(toml::get<toml::local_datetime>(v1) ==
|
||||||
|
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27),
|
||||||
|
toml::local_time(7, 32, 0)));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const toml::value v1 = "1979-05-27T07:32:00Z"_toml;
|
||||||
|
BOOST_TEST(v1.is_offset_datetime());
|
||||||
|
BOOST_TEST(toml::get<toml::offset_datetime>(v1) ==
|
||||||
|
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
|
||||||
|
toml::local_time(7, 32, 0), toml::time_offset(0, 0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_file_as_u8_literal)
|
||||||
|
{
|
||||||
|
using namespace toml::literals::toml_literals;
|
||||||
|
|
||||||
{
|
{
|
||||||
const toml::value r{{"a", 42}, {"b", "baz"}};
|
const toml::value r{{"a", 42}, {"b", "baz"}};
|
||||||
const toml::value v = u8R"(
|
const toml::value v = u8R"(
|
||||||
@@ -59,7 +223,7 @@ BOOST_AUTO_TEST_CASE(test_file_as_literal)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_value_as_literal)
|
BOOST_AUTO_TEST_CASE(test_value_as_u8_literal)
|
||||||
{
|
{
|
||||||
using namespace toml::literals::toml_literals;
|
using namespace toml::literals::toml_literals;
|
||||||
|
|
||||||
@@ -98,15 +262,18 @@ BOOST_AUTO_TEST_CASE(test_value_as_literal)
|
|||||||
const toml::value v2 = u8R"('foo')"_toml;
|
const toml::value v2 = u8R"('foo')"_toml;
|
||||||
const toml::value v3 = u8R"("""foo""")"_toml;
|
const toml::value v3 = u8R"("""foo""")"_toml;
|
||||||
const toml::value v4 = u8R"('''foo''')"_toml;
|
const toml::value v4 = u8R"('''foo''')"_toml;
|
||||||
|
const toml::value v5 = u8R"("ひらがな")"_toml;
|
||||||
|
|
||||||
BOOST_TEST(v1.is_string());
|
BOOST_TEST(v1.is_string());
|
||||||
BOOST_TEST(v2.is_string());
|
BOOST_TEST(v2.is_string());
|
||||||
BOOST_TEST(v3.is_string());
|
BOOST_TEST(v3.is_string());
|
||||||
BOOST_TEST(v4.is_string());
|
BOOST_TEST(v4.is_string());
|
||||||
|
BOOST_TEST(v5.is_string());
|
||||||
BOOST_TEST(toml::get<std::string>(v1) == "foo");
|
BOOST_TEST(toml::get<std::string>(v1) == "foo");
|
||||||
BOOST_TEST(toml::get<std::string>(v2) == "foo");
|
BOOST_TEST(toml::get<std::string>(v2) == "foo");
|
||||||
BOOST_TEST(toml::get<std::string>(v3) == "foo");
|
BOOST_TEST(toml::get<std::string>(v3) == "foo");
|
||||||
BOOST_TEST(toml::get<std::string>(v4) == "foo");
|
BOOST_TEST(toml::get<std::string>(v4) == "foo");
|
||||||
|
BOOST_TEST(toml::get<std::string>(v5) == "\xE3\x81\xB2\xE3\x82\x89\xE3\x81\x8C\xE3\x81\xAA");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -164,7 +331,7 @@ BOOST_AUTO_TEST_CASE(test_value_as_literal)
|
|||||||
toml::local_time(7, 32, 0)));
|
toml::local_time(7, 32, 0)));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const toml::value v1 = "1979-05-27T07:32:00Z"_toml;
|
const toml::value v1 = u8"1979-05-27T07:32:00Z"_toml;
|
||||||
BOOST_TEST(v1.is_offset_datetime());
|
BOOST_TEST(v1.is_offset_datetime());
|
||||||
BOOST_TEST(toml::get<toml::offset_datetime>(v1) ==
|
BOOST_TEST(toml::get<toml::offset_datetime>(v1) ==
|
||||||
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
|
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
|
||||||
|
|||||||
@@ -172,3 +172,18 @@ BOOST_AUTO_TEST_CASE(test_heterogeneous_array)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_comments_after_comma)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
array a;
|
||||||
|
a.push_back("foo");
|
||||||
|
a.push_back("bar");
|
||||||
|
a.push_back("baz");
|
||||||
|
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
|
||||||
|
"[ \"foo\" # comment\n"
|
||||||
|
", \"bar\" # comment\n"
|
||||||
|
", \"baz\" # comment\n"
|
||||||
|
"]", toml::value(a));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#define TOML11_TEST_PARSE_EQUAL(psr, tkn, expct) \
|
#define TOML11_TEST_PARSE_EQUAL(psr, tkn, expct) \
|
||||||
do { \
|
do { \
|
||||||
const std::string token(tkn); \
|
const std::string token(tkn); \
|
||||||
toml::detail::location<std::string> loc("test", token); \
|
toml::detail::location loc("test", token); \
|
||||||
const auto result = psr(loc); \
|
const auto result = psr(loc); \
|
||||||
BOOST_TEST(result.is_ok()); \
|
BOOST_TEST(result.is_ok()); \
|
||||||
if(result.is_ok()){ \
|
if(result.is_ok()){ \
|
||||||
@@ -23,7 +23,7 @@ do { \
|
|||||||
#define TOML11_TEST_PARSE_EQUAL_VALUE(psr, tkn, expct) \
|
#define TOML11_TEST_PARSE_EQUAL_VALUE(psr, tkn, expct) \
|
||||||
do { \
|
do { \
|
||||||
const std::string token(tkn); \
|
const std::string token(tkn); \
|
||||||
toml::detail::location<std::string> loc("test", token); \
|
toml::detail::location loc("test", token); \
|
||||||
const auto result = psr(loc); \
|
const auto result = psr(loc); \
|
||||||
BOOST_TEST(result.is_ok()); \
|
BOOST_TEST(result.is_ok()); \
|
||||||
if(result.is_ok()){ \
|
if(result.is_ok()){ \
|
||||||
|
|||||||
@@ -779,6 +779,22 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
|
|||||||
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
|
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// without newline
|
||||||
|
{
|
||||||
|
const std::string table(
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"[table]\n"
|
||||||
|
"key = \"value\"\n"
|
||||||
|
"a = 0"
|
||||||
|
);
|
||||||
|
std::istringstream iss(table);
|
||||||
|
const auto data = toml::parse(iss,
|
||||||
|
"test_files_end_with_newline.toml");
|
||||||
|
|
||||||
|
BOOST_TEST(toml::find<std::string>(data, "key") == "value");
|
||||||
|
BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// CRLF
|
// CRLF
|
||||||
|
|
||||||
@@ -889,3 +905,41 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_parse_function_compiles)
|
||||||
|
{
|
||||||
|
// toml::parse("");
|
||||||
|
const auto string_literal = toml::parse("toml/tests/example.toml");
|
||||||
|
|
||||||
|
BOOST_TEST_MESSAGE("string_literal");
|
||||||
|
|
||||||
|
const char* fname_cstring = "toml/tests/example.toml";
|
||||||
|
// toml::parse(const char*);
|
||||||
|
const auto cstring = toml::parse(fname_cstring);
|
||||||
|
|
||||||
|
BOOST_TEST_MESSAGE("const char*");
|
||||||
|
|
||||||
|
// toml::parse(char*);
|
||||||
|
std::array<char, 24> fname_char_ptr;
|
||||||
|
std::strncpy(fname_char_ptr.data(), fname_cstring, 24);
|
||||||
|
const auto char_ptr = toml::parse(fname_char_ptr.data());
|
||||||
|
|
||||||
|
BOOST_TEST_MESSAGE("char*");
|
||||||
|
|
||||||
|
// toml::parse(const std::string&);
|
||||||
|
const std::string fname_string("toml/tests/example.toml");
|
||||||
|
const auto string = toml::parse(fname_string);
|
||||||
|
std::string fname_string_mut("toml/tests/example.toml");
|
||||||
|
// toml::parse(std::string&);
|
||||||
|
const auto string_mutref = toml::parse(fname_string_mut);
|
||||||
|
// toml::parse(std::string&&);
|
||||||
|
const auto string_rref = toml::parse(std::move(fname_string_mut));
|
||||||
|
|
||||||
|
BOOST_TEST_MESSAGE("strings");
|
||||||
|
|
||||||
|
#ifdef TOML11_HAS_STD_FILESYSTEM
|
||||||
|
const std::filesystem::path fname_path(fname_string.begin(), fname_string.end());
|
||||||
|
const auto filesystem_path = toml::parse(fname_path);
|
||||||
|
BOOST_TEST_MESSAGE("path");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ BOOST_AUTO_TEST_CASE(test_inf)
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
const std::string token("inf");
|
const std::string token("inf");
|
||||||
toml::detail::location<std::string> loc("test", token);
|
toml::detail::location loc("test", token);
|
||||||
const auto r = parse_floating(loc);
|
const auto r = parse_floating(loc);
|
||||||
BOOST_CHECK(r.is_ok());
|
BOOST_CHECK(r.is_ok());
|
||||||
BOOST_CHECK(std::isinf(r.unwrap().first));
|
BOOST_CHECK(std::isinf(r.unwrap().first));
|
||||||
@@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE(test_inf)
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
const std::string token("+inf");
|
const std::string token("+inf");
|
||||||
toml::detail::location<std::string> loc("test", token);
|
toml::detail::location loc("test", token);
|
||||||
const auto r = parse_floating(loc);
|
const auto r = parse_floating(loc);
|
||||||
BOOST_CHECK(r.is_ok());
|
BOOST_CHECK(r.is_ok());
|
||||||
BOOST_CHECK(std::isinf(r.unwrap().first));
|
BOOST_CHECK(std::isinf(r.unwrap().first));
|
||||||
@@ -144,7 +144,7 @@ BOOST_AUTO_TEST_CASE(test_inf)
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
const std::string token("-inf");
|
const std::string token("-inf");
|
||||||
toml::detail::location<std::string> loc("test", token);
|
toml::detail::location loc("test", token);
|
||||||
const auto r = parse_floating(loc);
|
const auto r = parse_floating(loc);
|
||||||
BOOST_CHECK(r.is_ok());
|
BOOST_CHECK(r.is_ok());
|
||||||
BOOST_CHECK(std::isinf(r.unwrap().first));
|
BOOST_CHECK(std::isinf(r.unwrap().first));
|
||||||
@@ -156,21 +156,21 @@ BOOST_AUTO_TEST_CASE(test_nan)
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
const std::string token("nan");
|
const std::string token("nan");
|
||||||
toml::detail::location<std::string> loc("test", token);
|
toml::detail::location loc("test", token);
|
||||||
const auto r = parse_floating(loc);
|
const auto r = parse_floating(loc);
|
||||||
BOOST_CHECK(r.is_ok());
|
BOOST_CHECK(r.is_ok());
|
||||||
BOOST_CHECK(std::isnan(r.unwrap().first));
|
BOOST_CHECK(std::isnan(r.unwrap().first));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const std::string token("+nan");
|
const std::string token("+nan");
|
||||||
toml::detail::location<std::string> loc("test", token);
|
toml::detail::location loc("test", token);
|
||||||
const auto r = parse_floating(loc);
|
const auto r = parse_floating(loc);
|
||||||
BOOST_CHECK(r.is_ok());
|
BOOST_CHECK(r.is_ok());
|
||||||
BOOST_CHECK(std::isnan(r.unwrap().first));
|
BOOST_CHECK(std::isnan(r.unwrap().first));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const std::string token("-nan");
|
const std::string token("-nan");
|
||||||
toml::detail::location<std::string> loc("test", token);
|
toml::detail::location loc("test", token);
|
||||||
const auto r = parse_floating(loc);
|
const auto r = parse_floating(loc);
|
||||||
BOOST_CHECK(r.is_ok());
|
BOOST_CHECK(r.is_ok());
|
||||||
BOOST_CHECK(std::isnan(r.unwrap().first));
|
BOOST_CHECK(std::isnan(r.unwrap().first));
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ BOOST_AUTO_TEST_CASE(test_normal_table)
|
|||||||
"key2 = 42\n"
|
"key2 = 42\n"
|
||||||
"key3 = 3.14\n"
|
"key3 = 3.14\n"
|
||||||
);
|
);
|
||||||
location<std::string> loc("test", table);
|
location loc("test", table);
|
||||||
|
|
||||||
const auto result = toml::detail::parse_ml_table<toml::value>(loc);
|
const auto result = toml::detail::parse_ml_table<toml::value>(loc);
|
||||||
BOOST_TEST(result.is_ok());
|
BOOST_TEST(result.is_ok());
|
||||||
@@ -36,7 +36,7 @@ BOOST_AUTO_TEST_CASE(test_nested_table)
|
|||||||
"a.b = \"value\"\n"
|
"a.b = \"value\"\n"
|
||||||
"a.c.d = 42\n"
|
"a.c.d = 42\n"
|
||||||
);
|
);
|
||||||
location<std::string> loc("test", table);
|
location loc("test", table);
|
||||||
|
|
||||||
const auto result = toml::detail::parse_ml_table<toml::value>(loc);
|
const auto result = toml::detail::parse_ml_table<toml::value>(loc);
|
||||||
BOOST_TEST(result.is_ok());
|
BOOST_TEST(result.is_ok());
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
|
||||||
BOOST_AUTO_TEST_CASE(test_hard_example_unicode)
|
BOOST_AUTO_TEST_CASE(test_hard_example_unicode)
|
||||||
{
|
{
|
||||||
const auto data = toml::parse("toml/tests/hard_example_unicode.toml");
|
const auto data = toml::parse("toml/tests/hard_example_unicode.toml");
|
||||||
@@ -40,35 +39,3 @@ BOOST_AUTO_TEST_CASE(test_hard_example_unicode)
|
|||||||
BOOST_CHECK(toml::get<std::vector<std::string>>(bit.at("multi_line_array")) ==
|
BOOST_CHECK(toml::get<std::vector<std::string>>(bit.at("multi_line_array")) ==
|
||||||
expected_multi_line_array);
|
expected_multi_line_array);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
BOOST_AUTO_TEST_CASE(test_hard_example_unicode)
|
|
||||||
{
|
|
||||||
const auto data = toml::parse("toml/tests/hard_example_unicode.toml");
|
|
||||||
|
|
||||||
const auto the = toml::find<toml::table>(data, "the");
|
|
||||||
BOOST_TEST(toml::get<std::string>(the.at("test_string")) ==
|
|
||||||
std::string(u8"Ýôú'ℓℓ λáƭè ₥è áƒƭèř ƭλïƨ - #"));
|
|
||||||
|
|
||||||
const auto hard = toml::get<toml::table>(the.at("hard"));
|
|
||||||
const std::vector<std::string> expected_the_hard_test_array{"] ", " # "};
|
|
||||||
BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array")) ==
|
|
||||||
expected_the_hard_test_array);
|
|
||||||
const std::vector<std::string> expected_the_hard_test_array2{
|
|
||||||
std::string(u8"Tèƨƭ #11 ]ƥřôƲèδ ƭλáƭ"),
|
|
||||||
std::string(u8"Éжƥèřï₥èñƭ #9 ωáƨ á ƨúççèƨƨ")};
|
|
||||||
BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array2")) ==
|
|
||||||
expected_the_hard_test_array2);
|
|
||||||
BOOST_TEST(toml::get<std::string>(hard.at("another_test_string")) ==
|
|
||||||
std::string(u8"§á₥è ƭλïñϱ, βúƭ ωïƭλ á ƨƭřïñϱ #"));
|
|
||||||
BOOST_TEST(toml::get<std::string>(hard.at("harder_test_string")) ==
|
|
||||||
std::string(u8" Âñδ ωλèñ \"'ƨ ářè ïñ ƭλè ƨƭřïñϱ, áℓôñϱ ωïƭλ # \""));
|
|
||||||
|
|
||||||
const auto bit = toml::get<toml::table>(hard.at(std::string(u8"βïƭ#")));
|
|
||||||
BOOST_TEST(toml::get<std::string>(bit.at(std::string(u8"ωλáƭ?"))) ==
|
|
||||||
std::string(u8"Ýôú δôñ'ƭ ƭλïñƙ ƨô₥è úƨèř ωôñ'ƭ δô ƭλáƭ?"));
|
|
||||||
const std::vector<std::string> expected_multi_line_array{"]"};
|
|
||||||
BOOST_CHECK(toml::get<std::vector<std::string>>(bit.at("multi_line_array")) ==
|
|
||||||
expected_multi_line_array);
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
using namespace toml::literals::toml_literals;
|
using namespace toml::literals::toml_literals;
|
||||||
const auto data = u8R"(windows = "defines min and max as a macro")"_toml;
|
const auto data = R"(windows = "defines min and max as a macro")"_toml;
|
||||||
|
|
||||||
std::cout << toml::find<std::string>(data, "windows") << std::endl;
|
std::cout << toml::find<std::string>(data, "windows") << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -58,13 +58,9 @@ struct character
|
|||||||
{
|
{
|
||||||
static constexpr char target = C;
|
static constexpr char target = C;
|
||||||
|
|
||||||
template<typename Cont>
|
static result<region, none_t>
|
||||||
static result<region<Cont>, none_t>
|
invoke(location& loc)
|
||||||
invoke(location<Cont>& loc)
|
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
|
||||||
"internal error: container::value_type should be `char`.");
|
|
||||||
|
|
||||||
if(loc.iter() == loc.end()) {return none();}
|
if(loc.iter() == loc.end()) {return none();}
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
|
|
||||||
@@ -75,7 +71,7 @@ struct character
|
|||||||
}
|
}
|
||||||
loc.advance(); // update location
|
loc.advance(); // update location
|
||||||
|
|
||||||
return ok(region<Cont>(loc, first, loc.iter()));
|
return ok(region(loc, first, loc.iter()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template<char C>
|
template<char C>
|
||||||
@@ -91,13 +87,9 @@ struct in_range
|
|||||||
static constexpr char upper = Up;
|
static constexpr char upper = Up;
|
||||||
static constexpr char lower = Low;
|
static constexpr char lower = Low;
|
||||||
|
|
||||||
template<typename Cont>
|
static result<region, none_t>
|
||||||
static result<region<Cont>, none_t>
|
invoke(location& loc)
|
||||||
invoke(location<Cont>& loc)
|
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
|
||||||
"internal error: container::value_type should be `char`.");
|
|
||||||
|
|
||||||
if(loc.iter() == loc.end()) {return none();}
|
if(loc.iter() == loc.end()) {return none();}
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
|
|
||||||
@@ -108,7 +100,7 @@ struct in_range
|
|||||||
}
|
}
|
||||||
|
|
||||||
loc.advance();
|
loc.advance();
|
||||||
return ok(region<Cont>(loc, first, loc.iter()));
|
return ok(region(loc, first, loc.iter()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template<char L, char U> constexpr char in_range<L, U>::upper;
|
template<char L, char U> constexpr char in_range<L, U>::upper;
|
||||||
@@ -119,13 +111,9 @@ template<char L, char U> constexpr char in_range<L, U>::lower;
|
|||||||
template<typename Combinator>
|
template<typename Combinator>
|
||||||
struct exclude
|
struct exclude
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
static result<region, none_t>
|
||||||
static result<region<Cont>, none_t>
|
invoke(location& loc)
|
||||||
invoke(location<Cont>& loc)
|
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
|
||||||
"internal error: container::value_type should be `char`.");
|
|
||||||
|
|
||||||
if(loc.iter() == loc.end()) {return none();}
|
if(loc.iter() == loc.end()) {return none();}
|
||||||
auto first = loc.iter();
|
auto first = loc.iter();
|
||||||
|
|
||||||
@@ -136,7 +124,7 @@ struct exclude
|
|||||||
return none();
|
return none();
|
||||||
}
|
}
|
||||||
loc.reset(std::next(first)); // XXX maybe loc.advance() is okay but...
|
loc.reset(std::next(first)); // XXX maybe loc.advance() is okay but...
|
||||||
return ok(region<Cont>(loc, first, loc.iter()));
|
return ok(region(loc, first, loc.iter()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -144,19 +132,15 @@ struct exclude
|
|||||||
template<typename Combinator>
|
template<typename Combinator>
|
||||||
struct maybe
|
struct maybe
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
static result<region, none_t>
|
||||||
static result<region<Cont>, none_t>
|
invoke(location& loc)
|
||||||
invoke(location<Cont>& loc)
|
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
|
||||||
"internal error: container::value_type should be `char`.");
|
|
||||||
|
|
||||||
const auto rslt = Combinator::invoke(loc);
|
const auto rslt = Combinator::invoke(loc);
|
||||||
if(rslt.is_ok())
|
if(rslt.is_ok())
|
||||||
{
|
{
|
||||||
return rslt;
|
return rslt;
|
||||||
}
|
}
|
||||||
return ok(region<Cont>(loc));
|
return ok(region(loc));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -166,13 +150,9 @@ struct sequence;
|
|||||||
template<typename Head, typename ... Tail>
|
template<typename Head, typename ... Tail>
|
||||||
struct sequence<Head, Tail...>
|
struct sequence<Head, Tail...>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
static result<region, none_t>
|
||||||
static result<region<Cont>, none_t>
|
invoke(location& loc)
|
||||||
invoke(location<Cont>& loc)
|
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
|
||||||
"internal error: container::value_type should be `char`.");
|
|
||||||
|
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
const auto rslt = Head::invoke(loc);
|
const auto rslt = Head::invoke(loc);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
@@ -184,9 +164,9 @@ struct sequence<Head, Tail...>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// called from the above function only, recursively.
|
// called from the above function only, recursively.
|
||||||
template<typename Cont, typename Iterator>
|
template<typename Iterator>
|
||||||
static result<region<Cont>, none_t>
|
static result<region, none_t>
|
||||||
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
|
invoke(location& loc, region reg, Iterator first)
|
||||||
{
|
{
|
||||||
const auto rslt = Head::invoke(loc);
|
const auto rslt = Head::invoke(loc);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
@@ -203,9 +183,9 @@ template<typename Head>
|
|||||||
struct sequence<Head>
|
struct sequence<Head>
|
||||||
{
|
{
|
||||||
// would be called from sequence<T ...>::invoke only.
|
// would be called from sequence<T ...>::invoke only.
|
||||||
template<typename Cont, typename Iterator>
|
template<typename Iterator>
|
||||||
static result<region<Cont>, none_t>
|
static result<region, none_t>
|
||||||
invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
|
invoke(location& loc, region reg, Iterator first)
|
||||||
{
|
{
|
||||||
const auto rslt = Head::invoke(loc);
|
const auto rslt = Head::invoke(loc);
|
||||||
if(rslt.is_err())
|
if(rslt.is_err())
|
||||||
@@ -224,13 +204,9 @@ struct either;
|
|||||||
template<typename Head, typename ... Tail>
|
template<typename Head, typename ... Tail>
|
||||||
struct either<Head, Tail...>
|
struct either<Head, Tail...>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
static result<region, none_t>
|
||||||
static result<region<Cont>, none_t>
|
invoke(location& loc)
|
||||||
invoke(location<Cont>& loc)
|
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
|
||||||
"internal error: container::value_type should be `char`.");
|
|
||||||
|
|
||||||
const auto rslt = Head::invoke(loc);
|
const auto rslt = Head::invoke(loc);
|
||||||
if(rslt.is_ok()) {return rslt;}
|
if(rslt.is_ok()) {return rslt;}
|
||||||
return either<Tail...>::invoke(loc);
|
return either<Tail...>::invoke(loc);
|
||||||
@@ -239,12 +215,9 @@ struct either<Head, Tail...>
|
|||||||
template<typename Head>
|
template<typename Head>
|
||||||
struct either<Head>
|
struct either<Head>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
static result<region, none_t>
|
||||||
static result<region<Cont>, none_t>
|
invoke(location& loc)
|
||||||
invoke(location<Cont>& loc)
|
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<char, typename Cont::value_type>::value,
|
|
||||||
"internal error: container::value_type should be `char`.");
|
|
||||||
return Head::invoke(loc);
|
return Head::invoke(loc);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -259,11 +232,10 @@ struct unlimited{};
|
|||||||
template<typename T, std::size_t N>
|
template<typename T, std::size_t N>
|
||||||
struct repeat<T, exactly<N>>
|
struct repeat<T, exactly<N>>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
static result<region, none_t>
|
||||||
static result<region<Cont>, none_t>
|
invoke(location& loc)
|
||||||
invoke(location<Cont>& loc)
|
|
||||||
{
|
{
|
||||||
region<Cont> retval(loc);
|
region retval(loc);
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
for(std::size_t i=0; i<N; ++i)
|
for(std::size_t i=0; i<N; ++i)
|
||||||
{
|
{
|
||||||
@@ -282,11 +254,10 @@ struct repeat<T, exactly<N>>
|
|||||||
template<typename T, std::size_t N>
|
template<typename T, std::size_t N>
|
||||||
struct repeat<T, at_least<N>>
|
struct repeat<T, at_least<N>>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
static result<region, none_t>
|
||||||
static result<region<Cont>, none_t>
|
invoke(location& loc)
|
||||||
invoke(location<Cont>& loc)
|
|
||||||
{
|
{
|
||||||
region<Cont> retval(loc);
|
region retval(loc);
|
||||||
|
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
for(std::size_t i=0; i<N; ++i)
|
for(std::size_t i=0; i<N; ++i)
|
||||||
@@ -314,11 +285,10 @@ struct repeat<T, at_least<N>>
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
struct repeat<T, unlimited>
|
struct repeat<T, unlimited>
|
||||||
{
|
{
|
||||||
template<typename Cont>
|
static result<region, none_t>
|
||||||
static result<region<Cont>, none_t>
|
invoke(location& loc)
|
||||||
invoke(location<Cont>& loc)
|
|
||||||
{
|
{
|
||||||
region<Cont> retval(loc);
|
region retval(loc);
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
auto rslt = T::invoke(loc);
|
auto rslt = T::invoke(loc);
|
||||||
|
|||||||
37
toml/get.hpp
37
toml/get.hpp
@@ -189,8 +189,7 @@ get(const basic_value<C, M, V>& v)
|
|||||||
{
|
{
|
||||||
throw type_error(detail::format_underline("toml::value: "
|
throw type_error(detail::format_underline("toml::value: "
|
||||||
"bad_cast to std::chrono::system_clock::time_point", {
|
"bad_cast to std::chrono::system_clock::time_point", {
|
||||||
{std::addressof(detail::get_region(v)),
|
{v.location(), concat_to_string("the actual type is ", v.type())}
|
||||||
concat_to_string("the actual type is ", v.type())}
|
|
||||||
}), v.location());
|
}), v.location());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -336,7 +335,7 @@ get(const basic_value<C, M, V>& v)
|
|||||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
"toml::get: specified container size is ", container.size(),
|
"toml::get: specified container size is ", container.size(),
|
||||||
" but there are ", ar.size(), " elements in toml array."), {
|
" but there are ", ar.size(), " elements in toml array."), {
|
||||||
{std::addressof(detail::get_region(v)), "here"}
|
{v.location(), "here"}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
std::transform(ar.cbegin(), ar.cend(), container.begin(),
|
std::transform(ar.cbegin(), ar.cend(), container.begin(),
|
||||||
@@ -360,9 +359,7 @@ get(const basic_value<C, M, V>& v)
|
|||||||
{
|
{
|
||||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
"toml::get: specified std::pair but there are ", ar.size(),
|
"toml::get: specified std::pair but there are ", ar.size(),
|
||||||
" elements in toml array."), {
|
" elements in toml array."), {{v.location(), "here"}}));
|
||||||
{std::addressof(detail::get_region(v)), "here"}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
return std::make_pair(::toml::get<first_type >(ar.at(0)),
|
return std::make_pair(::toml::get<first_type >(ar.at(0)),
|
||||||
::toml::get<second_type>(ar.at(1)));
|
::toml::get<second_type>(ar.at(1)));
|
||||||
@@ -392,9 +389,7 @@ get(const basic_value<C, M, V>& v)
|
|||||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
"toml::get: specified std::tuple with ",
|
"toml::get: specified std::tuple with ",
|
||||||
std::tuple_size<T>::value, " elements, but there are ", ar.size(),
|
std::tuple_size<T>::value, " elements, but there are ", ar.size(),
|
||||||
" elements in toml array."), {
|
" elements in toml array."), {{v.location(), "here"}}));
|
||||||
{std::addressof(detail::get_region(v)), "here"}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
return detail::get_tuple_impl<T>(ar,
|
return detail::get_tuple_impl<T>(ar,
|
||||||
detail::make_index_sequence<std::tuple_size<T>::value>{});
|
detail::make_index_sequence<std::tuple_size<T>::value>{});
|
||||||
@@ -511,9 +506,7 @@ find(const basic_value<C, M, V>& v, const std::size_t idx)
|
|||||||
if(ary.size() <= idx)
|
if(ary.size() <= idx)
|
||||||
{
|
{
|
||||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
"index ", idx, " is out of range"), {
|
"index ", idx, " is out of range"), {{v.location(), "in this array"}}));
|
||||||
{std::addressof(detail::get_region(v)), "in this array"}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
return ary.at(idx);
|
return ary.at(idx);
|
||||||
}
|
}
|
||||||
@@ -525,9 +518,7 @@ basic_value<C, M, V>& find(basic_value<C, M, V>& v, const std::size_t idx)
|
|||||||
if(ary.size() <= idx)
|
if(ary.size() <= idx)
|
||||||
{
|
{
|
||||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
"index ", idx, " is out of range"), {
|
"index ", idx, " is out of range"), {{v.location(), "in this array"}}));
|
||||||
{std::addressof(detail::get_region(v)), "in this array"}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
return ary.at(idx);
|
return ary.at(idx);
|
||||||
}
|
}
|
||||||
@@ -539,9 +530,7 @@ basic_value<C, M, V> find(basic_value<C, M, V>&& v, const std::size_t idx)
|
|||||||
if(ary.size() <= idx)
|
if(ary.size() <= idx)
|
||||||
{
|
{
|
||||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
"index ", idx, " is out of range"), {
|
"index ", idx, " is out of range"), {{v.location(), "in this array"}}));
|
||||||
{std::addressof(detail::get_region(v)), "in this array"}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
return basic_value<C, M, V>(std::move(ary.at(idx)));
|
return basic_value<C, M, V>(std::move(ary.at(idx)));
|
||||||
}
|
}
|
||||||
@@ -599,9 +588,7 @@ find(const basic_value<C, M, V>& v, const std::size_t idx)
|
|||||||
if(ary.size() <= idx)
|
if(ary.size() <= idx)
|
||||||
{
|
{
|
||||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
"index ", idx, " is out of range"), {
|
"index ", idx, " is out of range"), {{v.location(), "in this array"}}));
|
||||||
{std::addressof(detail::get_region(v)), "in this array"}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
return ::toml::get<T>(ary.at(idx));
|
return ::toml::get<T>(ary.at(idx));
|
||||||
}
|
}
|
||||||
@@ -614,9 +601,7 @@ find(basic_value<C, M, V>& v, const std::size_t idx)
|
|||||||
if(ary.size() <= idx)
|
if(ary.size() <= idx)
|
||||||
{
|
{
|
||||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
"index ", idx, " is out of range"), {
|
"index ", idx, " is out of range"), {{v.location(), "in this array"}}));
|
||||||
{std::addressof(detail::get_region(v)), "in this array"}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
return ::toml::get<T>(ary.at(idx));
|
return ::toml::get<T>(ary.at(idx));
|
||||||
}
|
}
|
||||||
@@ -629,9 +614,7 @@ find(basic_value<C, M, V>&& v, const std::size_t idx)
|
|||||||
if(ary.size() <= idx)
|
if(ary.size() <= idx)
|
||||||
{
|
{
|
||||||
throw std::out_of_range(detail::format_underline(concat_to_string(
|
throw std::out_of_range(detail::format_underline(concat_to_string(
|
||||||
"index ", idx, " is out of range"), {
|
"index ", idx, " is out of range"), {{v.location(), "in this array"}}));
|
||||||
{std::addressof(detail::get_region(v)), "in this array"}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
return ::toml::get<T>(std::move(ary.at(idx)));
|
return ::toml::get<T>(std::move(ary.at(idx)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,12 +11,9 @@ inline namespace literals
|
|||||||
inline namespace toml_literals
|
inline namespace toml_literals
|
||||||
{
|
{
|
||||||
|
|
||||||
inline ::toml::value operator"" _toml(const char* str, std::size_t len)
|
// implementation
|
||||||
|
inline ::toml::value literal_internal_impl(::toml::detail::location loc)
|
||||||
{
|
{
|
||||||
::toml::detail::location<std::vector<char>>
|
|
||||||
loc(/* filename = */ std::string("TOML literal encoded in a C++ code"),
|
|
||||||
/* contents = */ std::vector<char>(str, str + len));
|
|
||||||
|
|
||||||
// if there are some comments or empty lines, skip them.
|
// if there are some comments or empty lines, skip them.
|
||||||
using skip_line = ::toml::detail::repeat<toml::detail::sequence<
|
using skip_line = ::toml::detail::repeat<toml::detail::sequence<
|
||||||
::toml::detail::maybe<::toml::detail::lex_ws>,
|
::toml::detail::maybe<::toml::detail::lex_ws>,
|
||||||
@@ -76,11 +73,34 @@ inline ::toml::value operator"" _toml(const char* str, std::size_t len)
|
|||||||
}
|
}
|
||||||
else // none of them.
|
else // none of them.
|
||||||
{
|
{
|
||||||
throw ::toml::syntax_error(data.unwrap_err(),
|
throw ::toml::syntax_error(data.unwrap_err(), source_location(loc));
|
||||||
source_location(std::addressof(loc)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline ::toml::value operator"" _toml(const char* str, std::size_t len)
|
||||||
|
{
|
||||||
|
::toml::detail::location loc(
|
||||||
|
std::string("TOML literal encoded in a C++ code"),
|
||||||
|
std::vector<char>(str, str + len));
|
||||||
|
return literal_internal_impl(std::move(loc));
|
||||||
|
}
|
||||||
|
|
||||||
|
// value of __cplusplus in C++2a/20 mode is not fixed yet along compilers.
|
||||||
|
// So here we use the feature test macro for `char8_t` itself.
|
||||||
|
#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L
|
||||||
|
// value of u8"" literal has been changed from char to char8_t and char8_t is
|
||||||
|
// NOT compatible to char
|
||||||
|
inline ::toml::value operator"" _toml(const char8_t* str, std::size_t len)
|
||||||
|
{
|
||||||
|
::toml::detail::location loc(
|
||||||
|
std::string("TOML literal encoded in a C++ code"),
|
||||||
|
std::vector<char>(reinterpret_cast<const char*>(str),
|
||||||
|
reinterpret_cast<const char*>(str) + len));
|
||||||
|
return literal_internal_impl(std::move(loc));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // toml_literals
|
} // toml_literals
|
||||||
} // literals
|
} // literals
|
||||||
} // toml
|
} // toml
|
||||||
|
|||||||
577
toml/parser.hpp
577
toml/parser.hpp
File diff suppressed because it is too large
Load Diff
140
toml/region.hpp
140
toml/region.hpp
@@ -67,22 +67,21 @@ struct region_base
|
|||||||
//
|
//
|
||||||
// it contains pointer to the file content and iterator that points the current
|
// it contains pointer to the file content and iterator that points the current
|
||||||
// location.
|
// location.
|
||||||
template<typename Container>
|
|
||||||
struct location final : public region_base
|
struct location final : public region_base
|
||||||
{
|
{
|
||||||
using const_iterator = typename Container::const_iterator;
|
using const_iterator = typename std::vector<char>::const_iterator;
|
||||||
using difference_type = typename const_iterator::difference_type;
|
using difference_type = typename const_iterator::difference_type;
|
||||||
using source_ptr = std::shared_ptr<const Container>;
|
using source_ptr = std::shared_ptr<const std::vector<char>>;
|
||||||
|
|
||||||
static_assert(std::is_same<char, typename Container::value_type>::value,"");
|
location(std::string name, std::vector<char> cont)
|
||||||
static_assert(std::is_same<std::random_access_iterator_tag,
|
: source_(std::make_shared<std::vector<char>>(std::move(cont))),
|
||||||
typename std::iterator_traits<const_iterator>::iterator_category>::value,
|
line_number_(1), source_name_(std::move(name)), iter_(source_->cbegin())
|
||||||
"container should be randomly accessible");
|
|
||||||
|
|
||||||
location(std::string name, Container cont)
|
|
||||||
: source_(std::make_shared<Container>(std::move(cont))), line_number_(1),
|
|
||||||
source_name_(std::move(name)), iter_(source_->cbegin())
|
|
||||||
{}
|
{}
|
||||||
|
location(std::string name, const std::string& cont)
|
||||||
|
: source_(std::make_shared<std::vector<char>>(cont.begin(), cont.end())),
|
||||||
|
line_number_(1), source_name_(std::move(name)), iter_(source_->cbegin())
|
||||||
|
{}
|
||||||
|
|
||||||
location(const location&) = default;
|
location(const location&) = default;
|
||||||
location(location&&) = default;
|
location(location&&) = default;
|
||||||
location& operator=(const location&) = default;
|
location& operator=(const location&) = default;
|
||||||
@@ -195,33 +194,27 @@ struct location final : public region_base
|
|||||||
//
|
//
|
||||||
// it contains pointer to the file content and iterator that points the first
|
// it contains pointer to the file content and iterator that points the first
|
||||||
// and last location.
|
// and last location.
|
||||||
template<typename Container>
|
|
||||||
struct region final : public region_base
|
struct region final : public region_base
|
||||||
{
|
{
|
||||||
using const_iterator = typename Container::const_iterator;
|
using const_iterator = typename std::vector<char>::const_iterator;
|
||||||
using source_ptr = std::shared_ptr<const Container>;
|
using source_ptr = std::shared_ptr<const std::vector<char>>;
|
||||||
|
|
||||||
static_assert(std::is_same<char, typename Container::value_type>::value,"");
|
|
||||||
static_assert(std::is_same<std::random_access_iterator_tag,
|
|
||||||
typename std::iterator_traits<const_iterator>::iterator_category>::value,
|
|
||||||
"container should be randomly accessible");
|
|
||||||
|
|
||||||
// delete default constructor. source_ never be null.
|
// delete default constructor. source_ never be null.
|
||||||
region() = delete;
|
region() = delete;
|
||||||
|
|
||||||
region(const location<Container>& loc)
|
explicit region(const location& loc)
|
||||||
: source_(loc.source()), source_name_(loc.name()),
|
: source_(loc.source()), source_name_(loc.name()),
|
||||||
first_(loc.iter()), last_(loc.iter())
|
first_(loc.iter()), last_(loc.iter())
|
||||||
{}
|
{}
|
||||||
region(location<Container>&& loc)
|
explicit region(location&& loc)
|
||||||
: source_(loc.source()), source_name_(loc.name()),
|
: source_(loc.source()), source_name_(loc.name()),
|
||||||
first_(loc.iter()), last_(loc.iter())
|
first_(loc.iter()), last_(loc.iter())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
region(const location<Container>& loc, const_iterator f, const_iterator l)
|
region(const location& loc, const_iterator f, const_iterator l)
|
||||||
: source_(loc.source()), source_name_(loc.name()), first_(f), last_(l)
|
: source_(loc.source()), source_name_(loc.name()), first_(f), last_(l)
|
||||||
{}
|
{}
|
||||||
region(location<Container>&& loc, const_iterator f, const_iterator l)
|
region(location&& loc, const_iterator f, const_iterator l)
|
||||||
: source_(loc.source()), source_name_(loc.name()), first_(f), last_(l)
|
: source_(loc.source()), source_name_(loc.name()), first_(f), last_(l)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -419,107 +412,6 @@ struct region final : public region_base
|
|||||||
const_iterator first_, last_;
|
const_iterator first_, last_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// to show a better error message.
|
|
||||||
inline std::string format_underline(const std::string& message,
|
|
||||||
const std::vector<std::pair<region_base const*, std::string>>& reg_com,
|
|
||||||
const std::vector<std::string>& helps = {},
|
|
||||||
const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED)
|
|
||||||
{
|
|
||||||
assert(!reg_com.empty());
|
|
||||||
|
|
||||||
const auto line_num_width = static_cast<int>(std::max_element(
|
|
||||||
reg_com.begin(), reg_com.end(),
|
|
||||||
[](std::pair<region_base const*, std::string> const& lhs,
|
|
||||||
std::pair<region_base const*, std::string> const& rhs)
|
|
||||||
{
|
|
||||||
return lhs.first->line_num().size() < rhs.first->line_num().size();
|
|
||||||
}
|
|
||||||
)->first->line_num().size());
|
|
||||||
|
|
||||||
std::ostringstream retval;
|
|
||||||
|
|
||||||
if(colorize)
|
|
||||||
{
|
|
||||||
retval << color::colorize; // turn on ANSI color
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX
|
|
||||||
// Here, before `colorize` support, it does not output `[error]` prefix
|
|
||||||
// automatically. So some user may output it manually and this change may
|
|
||||||
// duplicate the prefix. To avoid it, check the first 7 characters and
|
|
||||||
// if it is "[error]", it removes that part from the message shown.
|
|
||||||
if(message.size() > 7 && message.substr(0, 7) == "[error]")
|
|
||||||
{
|
|
||||||
retval << color::bold << color::red << "[error]" << color::reset
|
|
||||||
<< color::bold << message.substr(7) << color::reset << '\n';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
retval << color::bold << color::red << "[error] " << color::reset
|
|
||||||
<< color::bold << message << color::reset << '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto iter = reg_com.begin(); iter != reg_com.end(); ++iter)
|
|
||||||
{
|
|
||||||
// if the filenames are the same, print "..."
|
|
||||||
if(iter != reg_com.begin() &&
|
|
||||||
std::prev(iter)->first->name() == iter->first->name())
|
|
||||||
{
|
|
||||||
retval << color::bold << color::blue << "\n ...\n" << color::reset;
|
|
||||||
}
|
|
||||||
else // if filename differs, print " --> filename.toml"
|
|
||||||
{
|
|
||||||
if(iter != reg_com.begin()) {retval << '\n';}
|
|
||||||
retval << color::bold << color::blue << " --> " << color::reset
|
|
||||||
<< iter->first->name() << '\n';
|
|
||||||
// add one almost-empty line for readability
|
|
||||||
retval << make_string(static_cast<std::size_t>(line_num_width + 1), ' ')
|
|
||||||
<< color::bold << color::blue << " | " << color::reset << '\n';
|
|
||||||
}
|
|
||||||
const region_base* const reg = iter->first;
|
|
||||||
const std::string& comment = iter->second;
|
|
||||||
|
|
||||||
retval << ' ' << color::bold << color::blue << std::setw(line_num_width)
|
|
||||||
<< std::right << reg->line_num() << " | " << color::reset
|
|
||||||
<< reg->line() << '\n';
|
|
||||||
|
|
||||||
retval << make_string(static_cast<std::size_t>(line_num_width + 1), ' ')
|
|
||||||
<< color::bold << color::blue << " | " << color::reset
|
|
||||||
<< make_string(reg->before(), ' ');
|
|
||||||
|
|
||||||
if(reg->size() == 1)
|
|
||||||
{
|
|
||||||
// invalid
|
|
||||||
// ^------
|
|
||||||
retval << color::bold << color::red
|
|
||||||
<< '^' << make_string(reg->after(), '-') << color::reset;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// invalid
|
|
||||||
// ~~~~~~~
|
|
||||||
const auto underline_len = (std::min)(reg->size(), reg->line().size());
|
|
||||||
retval << color::bold << color::red
|
|
||||||
<< make_string(underline_len, '~') << color::reset;
|
|
||||||
}
|
|
||||||
retval << ' ';
|
|
||||||
retval << comment;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!helps.empty())
|
|
||||||
{
|
|
||||||
retval << '\n';
|
|
||||||
retval << make_string(static_cast<std::size_t>(line_num_width + 1), ' ');
|
|
||||||
retval << color::bold << color::blue << " | " << color::reset;
|
|
||||||
for(const auto& help : helps)
|
|
||||||
{
|
|
||||||
retval << color::bold << "\nHint: " << color::reset;
|
|
||||||
retval << help;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return retval.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
} // toml
|
} // toml
|
||||||
#endif// TOML11_REGION_H
|
#endif// TOML11_REGION_H
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ std::basic_string<charT, traits, Alloc>
|
|||||||
format_key(const std::basic_string<charT, traits, Alloc>& key)
|
format_key(const std::basic_string<charT, traits, Alloc>& key)
|
||||||
{
|
{
|
||||||
// check the key can be a bare (unquoted) key
|
// check the key can be a bare (unquoted) key
|
||||||
detail::location<toml::key> loc(key, key);
|
detail::location loc(key, std::vector<char>(key.begin(), key.end()));
|
||||||
detail::lex_unquoted_key::invoke(loc);
|
detail::lex_unquoted_key::invoke(loc);
|
||||||
if(loc.iter() == loc.end())
|
if(loc.iter() == loc.end())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -39,12 +39,12 @@ struct source_location
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
source_location()
|
source_location()
|
||||||
: line_num_(0), column_num_(0), region_size_(0),
|
: line_num_(1), column_num_(1), region_size_(1),
|
||||||
file_name_("unknown file"), line_str_("")
|
file_name_("unknown file"), line_str_("")
|
||||||
{}
|
{}
|
||||||
|
|
||||||
explicit source_location(const detail::region_base* reg)
|
explicit source_location(const detail::region_base* reg)
|
||||||
: line_num_(0), column_num_(0), region_size_(0),
|
: line_num_(1), column_num_(1), region_size_(1),
|
||||||
file_name_("unknown file"), line_str_("")
|
file_name_("unknown file"), line_str_("")
|
||||||
{
|
{
|
||||||
if(reg)
|
if(reg)
|
||||||
@@ -61,6 +61,21 @@ struct source_location
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
explicit source_location(const detail::region& reg)
|
||||||
|
: line_num_(static_cast<std::uint_least32_t>(std::stoul(reg.line_num()))),
|
||||||
|
column_num_(static_cast<std::uint_least32_t>(reg.before() + 1)),
|
||||||
|
region_size_(static_cast<std::uint_least32_t>(reg.size())),
|
||||||
|
file_name_(reg.name()),
|
||||||
|
line_str_ (reg.line())
|
||||||
|
{}
|
||||||
|
explicit source_location(const detail::location& loc)
|
||||||
|
: line_num_(static_cast<std::uint_least32_t>(std::stoul(loc.line_num()))),
|
||||||
|
column_num_(static_cast<std::uint_least32_t>(loc.before() + 1)),
|
||||||
|
region_size_(static_cast<std::uint_least32_t>(loc.size())),
|
||||||
|
file_name_(loc.name()),
|
||||||
|
line_str_ (loc.line())
|
||||||
|
{}
|
||||||
|
|
||||||
~source_location() = default;
|
~source_location() = default;
|
||||||
source_location(source_location const&) = default;
|
source_location(source_location const&) = default;
|
||||||
source_location(source_location &&) = default;
|
source_location(source_location &&) = default;
|
||||||
@@ -83,5 +98,135 @@ struct source_location
|
|||||||
std::string line_str_;
|
std::string line_str_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
// internal error message generation.
|
||||||
|
inline std::string format_underline(const std::string& message,
|
||||||
|
const std::vector<std::pair<source_location, std::string>>& loc_com,
|
||||||
|
const std::vector<std::string>& helps = {},
|
||||||
|
const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED)
|
||||||
|
{
|
||||||
|
std::size_t line_num_width = 0;
|
||||||
|
for(const auto& lc : loc_com)
|
||||||
|
{
|
||||||
|
std::uint_least32_t line = lc.first.line();
|
||||||
|
std::size_t digit = 0;
|
||||||
|
while(line != 0)
|
||||||
|
{
|
||||||
|
line /= 10;
|
||||||
|
digit += 1;
|
||||||
|
}
|
||||||
|
line_num_width = (std::max)(line_num_width, digit);
|
||||||
|
}
|
||||||
|
// 1 is the minimum width
|
||||||
|
line_num_width = std::max<std::size_t>(line_num_width, 1);
|
||||||
|
|
||||||
|
std::ostringstream retval;
|
||||||
|
|
||||||
|
if(colorize)
|
||||||
|
{
|
||||||
|
retval << color::colorize; // turn on ANSI color
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX
|
||||||
|
// Here, before `colorize` support, it does not output `[error]` prefix
|
||||||
|
// automatically. So some user may output it manually and this change may
|
||||||
|
// duplicate the prefix. To avoid it, check the first 7 characters and
|
||||||
|
// if it is "[error]", it removes that part from the message shown.
|
||||||
|
if(message.size() > 7 && message.substr(0, 7) == "[error]")
|
||||||
|
{
|
||||||
|
retval << color::bold << color::red << "[error]" << color::reset
|
||||||
|
<< color::bold << message.substr(7) << color::reset << '\n';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retval << color::bold << color::red << "[error] " << color::reset
|
||||||
|
<< color::bold << message << color::reset << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto format_one_location = [line_num_width]
|
||||||
|
(std::ostringstream& oss,
|
||||||
|
const source_location& loc, const std::string& comment) -> void
|
||||||
|
{
|
||||||
|
oss << ' ' << color::bold << color::blue
|
||||||
|
<< std::setw(static_cast<int>(line_num_width))
|
||||||
|
<< std::right << loc.line() << " | " << color::reset
|
||||||
|
<< loc.line_str() << '\n';
|
||||||
|
|
||||||
|
oss << make_string(line_num_width + 1, ' ')
|
||||||
|
<< color::bold << color::blue << " | " << color::reset
|
||||||
|
<< make_string(loc.column()-1 /*1-origin*/, ' ');
|
||||||
|
|
||||||
|
if(loc.region() == 1)
|
||||||
|
{
|
||||||
|
// invalid
|
||||||
|
// ^------
|
||||||
|
oss << color::bold << color::red << "^---" << color::reset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// invalid
|
||||||
|
// ~~~~~~~
|
||||||
|
const auto underline_len = (std::min)(
|
||||||
|
static_cast<std::size_t>(loc.region()), loc.line_str().size());
|
||||||
|
oss << color::bold << color::red
|
||||||
|
<< make_string(underline_len, '~') << color::reset;
|
||||||
|
}
|
||||||
|
oss << ' ';
|
||||||
|
oss << comment;
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
assert(!loc_com.empty());
|
||||||
|
|
||||||
|
// --> example.toml
|
||||||
|
// |
|
||||||
|
retval << color::bold << color::blue << " --> " << color::reset
|
||||||
|
<< loc_com.front().first.file_name() << '\n';
|
||||||
|
retval << make_string(line_num_width + 1, ' ')
|
||||||
|
<< color::bold << color::blue << " |\n" << color::reset;
|
||||||
|
// 1 | key value
|
||||||
|
// | ^--- missing =
|
||||||
|
format_one_location(retval, loc_com.front().first, loc_com.front().second);
|
||||||
|
|
||||||
|
// process the rest of the locations
|
||||||
|
for(std::size_t i=1; i<loc_com.size(); ++i)
|
||||||
|
{
|
||||||
|
const auto& prev = loc_com.at(i-1);
|
||||||
|
const auto& curr = loc_com.at(i);
|
||||||
|
|
||||||
|
retval << '\n';
|
||||||
|
// if the filenames are the same, print "..."
|
||||||
|
if(prev.first.file_name() == curr.first.file_name())
|
||||||
|
{
|
||||||
|
retval << color::bold << color::blue << " ...\n" << color::reset;
|
||||||
|
}
|
||||||
|
else // if filename differs, print " --> filename.toml" again
|
||||||
|
{
|
||||||
|
retval << color::bold << color::blue << " --> " << color::reset
|
||||||
|
<< curr.first.file_name() << '\n';
|
||||||
|
retval << make_string(line_num_width + 1, ' ')
|
||||||
|
<< color::bold << color::blue << " |\n" << color::reset;
|
||||||
|
}
|
||||||
|
|
||||||
|
format_one_location(retval, curr.first, curr.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!helps.empty())
|
||||||
|
{
|
||||||
|
retval << '\n';
|
||||||
|
retval << make_string(line_num_width + 1, ' ');
|
||||||
|
retval << color::bold << color::blue << " |" << color::reset;
|
||||||
|
for(const auto& help : helps)
|
||||||
|
{
|
||||||
|
retval << color::bold << "\nHint: " << color::reset;
|
||||||
|
retval << help;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retval.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // detail
|
||||||
} // toml
|
} // toml
|
||||||
#endif// TOML11_SOURCE_LOCATION_HPP
|
#endif// TOML11_SOURCE_LOCATION_HPP
|
||||||
|
|||||||
124
toml/value.hpp
124
toml/value.hpp
@@ -22,21 +22,15 @@ namespace detail
|
|||||||
|
|
||||||
// to show error messages. not recommended for users.
|
// to show error messages. not recommended for users.
|
||||||
template<typename Value>
|
template<typename Value>
|
||||||
inline region_base const& get_region(const Value& v)
|
inline region_base const* get_region(const Value& v)
|
||||||
{
|
{
|
||||||
return *(v.region_info_);
|
return v.region_info_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Value, typename Region>
|
template<typename Value>
|
||||||
void change_region(Value& v, Region&& reg)
|
void change_region(Value& v, region reg)
|
||||||
{
|
{
|
||||||
using region_type = typename std::remove_reference<
|
v.region_info_ = std::make_shared<region>(std::move(reg));
|
||||||
typename std::remove_cv<Region>::type
|
|
||||||
>::type;
|
|
||||||
|
|
||||||
std::shared_ptr<region_base> new_reg =
|
|
||||||
std::make_shared<region_type>(std::forward<region_type>(reg));
|
|
||||||
v.region_info_ = new_reg;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,8 +40,7 @@ throw_bad_cast(const std::string& funcname, value_t actual, const Value& v)
|
|||||||
{
|
{
|
||||||
throw type_error(detail::format_underline(
|
throw type_error(detail::format_underline(
|
||||||
concat_to_string(funcname, "bad_cast to ", Expected), {
|
concat_to_string(funcname, "bad_cast to ", Expected), {
|
||||||
{std::addressof(get_region(v)),
|
{v.location(), concat_to_string("the actual type is ", actual)}
|
||||||
concat_to_string("the actual type is ", actual)}
|
|
||||||
}), v.location());
|
}), v.location());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,8 +67,8 @@ throw_key_not_found_error(const Value& v, const key& ky)
|
|||||||
// It actually points to the top-level table at the first character,
|
// It actually points to the top-level table at the first character,
|
||||||
// not `[table]`. But it is too confusing. To avoid the confusion, the error
|
// not `[table]`. But it is too confusing. To avoid the confusion, the error
|
||||||
// message should explicitly say "key not found in the top-level table".
|
// message should explicitly say "key not found in the top-level table".
|
||||||
const auto& reg = get_region(v);
|
const auto loc = v.location();
|
||||||
if(reg.line_num() == "1" && reg.size() == 1)
|
if(loc.line() == 1 && loc.region() == 1)
|
||||||
{
|
{
|
||||||
// Here it assumes that top-level table starts at the first character.
|
// Here it assumes that top-level table starts at the first character.
|
||||||
// The region corresponds to the top-level table will be generated at
|
// The region corresponds to the top-level table will be generated at
|
||||||
@@ -111,16 +104,14 @@ throw_key_not_found_error(const Value& v, const key& ky)
|
|||||||
//
|
//
|
||||||
throw std::out_of_range(format_underline(concat_to_string(
|
throw std::out_of_range(format_underline(concat_to_string(
|
||||||
"key \"", ky, "\" not found in the top-level table"), {
|
"key \"", ky, "\" not found in the top-level table"), {
|
||||||
{std::addressof(reg), "the top-level table starts here"}
|
{loc, "the top-level table starts here"}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// normal table.
|
// normal table.
|
||||||
throw std::out_of_range(format_underline(concat_to_string(
|
throw std::out_of_range(format_underline(concat_to_string(
|
||||||
"key \"", ky, "\" not found"), {
|
"key \"", ky, "\" not found"), { {loc, "in this table"} }));
|
||||||
{std::addressof(reg), "in this table"}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1056,95 +1047,87 @@ class basic_value
|
|||||||
//
|
//
|
||||||
// Those constructors take detail::region that contains parse result.
|
// Those constructors take detail::region that contains parse result.
|
||||||
|
|
||||||
template<typename Container>
|
basic_value(boolean b, detail::region reg)
|
||||||
basic_value(boolean b, detail::region<Container> reg)
|
|
||||||
: type_(value_t::boolean),
|
: type_(value_t::boolean),
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
region_info_(std::make_shared<detail::region>(std::move(reg))),
|
||||||
comments_(region_info_->comments())
|
comments_(region_info_->comments())
|
||||||
{
|
{
|
||||||
assigner(this->boolean_, b);
|
assigner(this->boolean_, b);
|
||||||
}
|
}
|
||||||
template<typename T, typename Container, typename std::enable_if<
|
template<typename T, typename std::enable_if<
|
||||||
detail::conjunction<
|
detail::conjunction<
|
||||||
std::is_integral<T>, detail::negation<std::is_same<T, boolean>>
|
std::is_integral<T>, detail::negation<std::is_same<T, boolean>>
|
||||||
>::value, std::nullptr_t>::type = nullptr>
|
>::value, std::nullptr_t>::type = nullptr>
|
||||||
basic_value(T i, detail::region<Container> reg)
|
basic_value(T i, detail::region reg)
|
||||||
: type_(value_t::integer),
|
: type_(value_t::integer),
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
region_info_(std::make_shared<detail::region>(std::move(reg))),
|
||||||
comments_(region_info_->comments())
|
comments_(region_info_->comments())
|
||||||
{
|
{
|
||||||
assigner(this->integer_, static_cast<integer>(i));
|
assigner(this->integer_, static_cast<integer>(i));
|
||||||
}
|
}
|
||||||
template<typename T, typename Container, typename std::enable_if<
|
template<typename T, typename std::enable_if<
|
||||||
std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
|
std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
|
||||||
basic_value(T f, detail::region<Container> reg)
|
basic_value(T f, detail::region reg)
|
||||||
: type_(value_t::floating),
|
: type_(value_t::floating),
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
region_info_(std::make_shared<detail::region>(std::move(reg))),
|
||||||
comments_(region_info_->comments())
|
comments_(region_info_->comments())
|
||||||
{
|
{
|
||||||
assigner(this->floating_, static_cast<floating>(f));
|
assigner(this->floating_, static_cast<floating>(f));
|
||||||
}
|
}
|
||||||
template<typename Container>
|
basic_value(toml::string s, detail::region reg)
|
||||||
basic_value(toml::string s, detail::region<Container> reg)
|
|
||||||
: type_(value_t::string),
|
: type_(value_t::string),
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
region_info_(std::make_shared<detail::region>(std::move(reg))),
|
||||||
comments_(region_info_->comments())
|
comments_(region_info_->comments())
|
||||||
{
|
{
|
||||||
assigner(this->string_, std::move(s));
|
assigner(this->string_, std::move(s));
|
||||||
}
|
}
|
||||||
template<typename Container>
|
basic_value(const local_date& ld, detail::region reg)
|
||||||
basic_value(const local_date& ld, detail::region<Container> reg)
|
|
||||||
: type_(value_t::local_date),
|
: type_(value_t::local_date),
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
region_info_(std::make_shared<detail::region>(std::move(reg))),
|
||||||
comments_(region_info_->comments())
|
comments_(region_info_->comments())
|
||||||
{
|
{
|
||||||
assigner(this->local_date_, ld);
|
assigner(this->local_date_, ld);
|
||||||
}
|
}
|
||||||
template<typename Container>
|
basic_value(const local_time& lt, detail::region reg)
|
||||||
basic_value(const local_time& lt, detail::region<Container> reg)
|
|
||||||
: type_(value_t::local_time),
|
: type_(value_t::local_time),
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
region_info_(std::make_shared<detail::region>(std::move(reg))),
|
||||||
comments_(region_info_->comments())
|
comments_(region_info_->comments())
|
||||||
{
|
{
|
||||||
assigner(this->local_time_, lt);
|
assigner(this->local_time_, lt);
|
||||||
}
|
}
|
||||||
template<typename Container>
|
basic_value(const local_datetime& ldt, detail::region reg)
|
||||||
basic_value(const local_datetime& ldt, detail::region<Container> reg)
|
|
||||||
: type_(value_t::local_datetime),
|
: type_(value_t::local_datetime),
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
region_info_(std::make_shared<detail::region>(std::move(reg))),
|
||||||
comments_(region_info_->comments())
|
comments_(region_info_->comments())
|
||||||
{
|
{
|
||||||
assigner(this->local_datetime_, ldt);
|
assigner(this->local_datetime_, ldt);
|
||||||
}
|
}
|
||||||
template<typename Container>
|
basic_value(const offset_datetime& odt, detail::region reg)
|
||||||
basic_value(const offset_datetime& odt, detail::region<Container> reg)
|
|
||||||
: type_(value_t::offset_datetime),
|
: type_(value_t::offset_datetime),
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
region_info_(std::make_shared<detail::region>(std::move(reg))),
|
||||||
comments_(region_info_->comments())
|
comments_(region_info_->comments())
|
||||||
{
|
{
|
||||||
assigner(this->offset_datetime_, odt);
|
assigner(this->offset_datetime_, odt);
|
||||||
}
|
}
|
||||||
template<typename Container>
|
basic_value(const array_type& ary, detail::region reg)
|
||||||
basic_value(const array_type& ary, detail::region<Container> reg)
|
|
||||||
: type_(value_t::array),
|
: type_(value_t::array),
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
region_info_(std::make_shared<detail::region>(std::move(reg))),
|
||||||
comments_(region_info_->comments())
|
comments_(region_info_->comments())
|
||||||
{
|
{
|
||||||
assigner(this->array_, ary);
|
assigner(this->array_, ary);
|
||||||
}
|
}
|
||||||
template<typename Container>
|
basic_value(const table_type& tab, detail::region reg)
|
||||||
basic_value(const table_type& tab, detail::region<Container> reg)
|
|
||||||
: type_(value_t::table),
|
: type_(value_t::table),
|
||||||
region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
|
region_info_(std::make_shared<detail::region>(std::move(reg))),
|
||||||
comments_(region_info_->comments())
|
comments_(region_info_->comments())
|
||||||
{
|
{
|
||||||
assigner(this->table_, tab);
|
assigner(this->table_, tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename Container, typename std::enable_if<
|
template<typename T, typename std::enable_if<
|
||||||
detail::is_exact_toml_type<T, value_type>::value,
|
detail::is_exact_toml_type<T, value_type>::value,
|
||||||
std::nullptr_t>::type = nullptr>
|
std::nullptr_t>::type = nullptr>
|
||||||
basic_value(std::pair<T, detail::region<Container>> parse_result)
|
basic_value(std::pair<T, detail::region> parse_result)
|
||||||
: basic_value(std::move(parse_result.first), std::move(parse_result.second))
|
: basic_value(std::move(parse_result.first), std::move(parse_result.second))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -1578,9 +1561,9 @@ class basic_value
|
|||||||
{
|
{
|
||||||
throw std::out_of_range(detail::format_underline(
|
throw std::out_of_range(detail::format_underline(
|
||||||
"toml::value::at(idx): no element corresponding to the index", {
|
"toml::value::at(idx): no element corresponding to the index", {
|
||||||
{this->region_info_.get(),
|
{this->location(), concat_to_string("the length is ",
|
||||||
concat_to_string("the length is ", this->as_array(std::nothrow).size(),
|
this->as_array(std::nothrow).size(),
|
||||||
", and the specified index is ", idx)}
|
", and the specified index is ", idx)}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
return this->as_array().at(idx);
|
return this->as_array().at(idx);
|
||||||
@@ -1596,9 +1579,9 @@ class basic_value
|
|||||||
{
|
{
|
||||||
throw std::out_of_range(detail::format_underline(
|
throw std::out_of_range(detail::format_underline(
|
||||||
"toml::value::at(idx): no element corresponding to the index", {
|
"toml::value::at(idx): no element corresponding to the index", {
|
||||||
{this->region_info_.get(),
|
{this->location(), concat_to_string("the length is ",
|
||||||
concat_to_string("the length is ", this->as_array(std::nothrow).size(),
|
this->as_array(std::nothrow).size(),
|
||||||
", and the specified index is ", idx)}
|
", and the specified index is ", idx)}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
return this->as_array(std::nothrow).at(idx);
|
return this->as_array(std::nothrow).at(idx);
|
||||||
@@ -1668,7 +1651,7 @@ class basic_value
|
|||||||
{
|
{
|
||||||
throw type_error(detail::format_underline(
|
throw type_error(detail::format_underline(
|
||||||
"toml::value::size(): bad_cast to container types", {
|
"toml::value::size(): bad_cast to container types", {
|
||||||
{this->region_info_.get(),
|
{this->location(),
|
||||||
concat_to_string("the actual type is ", this->type_)}
|
concat_to_string("the actual type is ", this->type_)}
|
||||||
}), this->location());
|
}), this->location());
|
||||||
}
|
}
|
||||||
@@ -1718,10 +1701,10 @@ class basic_value
|
|||||||
|
|
||||||
// for error messages
|
// for error messages
|
||||||
template<typename Value>
|
template<typename Value>
|
||||||
friend region_base const& detail::get_region(const Value& v);
|
friend region_base const* detail::get_region(const Value& v);
|
||||||
|
|
||||||
template<typename Value, typename Region>
|
template<typename Value>
|
||||||
friend void detail::change_region(Value& v, Region&& reg);
|
friend void detail::change_region(Value& v, detail::region reg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -1926,10 +1909,8 @@ inline std::string format_error(const std::string& err_msg,
|
|||||||
std::vector<std::string> hints = {},
|
std::vector<std::string> hints = {},
|
||||||
const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED)
|
const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED)
|
||||||
{
|
{
|
||||||
return detail::format_underline(err_msg,
|
return detail::format_underline(err_msg, {{v.location(), comment}},
|
||||||
std::vector<std::pair<detail::region_base const*, std::string>>{
|
std::move(hints), colorize);
|
||||||
{std::addressof(detail::get_region(v)), comment}
|
|
||||||
}, std::move(hints), colorize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename C, template<typename ...> class T, template<typename ...> class A>
|
template<typename C, template<typename ...> class T, template<typename ...> class A>
|
||||||
@@ -1939,10 +1920,8 @@ inline std::string format_error(const std::string& err_msg,
|
|||||||
std::vector<std::string> hints = {},
|
std::vector<std::string> hints = {},
|
||||||
const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED)
|
const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED)
|
||||||
{
|
{
|
||||||
return detail::format_underline(err_msg,
|
return detail::format_underline(err_msg, {
|
||||||
std::vector<std::pair<detail::region_base const*, std::string>>{
|
{v1.location(), comment1}, {v2.location(), comment2}
|
||||||
{std::addressof(detail::get_region(v1)), comment1},
|
|
||||||
{std::addressof(detail::get_region(v2)), comment2}
|
|
||||||
}, std::move(hints), colorize);
|
}, std::move(hints), colorize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1954,11 +1933,8 @@ inline std::string format_error(const std::string& err_msg,
|
|||||||
std::vector<std::string> hints = {},
|
std::vector<std::string> hints = {},
|
||||||
const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED)
|
const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED)
|
||||||
{
|
{
|
||||||
return detail::format_underline(err_msg,
|
return detail::format_underline(err_msg, {{v1.location(), comment1},
|
||||||
std::vector<std::pair<detail::region_base const*, std::string>>{
|
{v2.location(), comment2}, {v3.location(), comment3}
|
||||||
{std::addressof(detail::get_region(v1)), comment1},
|
|
||||||
{std::addressof(detail::get_region(v2)), comment2},
|
|
||||||
{std::addressof(detail::get_region(v3)), comment3}
|
|
||||||
}, std::move(hints), colorize);
|
}, std::move(hints), colorize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user