diff --git a/README.md b/README.md index eee76a9..b5aad61 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Use the following commands with autom: ## Configuration -The configuration file is located at your home directory: `~/.autom/.automconfig.toml`. +The configuration file is located at your home directory: `~/.autom/.automconfig.json`. ## Contributing diff --git a/lib/toml/.circleci/config.yml b/lib/toml/.circleci/config.yml deleted file mode 100644 index d338652..0000000 --- a/lib/toml/.circleci/config.yml +++ /dev/null @@ -1,88 +0,0 @@ -version: 2.1 - -jobs: - test_suite: - docker: - - image: cimg/go:1.16 - steps: - - checkout - - run: - command: | - g++ --version - cd tests/ - g++ -std=c++11 -O2 -Wall -Wextra -Werror -I../ check_toml_test.cpp -o check_toml_test - export PATH=$(pwd):${PATH} - git clone https://github.com/BurntSushi/toml-test.git - cd toml-test/ - go install -v ./cmd/toml-test - cd - - toml-test check_toml_test -# go clean -modcache -# go get github.com/BurntSushi/toml-test/cmd/toml-test -# $GOPATH/bin/toml-test ./check_toml_test - test_serialization: - docker: - - image: circleci/buildpack-deps:bionic - steps: - - checkout - - run: - command: | - g++ --version - cd tests/ - g++ -std=c++11 -O2 -Wall -Wextra -Wpedantic -Werror -I../ check_serialization.cpp -o check_serialization - git clone https://github.com/BurntSushi/toml-test.git - cp check_serialization toml-test/tests/valid - cd toml-test/tests/valid - for f in $(ls ./*.toml); - do echo "==> ${f}"; - cat ${f}; - echo "---------------------------------------"; - ./check_serialization ${f}; - if [ $? -ne 0 ] ; then - exit 1 - fi - echo "======================================="; - done - output_result: - docker: - - image: circleci/buildpack-deps:bionic - steps: - - checkout - - run: - command: | - g++ --version - cd tests/ - g++ -std=c++11 -O2 -Wall -Wextra -Wpedantic -Werror -I../ check.cpp -o check - git clone https://github.com/BurntSushi/toml-test.git - cp check toml-test/tests/invalid - cp check toml-test/tests/valid - cd toml-test/tests/invalid - for f in $(ls ./*.toml); - do echo "==> ${f}"; - cat ${f}; - echo "---------------------------------------"; - ./check ${f} invalid; - if [ $? -ne 0 ] ; then - exit 1 - fi - echo "======================================="; - done - cd ../valid - for f in $(ls ./*.toml); - do echo "==> ${f}"; - cat ${f}; - echo "---------------------------------------"; - ./check ${f} valid; - if [ $? -ne 0 ] ; then - exit 1 - fi - echo "======================================="; - done - -workflows: - version: 2.1 - test: - jobs: - - test_suite - - test_serialization - - output_result diff --git a/lib/toml/.github/workflows/main.yml b/lib/toml/.github/workflows/main.yml deleted file mode 100644 index 2a20744..0000000 --- a/lib/toml/.github/workflows/main.yml +++ /dev/null @@ -1,149 +0,0 @@ -name: build - -on: [push, pull_request] - -jobs: - build-linux-gcc: - runs-on: Ubuntu-18.04 - strategy: - matrix: - # g++-4.8 and 4.9 are tested on Travis.CI. - compiler: ['g++-11', 'g++-10', 'g++-9', 'g++-8', 'g++-7', 'g++-6', 'g++-5'] - standard: ['11', '14', '17', '20'] - exclude: - - {compiler: 'g++-5', standard: '17'} - - {compiler: 'g++-6', standard: '17'} - - {compiler: 'g++-5', standard: '20'} - - {compiler: 'g++-6', standard: '20'} - - {compiler: 'g++-7', standard: '20'} - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - submodules: true - - name: Install - run: | - sudo apt-add-repository ppa:mhier/libboost-latest - sudo apt-get update - sudo apt-get install boost1.70 - sudo apt-add-repository ppa:ubuntu-toolchain-r/test - sudo apt-get update - sudo apt-get install ${{ matrix.compiler }} - - name: Configure - run: | - mkdir build && cd build - 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 - run: | - cd build && cmake --build . - - name: Test - run: | - cd build && ctest --output-on-failure - build-linux-clang: - runs-on: Ubuntu-18.04 - strategy: - matrix: - compiler: ['10', '9', '8', '7', '6.0', '5.0', '4.0', '3.9'] - standard: ['11', '14', '17', '20'] - exclude: - - {compiler: '3.9', standard: '17'} - - {compiler: '4.0', standard: '17'} - - {compiler: '5.0', standard: '17'} - - {compiler: '3.9', standard: '20'} - - {compiler: '4.0', standard: '20'} - - {compiler: '5.0', standard: '20'} - - {compiler: '6.0', standard: '20'} - - {compiler: '7', standard: '20'} - - {compiler: '8', standard: '20'} - - {compiler: '9', standard: '20'} - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - submodules: true - - name: Install - run: | - sudo apt-add-repository ppa:mhier/libboost-latest - sudo apt-get update - sudo apt-get install boost1.70 - sudo apt-add-repository ppa:ubuntu-toolchain-r/test - sudo apt-get update - sudo apt-get install clang-${{ matrix.compiler }} - - name: Configure - run: | - mkdir build && cd build - cmake .. -Dtoml11_BUILD_TEST=ON -DCMAKE_C_COMPILER=clang-${{ matrix.compiler }} -DCMAKE_CXX_COMPILER=clang++-${{ matrix.compiler }} -DCMAKE_CXX_STANDARD=${{ matrix.standard }} - - name: Build - run: | - cd build && cmake --build . - - name: Test - run: | - cd build && ctest --output-on-failure - - build-osx: - runs-on: macos-10.15 - strategy: - matrix: - standard: ['11', '14', '17', '20'] - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - submodules: true - - name: Install - run: | - brew install boost - - name: Configure - run: | - mkdir build && cd build - cmake .. -Dtoml11_BUILD_TEST=ON -DCMAKE_CXX_STANDARD=${{ matrix.standard }} - - name: Build - run: | - cd build && cmake --build . - - name: Test - run: | - cd build && ctest --output-on-failure - - build-windows-msvc: - runs-on: windows-2019 - strategy: - matrix: - standard: ['11', '14', '17', '20'] - config: ['Release', 'Debug'] - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - submodules: true - - name: Install - run: | - (New-Object System.Net.WebClient).DownloadFile("https://github.com/actions/boost-versions/releases/download/1.72.0-20200608.4/boost-1.72.0-win32-msvc14.2-x86_64.tar.gz", "$env:TEMP\\boost.tar.gz") - 7z.exe x "$env:TEMP\\boost.tar.gz" -o"$env:TEMP\\boostArchive" -y | Out-Null - 7z.exe x "$env:TEMP\\boostArchive" -o"$env:TEMP\\boost" -y | Out-Null - Push-Location -Path "$env:TEMP\\boost" - Invoke-Expression .\\setup.ps1 - - uses: ilammy/msvc-dev-cmd@v1 - - name: Configure - shell: cmd - run: | - file --mime-encoding tests/test_literals.cpp - mkdir build - cd build - cmake ../ -G "NMake Makefiles" -Dtoml11_BUILD_TEST=ON -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DBoost_NO_BOOST_CMAKE=ON -DBOOST_ROOT="C:\\hostedtoolcache\\windows\\Boost\\1.72.0\\x86_64" - - name: Build - working-directory: ./build - run: | - cmake --build . --config "${{ matrix.config }}" - - name: Test - working-directory: ./build - run: | - ./tests/test_literals --log_level=all - file --mime-encoding tests/toml/tests/example.toml - file --mime-encoding tests/toml/tests/fruit.toml - file --mime-encoding tests/toml/tests/hard_example.toml - file --mime-encoding tests/toml/tests/hard_example_unicode.toml - ctest --build-config "${{ matrix.config }}" --output-on-failure diff --git a/lib/toml/.gitignore b/lib/toml/.gitignore deleted file mode 100644 index a007fea..0000000 --- a/lib/toml/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build/* diff --git a/lib/toml/.travis.yml b/lib/toml/.travis.yml deleted file mode 100644 index ce291a8..0000000 --- a/lib/toml/.travis.yml +++ /dev/null @@ -1,337 +0,0 @@ -dist: trusty - -matrix: - include: - - os: linux - language: cpp - compiler: gcc - env: COMPILER="g++-4.8" CXX_STANDARD=11 - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - packages: - - g++-4.8 - - boost1.70 - - os: linux - language: cpp - compiler: gcc - env: COMPILER="g++-4.9" CXX_STANDARD=11 - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - packages: - - g++-4.9 - - boost1.70 - - os: linux - language: cpp - compiler: gcc - env: COMPILER="g++-5" CXX_STANDARD=11 - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - packages: - - g++-5 - - boost1.70 - - os: linux - language: cpp - compiler: gcc - env: COMPILER="g++-6" CXX_STANDARD=11 - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - packages: - - g++-6 - - boost1.70 - - os: linux - language: cpp - compiler: gcc - env: COMPILER="g++-7" CXX_STANDARD=11 - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - packages: - - g++-7 - - boost1.70 - - os: linux - language: cpp - compiler: gcc - env: COMPILER="g++-8" CXX_STANDARD=11 - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - packages: - - g++-8 - - boost1.70 - - os: linux - language: cpp - compiler: gcc - env: COMPILER="g++-8" CXX_STANDARD=11 TOML_HEAD=ON - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - packages: - - g++-8 - - boost1.70 - - os: linux - language: cpp - compiler: gcc - env: COMPILER="g++-8" CXX_STANDARD=14 - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - packages: - - g++-8 - - boost1.70 - - os: linux - language: cpp - compiler: gcc - env: COMPILER="g++-8" CXX_STANDARD=17 REQUIRE_FILESYSTEM_LIBRARY=ON - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - packages: - - g++-8 - - boost1.70 - - os: linux - language: cpp - compiler: gcc - env: COMPILER="g++-8" CXX_STANDARD=17 TOML_HEAD=ON REQUIRE_FILESYSTEM_LIBRARY=ON - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - packages: - - g++-8 - - boost1.70 - - os: linux - language: cpp - compiler: clang - env: COMPILER="clang++-3.9" CXX_STANDARD=11 - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - - llvm-toolchain-trusty-3.9 - packages: - - g++-8 - - clang-3.9 - - boost1.70 - - os: linux - language: cpp - compiler: clang - env: COMPILER="clang++-4.0" CXX_STANDARD=11 - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - - llvm-toolchain-trusty-4.0 - packages: - - g++-8 - - clang-4.0 - - boost1.70 - - os: linux - language: cpp - compiler: clang - env: COMPILER="clang++-5.0" CXX_STANDARD=11 - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - - llvm-toolchain-trusty-5.0 - packages: - - g++-8 - - clang-5.0 - - boost1.70 - - os: linux - language: cpp - compiler: clang - env: COMPILER="clang++-6.0" CXX_STANDARD=11 - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - - llvm-toolchain-trusty-6.0 - packages: - - g++-8 - - clang-6.0 - - boost1.70 - - os: linux - language: cpp - compiler: clang - env: COMPILER="clang++-7" CXX_STANDARD=11 - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - - llvm-toolchain-trusty-7 - packages: - - g++-8 - - clang-7 - - boost1.70 - - os: linux - language: cpp - compiler: clang - env: COMPILER="clang++-8" CXX_STANDARD=11 - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - - llvm-toolchain-trusty-8 - packages: - - g++-8 - - clang-8 - - boost1.70 - - os: linux - language: cpp - compiler: clang - env: COMPILER="clang++-8" CXX_STANDARD=11 TOML_HEAD=ON - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - - llvm-toolchain-trusty-8 - packages: - - g++-8 - - clang-8 - - boost1.70 - - os: linux - language: cpp - compiler: clang - env: COMPILER="clang++-8" CXX_STANDARD=14 - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - - llvm-toolchain-trusty-8 - packages: - - clang-8 - - g++-8 - - boost1.70 - - os: linux - language: cpp - compiler: clang - env: COMPILER="clang++-8" CXX_STANDARD=17 REQUIRE_FILESYSTEM_LIBRARY=ON - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - - llvm-toolchain-trusty-8 - packages: - - clang-8 - - g++-8 - - boost1.70 - - os: linux - language: cpp - compiler: clang - env: COMPILER="clang++-8" CXX_STANDARD=17 TOML_HEAD=ON REQUIRE_FILESYSTEM_LIBRARY=ON - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - - llvm-toolchain-trusty-8 - packages: - - clang-8 - - g++-8 - - boost1.70 - - os: linux - language: cpp - compiler: clang - env: COMPILER="clang++-8" CXX_STANDARD=11 WITH_ASAN=ON - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - - llvm-toolchain-trusty-8 - packages: - - clang-8 - - g++-8 - - boost1.70 - - os: linux - language: cpp - compiler: clang - env: COMPILER="clang++-8" CXX_STANDARD=11 WITH_UBSAN=ON - addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:mhier/libboost-latest' - - llvm-toolchain-trusty-8 - packages: - - clang-8 - - g++-8 - - boost1.70 - - os: osx - language: cpp - compiler: clang - -script: -- | - if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then - mkdir -p cmake - travis_retry wget "https://github.com/Kitware/CMake/releases/download/v3.14.5/cmake-3.14.5-Linux-x86_64.tar.gz" - tar xf cmake-3.14.5-Linux-x86_64.tar.gz -C cmake --strip-components=1 - export PATH=${TRAVIS_BUILD_DIR}/cmake/bin:${PATH} - fi -- | - if [[ "${CXX_STANDARD}" == "" ]]; then - export CXX_STANDARD="11" - fi -- | - if [[ "${TOML_HEAD}" != "ON" ]]; then - export TOML_HEAD="OFF" - fi -- echo "TOML_HEAD = ${TOML_HEAD}" -- | - if [[ "${WITH_ASAN}" != "ON" ]]; then - export WITH_ASAN="OFF" - fi -- echo "WITH_ASAN = ${WITH_ASAN}" -- | - if [[ "${WITH_UBSAN}" != "ON" ]]; then - export WITH_UBSAN="OFF" - fi -- 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 -- mkdir build -- cd build -- echo "COMPILER = ${COMPILER}" -- echo "CXX_STANDARD = ${CXX_STANDARD}" -- 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 -- ctest --output-on-failure diff --git a/lib/toml/CMakeLists.txt b/lib/toml/CMakeLists.txt deleted file mode 100644 index 911874c..0000000 --- a/lib/toml/CMakeLists.txt +++ /dev/null @@ -1,116 +0,0 @@ -cmake_minimum_required(VERSION 3.1) -enable_testing() - -project(toml11 VERSION 3.7.1) - -option(toml11_BUILD_TEST "Build toml tests" OFF) -option(toml11_INSTALL "Install CMake targets during install step." ON) -option(toml11_TEST_WITH_ASAN "use LLVM address sanitizer" OFF) -option(toml11_TEST_WITH_UBSAN "use LLVM undefined behavior sanitizer" OFF) - -include(CheckCXXCompilerFlag) -if("${CMAKE_VERSION}" VERSION_GREATER 3.1) - set(CMAKE_CXX_EXTENSIONS OFF CACHE BOOL "Boolean specifying whether compiler specific extensions are requested.") - if(NOT DEFINED CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 11 CACHE STRING "The C++ standard whose features are requested to build all targets.") - endif() - set(CMAKE_CXX_STANDARD_REQUIRED ON CACHE BOOL "Boolean describing whether the value of CXX_STANDARD is a requirement.") -else() - # Manually check for C++11 compiler flag. - CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) - CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) - CHECK_CXX_COMPILER_FLAG("-std=gnu++11" COMPILER_SUPPORTS_GNU11) - CHECK_CXX_COMPILER_FLAG("-std=gnu++0x" COMPILER_SUPPORTS_GNU0X) - if(COMPILER_SUPPORTS_CXX11) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - elseif(COMPILER_SUPPORTS_CXXOX) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") - elseif(COMPILER_SUPPORTS_GNU11) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11") - elseif(COMPILER_SUPPORTS_GNU0X) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x") - else() - if(MSVC) - if(MSVC_VERSION LESS 1900) - message(SEND_ERROR "MSVC < 14.0 is not supported. Please update your compiler or use mingw") - endif() - else() - message(SEND_ERROR "The ${CMAKE_CXX_COMPILER} compiler lacks C++11 support. Use another compiler.") - endif() - endif() -endif() - -if(MSVC) -# add_definitions("/Zc:__cplusplus") # define __cplusplus value correctly - add_definitions("/utf-8") # enable to use u8"" literal - if(MSVC_VERSION LESS 1910) - message(STATUS "MSVC < 1910. DEFINE_CONVERSION_NON_INTRUSIVE is disabled") - add_definitions(-DTOML11_WITHOUT_DEFINE_NON_INTRUSIVE) - elseif(MSVC_VERSION LESS 1920) - add_definitions("/experimental:preprocessor") # MSVC 2017 - else() - add_definitions("/Zc:preprocessor") # MSVC 2019 - endif() -endif() - -# Set some common directories -include(GNUInstallDirs) -set(toml11_install_cmake_dir ${CMAKE_INSTALL_LIBDIR}/cmake/toml11) -set(toml11_install_include_dir ${CMAKE_INSTALL_INCLUDEDIR}) -set(toml11_config_dir ${CMAKE_CURRENT_BINARY_DIR}/cmake/) -set(toml11_config ${toml11_config_dir}/toml11Config.cmake) -set(toml11_config_version ${toml11_config_dir}/toml11ConfigVersion.cmake) - -add_library(toml11 INTERFACE) -target_include_directories(toml11 INTERFACE - $ - $ -) -add_library(toml11::toml11 ALIAS toml11) - -# Write config and version config files -include(CMakePackageConfigHelpers) -write_basic_package_version_file( - ${toml11_config_version} - VERSION ${toml11_VERSION} - COMPATIBILITY SameMajorVersion -) - -if (toml11_INSTALL) - configure_package_config_file( - cmake/toml11Config.cmake.in - ${toml11_config} - INSTALL_DESTINATION ${toml11_install_cmake_dir} - PATH_VARS toml11_install_cmake_dir - ) - - # Install config files - install(FILES ${toml11_config} ${toml11_config_version} - DESTINATION ${toml11_install_cmake_dir} - ) - - # Install header files - install( - FILES toml.hpp - DESTINATION "${toml11_install_include_dir}" - ) - install( - DIRECTORY "toml" - DESTINATION "${toml11_install_include_dir}" - FILES_MATCHING PATTERN "*.hpp" - ) - - # Export targets and install them - install(TARGETS toml11 - EXPORT toml11Targets - ) - install(EXPORT toml11Targets - FILE toml11Targets.cmake - DESTINATION ${toml11_install_cmake_dir} - NAMESPACE toml11:: - ) -endif() - -if (toml11_BUILD_TEST) - add_subdirectory(tests) -endif () diff --git a/lib/toml/LICENSE b/lib/toml/LICENSE deleted file mode 100644 index f55c511..0000000 --- a/lib/toml/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2017 Toru Niina - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/lib/toml/README.md b/lib/toml/README.md deleted file mode 100644 index 6471b2e..0000000 --- a/lib/toml/README.md +++ /dev/null @@ -1,1967 +0,0 @@ -toml11 -====== - -[![Build Status on GitHub Actions](https://github.com/ToruNiina/toml11/workflows/build/badge.svg)](https://github.com/ToruNiina/toml11/actions) -[![Build Status on TravisCI](https://travis-ci.org/ToruNiina/toml11.svg?branch=master)](https://travis-ci.org/ToruNiina/toml11) -[![Build status on Appveyor](https://ci.appveyor.com/api/projects/status/m2n08a926asvg5mg/branch/master?svg=true)](https://ci.appveyor.com/project/ToruNiina/toml11/branch/master) -[![Build status on CircleCI](https://circleci.com/gh/ToruNiina/toml11/tree/master.svg?style=svg)](https://circleci.com/gh/ToruNiina/toml11/tree/master) -[![Version](https://img.shields.io/github/release/ToruNiina/toml11.svg?style=flat)](https://github.com/ToruNiina/toml11/releases) -[![License](https://img.shields.io/github/license/ToruNiina/toml11.svg?style=flat)](LICENSE) -[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.1209136.svg)](https://doi.org/10.5281/zenodo.1209136) - -toml11 is a C++11 (or later) header-only toml parser/encoder depending only on C++ standard library. - -- It is compatible to the latest version of [TOML v1.0.0](https://toml.io/en/v1.0.0). -- It is one of the most TOML standard compliant libraries, tested with [the language agnostic test suite for TOML parsers by BurntSushi](https://github.com/BurntSushi/toml-test). -- It shows highly informative error messages. You can see the error messages about invalid files at [CircleCI](https://circleci.com/gh/ToruNiina/toml11). -- It has configurable container. You can use any random-access containers and key-value maps as backend containers. -- It optionally preserves comments without any overhead. -- It has configurable serializer that supports comments, inline tables, literal strings and multiline strings. -- It supports user-defined type conversion from/into toml values. -- It correctly handles UTF-8 sequences, with or without BOM, both on posix and Windows. - -## Example - -```cpp -#include -#include - -int main() -{ - // ```toml - // title = "an example toml file" - // nums = [3, 1, 4, 1, 5] - // ``` - auto data = toml::parse("example.toml"); - - // find a value with the specified type from a table - std::string title = toml::find(data, "title"); - - // convert the whole array into any container automatically - std::vector nums = toml::find>(data, "nums"); - - // access with STL-like manner - if(!data.contains("foo")) - { - data["foo"] = "bar"; - } - - // pass a fallback - std::string name = toml::find_or(data, "name", "not found"); - - // width-dependent formatting - std::cout << std::setw(80) << data << std::endl; - - return 0; -} -``` - -## Table of Contents - -- [Integration](#integration) -- [Decoding a toml file](#decoding-a-toml-file) - - [In the case of syntax error](#in-the-case-of-syntax-error) - - [Invalid UTF-8 Codepoints](#invalid-utf-8-codepoints) -- [Finding a toml value](#finding-a-toml-value) - - [Finding a value in a table](#finding-a-value-in-a-table) - - [In case of error](#in-case-of-error) - - [Dotted keys](#dotted-keys) -- [Casting a toml value](#casting-a-toml-value) -- [Checking value type](#checking-value-type) -- [More about conversion](#more-about-conversion) - - [Converting an array](#converting-an-array) - - [Converting a table](#converting-a-table) - - [Getting an array of tables](#getting-an-array-of-tables) - - [Cost of conversion](#cost-of-conversion) - - [Converting datetime and its variants](#converting-datetime-and-its-variants) -- [Getting with a fallback](#getting-with-a-fallback) -- [Expecting conversion](#expecting-conversion) -- [Visiting a toml::value](#visiting-a-tomlvalue) -- [Constructing a toml::value](#constructing-a-tomlvalue) -- [Preserving Comments](#preserving-comments) -- [Customizing containers](#customizing-containers) -- [TOML literal](#toml-literal) -- [Conversion between toml value and arbitrary types](#conversion-between-toml-value-and-arbitrary-types) -- [Formatting user-defined error messages](#formatting-user-defined-error-messages) -- [Obtaining location information](#obtaining-location-information) -- [Exceptions](#exceptions) -- [Colorize Error Messages](#colorize-error-messages) -- [Serializing TOML data](#serializing-toml-data) -- [Underlying types](#underlying-types) -- [Unreleased TOML features](#unreleased-toml-features) -- [Breaking Changes from v2](#breaking-changes-from-v2) -- [Running Tests](#running-tests) -- [Contributors](#contributors) -- [Licensing Terms](#licensing-terms) - -## Integration - -Just include the file after adding it to the include path. - -```cpp -#include // that's all! now you can use it. -#include - -int main() -{ - const auto data = toml::parse("example.toml"); - const auto title = toml::find(data, "title"); - std::cout << "the title is " << title << std::endl; - return 0; -} -``` - -The convenient way is to add this repository as a git-submodule or to install -it in your system by CMake. - -Note for MSVC: We recommend to set `/Zc:__cplusplus` to detect C++ version correctly. - -## Decoding a toml file - -To parse a toml file, the only thing you have to do is -to pass a filename to the `toml::parse` function. - -```cpp -const std::string fname("sample.toml"); -const toml::value data = toml::parse(fname); -``` - -As required by the TOML specification, the top-level value is always a table. -You can find a value inside it, cast it into a table explicitly, and insert it as a value into other `toml::value`. - -If it encounters an error while opening a file, it will throw `std::runtime_error`. - -You can also pass a `std::istream` to the `toml::parse` function. -To show a filename in an error message, however, it is recommended to pass the -filename with the stream. - -```cpp -std::ifstream ifs("sample.toml", std::ios_base::binary); -assert(ifs.good()); -const auto data = toml::parse(ifs, /*optional -> */ "sample.toml"); -``` - -**Note**: When you are **on Windows, open a file in binary mode**. -If a file is opened in text-mode, CRLF ("\r\n") will automatically be -converted to LF ("\n") and this causes inconsistency between file size -and the contents that would be read. This causes weird error. - -### In the case of syntax error - -If there is a syntax error in a toml file, `toml::parse` will throw -`toml::syntax_error` that inherits `std::exception`. - -toml11 has clean and informative error messages inspired by Rust and -it looks like the following. - -```console -terminate called after throwing an instance of 'toml::syntax_error' - what(): [error] toml::parse_table: invalid line format # error description - --> example.toml # file name - 3 | a = 42 = true # line num and content - | ^------ expected newline, but got '='. # error reason -``` - -If you (mistakenly) duplicate tables and got an error, it is helpful to see -where they are. toml11 shows both at the same time like the following. - -```console -terminate called after throwing an instance of 'toml::syntax_error' - what(): [error] toml::insert_value: table ("table") already exists. - --> duplicate-table.toml - 1 | [table] - | ~~~~~~~ table already exists here - ... - 3 | [table] - | ~~~~~~~ table defined twice -``` - -When toml11 encounters a malformed value, it tries to detect what type it is. -Then it shows hints to fix the format. An error message while reading one of -the malformed files in [the language agnostic test suite](https://github.com/BurntSushi/toml-test). -is shown below. - -```console -what(): [error] bad time: should be HH:MM:SS.subsec - --> ./datetime-malformed-no-secs.toml - 1 | no-secs = 1987-07-05T17:45Z - | ^------- HH:MM:SS.subsec - | -Hint: pass: 1979-05-27T07:32:00, 1979-05-27 07:32:00.999999 -Hint: fail: 1979-05-27T7:32:00, 1979-05-27 17:32 -``` - -You can find other examples in a job named `output_result` on -[CircleCI](https://circleci.com/gh/ToruNiina/toml11). - -Since the error message generation is generally a difficult task, the current -status is not ideal. If you encounter a weird error message, please let us know -and contribute to improve the quality! - -### Invalid UTF-8 codepoints - -It throws `syntax_error` if a value of an escape sequence -representing unicode character is not a valid UTF-8 codepoint. - -```console - what(): [error] toml::read_utf8_codepoint: input codepoint is too large. - --> utf8.toml - 1 | exceeds_unicode = "\U0011FFFF example" - | ^--------- should be in [0x00..0x10FFFF] -``` - -## Finding a toml value - -After parsing successfully, you can obtain the values from the result of -`toml::parse` using `toml::find` function. - -```toml -# sample.toml -answer = 42 -pi = 3.14 -numbers = [1,2,3] -time = 1979-05-27T07:32:00Z -``` - -``` cpp -const auto data = toml::parse("sample.toml"); -const auto answer = toml::find(data, "answer"); -const auto pi = toml::find(data, "pi"); -const auto numbers = toml::find>(data, "numbers"); -const auto timepoint = toml::find(data, "time"); -``` - -By default, `toml::find` returns a `toml::value`. - -```cpp -const toml::value& answer = toml::find(data, "answer"); -``` - -When you pass an exact TOML type that does not require type conversion, -`toml::find` returns a reference without copying the value. - -```cpp -const auto data = toml::parse("sample.toml"); -const auto& answer = toml::find(data, "answer"); -``` - -If the specified type requires conversion, you can't take a reference to the value. -See also [underlying types](#underlying-types). - -**NOTE**: For some technical reason, automatic conversion between `integer` and -`floating` is not supported. If you want to get a floating value even if a value -has integer value, you need to convert it manually after obtaining a value, -like the following. - -```cpp -const auto vx = toml::find(data, "x"); -double x = vx.is_floating() ? vx.as_floating(std::nothrow) : - static_cast(vx.as_integer()); // it throws if vx is neither - // floating nor integer. -``` - -### Finding a value in a table - -There are several way to get a value defined in a table. -First, you can get a table as a normal value and find a value from the table. - -```toml -[fruit] -name = "apple" -[fruit.physical] -color = "red" -shape = "round" -``` - -``` cpp -const auto data = toml::parse("fruit.toml"); -const auto& fruit = toml::find(data, "fruit"); -const auto name = toml::find(fruit, "name"); - -const auto& physical = toml::find(fruit, "physical"); -const auto color = toml::find(physical, "color"); -const auto shape = toml::find(physical, "shape"); -``` - -Here, variable `fruit` is a `toml::value` and can be used as the first argument -of `toml::find`. - -Second, you can pass as many arguments as the number of subtables to `toml::find`. - -```cpp -const auto data = toml::parse("fruit.toml"); -const auto color = toml::find(data, "fruit", "physical", "color"); -const auto shape = toml::find(data, "fruit", "physical", "shape"); -``` - -### Finding a value in an array - -You can find n-th value in an array by `toml::find`. - -```toml -values = ["foo", "bar", "baz"] -``` - -``` cpp -const auto data = toml::parse("sample.toml"); -const auto values = toml::find(data, "values"); -const auto bar = toml::find(values, 1); -``` - -`toml::find` can also search array recursively. - -```cpp -const auto data = toml::parse("fruit.toml"); -const auto bar = toml::find(data, "values", 1); -``` - -Before calling `toml::find`, you can check if a value corresponding to a key -exists. You can use both `bool toml::value::contains(const key&) const` and -`std::size_t toml::value::count(const key&) const`. Those behaves like the -`std::map::contains` and `std::map::count`. - -```cpp -const auto data = toml::parse("fruit.toml"); -if(data.contains("fruit") && data.at("fruit").count("physical") != 0) -{ - // ... -} -``` - -### In case of error - -If the value does not exist, `toml::find` throws `std::out_of_range` with the -location of the table. - -```console -terminate called after throwing an instance of 'std::out_of_range' - what(): [error] key "answer" not found - --> example.toml - 6 | [tab] - | ~~~~~ in this table -``` - ----- - -If the specified type differs from the actual value contained, it throws -`toml::type_error` that inherits `std::exception`. - -Similar to the case of syntax error, toml11 also displays clean error messages. -The error message when you choose `int` to get `string` value would be like this. - -```console -terminate called after throwing an instance of 'toml::type_error' - what(): [error] toml::value bad_cast to integer - --> example.toml - 3 | title = "TOML Example" - | ~~~~~~~~~~~~~~ the actual type is string -``` - -**NOTE**: In order to show this kind of error message, all the toml values have -a pointer to represent its range in a file. The entire contents of a file is -shared by `toml::value`s and remains on the heap memory. It is recommended to -destruct all the `toml::value` classes after configuring your application -if you have a large TOML file compared to the memory resource. - -### Dotted keys - -TOML v0.5.0 has a new feature named "dotted keys". -You can chain keys to represent the structure of the data. - -```toml -physical.color = "orange" -physical.shape = "round" -``` - -This is equivalent to the following. - -```toml -[physical] -color = "orange" -shape = "round" -``` - -You can get both of the above tables with the same c++ code. - -```cpp -const auto physical = toml::find(data, "physical"); -const auto color = toml::find(physical, "color"); -``` - -The following code does not work for the above toml file. - -```cpp -// XXX this does not work! -const auto color = toml::find(data, "physical.color"); -``` - -The above code works with the following toml file. - -```toml -"physical.color" = "orange" -# equivalent to {"physical.color": "orange"}, -# NOT {"physical": {"color": "orange"}}. -``` - - -## Casting a toml value - -### `toml::get` - -`toml::parse` returns `toml::value`. `toml::value` is a union type that can -contain one of the following types. - -- `toml::boolean` (`bool`) -- `toml::integer` (`std::int64_t`) -- `toml::floating` (`double`) -- `toml::string` (a type convertible to std::string) -- `toml::local_date` -- `toml::local_time` -- `toml::local_datetime` -- `toml::offset_datetime` -- `toml::array` (by default, `std::vector`) - - It depends. See [customizing containers](#customizing-containers) for detail. -- `toml::table` (by default, `std::unordered_map`) - - It depends. See [customizing containers](#customizing-containers) for detail. - -To get a value inside, you can use `toml::get()`. The usage is the same as -`toml::find` (actually, `toml::find` internally uses `toml::get` after casting -a value to `toml::table`). - -``` cpp -const toml::value data = toml::parse("sample.toml"); -const toml::value answer_ = toml::get(data).at("answer"); -const std::int64_t answer = toml::get(answer_); -``` - -When you pass an exact TOML type that does not require type conversion, -`toml::get` returns a reference through which you can modify the content -(if the `toml::value` is `const`, it returns `const` reference). - -```cpp -toml::value data = toml::parse("sample.toml"); -toml::value answer_ = toml::get(data).at("answer"); -toml::integer& answer = toml::get(answer_); -answer = 6 * 9; // write to data.answer. now `answer_` contains 54. -``` - -If the specified type requires conversion, you can't take a reference to the value. -See also [underlying types](#underlying-types). - -It also throws a `toml::type_error` if the type differs. - -### `as_xxx` - -You can also use a member function to cast a value. - -```cpp -const std::int64_t answer = data.as_table().at("answer").as_integer(); -``` - -It also throws a `toml::type_error` if the type differs. If you are sure that -the value `v` contains a value of the specified type, you can suppress checking -by passing `std::nothrow`. - -```cpp -const auto& answer = data.as_table().at("answer"); -if(answer.is_integer() && answer.as_integer(std::nothrow) == 42) -{ - std::cout << "value is 42" << std::endl; -} -``` - -If `std::nothrow` is passed, the functions are marked as noexcept. - -By casting a `toml::value` into an array or a table, you can iterate over the -elements. - -```cpp -const auto data = toml::parse("example.toml"); -std::cout << "keys in the top-level table are the following: \n"; -for(const auto& [k, v] : data.as_table()) -{ - std::cout << k << '\n'; -} - -const auto& fruits = toml::find(data, "fruits"); -for(const auto& v : fruits.as_array()) -{ - std::cout << toml::find(v, "name") << '\n'; -} -``` - -The full list of the functions is below. - -```cpp -namespace toml { -class value { - // ... - const boolean& as_boolean() const&; - const integer& as_integer() const&; - const floating& as_floating() const&; - const string& as_string() const&; - const offset_datetime& as_offset_datetime() const&; - const local_datetime& as_local_datetime() const&; - const local_date& as_local_date() const&; - const local_time& as_local_time() const&; - const array& as_array() const&; - const table& as_table() const&; - // -------------------------------------------------------- - // non-const version - boolean& as_boolean() &; - // ditto... - // -------------------------------------------------------- - // rvalue version - boolean&& as_boolean() &&; - // ditto... - - // -------------------------------------------------------- - // noexcept versions ... - const boolean& as_boolean(const std::nothrow_t&) const& noexcept; - boolean& as_boolean(const std::nothrow_t&) & noexcept; - boolean&& as_boolean(const std::nothrow_t&) && noexcept; - // ditto... -}; -} // toml -``` - -### `at()` - -You can access to the element of a table and an array by `toml::basic_value::at`. - -```cpp -const toml::value v{1,2,3,4,5}; -std::cout << v.at(2).as_integer() << std::endl; // 3 - -const toml::value v{{"foo", 42}, {"bar", 3.14}}; -std::cout << v.at("foo").as_integer() << std::endl; // 42 -``` - -If an invalid key (integer for a table, string for an array), it throws -`toml::type_error` for the conversion. If the provided key is out-of-range, -it throws `std::out_of_range`. - -Note that, although `std::string` has `at()` member function, `toml::value::at` -throws if the contained type is a string. Because `std::string` does not -contain `toml::value`. - -### `operator[]` - -You can also access to the element of a table and an array by -`toml::basic_value::operator[]`. - -```cpp -const toml::value v{1,2,3,4,5}; -std::cout << v[2].as_integer() << std::endl; // 3 - -const toml::value v{{"foo", 42}, {"bar", 3.14}}; -std::cout << v["foo"].as_integer() << std::endl; // 42 -``` - -When you access to a `toml::value` that is not initialized yet via -`operator[](const std::string&)`, the `toml::value` will be a table, -just like the `std::map`. - -```cpp -toml::value v; // not initialized as a table. -v["foo"] = 42; // OK. `v` will be a table. -``` - -Contrary, if you access to a `toml::value` that contains an array via `operator[]`, -it does not check anything. It converts `toml::value` without type check and then -access to the n-th element without boundary check, just like the `std::vector::operator[]`. - -```cpp -toml::value v; // not initialized as an array -v[2] = 42; // error! UB -``` - -Please make sure that the `toml::value` has an array inside when you access to -its element via `operator[]`. - -## Checking value type - -You can check the type of a value by `is_xxx` function. - -```cpp -const toml::value v = /* ... */; -if(v.is_integer()) -{ - std::cout << "value is an integer" << std::endl; -} -``` - -The complete list of the functions is below. - -```cpp -namespace toml { -class value { - // ... - bool is_boolean() const noexcept; - bool is_integer() const noexcept; - bool is_floating() const noexcept; - bool is_string() const noexcept; - bool is_offset_datetime() const noexcept; - bool is_local_datetime() const noexcept; - bool is_local_date() const noexcept; - bool is_local_time() const noexcept; - bool is_array() const noexcept; - bool is_table() const noexcept; - bool is_uninitialized() const noexcept; - // ... -}; -} // toml -``` - -Also, you can get `enum class value_t` from `toml::value::type()`. - -```cpp -switch(data.at("something").type()) -{ - case toml::value_t::integer: /*do some stuff*/ ; break; - case toml::value_t::floating: /*do some stuff*/ ; break; - case toml::value_t::string : /*do some stuff*/ ; break; - default : throw std::runtime_error( - "unexpected type : " + toml::stringize(data.at("something").type())); -} -``` - -The complete list of the `enum`s can be found in the section -[underlying types](#underlying-types). - -The `enum`s can be used as a parameter of `toml::value::is` function like the following. - -```cpp -toml::value v = /* ... */; -if(v.is(toml::value_t::boolean)) // ... -``` - -## More about conversion - -Since `toml::find` internally uses `toml::get`, all the following examples work -with both `toml::get` and `toml::find`. - -### Converting an array - -You can get any kind of `container` class from a `toml::array` -except for `map`-like classes. - -``` cpp -// # sample.toml -// numbers = [1,2,3] - -const auto numbers = toml::find(data, "numbers"); - -const auto vc = toml::get >(numbers); -const auto ls = toml::get >(numbers); -const auto dq = toml::get >(numbers); -const auto ar = toml::get>(numbers); -// if the size of data.at("numbers") is larger than that of std::array, -// it will throw toml::type_error because std::array is not resizable. -``` - -Surprisingly, you can convert `toml::array` into `std::pair` and `std::tuple`. - -```cpp -// numbers = [1,2,3] -const auto tp = toml::get>(numbers); -``` - -This functionality is helpful when you have a toml file like the following. - -```toml -array_of_arrays = [[1, 2, 3], ["foo", "bar", "baz"]] # toml allows this -``` - -What is the corresponding C++ type? -Obviously, it is a `std::pair` of `std::vector`s. - -```cpp -const auto array_of_arrays = toml::find(data, "array_of_arrays"); -const auto aofa = toml::get< - std::pair, std::vector> - >(array_of_arrays); -``` - -If you don't know the type of the elements, you can use `toml::array`, -which is a `std::vector` of `toml::value`, instead. - -```cpp -const auto a_of_a = toml::get(array_of_arrays); -const auto first = toml::get>(a_of_a.at(0)); -``` - -You can change the implementation of `toml::array` with `std::deque` or some -other array-like container. See [Customizing containers](#customizing-containers) -for detail. - -### Converting a table - -When all the values of the table have the same type, toml11 allows you to -convert a `toml::table` to a `map` that contains the convertible type. - -```toml -[tab] -key1 = "foo" # all the values are -key2 = "bar" # toml String -``` - -```cpp -const auto data = toml::parse("sample.toml"); -const auto tab = toml::find>(data, "tab"); -std::cout << tab["key1"] << std::endl; // foo -std::cout << tab["key2"] << std::endl; // bar -``` - -But since `toml::table` is just an alias of `std::unordered_map`, -normally you don't need to convert it because it has all the functionalities that -`std::unordered_map` has (e.g. `operator[]`, `count`, and `find`). In most cases -`toml::table` is sufficient. - -```cpp -toml::table tab = toml::get(data); -if(data.count("title") != 0) -{ - data["title"] = std::string("TOML example"); -} -``` - -You can change the implementation of `toml::table` with `std::map` or some -other map-like container. See [Customizing containers](#customizing-containers) -for detail. - -### Getting an array of tables - -An array of tables is just an array of tables. -You can get it in completely the same way as the other arrays and tables. - -```toml -# sample.toml -array_of_inline_tables = [{key = "value1"}, {key = "value2"}, {key = "value3"}] - -[[array_of_tables]] -key = "value4" -[[array_of_tables]] -key = "value5" -[[array_of_tables]] -key = "value6" -``` - -```cpp -const auto data = toml::parse("sample.toml"); -const auto aot1 = toml::find>(data, "array_of_inline_tables"); -const auto aot2 = toml::find>(data, "array_of_tables"); -``` - -### Cost of conversion - -Although conversion through `toml::(get|find)` is convenient, it has additional -copy-cost because it copies data contained in `toml::value` to the -user-specified type. Of course in some cases this overhead is not ignorable. - -```cpp -// the following code constructs a std::vector. -// it requires heap allocation for vector and element conversion. -const auto array = toml::find>(data, "foo"); -``` - -By passing the exact types, `toml::get` returns reference that has no overhead. - -``` cpp -const auto& tab = toml::find(data, "tab"); -const auto& numbers = toml::find(data, "numbers"); -``` - -Also, `as_xxx` are zero-overhead because they always return a reference. - -``` cpp -const auto& tab = toml::find(data, "tab" ).as_table(); -const auto& numbers = toml::find(data, "numbers").as_array(); -``` - -In this case you need to call `toml::get` each time you access to -the element of `toml::array` because `toml::array` is an array of `toml::value`. - -```cpp -const auto& num0 = toml::get(numbers.at(0)); -const auto& num1 = toml::get(numbers.at(1)); -const auto& num2 = toml::get(numbers.at(2)); -``` - -### Converting datetime and its variants - -TOML v0.5.0 has 4 different datetime objects, `local_date`, `local_time`, -`local_datetime`, and `offset_datetime`. - -Since `local_date`, `local_datetime`, and `offset_datetime` represent a time -point, you can convert them to `std::chrono::system_clock::time_point`. - -Contrary, `local_time` does not represents a time point because they lack a -date information, but it can be converted to `std::chrono::duration` that -represents a duration from the beginning of the day, `00:00:00.000`. - -```toml -# sample.toml -date = 2018-12-23 -time = 12:30:00 -l_dt = 2018-12-23T12:30:00 -o_dt = 2018-12-23T12:30:00+09:30 -``` - -```cpp -const auto data = toml::parse("sample.toml"); - -const auto date = toml::get(data.at("date")); -const auto l_dt = toml::get(data.at("l_dt")); -const auto o_dt = toml::get(data.at("o_dt")); - -const auto time = toml::get(data.at("time")); // 12 * 60 + 30 min -``` - -`local_date` and `local_datetime` are assumed to be in the local timezone when -they are converted into `time_point`. On the other hand, `offset_datetime` only -uses the offset part of the data and it does not take local timezone into account. - -To contain datetime data, toml11 defines its own datetime types. -For more detail, you can see the definitions in [toml/datetime.hpp](toml/datetime.hpp). - -## Getting with a fallback - -`toml::find_or` returns a default value if the value is not found or has a -different type. - -```cpp -const auto data = toml::parse("example.toml"); -const auto num = toml::find_or(data, "num", 42); -``` - -It works recursively if you pass several keys for subtables. -In that case, the last argument is considered to be the optional value. -All other arguments between `toml::value` and the optinoal value are considered as keys. - -```cpp -// [fruit.physical] -// color = "red" -auto data = toml::parse("fruit.toml"); -auto color = toml::find_or(data, "fruit", "physical", "color", "red"); -// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ -// arguments optional value -``` - -Also, `toml::get_or` returns a default value if `toml::get` failed. - -```cpp -toml::value v("foo"); // v contains String -const int value = toml::get_or(v, 42); // conversion fails. it returns 42. -``` - -These functions automatically deduce what type you want to get -from the default value you passed. - -To get a reference through this function, take care about the default value. - -```cpp -toml::value v("foo"); // v contains String -toml::integer& i = toml::get_or(v, 42); // does not work because binding `42` - // to `integer&` is invalid -toml::integer opt = 42; -toml::integer& i = toml::get_or(v, opt); // this works. -``` - -## Expecting conversion - -By using `toml::expect`, you will get your expected value or an error message -without throwing `toml::type_error`. - -```cpp -const auto value = toml::expect(data.at("title")); -if(value.is_ok()) { - std::cout << value.unwrap() << std::endl; -} else { - std::cout << value.unwrap_err() << std::endl; -} -``` - -Also, you can pass a function object to modify the expected value. - -```cpp -const auto value = toml::expect(data.at("number")) - .map(// function that receives expected type (here, int) - [](const int number) -> double { - return number * 1.5 + 1.0; - }).unwrap_or(/*default value =*/ 3.14); -``` - -## Visiting a toml::value - -toml11 provides `toml::visit` to apply a function to `toml::value` in the -same way as `std::variant`. - -```cpp -const toml::value v(3.14); -toml::visit([](const auto& val) -> void { - std::cout << val << std::endl; - }, v); -``` - -The function object that would be passed to `toml::visit` must be able to -receive all the possible TOML types. Also, the result types should be the same -each other. - -## Constructing a toml::value - -`toml::value` can be constructed in various ways. - -```cpp -toml::value v(true); // boolean -toml::value v(42); // integer -toml::value v(3.14); // floating -toml::value v("foobar"); // string -toml::value v(toml::local_date(2019, toml::month_t::Apr, 1)); // date -toml::value v{1, 2, 3, 4, 5}; // array -toml::value v{{"foo", 42}, {"bar", 3.14}, {"baz", "qux"}}; // table -``` - -When constructing a string, you can choose to use either literal or basic string. -By default, it will be a basic string. - -```cpp -toml::value v("foobar", toml::string_t::basic ); -toml::value v("foobar", toml::string_t::literal); -``` - -Datetime objects can be constructed from `std::tm` and -`std::chrono::system_clock::time_point`. But you need to specify what type -you use to avoid ambiguity. - -```cpp -const auto now = std::chrono::system_clock::now(); -toml::value v(toml::local_date(now)); -toml::value v(toml::local_datetime(now)); -toml::value v(toml::offset_datetime(now)); -``` - -Since local time is not equivalent to a time point, because it lacks date -information, it will be constructed from `std::chrono::duration`. - -```cpp -toml::value v(toml::local_time(std::chrono::hours(10))); -``` - -You can construct an array object not only from `initializer_list`, but also -from STL containers. In that case, the element type must be convertible to -`toml::value`. - -```cpp -std::vector vec{1,2,3,4,5}; -toml::value v(vec); -``` - -When you construct an array value, all the elements of `initializer_list` -must be convertible into `toml::value`. - -If a `toml::value` has an array, you can `push_back` an element in it. - -```cpp -toml::value v{1,2,3,4,5}; -v.push_back(6); -``` - -`emplace_back` also works. - -## Preserving comments - -toml11 v3 or later allows you yo choose whether comments are preserved or not via template parameter - -```cpp -const auto data1 = toml::parse("example.toml"); -const auto data2 = toml::parse("example.toml"); -``` - -or macro definition. - -```cpp -#define TOML11_PRESERVE_COMMENTS_BY_DEFAULT -#include -``` - -This feature is controlled by template parameter in `toml::basic_value<...>`. -`toml::value` is an alias of `toml::basic_value<...>`. - -If template parameter is explicitly specified, the return value of `toml::parse` -will be `toml::basic_value`. -If the macro is defined, the alias `toml::value` will be -`toml::basic_value`. - -Comments related to a value can be obtained by `toml::value::comments()`. -The return value has the same interface as `std::vector`. - -```cpp -const auto& com = v.comments(); -for(const auto& c : com) -{ - std::cout << c << std::endl; -} -``` - -Comments just before and just after (within the same line) a value are kept in a value. - -```toml -# this is a comment for v1. -v1 = "foo" - -v2 = "bar" # this is a comment for v2. -# Note that this comment is NOT a comment for v2. - -# this comment is not related to any value -# because there are empty lines between v3. -# this comment will be ignored even if you set `preserve_comments`. - -# this is a comment for v3 -# this is also a comment for v3. -v3 = "baz" # ditto. -``` - -Each comment line becomes one element of a `std::vector`. - -Hash signs will be removed, but spaces after hash sign will not be removed. - -```cpp -v1.comments().at(0) == " this is a comment for v1."s; - -v2.comments().at(1) == " this is a comment for v1."s; - -v3.comments().at(0) == " this is a comment for v3."s; -v3.comments().at(1) == " this is also a comment for v3."s; -v3.comments().at(2) == " ditto."s; -``` - -Note that a comment just after an opening brace of an array will not be a -comment for the array. - -```toml -# this is a comment for a. -a = [ # this is not a comment for a. this will be ignored. - 1, 2, 3, - # this is a comment for `42`. - 42, # this is also a comment for `42`. - 5 -] # this is a comment for a. -``` - -You can also append and modify comments. -The interfaces are the same as `std::vector`. - -```cpp -toml::basic_value v(42); -v.comments().push_back(" add this comment."); -// # add this comment. -// i = 42 -``` - -Also, you can pass a `std::vector` when constructing a -`toml::basic_value`. - -```cpp -std::vector comments{"comment 1", "comment 2"}; -const toml::basic_value v1(42, std::move(comments)); -const toml::basic_value v2(42, {"comment 1", "comment 2"}); -``` - -When `toml::discard_comments` is chosen, comments will not be contained in a value. -`value::comments()` will always be kept empty. -All the modification on comments would be ignored. -All the element access in a `discard_comments` causes the same error as accessing -an element of an empty `std::vector`. - -The comments will also be serialized. If comments exist, those comments will be -added just before the values. - -__NOTE__: Result types from `toml::parse(...)` and -`toml::parse(...)` are different. - -## Customizing containers - -Actually, `toml::basic_value` has 3 template arguments. - -```cpp -template class Table = std::unordered_map, - template class Array = std::vector> -class basic_value; -``` - -This enables you to change the containers used inside. E.g. you can use -`std::map` to contain a table object instead of `std::unordered_map`. -And also can use `std::deque` as a array object instead of `std::vector`. - -You can set these parameters while calling `toml::parse` function. - -```cpp -const auto data = toml::parse< - toml::preserve_comments, std::map, std::deque - >("example.toml"); -``` - -Needless to say, the result types from `toml::parse(...)` and -`toml::parse(...)` are different (unless you specify the same -types as default). - -Note that, since `toml::table` and `toml::array` is an alias for a table and an -array of a default `toml::value`, so it is different from the types actually -contained in a `toml::basic_value` when you customize containers. -To get the actual type in a generic way, use -`typename toml::basic_type::table_type` and -`typename toml::basic_type::array_type`. - -## TOML literal - -toml11 supports `"..."_toml` literal. -It accept both a bare value and a file content. - -```cpp -using namespace toml::literals::toml_literals; - -// `_toml` can convert a bare value without key -const toml::value v = u8"0xDEADBEEF"_toml; -// v is an Integer value containing 0xDEADBEEF. - -// raw string literal (`R"(...)"` is useful for this purpose) -const toml::value t = u8R"( - title = "this is TOML literal" - [table] - key = "value" -)"_toml; -// the literal will be parsed and the result will be contained in t -``` - -The literal function is defined in the same way as the standard library literals -such as `std::literals::string_literals::operator""s`. - -```cpp -namespace toml -{ -inline namespace literals -{ -inline namespace toml_literals -{ -toml::value operator"" _toml(const char* str, std::size_t len); -} // toml_literals -} // literals -} // toml -``` - -Access to the operator can be gained with `using namespace toml::literals;`, -`using namespace toml::toml_literals`, and `using namespace toml::literals::toml_literals`. - -Note that a key that is composed only of digits is allowed in TOML. -And, unlike the file parser, toml-literal allows a bare value without a key. -Thus it is difficult to distinguish arrays having integers and definitions of -tables that are named as digits. -Currently, literal `[1]` becomes a table named "1". -To ensure a literal to be considered as an array with one element, you need to -add a comma after the first element (like `[1,]`). - -```cpp -"[1,2,3]"_toml; // This is an array -"[table]"_toml; // This is a table that has an empty table named "table" inside. -"[[1,2,3]]"_toml; // This is an array of arrays -"[[table]]"_toml; // This is a table that has an array of tables inside. - -"[[1]]"_toml; // This literal is ambiguous. - // Currently, it becomes a table that has array of table "1". -"1 = [{}]"_toml; // This is a table that has an array of table named 1. -"[[1,]]"_toml; // This is an array of arrays. -"[[1],]"_toml; // ditto. -``` - -NOTE: `_toml` literal returns a `toml::value` that does not have comments. - -## Conversion between toml value and arbitrary types - -You can also use `toml::get` and other related functions with the types -you defined after you implement a way to convert it. - -```cpp -namespace ext -{ -struct foo -{ - int a; - double b; - std::string c; -}; -} // ext - -const auto data = toml::parse("example.toml"); - -// to do this -const foo f = toml::find(data, "foo"); -``` - -There are 3 ways to use `toml::get` with the types that you defined. - -The first one is to implement `from_toml(const toml::value&)` member function. - -```cpp -namespace ext -{ -struct foo -{ - int a; - double b; - std::string c; - - void from_toml(const toml::value& v) - { - this->a = toml::find(v, "a"); - this->b = toml::find(v, "b"); - this->c = toml::find(v, "c"); - return; - } -}; -} // ext -``` - -In this way, because `toml::get` first constructs `foo` without arguments, -the type should be default-constructible. - -The second is to implement `constructor(const toml::value&)`. - -```cpp -namespace ext -{ -struct foo -{ - explicit foo(const toml::value& v) - : a(toml::find(v, "a")), b(toml::find(v, "b")), - c(toml::find(v, "c")) - {} - - int a; - double b; - std::string c; -}; -} // ext -``` - -Note that implicit default constructor declaration will be suppressed -when a constructor is defined. If you want to use the struct (here, `foo`) -in a container (e.g. `std::vector`), you may need to define default -constructor explicitly. - -The third is to implement specialization of `toml::from` for your type. - -```cpp -namespace ext -{ -struct foo -{ - int a; - double b; - std::string c; -}; -} // ext - -namespace toml -{ -template<> -struct from -{ - static ext::foo from_toml(const value& v) - { - ext::foo f; - f.a = find(v, "a"); - f.b = find(v, "b"); - f.c = find(v, "c"); - return f; - } -}; -} // toml -``` - -In this way, since the conversion function is defined outside of the class, -you can add conversion between `toml::value` and classes defined in another library. - -In some cases, a class has a templatized constructor that takes a template, `T`. -It confuses `toml::get/find` because it makes the class "constructible" from -`toml::value`. To avoid this problem, `toml::from` and `from_toml` always -precede constructor. It makes easier to implement conversion between -`toml::value` and types defined in other libraries because it skips constructor. - -But, importantly, you cannot define `toml::from` and `T.from_toml` at the same -time because it causes ambiguity in the overload resolution of `toml::get` and `toml::find`. - -So the precedence is `toml::from` == `T.from_toml()` > `T(toml::value)`. - -If you want to convert any versions of `toml::basic_value`, -you need to templatize the conversion function as follows. - -```cpp -struct foo -{ - template class M, template class A> - void from_toml(const toml::basic_value& v) - { - this->a = toml::find(v, "a"); - this->b = toml::find(v, "b"); - this->c = toml::find(v, "c"); - return; - } -}; -// or -namespace toml -{ -template<> -struct from -{ - template class M, template class A> - static ext::foo from_toml(const basic_value& v) - { - ext::foo f; - f.a = find(v, "a"); - f.b = find(v, "b"); - f.c = find(v, "c"); - return f; - } -}; -} // toml -``` - ----- - -The opposite direction is also supported in a similar way. You can directly -pass your type to `toml::value`'s constructor by introducing `into_toml` or -`toml::into`. - -```cpp -namespace ext -{ -struct foo -{ - int a; - double b; - std::string c; - - toml::value into_toml() const // you need to mark it const. - { - return toml::value{{"a", this->a}, {"b", this->b}, {"c", this->c}}; - } -}; -} // ext - -ext::foo f{42, 3.14, "foobar"}; -toml::value v(f); -``` - -The definition of `toml::into` is similar to `toml::from`. - -```cpp -namespace ext -{ -struct foo -{ - int a; - double b; - std::string c; -}; -} // ext - -namespace toml -{ -template<> -struct into -{ - static toml::value into_toml(const ext::foo& f) - { - return toml::value{{"a", f.a}, {"b", f.b}, {"c", f.c}}; - } -}; -} // toml - -ext::foo f{42, 3.14, "foobar"}; -toml::value v(f); -``` - -Any type that can be converted to `toml::value`, e.g. `int`, `toml::table` and -`toml::array` are okay to return from `into_toml`. - -You can also return a custom `toml::basic_value` from `toml::into`. - -```cpp -namespace toml -{ -template<> -struct into -{ - static toml::basic_value into_toml(const ext::foo& f) - { - toml::basic_value v{{"a", f.a}, {"b", f.b}, {"c", f.c}}; - v.comments().push_back(" comment"); - return v; - } -}; -} // toml -``` - -But note that, if this `basic_value` would be assigned into other `toml::value` -that discards `comments`, the comments would be dropped. - -### Macro to automatically define conversion functions - -There is a helper macro that automatically generates conversion functions `from` and `into` for a simple struct. - -```cpp -namespace foo -{ -struct Foo -{ - std::string s; - double d; - int i; -}; -} // foo - -TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(foo::Foo, s, d, i) - -int main() -{ - const auto file = toml::parse("example.toml"); - auto f = toml::find(file, "foo"); -} -``` - -And then you can use `toml::find(file, "foo");` - -**Note** that, because of a slight difference in implementation of preprocessor between gcc/clang and MSVC, [you need to define `/Zc:preprocessor`](https://github.com/ToruNiina/toml11/issues/139#issuecomment-803683682) to use it in MSVC (Thank you @glebm !). - -## Formatting user-defined error messages - -When you encounter an error after you read the toml value, you may want to -show the error with the value. - -toml11 provides you a function that formats user-defined error message with -related values. With a code like the following, - -```cpp -const auto value = toml::find(data, "num"); -if(value < 0) -{ - std::cerr << toml::format_error("[error] value should be positive", - data.at("num"), "positive number required") - << std::endl; -} -``` - -you will get an error message like this. - -```console -[error] value should be positive - --> example.toml - 3 | num = -42 - | ~~~ positive number required -``` - -When you pass two values to `toml::format_error`, - -```cpp -const auto min = toml::find(range, "min"); -const auto max = toml::find(range, "max"); -if(max < min) -{ - std::cerr << toml::format_error("[error] max should be larger than min", - data.at("min"), "minimum number here", - data.at("max"), "maximum number here"); - << std::endl; -} -``` - -you will get an error message like this. - -```console -[error] max should be larger than min - --> example.toml - 3 | min = 54 - | ~~ minimum number here - ... - 4 | max = 42 - | ~~ maximum number here -``` - -You can print hints at the end of the message. - -```cpp -std::vector hints; -hints.push_back("positive number means n >= 0."); -hints.push_back("negative number is not positive."); -std::cerr << toml::format_error("[error] value should be positive", - data.at("num"), "positive number required", hints) - << std::endl; -``` - -```console -[error] value should be positive - --> example.toml - 2 | num = 42 - | ~~ positive number required - | -Hint: positive number means n >= 0. -Hint: negative number is not positive. -``` - -## Obtaining location information - -You can also format error messages in your own way by using `source_location`. - -```cpp -struct source_location -{ - std::uint_least32_t line() const noexcept; - std::uint_least32_t column() const noexcept; - std::uint_least32_t region() const noexcept; - std::string const& file_name() const noexcept; - std::string const& line_str() const noexcept; -}; -// +-- line() +--- length of the region (here, region() == 9) -// v .---+---. -// 12 | value = "foo bar" <- line_str() returns the line itself. -// ^-------- column() points here -``` - -You can get this by -```cpp -const toml::value v = /*...*/; -const toml::source_location loc = v.location(); -``` - -## Exceptions - -The following `exception` classes inherits `toml::exception` that inherits -`std::exception`. - -```cpp -namespace toml { -struct exception : public std::exception {/**/}; -struct syntax_error : public toml::exception {/**/}; -struct type_error : public toml::exception {/**/}; -struct internal_error : public toml::exception {/**/}; -} // toml -``` - -`toml::exception` has `toml::exception::location()` member function that returns -`toml::source_location`, in addition to `what()`. - -```cpp -namespace toml { -struct exception : public std::exception -{ - // ... - source_location const& location() const noexcept; -}; -} // toml -``` - -It represents where the error occurs. - -`syntax_error` will be thrown from `toml::parse` and `_toml` literal. -`type_error` will be thrown from `toml::get/find`, `toml::value::as_xxx()`, and -other functions that takes a content inside of `toml::value`. - -Note that, currently, from `toml::value::at()` and `toml::find(value, key)` -may throw an `std::out_of_range` that does not inherits `toml::exception`. - -Also, in some cases, most likely in the file open error, it will throw an -`std::runtime_error`. - -## Colorize Error Messages - -By defining `TOML11_COLORIZE_ERROR_MESSAGE`, the error messages from -`toml::parse` and `toml::find|get` will be colorized. By default, this feature -is turned off. - -With the following toml file taken from `toml-lang/toml/tests/hard_example.toml`, - -```toml -[error] -array = [ - "This might most likely happen in multiline arrays", - Like here, - "or here, - and here" - ] End of array comment, forgot the # -``` - -the error message would be like this. - -![error-message-1](https://github.com/ToruNiina/toml11/blob/misc/misc/toml11-err-msg-1.png) - -With the following, - -```toml -[error] -# array = [ -# "This might most likely happen in multiline arrays", -# Like here, -# "or here, -# and here" -# ] End of array comment, forgot the # -number = 3.14 pi <--again forgot the # -``` - -the error message would be like this. - -![error-message-2](https://github.com/ToruNiina/toml11/blob/misc/misc/toml11-err-msg-2.png) - -The message would be messy when it is written to a file, not a terminal because -it uses [ANSI escape code](https://en.wikipedia.org/wiki/ANSI_escape_code). - -Without `TOML11_COLORIZE_ERROR_MESSAGE`, you can still colorize user-defined -error message by passing `true` to the `toml::format_error` function. -If you define `TOML11_COLORIZE_ERROR_MESSAGE`, the value is `true` by default. -If not, the default value would be `false`. - -```cpp -std::cerr << toml::format_error("[error] value should be positive", - data.at("num"), "positive number required", - hints, /*colorize = */ true) << std::endl; -``` - -Note: It colorize `[error]` in red. That means that it detects `[error]` prefix -at the front of the error message. If there is no `[error]` prefix, -`format_error` adds it to the error message. - -## Serializing TOML data - -toml11 enables you to serialize data into toml format. - -```cpp -const toml::value data{{"foo", 42}, {"bar", "baz"}}; -std::cout << data << std::endl; -// bar = "baz" -// foo = 42 -``` - -toml11 automatically makes a small table and small array inline. -You can specify the width to make them inline by `std::setw` for streams. - -```cpp -const toml::value data{ - {"qux", {{"foo", 42}, {"bar", "baz"}}}, - {"quux", {"small", "array", "of", "strings"}}, - {"foobar", {"this", "array", "of", "strings", "is", "too", "long", - "to", "print", "into", "single", "line", "isn't", "it?"}}, -}; - -// the threshold becomes 80. -std::cout << std::setw(80) << data << std::endl; -// foobar = [ -// "this","array","of","strings","is","too","long","to","print","into", -// "single","line","isn't","it?", -// ] -// quux = ["small","array","of","strings"] -// qux = {bar="baz",foo=42} - - -// the width is 0. nothing become inline. -std::cout << std::setw(0) << data << std::endl; -// foobar = [ -// "this", -// ... (snip) -// "it?", -// ] -// quux = [ -// "small", -// "array", -// "of", -// "strings", -// ] -// [qux] -// bar = "baz" -// foo = 42 -``` - -It is recommended to set width before printing data. Some I/O functions changes -width to 0, and it makes all the stuff (including `toml::array`) multiline. -The resulting files becomes too long. - -To control the precision of floating point numbers, you need to pass -`std::setprecision` to stream. - -```cpp -const toml::value data{ - {"pi", 3.141592653589793}, - {"e", 2.718281828459045} -}; -std::cout << std::setprecision(17) << data << std::endl; -// e = 2.7182818284590451 -// pi = 3.1415926535897931 -std::cout << std::setprecision( 7) << data << std::endl; -// e = 2.718282 -// pi = 3.141593 -``` - -There is another way to format toml values, `toml::format()`. -It returns `std::string` that represents a value. - -```cpp -const toml::value v{{"a", 42}}; -const std::string fmt = toml::format(v); -// a = 42 -``` - -Note that since `toml::format` formats a value, the resulting string may lack -the key value. - -```cpp -const toml::value v{3.14}; -const std::string fmt = toml::format(v); -// 3.14 -``` - -To control the width and precision, `toml::format` receives optional second and -third arguments to set them. By default, the width is 80 and the precision is -`std::numeric_limits::max_digit10`. - -```cpp -const auto serial = toml::format(data, /*width = */ 0, /*prec = */ 17); -``` - -When you pass a comment-preserving-value, the comment will also be serialized. -An array or a table containing a value that has a comment would not be inlined. - -## Underlying types - -The toml types (can be used as `toml::*` in this library) and corresponding `enum` names are listed in the table below. - -| TOML type | underlying c++ type | enum class | -| -------------- | ---------------------------------- | -------------------------------- | -| Boolean | `bool` | `toml::value_t::boolean` | -| Integer | `std::int64_t` | `toml::value_t::integer` | -| Float | `double` | `toml::value_t::floating` | -| String | `toml::string` | `toml::value_t::string` | -| LocalDate | `toml::local_date` | `toml::value_t::local_date` | -| LocalTime | `toml::local_time` | `toml::value_t::local_time` | -| LocalDatetime | `toml::local_datetime` | `toml::value_t::local_datetime` | -| OffsetDatetime | `toml::offset_datetime` | `toml::value_t::offset_datetime` | -| Array | `array-like` | `toml::value_t::array` | -| Table | `map-like` | `toml::value_t::table` | - -`array-like` and `map-like` are the STL containers that works like a `std::vector` and -`std::unordered_map`, respectively. By default, `std::vector` and `std::unordered_map` -are used. See [Customizing containers](#customizing-containers) for detail. - -`toml::string` is effectively the same as `std::string` but has an additional -flag that represents a kind of a string, `string_t::basic` and `string_t::literal`. -Although `std::string` is not an exact toml type, still you can get a reference -that points to internal `std::string` by using `toml::get()` for convenience. -The most important difference between `std::string` and `toml::string` is that -`toml::string` will be formatted as a TOML string when outputted with `ostream`. -This feature is introduced to make it easy to write a custom serializer. - -`Datetime` variants are `struct` that are defined in this library. -Because `std::chrono::system_clock::time_point` is a __time point__, -not capable of representing a Local Time independent from a specific day. - -## Unreleased TOML features - -Since TOML v1.0.0-rc.1 has been released, those features are now activated by -default. We no longer need to define `TOML11_USE_UNRELEASED_FEATURES`. - -- Leading zeroes in exponent parts of floats are permitted. - - e.g. `1.0e+01`, `5e+05` - - [toml-lang/toml/PR/656](https://github.com/toml-lang/toml/pull/656) -- Allow raw tab characters in basic strings and multi-line basic strings. - - [toml-lang/toml/PR/627](https://github.com/toml-lang/toml/pull/627) -- Allow heterogeneous arrays - - [toml-lang/toml/PR/676](https://github.com/toml-lang/toml/pull/676) - -## Note about heterogeneous arrays - -Although `toml::parse` allows heterogeneous arrays, constructor of `toml::value` -does not. Here the reason is explained. - -```cpp -// this won't be compiled -toml::value v{ - "foo", 3.14, 42, {1,2,3,4,5}, {{"key", "value"}} -} -``` - -There is a workaround for this. By explicitly converting values into -`toml::value`, you can initialize `toml::value` with a heterogeneous array. -Also, you can first initialize a `toml::value` with an array and then -`push_back` into it. - -```cpp -// OK! -toml::value v{ - toml::value("foo"), toml::value(3.14), toml::value(42), - toml::value{1,2,3,4,5}, toml::value{{"key", "value"}} -} - -// OK! -toml::value v(toml::array{}); -v.push_back("foo"); -v.push_back(3.14); - -// OK! -toml::array a; -a.push_back("foo"); -a.push_back(3.14); -toml::value v(std::move(a)); -``` - -The reason why the first example is not allowed is the following. -Let's assume that you are initializing a `toml::value` with a table. - -```cpp - // # expecting TOML table. -toml::value v{ // [v] - {"answer", 42}, // answer = 42 - {"pi", 3.14}, // pi = 3.14 - {"foo", "bar"} // foo = "bar" -}; -``` - -This is indistinguishable from a (heterogeneous) TOML array definition. - -```toml -v = [ - ["answer", 42], - ["pi", 3.14], - ["foo", "bar"], -] -``` - -This means that the above C++ code makes constructor's overload resolution -ambiguous. So a constructor that allows both "table as an initializer-list" and -"heterogeneous array as an initializer-list" cannot be implemented. - -Thus, although it is painful, we need to explicitly cast values into -`toml::value` when you initialize heterogeneous array in a C++ code. - -```cpp -toml::value v{ - toml::value("foo"), toml::value(3.14), toml::value(42), - toml::value{1,2,3,4,5}, toml::value{{"key", "value"}} -}; -``` - -## Breaking Changes from v2 - -Although toml11 is relatively new library (it's three years old now), it had -some confusing and inconvenient user-interfaces because of historical reasons. - -Between v2 and v3, those interfaces are rearranged. - -- `toml::parse` now returns a `toml::value`, not `toml::table`. -- `toml::value` is now an alias of `toml::basic_value`. - - See [Customizing containers](#customizing-containers) for detail. -- The elements of `toml::value_t` are renamed as `snake_case`. - - See [Underlying types](#underlying-types) for detail. -- Supports for the CamelCaseNames are dropped. - - See [Underlying types](#underlying-types) for detail. -- `(is|as)_float` has been removed to make the function names consistent with others. - - Since `float` is a keyword, toml11 named a float type as `toml::floating`. - - Also a `value_t` corresponds to `toml::floating` is named `value_t::floating`. - - So `(is|as)_floating` is introduced and `is_float` has been removed. - - See [Casting a toml::value](#casting-a-tomlvalue) and [Checking value type](#checking-value-type) for detail. -- An overload of `toml::find` for `toml::table` has been dropped. Use `toml::value` version instead. - - Because type conversion between a table and a value causes ambiguity while overload resolution - - Since `toml::parse` now returns a `toml::value`, this feature becomes less important. - - Also because `toml::table` is a normal STL container, implementing utility function is easy. - - See [Finding a toml::value](#finding-a-toml-value) for detail. -- An overload of `operator<<` and `toml::format` for `toml::table`s are dropped. - - Use `toml::value` instead. - - See [Serializing TOML data](#serializing-toml-data) for detail. -- Interface around comments. - - See [Preserving Comments](#preserving-comments) for detail. -- An ancient `from_toml/into_toml` has been removed. Use arbitrary type conversion support. - - See [Conversion between toml value and arbitrary types](#conversion-between-toml-value-and-arbitrary-types) for detail. - -Such a big change will not happen in the coming years. - -## Running Tests - -After cloning this repository, run the following command (thank you @jwillikers -for automating test set fetching!). - -```sh -$ mkdir build -$ cd build -$ cmake .. -Dtoml11_BUILD_TEST=ON -$ make -$ make test -``` - -To run the language agnostic test suite, you need to compile -`tests/check_toml_test.cpp` and pass it to the tester. - -## Contributors - -I appreciate the help of the contributors who introduced the great feature to this library. - -- Guillaume Fraux (@Luthaf) - - Windows support and CI on Appvayor - - Intel Compiler support -- Quentin Khan (@xaxousis) - - Found & Fixed a bug around ODR - - Improved error messages for invalid keys to show the location where the parser fails -- Petr Beneš (@wbenny) - - Fixed warnings on MSVC -- Ivan Shynkarenka (@chronoxor) - - Fixed Visual Studio 2019 warnings -- Khoi Dinh Trinh (@khoitd1997) - - Fixed warnings while type conversion -- @KerstinKeller - - Added installation script to CMake -- J.C. Moyer (@jcmoyer) - - Fixed an example code in the documentation -- Jt Freeman (@blockparty-sh) - - Fixed feature test macro around `localtime_s` - - Suppress warnings in Debug mode -- OGAWA Kenichi (@kenichiice) - - Suppress warnings on intel compiler -- Jordan Williams (@jwillikers) - - Fixed clang range-loop-analysis warnings - - Fixed feature test macro to suppress -Wundef - - Use cache variables in CMakeLists.txt - - Automate test set fetching, update and refactor CMakeLists.txt -- Scott McCaskill - - Parse 9 digits (nanoseconds) of fractional seconds in a `local_time` -- 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 -- Ivan Shynkarenka (@chronoxor) - - Fix compilation error in `` with MinGW -- Alex Merry (@amerry) - - Add missing include files -- sneakypete81 (@sneakypete81) - - Fix typo in error message -- Oliver Kahrmann (@founderio) - - Fix missing filename in error message if parsed file is empty -- Karl Nilsson (@karl-nilsson) - - Fix many spelling errors -- ohdarling88 (@ohdarling) - - Fix a bug in a constructor of serializer -- estshorter (@estshorter) - - Fix MSVC warning C26478 -- Philip Top (@phlptp) - - Improve checking standard library feature availability check -- Louis Marascio (@marascio) - - Fix free-nonheap-object warning -- Axel Huebl (@ax3l) - - Make installation optional if the library is embedded - -## Licensing terms - -This product is licensed under the terms of the [MIT License](LICENSE). - -- Copyright (c) 2017-2022 Toru Niina - -All rights reserved. diff --git a/lib/toml/appveyor.yml b/lib/toml/appveyor.yml deleted file mode 100644 index 9fc6a73..0000000 --- a/lib/toml/appveyor.yml +++ /dev/null @@ -1,25 +0,0 @@ -version: "{build}" -os: Visual Studio 2015 - -environment: - matrix: - - generator: Visual Studio 14 2015 Win64 - - generator: Visual Studio 14 2015 - -configuration: - - Release - - Debug - -clone_depth: 10 -clone_folder: c:\toml11 - -build_script: - - cd C:\toml11 - - mkdir build - - cd build - - cmake -G"%generator%" -DBOOST_ROOT=C:/Libraries/boost_1_69_0 -Dtoml11_BUILD_TEST=ON .. - - cmake --build . --config "%configuration%" - - file --mime-encoding tests/toml/tests/hard_example_unicode.toml - -test_script: - - ctest --build-config "%configuration%" --timeout 300 --output-on-failure diff --git a/lib/toml/cmake/toml11Config.cmake.in b/lib/toml/cmake/toml11Config.cmake.in deleted file mode 100644 index edc73f6..0000000 --- a/lib/toml/cmake/toml11Config.cmake.in +++ /dev/null @@ -1,2 +0,0 @@ -@PACKAGE_INIT@ -include("@PACKAGE_toml11_install_cmake_dir@/toml11Targets.cmake") diff --git a/lib/toml/tests/CMakeLists.txt b/lib/toml/tests/CMakeLists.txt deleted file mode 100644 index 99d73b9..0000000 --- a/lib/toml/tests/CMakeLists.txt +++ /dev/null @@ -1,239 +0,0 @@ -include(ExternalProject) -ExternalProject_Add(toml - SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/toml - GIT_REPOSITORY https://github.com/toml-lang/toml - GIT_TAG v0.5.0 - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "") - -set(TEST_NAMES - test_datetime - test_string - test_utility - test_result - test_traits - test_value - test_lex_boolean - test_lex_integer - test_lex_floating - test_lex_datetime - test_lex_string - test_lex_key_comment - test_parse_boolean - test_parse_integer - test_parse_floating - test_parse_string - test_parse_datetime - test_parse_array - test_parse_table - test_parse_inline_table - test_parse_key - test_parse_table_key - test_literals - test_comments - test_get - test_get_or - test_find - test_find_or - test_find_or_recursive - test_expect - test_parse_file - test_serialize_file - test_parse_unicode - test_error_detection - test_format_error - test_extended_conversions -) - -CHECK_CXX_COMPILER_FLAG("-Wall" COMPILER_SUPPORTS_WALL) -CHECK_CXX_COMPILER_FLAG("-Wextra" COMPILER_SUPPORTS_WEXTRA) -CHECK_CXX_COMPILER_FLAG("-Wpedantic" COMPILER_SUPPORTS_WPEDANTIC) -CHECK_CXX_COMPILER_FLAG("-Werror" COMPILER_SUPPORTS_WERROR) - -CHECK_CXX_COMPILER_FLAG("-Wsign-conversion" COMPILER_SUPPORTS_WSIGN_CONVERSION) -CHECK_CXX_COMPILER_FLAG("-Wconversion" COMPILER_SUPPORTS_WCONVERSION) -CHECK_CXX_COMPILER_FLAG("-Wduplicated-cond" COMPILER_SUPPORTS_WDUPLICATED_COND) -CHECK_CXX_COMPILER_FLAG("-Wduplicated-branches" COMPILER_SUPPORTS_WDUPLICATED_BRANCHES) -CHECK_CXX_COMPILER_FLAG("-Wlogical-op" COMPILER_SUPPORTS_WLOGICAL_OP) -CHECK_CXX_COMPILER_FLAG("-Wuseless-cast" COMPILER_SUPPORTS_WUSELESS_CAST) -CHECK_CXX_COMPILER_FLAG("-Wdouble-promotion" COMPILER_SUPPORTS_WDOUBLE_PROMOTION) -CHECK_CXX_COMPILER_FLAG("-Wrange-loop-analysis" COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS) -CHECK_CXX_COMPILER_FLAG("-Wundef" COMPILER_SUPPORTS_WUNDEF) -CHECK_CXX_COMPILER_FLAG("-Wshadow" COMPILER_SUPPORTS_WSHADOW) - -if(COMPILER_SUPPORTS_WALL) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") -endif() -if(COMPILER_SUPPORTS_WEXTRA) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra") -endif() -if(COMPILER_SUPPORTS_WPEDANTIC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic") -endif() -if(COMPILER_SUPPORTS_WERROR) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") -endif() -if(COMPILER_SUPPORTS_WSHADOW) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow") -endif() -if(COMPILER_SUPPORTS_WSIGN_CONVERSION) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsign-conversion") -endif() -if(COMPILER_SUPPORTS_WCONVERSION) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wconversion") -endif() -if(COMPILER_SUPPORTS_WDUPLICATED_COND) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wduplicated-cond") -endif() -if(COMPILER_SUPPORTS_WDUPLICATED_BRANCHES) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wduplicated-branches") -endif() -if(COMPILER_SUPPORTS_WLOGICAL_OP) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wlogical-op") -endif() -if(COMPILER_SUPPORTS_WUSELESS_CAST) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wuseless-cast") -endif() -if(COMPILER_SUPPORTS_WDOUBLE_PROMOTION) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wdouble-promotion") -endif() -if(COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wrange-loop-analysis") -endif() -if(COMPILER_SUPPORTS_WUNDEF) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wundef") -endif() - -option(TOML11_USE_UNRELEASED_TOML_FEATURES - "use features in toml-lang/toml master while testing" OFF) - -if(TOML11_USE_UNRELEASED_TOML_FEATURES) - message(STATUS "adding TOML11_USE_UNRELEASED_TOML_FEATURES flag") - add_definitions("-DTOML11_USE_UNRELEASED_TOML_FEATURES") -endif() - -# Disable some MSVC warnings -if(MSVC) - # conversion from 'double' to 'unsigned int', possible loss of data - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4244") - # conversion from 'int' to 'unsigned int', signed/unsigned mismatch - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4365") - # layout of class may have changed from a previous version of the compiler - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4371") - # enumerator in switch of enum is not explicitly handled by a case label - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4061") - # unreferenced inline function has been removed - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4514") - # constructor is not implicitly called - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4582") - # destructor is not implicitly called - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4583") - # pragma warning: there is no warning number - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4619") - # default constructor was implicitly defined as deleted - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4623") - # copy constructor was implicitly defined as deleted - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4625") - # assignment operator was implicitly defined as deleted - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4626") - # move assignment operator was implicitly defined as deleted - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4627") - # is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4668") - # function not inlined - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4710") - # function selected for automatic inlining - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4711") - # bytes padding added after data member - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4820") - # pragma warning(pop): likely mismatch, popping warning state pushed in different file - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd5031") - # pragma warning(pop): spectre warnings in tests - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd5045") - # pragma warning(pop): spectre warnings in tests - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4265") -endif() - -find_package(Boost COMPONENTS unit_test_framework REQUIRED) -add_definitions(-DBOOST_TEST_DYN_LINK) -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 -#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 . -# 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}) - add_executable(${TEST_NAME} ${TEST_NAME}.cpp) - target_link_libraries(${TEST_NAME} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} toml11::toml11) - target_include_directories(${TEST_NAME} SYSTEM PRIVATE ${Boost_INCLUDE_DIRS}) - - # to compile tests with ... - 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}) - - if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - if(toml11_TEST_WITH_ASAN) - set_target_properties(${TEST_NAME} PROPERTIES - COMPILE_FLAGS "-fsanitize=address -fno-omit-frame-pointer" - LINK_FLAGS "-fsanitize=address -fno-omit-frame-pointer") - elseif(toml11_TEST_WITH_UBSAN) - set_target_properties(${TEST_NAME} PROPERTIES - COMPILE_FLAGS "-fsanitize=undefined" - LINK_FLAGS "-fsanitize=undefined") - endif() - endif() - - add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - - # Set the PATH to be able to find Boost DLL - if(WIN32) - STRING(REPLACE ";" "\\;" PATH_STRING "$ENV{PATH}") - set_tests_properties(${TEST_NAME} - PROPERTIES ENVIRONMENT "PATH=${PATH_STRING}\;${Boost_LIBRARY_DIRS}" - ) - endif() -endforeach(TEST_NAME) - - -# this test is to check it compiles. it will not run -add_executable(test_multiple_translation_unit - test_multiple_translation_unit_1.cpp - test_multiple_translation_unit_2.cpp) -target_link_libraries(test_multiple_translation_unit toml11::toml11) - -if(WIN32) - add_executable(test_windows test_windows.cpp) - target_link_libraries(test_windows toml11::toml11) -endif() - diff --git a/lib/toml/tests/check.cpp b/lib/toml/tests/check.cpp deleted file mode 100644 index a271f3f..0000000 --- a/lib/toml/tests/check.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "toml.hpp" -#include -#include - -int main(int argc, char **argv) -{ - if(argc != 3) - { - std::cerr << "usage: ./check [filename] [valid|invalid]" << std::endl; - return 1; - } - - const std::string file_kind(argv[2]); - - try - { - const auto data = toml::parse(argv[1]); - std::cout << std::setprecision(16) << std::setw(80) << data; - if(file_kind == "valid") - { - return 0; - } - else - { - return 1; - } - } - catch(const toml::syntax_error& err) - { - std::cout << "what(): " << err.what() << std::endl; - if(file_kind == "invalid") - { - return 0; - } - else - { - return 1; - } - } - return 127; -} diff --git a/lib/toml/tests/check_serialization.cpp b/lib/toml/tests/check_serialization.cpp deleted file mode 100644 index 6f60103..0000000 --- a/lib/toml/tests/check_serialization.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "toml.hpp" -#include -#include - -int main(int argc, char **argv) -{ - if(argc != 2) - { - std::cerr << "usage: ./check [filename]" << std::endl; - return 1; - } - - const std::string filename(argv[1]); - - { - const auto data = toml::parse(filename); - { - std::ofstream ofs("tmp.toml"); - ofs << std::setprecision(16) << std::setw(80) << data; - } - const auto serialized = toml::parse("tmp.toml"); - - if(data != serialized) - { - // this is really a ditry hack, but is the easiest way... - // TODO: cleanup by adding comparison function to check if a value is NaN or not - if(filename.substr(filename.size() - 22, 22) == "float-inf-and-nan.toml" && - std::isnan (toml::find(serialized, "nan")) && - !std::signbit (toml::find(serialized, "nan")) && - std::isnan (toml::find(serialized, "nan_plus")) && - !std::signbit (toml::find(serialized, "nan_plus")) && - std::isnan (toml::find(serialized, "nan_neg")) && - std::signbit (toml::find(serialized, "nan_neg")) && - !std::isnan (toml::find(serialized, "infinity")) && - !std::isfinite(toml::find(serialized, "infinity")) && - !std::signbit (toml::find(serialized, "infinity")) && - !std::isnan (toml::find(serialized, "infinity_plus")) && - !std::isfinite(toml::find(serialized, "infinity_plus")) && - !std::signbit (toml::find(serialized, "infinity_plus")) && - !std::isnan (toml::find(serialized, "infinity_neg")) && - !std::isfinite(toml::find(serialized, "infinity_neg")) && - std::signbit (toml::find(serialized, "infinity_neg"))) - { - // then it is correctly serialized. - // Note that, the result of (nan == nan) is false. so `data == serialized` is false. - } - else - { - std::cerr << "============================================================\n"; - std::cerr << "result (w/o comment) different: " << filename << std::endl; - std::cerr << "------------------------------------------------------------\n"; - std::cerr << "# serialized\n"; - std::cerr << serialized; - std::cerr << "------------------------------------------------------------\n"; - std::cerr << "# data\n"; - std::cerr << data; - return 1; - } - } - } - { - const auto data = toml::parse(filename); - { - std::ofstream ofs("tmp.toml"); - ofs << std::setprecision(16) << std::setw(80) << data; - } - const auto serialized = toml::parse("tmp.toml"); - if(data != serialized) - { - // this is really a ditry hack, but is the easiest way... - // TODO: cleanup by adding comparison function to check if a value is NaN or not - if(filename.substr(filename.size() - 22, 22) == "float-inf-and-nan.toml" && - std::isnan (toml::find(serialized, "nan")) && - !std::signbit (toml::find(serialized, "nan")) && - std::isnan (toml::find(serialized, "nan_plus")) && - !std::signbit (toml::find(serialized, "nan_plus")) && - std::isnan (toml::find(serialized, "nan_neg")) && - std::signbit (toml::find(serialized, "nan_neg")) && - !std::isnan (toml::find(serialized, "infinity")) && - !std::isfinite(toml::find(serialized, "infinity")) && - !std::signbit (toml::find(serialized, "infinity")) && - !std::isnan (toml::find(serialized, "infinity_plus")) && - !std::isfinite(toml::find(serialized, "infinity_plus")) && - !std::signbit (toml::find(serialized, "infinity_plus")) && - !std::isnan (toml::find(serialized, "infinity_neg")) && - !std::isfinite(toml::find(serialized, "infinity_neg")) && - std::signbit (toml::find(serialized, "infinity_neg")) && - toml::find(data, "nan").comments() == toml::find(serialized, "nan").comments() && - toml::find(data, "nan_plus").comments() == toml::find(serialized, "nan_plus").comments() && - toml::find(data, "nan_neg").comments() == toml::find(serialized, "nan_neg").comments() && - toml::find(data, "infinity").comments() == toml::find(serialized, "infinity").comments() && - toml::find(data, "infinity_plus").comments() == toml::find(serialized, "infinity_plus").comments() && - toml::find(data, "infinity_neg").comments() == toml::find(serialized, "infinity_neg").comments() ) - { - // then it is correctly serialized. - // Note that, the result of (nan == nan) is false. so `data == serialized` is false. - } - else - { - std::cerr << "============================================================\n"; - std::cerr << "result (w/ comment) different: " << filename << std::endl; - std::cerr << "------------------------------------------------------------\n"; - std::cerr << "# serialized\n"; - std::cerr << serialized; - std::cerr << "------------------------------------------------------------\n"; - std::cerr << "# data\n"; - std::cerr << data; - return 1; - } - } - } - return 0; -} diff --git a/lib/toml/tests/check_toml_test.cpp b/lib/toml/tests/check_toml_test.cpp deleted file mode 100644 index 9c57572..0000000 --- a/lib/toml/tests/check_toml_test.cpp +++ /dev/null @@ -1,138 +0,0 @@ -#include "toml.hpp" -#include -#include - -struct json_serializer -{ - void operator()(toml::boolean v) - { - std::cout << "{\"type\":\"bool\",\"value\":\"" << toml::value(v) << "\"}"; - return ; - } - void operator()(toml::integer v) - { - std::cout << "{\"type\":\"integer\",\"value\":\"" << toml::value(v) << "\"}"; - return ; - } - void operator()(toml::floating v) - { - if(std::isnan(v) && std::signbit(v)) - { - // toml-test does not allow negative NaN represented in "-nan" because - // there are languages that does not distinguish nan and -nan. - // But toml11 keeps sign from input. To resolve this difference, - // we convert -nan to nan here. - v = std::numeric_limits::quiet_NaN(); - } - std::cout << "{\"type\":\"float\",\"value\":\"" << toml::value(v) << "\"}"; - return ; - } - void operator()(const toml::string& v) - { - // since toml11 automatically convert string to multiline string that is - // valid only in TOML, we need to format the string to make it valid in - // JSON. - toml::serializer ser(std::numeric_limits::max()); - std::cout << "{\"type\":\"string\",\"value\":" - << ser(v.str) << "}"; - return ; - } - void operator()(const toml::local_time& v) - { - std::cout << "{\"type\":\"time-local\",\"value\":\"" << toml::value(v) << "\"}"; - return ; - } - void operator()(const toml::local_date& v) - { - std::cout << "{\"type\":\"date-local\",\"value\":\"" << toml::value(v) << "\"}"; - return ; - } - void operator()(const toml::local_datetime& v) - { - std::cout << "{\"type\":\"datetime-local\",\"value\":\"" << toml::value(v) << "\"}"; - return ; - } - void operator()(const toml::offset_datetime& v) - { - std::cout << "{\"type\":\"datetime\",\"value\":\"" << toml::value(v) << "\"}"; - return ; - } - void operator()(const toml::array& v) - { - if(!v.empty() && v.front().is_table()) - { - std::cout << '['; - bool is_first = true; - for(const auto& elem : v) - { - if(!is_first) {std::cout << ", ";} - is_first = false; - toml::visit(*this, elem); - } - std::cout << ']'; - } - else - { -// std::cout << "{\"type\":\"array\",\"value\":["; - std::cout << "["; - bool is_first = true; - for(const auto& elem : v) - { - if(!is_first) {std::cout << ", ";} - is_first = false; - toml::visit(*this, elem); - } - std::cout << "]"; - } - return ; - } - void operator()(const toml::table& v) - { - std::cout << '{'; - bool is_first = true; - for(const auto& elem : v) - { - if(!is_first) {std::cout << ", ";} - is_first = false; - const auto k = toml::format_key(elem.first); - if(k.at(0) == '"') - { - std::cout << k << ":"; - } - else // bare key - { - std::cout << '\"' << k << "\":"; - } - toml::visit(*this, elem.second); - } - std::cout << '}'; - return ; - } -}; - -int main() -{ - try - { - std::vector buf; - std::cin.peek(); - while(!std::cin.eof()) - { - buf.push_back(std::cin.get()); - std::cin.peek(); - } - std::string bufstr(buf.begin(), buf.end()); - - std::istringstream ss(bufstr); - - const auto data = toml::parse(ss); - std::cout << std::setprecision(std::numeric_limits::max_digits10); - toml::visit(json_serializer(), data); - return 0; - } - catch(const toml::syntax_error& err) - { - std::cout << "what(): " << err.what() << std::endl; - return 1; - } -} diff --git a/lib/toml/tests/test_comments.cpp b/lib/toml/tests/test_comments.cpp deleted file mode 100644 index 8cc6573..0000000 --- a/lib/toml/tests/test_comments.cpp +++ /dev/null @@ -1,551 +0,0 @@ -#define BOOST_TEST_MODULE "test_comments" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif - -#include - -BOOST_AUTO_TEST_CASE(test_comment_before) -{ - { - const std::string file = R"( - # comment for a. - a = 42 - # comment for b. - b = "baz" - )"; - std::istringstream iss(file); - const auto v = toml::parse(iss); - - const auto& a = toml::find(v, "a"); - const auto& b = toml::find(v, "b"); - - BOOST_TEST(a.comments().size() == 1u); - BOOST_TEST(a.comments().front() == " comment for a."); - BOOST_TEST(b.comments().size() == 1u); - BOOST_TEST(b.comments().front() == " comment for b."); - } - { - const std::string file = R"( - # comment for a. - # another comment for a. - a = 42 - # comment for b. - # also comment for b. - b = "baz" - )"; - - std::istringstream iss(file); - const auto v = toml::parse(iss); - - const auto& a = toml::find(v, "a"); - const auto& b = toml::find(v, "b"); - - BOOST_TEST(a.comments().size() == 2u); - BOOST_TEST(a.comments().front() == " comment for a."); - BOOST_TEST(a.comments().back() == " another comment for a."); - BOOST_TEST(b.comments().size() == 2u); - BOOST_TEST(b.comments().front() == " comment for b."); - BOOST_TEST(b.comments().back() == " also comment for b."); - } -} - -BOOST_AUTO_TEST_CASE(test_comment_inline) -{ - { - const std::string file = R"( - a = 42 # comment for a. - b = "baz" # comment for b. - )"; - - std::istringstream iss(file); - const auto v = toml::parse(iss); - - const auto& a = toml::find(v, "a"); - const auto& b = toml::find(v, "b"); - - BOOST_TEST(a.comments().size() == 1u); - BOOST_TEST(a.comments().front() == " comment for a."); - BOOST_TEST(b.comments().size() == 1u); - BOOST_TEST(b.comments().front() == " comment for b."); - } - { - const std::string file = R"( - a = [ - 42, - ] # comment for a. - b = [ - "bar", # this is not a comment for b, but "bar" - ] # this is a comment for b. - )"; - - std::istringstream iss(file); - const auto v = toml::parse(iss); - - const auto& a = toml::find(v, "a"); - const auto& b = toml::find(v, "b"); - const auto& b0 = b.as_array().at(0); - - BOOST_TEST(a.comments().size() == 1u); - BOOST_TEST(a.comments().front() == " comment for a."); - BOOST_TEST(b.comments().size() == 1u); - BOOST_TEST(b.comments().front() == " this is a comment for b."); - BOOST_TEST(b0.comments().size() == 1u); - BOOST_TEST(b0.comments().front() == " this is not a comment for b, but \"bar\""); - } -} - -BOOST_AUTO_TEST_CASE(test_comment_both) -{ - { - const std::string file = R"( - # comment for a. - a = 42 # inline comment for a. - # comment for b. - b = "baz" # inline comment for b. - # comment for c. - c = [ # this comment will be ignored - # comment for the first element. - 10 # this also. - ] # another comment for c. - )"; - - std::istringstream iss(file); - const auto v = toml::parse(iss); - - const auto& a = toml::find(v, "a"); - const auto& b = toml::find(v, "b"); - const auto& c = toml::find(v, "c"); - const auto& c0 = c.as_array().at(0); - - BOOST_TEST(a.comments().size() == 2u); - BOOST_TEST(a.comments().front() == " comment for a."); - BOOST_TEST(a.comments().back() == " inline comment for a."); - BOOST_TEST(b.comments().size() == 2u); - BOOST_TEST(b.comments().front() == " comment for b."); - BOOST_TEST(b.comments().back() == " inline comment for b."); - - BOOST_TEST(c.comments().size() == 2u); - BOOST_TEST(c.comments().front() == " comment for c."); - BOOST_TEST(c.comments().back() == " another comment for c."); - - BOOST_TEST(c0.comments().size() == 2u); - BOOST_TEST(c0.comments().front() == " comment for the first element."); - BOOST_TEST(c0.comments().back() == " this also."); - } -} - -BOOST_AUTO_TEST_CASE(test_comments_on_implicit_values) -{ - { - const std::string file = R"( - # comment for the first element of array-of-tables. - [[array-of-tables]] - foo = "bar" - )"; - std::istringstream iss(file); - const auto v = toml::parse(iss); - - const auto aot = toml::find(v, "array-of-tables"); - const auto elm = aot.at(0); - BOOST_TEST(aot.comments().empty()); - BOOST_TEST(elm.comments().size() == 1); - BOOST_TEST(elm.comments().front() == " comment for the first element of array-of-tables."); - } - { - const std::string file = R"( - # comment for the array itself - array-of-tables = [ - # comment for the first element of array-of-tables. - {foo = "bar"} - ] - )"; - std::istringstream iss(file); - const auto v = toml::parse(iss); - - const auto aot = toml::find(v, "array-of-tables"); - const auto elm = aot.at(0); - BOOST_TEST(aot.comments().size() == 1); - BOOST_TEST(aot.comments().front() == " comment for the array itself"); - BOOST_TEST(elm.comments().size() == 1); - BOOST_TEST(elm.comments().front() == " comment for the first element of array-of-tables."); - } -} - -BOOST_AUTO_TEST_CASE(test_discard_comment) -{ - const std::string file = R"( - # comment for a. - a = 42 # inline comment for a. - # comment for b. - b = "baz" # inline comment for b. - # comment for c. - c = [ # this comment will be ignored - # comment for the first element. - 10 # this also. - ] # another comment for c. - )"; - - std::istringstream iss(file); - const auto v = toml::parse(iss); - - const auto& a = toml::find(v, "a"); - const auto& b = toml::find(v, "b"); - const auto& c = toml::find(v, "c"); - const auto& c0 = c.as_array().at(0); - - BOOST_TEST(a.comments().empty()); - BOOST_TEST(b.comments().empty()); - BOOST_TEST(c.comments().empty()); - BOOST_TEST(c0.comments().empty()); -} - -BOOST_AUTO_TEST_CASE(test_construct_value_with_comments) -{ - using value_type = toml::basic_value; - { - const value_type v(true, {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_boolean()); - BOOST_TEST(v.as_boolean() == true); - } - { - const value_type v(42, {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_integer()); - BOOST_TEST(v.as_integer() == 42); - } - { - const value_type v(3.14, {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_floating()); - BOOST_TEST(v.as_floating() == 3.14); - } - { - const value_type v(toml::string("str"), {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_string()); - BOOST_TEST(v.as_string() == "str"); - } - { - const value_type v(std::string("str"), {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_string()); - BOOST_TEST(v.as_string() == "str"); - } - { - const value_type v(std::string("str"), toml::string_t::literal, - {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_string()); - BOOST_TEST(v.as_string() == "str"); - } - { - const value_type v("str", {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_string()); - BOOST_TEST(v.as_string() == "str"); - } - { - const value_type v("str", toml::string_t::literal, - {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_string()); - BOOST_TEST(v.as_string() == "str"); - } -#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L - { - using namespace std::literals::string_view_literals; - const value_type v("str"sv, {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_string()); - BOOST_TEST(v.as_string() == "str"); - } - { - using namespace std::literals::string_view_literals; - const value_type v("str"sv, toml::string_t::literal, - {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_string()); - BOOST_TEST(v.as_string() == "str"); - } -#endif - const toml::local_date ld{2019, toml::month_t::Apr, 1}; - const toml::local_time lt{12, 30, 45}; - const toml::local_datetime ldt{ld, lt}; - const toml::offset_datetime odt{ld, lt, toml::time_offset{9, 0}}; - { - const value_type v(ld, {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_local_date()); - BOOST_TEST(v.as_local_date() == ld); - } - { - const value_type v(lt, {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_local_time()); - BOOST_TEST(v.as_local_time() == lt); - } - { - const toml::local_time three_hours{3,0,0}; - const value_type v(std::chrono::hours(3), {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_local_time()); - BOOST_TEST(v.as_local_time() == three_hours); - } - { - const value_type v(ldt, {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_local_datetime()); - BOOST_TEST(v.as_local_datetime() == ldt); - } - { - const value_type v(odt, {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_offset_datetime()); - BOOST_TEST(v.as_offset_datetime() == odt); - } - { - const auto systp = static_cast(odt); - const value_type v(systp, {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_offset_datetime()); - - // While the conversion, the information about time offset may change. - const auto systp2 = static_cast( - v.as_offset_datetime()); - const bool result = systp == systp2; // because there is no operator<< - BOOST_TEST(result); - } - { - const typename value_type::array_type a{1,2,3,4,5}; - const value_type v(a, {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_array()); - BOOST_TEST(v.as_array().at(0).is_integer()); - BOOST_TEST(v.as_array().at(1).is_integer()); - BOOST_TEST(v.as_array().at(2).is_integer()); - BOOST_TEST(v.as_array().at(3).is_integer()); - BOOST_TEST(v.as_array().at(4).is_integer()); - BOOST_TEST(v.as_array().at(0).as_integer() == 1); - BOOST_TEST(v.as_array().at(1).as_integer() == 2); - BOOST_TEST(v.as_array().at(2).as_integer() == 3); - BOOST_TEST(v.as_array().at(3).as_integer() == 4); - BOOST_TEST(v.as_array().at(4).as_integer() == 5); - } - { - const std::initializer_list a = {1,2,3,4,5}; - const value_type v(a, {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_array()); - BOOST_TEST(v.as_array().at(0).is_integer()); - BOOST_TEST(v.as_array().at(1).is_integer()); - BOOST_TEST(v.as_array().at(2).is_integer()); - BOOST_TEST(v.as_array().at(3).is_integer()); - BOOST_TEST(v.as_array().at(4).is_integer()); - BOOST_TEST(v.as_array().at(0).as_integer() == 1); - BOOST_TEST(v.as_array().at(1).as_integer() == 2); - BOOST_TEST(v.as_array().at(2).as_integer() == 3); - BOOST_TEST(v.as_array().at(3).as_integer() == 4); - BOOST_TEST(v.as_array().at(4).as_integer() == 5); - } - { - const std::vector a = {1,2,3,4,5}; - const value_type v(a, {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_array()); - BOOST_TEST(v.as_array().at(0).is_integer()); - BOOST_TEST(v.as_array().at(1).is_integer()); - BOOST_TEST(v.as_array().at(2).is_integer()); - BOOST_TEST(v.as_array().at(3).is_integer()); - BOOST_TEST(v.as_array().at(4).is_integer()); - BOOST_TEST(v.as_array().at(0).as_integer() == 1); - BOOST_TEST(v.as_array().at(1).as_integer() == 2); - BOOST_TEST(v.as_array().at(2).as_integer() == 3); - BOOST_TEST(v.as_array().at(3).as_integer() == 4); - BOOST_TEST(v.as_array().at(4).as_integer() == 5); - } - { - const typename value_type::table_type t{ - {"key1", 42}, {"key2", "foobar"} - }; - const value_type v(t, {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_table()); - BOOST_TEST(v.as_table().at("key1").is_integer()); - BOOST_TEST(v.as_table().at("key1").as_integer() == 42); - BOOST_TEST(v.as_table().at("key2").is_string()); - BOOST_TEST(v.as_table().at("key2").as_string() == "foobar"); - } - { - const std::initializer_list> t{ - {"key1", 42}, {"key2", "foobar"} - }; - const value_type v(t, {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_table()); - BOOST_TEST(v.as_table().at("key1").is_integer()); - BOOST_TEST(v.as_table().at("key1").as_integer() == 42); - BOOST_TEST(v.as_table().at("key2").is_string()); - BOOST_TEST(v.as_table().at("key2").as_string() == "foobar"); - } - { - const std::map t{ - {"key1", 42}, {"key2", "foobar"} - }; - const value_type v(t, {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_table()); - BOOST_TEST(v.as_table().at("key1").is_integer()); - BOOST_TEST(v.as_table().at("key1").as_integer() == 42); - BOOST_TEST(v.as_table().at("key2").is_string()); - BOOST_TEST(v.as_table().at("key2").as_string() == "foobar"); - } -} - -BOOST_AUTO_TEST_CASE(test_overwrite_comments) -{ - using value_type = toml::basic_value; - { - const value_type v(42, {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_integer()); - BOOST_TEST(v.as_integer() == 42); - - const value_type u(v, {"comment3", "comment4"}); - BOOST_TEST(u.comments().size() == 2u); - BOOST_TEST(u.comments().at(0) == "comment3"); - BOOST_TEST(u.comments().at(1) == "comment4"); - BOOST_TEST(u.is_integer()); - BOOST_TEST(u.as_integer() == 42); - } - { - const value_type v(42, {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_integer()); - BOOST_TEST(v.as_integer() == 42); - - const value_type u(v); - BOOST_TEST(u.comments().size() == 2u); - BOOST_TEST(u.comments().at(0) == "comment1"); - BOOST_TEST(u.comments().at(1) == "comment2"); - BOOST_TEST(u.is_integer()); - BOOST_TEST(u.as_integer() == 42); - } - { - const value_type v(42, {"comment1", "comment2"}); - BOOST_TEST(v.comments().size() == 2u); - BOOST_TEST(v.comments().at(0) == "comment1"); - BOOST_TEST(v.comments().at(1) == "comment2"); - BOOST_TEST(v.is_integer()); - BOOST_TEST(v.as_integer() == 42); - - const value_type u(v, {}); - BOOST_TEST(u.comments().size() == 0u); - BOOST_TEST(u.is_integer()); - BOOST_TEST(u.as_integer() == 42); - } -} - -BOOST_AUTO_TEST_CASE(test_output_comments) -{ - using value_type = toml::basic_value; - { - const value_type v(42, {"comment1", "comment2"}); - std::ostringstream oss; - oss << v.comments(); - - std::ostringstream ref; - ref << "#comment1\n"; - ref << "#comment2\n"; - - BOOST_TEST(oss.str() == ref.str()); - } - { - const value_type v(42, {"comment1", "comment2"}); - std::ostringstream oss; - - // If v is not a table, toml11 assumes that user is writing something - // like the following. - - oss << "answer = " << v; - - BOOST_TEST(oss.str() == "answer = 42 #comment1comment2"); - } - - { - const value_type v(42, {"comment1", "comment2"}); - std::ostringstream oss; - - // If v is not a table, toml11 assumes that user is writing something - // like the following. - - oss << toml::nocomment << "answer = " << v; - - BOOST_TEST(oss.str() == "answer = 42"); - } - - { - const value_type v(42, {"comment1", "comment2"}); - std::ostringstream oss; - - // If v is not a table, toml11 assumes that user is writing something - // like the following. - - oss << toml::nocomment << toml::showcomment << "answer = " << v; - - BOOST_TEST(oss.str() == "answer = 42 #comment1comment2"); - } - -} diff --git a/lib/toml/tests/test_datetime.cpp b/lib/toml/tests/test_datetime.cpp deleted file mode 100644 index 395949e..0000000 --- a/lib/toml/tests/test_datetime.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#define BOOST_TEST_MODULE "test_datetime" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include - -BOOST_AUTO_TEST_CASE(test_local_date) -{ - const toml::local_date date(2018, toml::month_t::Jan, 1); - const toml::local_date date1(date); - BOOST_TEST(date == date1); - - const std::chrono::system_clock::time_point tp(date); - const toml::local_date date2(tp); - BOOST_TEST(date == date2); - - const toml::local_date date3(2017, toml::month_t::Dec, 31); - BOOST_TEST(date > date3); - - std::ostringstream oss; - oss << date; - BOOST_TEST(oss.str() == std::string("2018-01-01")); -} - -BOOST_AUTO_TEST_CASE(test_local_time) -{ - const toml::local_time time(12, 30, 45); - const toml::local_time time1(time); - BOOST_TEST(time == time1); - - const std::chrono::nanoseconds dur(time); - std::chrono::nanoseconds ns(0); - ns += std::chrono::hours (12); - ns += std::chrono::minutes(30); - ns += std::chrono::seconds(45); - BOOST_TEST(dur.count() == ns.count()); - - const toml::local_time time3(12, 15, 45); - BOOST_TEST(time > time3); - - { - std::ostringstream oss; - oss << time; - BOOST_TEST(oss.str() == std::string("12:30:45")); - } - - { - const toml::local_time time4(12, 30, 45, 123, 456); - std::ostringstream oss; - oss << time4; - BOOST_TEST(oss.str() == std::string("12:30:45.123456")); - } -} - -BOOST_AUTO_TEST_CASE(test_time_offset) -{ - const toml::time_offset time(9, 30); - const toml::time_offset time1(time); - BOOST_TEST(time == time1); - - const std::chrono::minutes dur(time); - std::chrono::minutes m(0); - m += std::chrono::hours (9); - m += std::chrono::minutes(30); - BOOST_TEST(dur.count() == m.count()); - - const toml::time_offset time2(9, 0); - BOOST_TEST(time2 < time); - - std::ostringstream oss; - oss << time; - BOOST_TEST(oss.str() == std::string("+09:30")); -} - -BOOST_AUTO_TEST_CASE(test_local_datetime) -{ - const toml::local_datetime dt(toml::local_date(2018, toml::month_t::Jan, 1), - toml::local_time(12, 30, 45)); - const toml::local_datetime dt1(dt); - BOOST_TEST(dt == dt1); - - const std::chrono::system_clock::time_point tp(dt); - const toml::local_datetime dt2(tp); - BOOST_TEST(dt == dt2); - - std::ostringstream oss; - oss << dt; - BOOST_TEST(oss.str() == std::string("2018-01-01T12:30:45")); -} - -BOOST_AUTO_TEST_CASE(test_offset_datetime) -{ - const toml::offset_datetime dt(toml::local_date(2018, toml::month_t::Jan, 1), - toml::local_time(12, 30, 45), - toml::time_offset(9, 30)); - const toml::offset_datetime dt1(dt); - BOOST_TEST(dt == dt1); - - const std::chrono::system_clock::time_point tp1(dt); - const toml::offset_datetime dt2(tp1); - const std::chrono::system_clock::time_point tp2(dt2); - const bool tp_same = (tp1 == tp2); - BOOST_TEST(tp_same); - - { - std::ostringstream oss; - oss << dt; - BOOST_TEST(oss.str() == std::string("2018-01-01T12:30:45+09:30")); - } - { - const toml::offset_datetime dt3( - toml::local_date(2018, toml::month_t::Jan, 1), - toml::local_time(12, 30, 45), - toml::time_offset(0, 0)); - std::ostringstream oss; - oss << dt3; - BOOST_TEST(oss.str() == std::string("2018-01-01T12:30:45Z")); - } -} diff --git a/lib/toml/tests/test_error_detection.cpp b/lib/toml/tests/test_error_detection.cpp deleted file mode 100644 index 07c607f..0000000 --- a/lib/toml/tests/test_error_detection.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#define BOOST_TEST_MODULE "test_error_detection" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include -#include - -BOOST_AUTO_TEST_CASE(test_detect_empty_key) -{ - std::istringstream stream(std::string("= \"value\"")); - BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error); -} - -BOOST_AUTO_TEST_CASE(test_detect_missing_value) -{ - std::istringstream stream(std::string("a =")); - BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error); -} - -BOOST_AUTO_TEST_CASE(test_detect_too_many_value) -{ - std::istringstream stream(std::string("a = 1 = \"value\"")); - BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error); -} - -BOOST_AUTO_TEST_CASE(test_detect_duplicate_table) -{ - std::istringstream stream(std::string( - "[table]\n" - "a = 42\n" - "[table]\n" - "b = 42\n" - )); - BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error); -} - -BOOST_AUTO_TEST_CASE(test_detect_conflict_array_table) -{ - std::istringstream stream(std::string( - "[[table]]\n" - "a = 42\n" - "[table]\n" - "b = 42\n" - )); - BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error); -} - -BOOST_AUTO_TEST_CASE(test_detect_conflict_table_array) -{ - std::istringstream stream(std::string( - "[table]\n" - "a = 42\n" - "[[table]]\n" - "b = 42\n" - )); - BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error); -} - -BOOST_AUTO_TEST_CASE(test_detect_duplicate_value) -{ - std::istringstream stream(std::string( - "a = 1\n" - "a = 2\n" - )); - BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error); -} - -BOOST_AUTO_TEST_CASE(test_detect_conflicting_value) -{ - std::istringstream stream(std::string( - "a.b = 1\n" - "a.b.c = 2\n" - )); - BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error); -} - -BOOST_AUTO_TEST_CASE(test_detect_inhomogeneous_array) -{ -#ifdef TOML11_DISALLOW_HETEROGENEOUS_ARRAYS - std::istringstream stream(std::string( - "a = [1, 1.0]\n" - )); - BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error); -#else - BOOST_TEST_MESSAGE("After v1.0.0-rc.1, heterogeneous arrays are allowed"); -#endif -} - -BOOST_AUTO_TEST_CASE(test_detect_appending_array_of_table) -{ - std::istringstream stream(std::string( - "a = [{b = 1}]\n" - "[[a]]\n" - "b = 2\n" - )); - BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error); -} diff --git a/lib/toml/tests/test_expect.cpp b/lib/toml/tests/test_expect.cpp deleted file mode 100644 index 2971f0c..0000000 --- a/lib/toml/tests/test_expect.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#define BOOST_TEST_MODULE "test_expect" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include -#include -#include -#include -#include - -BOOST_AUTO_TEST_CASE(test_expect) -{ - { - toml::value v1(42); - toml::value v2(3.14); - const auto v1_or_0 = toml::expect(v1).unwrap_or(0); - const auto v2_or_0 = toml::expect(v2).unwrap_or(0); - BOOST_TEST(42 == v1_or_0); - BOOST_TEST( 0 == v2_or_0); - - const auto v1_or_none = toml::expect(v1).map([](int i){return std::to_string(i);}).unwrap_or(std::string("none")); - const auto v2_or_none = toml::expect(v2).map([](int i){return std::to_string(i);}).unwrap_or(std::string("none")); - BOOST_TEST("42" == v1_or_none); - BOOST_TEST("none" == v2_or_none); - } -} diff --git a/lib/toml/tests/test_extended_conversions.cpp b/lib/toml/tests/test_extended_conversions.cpp deleted file mode 100644 index 7e727ac..0000000 --- a/lib/toml/tests/test_extended_conversions.cpp +++ /dev/null @@ -1,631 +0,0 @@ -#define BOOST_TEST_MODULE "test_extended_conversions" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include -#include - -namespace extlib -{ -struct foo -{ - int a; - std::string b; -}; -struct bar -{ - int a; - std::string b; - - void from_toml(const toml::value& v) - { - this->a = toml::find(v, "a"); - this->b = toml::find(v, "b"); - return ; - } - - toml::table into_toml() const - { - return toml::table{{"a", this->a}, {"b", this->b}}; - } -}; - -struct baz -{ - int a; - std::string b; -}; -struct qux -{ - int a; - std::string b; -}; - -struct foobar -{ - // via constructor - explicit foobar(const toml::value& v) - : a(toml::find(v, "a")), b(toml::find(v, "b")) - {} - int a; - std::string b; -}; -} // extlib - -namespace toml -{ -template<> -struct from -{ - static extlib::foo from_toml(const toml::value& v) - { - return extlib::foo{toml::find(v, "a"), toml::find(v, "b")}; - } -}; - -template<> -struct into -{ - static toml::value into_toml(const extlib::foo& f) - { - return toml::value{{"a", f.a}, {"b", f.b}}; - } -}; - -template<> -struct from -{ - static extlib::baz from_toml(const toml::value& v) - { - return extlib::baz{toml::find(v, "a"), toml::find(v, "b")}; - } -}; - -template<> -struct into -{ - static toml::table into_toml(const extlib::qux& f) - { - return toml::table{{"a", f.a}, {"b", f.b}}; - } -}; -} // toml - -// --------------------------------------------------------------------------- - -namespace extlib2 -{ -struct foo -{ - int a; - std::string b; -}; -struct bar -{ - int a; - std::string b; - - template class M, template class A> - void from_toml(const toml::basic_value& v) - { - this->a = toml::find(v, "a"); - this->b = toml::find(v, "b"); - return ; - } - - toml::table into_toml() const - { - return toml::table{{"a", this->a}, {"b", this->b}}; - } -}; -struct baz -{ - int a; - std::string b; -}; -struct qux -{ - int a; - std::string b; -}; - -struct foobar -{ - template class M, template class A> - explicit foobar(const toml::basic_value& v) - : a(toml::find(v, "a")), b(toml::find(v, "b")) - {} - int a; - std::string b; -}; - -} // extlib2 - -namespace toml -{ -template<> -struct from -{ - template class M, template class A> - static extlib2::foo from_toml(const toml::basic_value& v) - { - return extlib2::foo{toml::find(v, "a"), toml::find(v, "b")}; - } -}; - -template<> -struct into -{ - static toml::table into_toml(const extlib2::foo& f) - { - return toml::table{{"a", f.a}, {"b", f.b}}; - } -}; - -template<> -struct from -{ - template class M, template class A> - static extlib2::baz from_toml(const toml::basic_value& v) - { - return extlib2::baz{toml::find(v, "a"), toml::find(v, "b")}; - } -}; - -template<> -struct into -{ - static toml::basic_value - into_toml(const extlib2::qux& f) - { - return toml::basic_value{ - {"a", f.a}, {"b", f.b} - }; - } -}; -} // toml - -// --------------------------------------------------------------------------- - -BOOST_AUTO_TEST_CASE(test_conversion_by_member_methods) -{ - { - const toml::value v{{"a", 42}, {"b", "baz"}}; - - const auto foo = toml::get(v); - BOOST_TEST(foo.a == 42); - BOOST_TEST(foo.b == "baz"); - - const toml::value v2(foo); - - BOOST_TEST(v == v2); - } - - { - const toml::value v{{"a", 42}, {"b", "baz"}}; - - const auto foo = toml::get(v); - BOOST_TEST(foo.a == 42); - BOOST_TEST(foo.b == "baz"); - - const toml::value v2(foo); - BOOST_TEST(v == v2); - } - - { - const toml::basic_value - v{{"a", 42}, {"b", "baz"}}; - - const auto foo = toml::get(v); - BOOST_TEST(foo.a == 42); - BOOST_TEST(foo.b == "baz"); - - const toml::basic_value - v2(foo); - - BOOST_TEST(v == v2); - } -} - -BOOST_AUTO_TEST_CASE(test_conversion_by_specialization) -{ - { - const toml::value v{{"a", 42}, {"b", "baz"}}; - - const auto bar = toml::get(v); - BOOST_TEST(bar.a == 42); - BOOST_TEST(bar.b == "baz"); - - const toml::value v2(bar); - - BOOST_TEST(v == v2); - } - { - const toml::value v{{"a", 42}, {"b", "baz"}}; - - const auto bar = toml::get(v); - BOOST_TEST(bar.a == 42); - BOOST_TEST(bar.b == "baz"); - - const toml::value v2(bar); - - BOOST_TEST(v == v2); - } - { - const toml::basic_value - v{{"a", 42}, {"b", "baz"}}; - - const auto bar = toml::get(v); - BOOST_TEST(bar.a == 42); - BOOST_TEST(bar.b == "baz"); - - const toml::basic_value - v2(bar); - - BOOST_TEST(v == v2); - } -} - -BOOST_AUTO_TEST_CASE(test_conversion_one_way) -{ - { - const toml::value v{{"a", 42}, {"b", "baz"}}; - - const auto baz = toml::get(v); - BOOST_TEST(baz.a == 42); - BOOST_TEST(baz.b == "baz"); - } - { - const extlib::qux q{42, "qux"}; - const toml::value v(q); - - BOOST_TEST(toml::find(v, "a") == 42); - BOOST_TEST(toml::find(v, "b") == "qux"); - } - - { - const toml::basic_value v{ - {"a", 42}, {"b", "baz"} - }; - - const auto baz = toml::get(v); - BOOST_TEST(baz.a == 42); - BOOST_TEST(baz.b == "baz"); - } - { - const extlib::qux q{42, "qux"}; - const toml::basic_value v(q); - - BOOST_TEST(toml::find(v, "a") == 42); - BOOST_TEST(toml::find(v, "b") == "qux"); - } -} - -BOOST_AUTO_TEST_CASE(test_conversion_via_constructor) -{ - { - const toml::value v{{"a", 42}, {"b", "foobar"}}; - - const auto foobar = toml::get(v); - BOOST_TEST(foobar.a == 42); - BOOST_TEST(foobar.b == "foobar"); - } - - { - const toml::basic_value v{ - {"a", 42}, {"b", "foobar"} - }; - - const auto foobar = toml::get(v); - BOOST_TEST(foobar.a == 42); - BOOST_TEST(foobar.b == "foobar"); - } -} - -BOOST_AUTO_TEST_CASE(test_recursive_conversion) -{ - { - const toml::value v{ - toml::table{{"a", 42}, {"b", "baz"}}, - toml::table{{"a", 43}, {"b", "qux"}}, - toml::table{{"a", 44}, {"b", "quux"}}, - toml::table{{"a", 45}, {"b", "foobar"}}, - }; - - const auto foos = toml::get>(v); - BOOST_TEST(foos.size() == 4ul); - BOOST_TEST(foos.at(0).a == 42); - BOOST_TEST(foos.at(1).a == 43); - BOOST_TEST(foos.at(2).a == 44); - BOOST_TEST(foos.at(3).a == 45); - - BOOST_TEST(foos.at(0).b == "baz"); - BOOST_TEST(foos.at(1).b == "qux"); - BOOST_TEST(foos.at(2).b == "quux"); - BOOST_TEST(foos.at(3).b == "foobar"); - - const auto bars = toml::get>(v); - BOOST_TEST(bars.size() == 4ul); - BOOST_TEST(bars.at(0).a == 42); - BOOST_TEST(bars.at(1).a == 43); - BOOST_TEST(bars.at(2).a == 44); - BOOST_TEST(bars.at(3).a == 45); - - BOOST_TEST(bars.at(0).b == "baz"); - BOOST_TEST(bars.at(1).b == "qux"); - BOOST_TEST(bars.at(2).b == "quux"); - BOOST_TEST(bars.at(3).b == "foobar"); - } - { - const toml::value v{ - toml::table{{"a", 42}, {"b", "baz"}}, - toml::table{{"a", 43}, {"b", "qux"}}, - toml::table{{"a", 44}, {"b", "quux"}}, - toml::table{{"a", 45}, {"b", "foobar"}}, - }; - - const auto foos = toml::get>(v); - BOOST_TEST(foos.size() == 4ul); - BOOST_TEST(foos.at(0).a == 42); - BOOST_TEST(foos.at(1).a == 43); - BOOST_TEST(foos.at(2).a == 44); - BOOST_TEST(foos.at(3).a == 45); - - BOOST_TEST(foos.at(0).b == "baz"); - BOOST_TEST(foos.at(1).b == "qux"); - BOOST_TEST(foos.at(2).b == "quux"); - BOOST_TEST(foos.at(3).b == "foobar"); - - const auto bars = toml::get>(v); - BOOST_TEST(bars.size() == 4ul); - BOOST_TEST(bars.at(0).a == 42); - BOOST_TEST(bars.at(1).a == 43); - BOOST_TEST(bars.at(2).a == 44); - BOOST_TEST(bars.at(3).a == 45); - - BOOST_TEST(bars.at(0).b == "baz"); - BOOST_TEST(bars.at(1).b == "qux"); - BOOST_TEST(bars.at(2).b == "quux"); - BOOST_TEST(bars.at(3).b == "foobar"); - } - - { - const toml::basic_value - v{ - toml::table{{"a", 42}, {"b", "baz"}}, - toml::table{{"a", 43}, {"b", "qux"}}, - toml::table{{"a", 44}, {"b", "quux"}}, - toml::table{{"a", 45}, {"b", "foobar"}} - }; - - const auto foos = toml::get>(v); - BOOST_TEST(foos.size() == 4ul); - BOOST_TEST(foos.at(0).a == 42); - BOOST_TEST(foos.at(1).a == 43); - BOOST_TEST(foos.at(2).a == 44); - BOOST_TEST(foos.at(3).a == 45); - - BOOST_TEST(foos.at(0).b == "baz"); - BOOST_TEST(foos.at(1).b == "qux"); - BOOST_TEST(foos.at(2).b == "quux"); - BOOST_TEST(foos.at(3).b == "foobar"); - - const auto bars = toml::get>(v); - BOOST_TEST(bars.size() == 4ul); - BOOST_TEST(bars.at(0).a == 42); - BOOST_TEST(bars.at(1).a == 43); - BOOST_TEST(bars.at(2).a == 44); - BOOST_TEST(bars.at(3).a == 45); - - BOOST_TEST(bars.at(0).b == "baz"); - BOOST_TEST(bars.at(1).b == "qux"); - BOOST_TEST(bars.at(2).b == "quux"); - BOOST_TEST(bars.at(3).b == "foobar"); - } - - // via constructor - { - const toml::value v{ - toml::table{{"a", 42}, {"b", "baz"}}, - toml::table{{"a", 43}, {"b", "qux"}}, - toml::table{{"a", 44}, {"b", "quux"}}, - toml::table{{"a", 45}, {"b", "foobar"}} - }; - - { - const auto foobars = toml::get>(v); - BOOST_TEST(foobars.size() == 4ul); - BOOST_TEST(foobars.at(0).a == 42); - BOOST_TEST(foobars.at(1).a == 43); - BOOST_TEST(foobars.at(2).a == 44); - BOOST_TEST(foobars.at(3).a == 45); - - BOOST_TEST(foobars.at(0).b == "baz"); - BOOST_TEST(foobars.at(1).b == "qux"); - BOOST_TEST(foobars.at(2).b == "quux"); - BOOST_TEST(foobars.at(3).b == "foobar"); - } - { - const auto foobars = toml::get>(v); - BOOST_TEST(foobars.size() == 4ul); - BOOST_TEST(foobars.at(0).a == 42); - BOOST_TEST(foobars.at(1).a == 43); - BOOST_TEST(foobars.at(2).a == 44); - BOOST_TEST(foobars.at(3).a == 45); - - BOOST_TEST(foobars.at(0).b == "baz"); - BOOST_TEST(foobars.at(1).b == "qux"); - BOOST_TEST(foobars.at(2).b == "quux"); - BOOST_TEST(foobars.at(3).b == "foobar"); - } - } - { - const toml::basic_value - v{ - toml::table{{"a", 42}, {"b", "baz"}}, - toml::table{{"a", 43}, {"b", "qux"}}, - toml::table{{"a", 44}, {"b", "quux"}}, - toml::table{{"a", 45}, {"b", "foobar"}} - }; - - const auto foobars = toml::get>(v); - BOOST_TEST(foobars.size() == 4ul); - BOOST_TEST(foobars.at(0).a == 42); - BOOST_TEST(foobars.at(1).a == 43); - BOOST_TEST(foobars.at(2).a == 44); - BOOST_TEST(foobars.at(3).a == 45); - - BOOST_TEST(foobars.at(0).b == "baz"); - BOOST_TEST(foobars.at(1).b == "qux"); - BOOST_TEST(foobars.at(2).b == "quux"); - BOOST_TEST(foobars.at(3).b == "foobar"); - } - - // via constructor - { - const toml::value v{ - {"0", toml::table{{"a", 42}, {"b", "baz"}}}, - {"1", toml::table{{"a", 43}, {"b", "qux"}}}, - {"2", toml::table{{"a", 44}, {"b", "quux"}}}, - {"3", toml::table{{"a", 45}, {"b", "foobar"}}} - }; - - { - const auto foobars = toml::get>(v); - BOOST_TEST(foobars.size() == 4ul); - BOOST_TEST(foobars.at("0").a == 42); - BOOST_TEST(foobars.at("1").a == 43); - BOOST_TEST(foobars.at("2").a == 44); - BOOST_TEST(foobars.at("3").a == 45); - - BOOST_TEST(foobars.at("0").b == "baz"); - BOOST_TEST(foobars.at("1").b == "qux"); - BOOST_TEST(foobars.at("2").b == "quux"); - BOOST_TEST(foobars.at("3").b == "foobar"); - } - { - const auto foobars = toml::get>(v); - BOOST_TEST(foobars.size() == 4ul); - BOOST_TEST(foobars.at("0").a == 42); - BOOST_TEST(foobars.at("1").a == 43); - BOOST_TEST(foobars.at("2").a == 44); - BOOST_TEST(foobars.at("3").a == 45); - - BOOST_TEST(foobars.at("0").b == "baz"); - BOOST_TEST(foobars.at("1").b == "qux"); - BOOST_TEST(foobars.at("2").b == "quux"); - BOOST_TEST(foobars.at("3").b == "foobar"); - } - } - { - const toml::basic_value - v{ - {"0", toml::table{{"a", 42}, {"b", "baz"}}}, - {"1", toml::table{{"a", 43}, {"b", "qux"}}}, - {"2", toml::table{{"a", 44}, {"b", "quux"}}}, - {"3", toml::table{{"a", 45}, {"b", "foobar"}}} - }; - - const auto foobars = toml::get>(v); - BOOST_TEST(foobars.size() == 4ul); - BOOST_TEST(foobars.at("0").a == 42); - BOOST_TEST(foobars.at("1").a == 43); - BOOST_TEST(foobars.at("2").a == 44); - BOOST_TEST(foobars.at("3").a == 45); - - BOOST_TEST(foobars.at("0").b == "baz"); - BOOST_TEST(foobars.at("1").b == "qux"); - BOOST_TEST(foobars.at("2").b == "quux"); - BOOST_TEST(foobars.at("3").b == "foobar"); - } - -} - -// =========================================================================== - -#ifndef TOML11_WITHOUT_DEFINE_NON_INTRUSIVE - -namespace extlib3 -{ -struct foo -{ - int a; - std::string b; -}; -struct bar -{ - int a; - std::string b; - foo f; -}; - -} // extlib3 - -TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(extlib3::foo, a, b) -TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(extlib3::bar, a, b, f) - -BOOST_AUTO_TEST_CASE(test_conversion_via_macro) -{ - { - const toml::value v{{"a", 42}, {"b", "baz"}}; - - const auto foo = toml::get(v); - BOOST_TEST(foo.a == 42); - BOOST_TEST(foo.b == "baz"); - - const toml::value v2(foo); - BOOST_TEST(v2 == v); - } - { - const toml::basic_value v{ - {"a", 42}, {"b", "baz"} - }; - - const auto foo = toml::get(v); - BOOST_TEST(foo.a == 42); - BOOST_TEST(foo.b == "baz"); - - const toml::basic_value v2(foo); - BOOST_TEST(v2 == v); - } - - // ----------------------------------------------------------------------- - - { - const toml::value v{ - {"a", 42}, - {"b", "bar.b"}, - {"f", toml::table{{"a", 42}, {"b", "foo.b"}}} - }; - - const auto bar = toml::get(v); - BOOST_TEST(bar.a == 42); - BOOST_TEST(bar.b == "bar.b"); - BOOST_TEST(bar.f.a == 42); - BOOST_TEST(bar.f.b == "foo.b"); - - const toml::value v2(bar); - BOOST_TEST(v2 == v); - } - { - const toml::basic_value v{ - {"a", 42}, - {"b", "bar.b"}, - {"f", toml::table{{"a", 42}, {"b", "foo.b"}}} - }; - - const auto bar = toml::get(v); - BOOST_TEST(bar.a == 42); - BOOST_TEST(bar.b == "bar.b"); - BOOST_TEST(bar.f.a == 42); - BOOST_TEST(bar.f.b == "foo.b"); - - const toml::basic_value v2(bar); - BOOST_TEST(v2 == v); - } -} -#endif // TOML11_WITHOUT_DEFINE_NON_INTRUSIVE diff --git a/lib/toml/tests/test_find.cpp b/lib/toml/tests/test_find.cpp deleted file mode 100644 index aa44b7b..0000000 --- a/lib/toml/tests/test_find.cpp +++ /dev/null @@ -1,833 +0,0 @@ -#define BOOST_TEST_MODULE "test_find" - -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif - -#include -#include -#include -#include -#include -#include -#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L -#include -#endif -#include - -using test_value_types = std::tuple< - toml::basic_value, - toml::basic_value, - toml::basic_value, - toml::basic_value - >; - -BOOST_AUTO_TEST_CASE(test_find_throws) -{ - // ----------------------------------------------------------------------- - // const-reference version - { - // value is not a table - const toml::value v(true); - BOOST_CHECK_THROW(toml::find(v, "key"), toml::type_error); - } - { - // the value corresponding to the key is not the expected type - const toml::value v{{"key", 42}}; - BOOST_CHECK_THROW(toml::find(v, "key"), toml::type_error); - } - { - // the value corresponding to the key is not found - const toml::value v{{"key", 42}}; - BOOST_CHECK_THROW(toml::find(v, "different_key"), - std::out_of_range); - } - { - // the positive control. - const toml::value v{{"key", 42}}; - BOOST_TEST(42 == toml::find(v, "key")); - } - - // ----------------------------------------------------------------------- - // reference version - { - // value is not a table - toml::value v(true); - BOOST_CHECK_THROW(toml::find(v, "key"), toml::type_error); - } - { - // the value corresponding to the key is not the expected type - toml::value v{{"key", 42}}; - BOOST_CHECK_THROW(toml::find(v, "key"), toml::type_error); - } - { - // the value corresponding to the key is not found - toml::value v{{"key", 42}}; - BOOST_CHECK_THROW(toml::find(v, "different_key"), - std::out_of_range); - } - { - // the positive control. - toml::value v{{"key", 42}}; - BOOST_TEST(42 == toml::find(v, "key")); - } - - // ----------------------------------------------------------------------- - // move version - - { - // value is not a table - toml::value v(true); - BOOST_CHECK_THROW(toml::find(std::move(v), "key"), toml::type_error); - } - { - // the value corresponding to the key is not the expected type - toml::value v{{"key", 42}}; - BOOST_CHECK_THROW(toml::find(std::move(v), "key"), toml::type_error); - } - { - // the value corresponding to the key is not found - toml::value v{{"key", 42}}; - BOOST_CHECK_THROW(toml::find(std::move(v), "different_key"), - std::out_of_range); - } - { - // the positive control. - toml::value v{{"key", 42}}; - BOOST_TEST(42 == toml::find(std::move(v), "key")); - } -} - -BOOST_AUTO_TEST_CASE(test_find_array_throws) -{ - // ----------------------------------------------------------------------- - // const-reference version - { - // value is not an array - const toml::value v(true); - BOOST_CHECK_THROW(toml::find(v, 0), toml::type_error); - } - { - // the value corresponding to the key is not the expected type - const toml::value v{1, 2, 3, 4, 5}; - BOOST_CHECK_THROW(toml::find(v, 0), toml::type_error); - } - { - // the value corresponding to the key is not found - const toml::value v{1, 2, 3, 4, 5}; - BOOST_CHECK_THROW(toml::find(v, 6), std::out_of_range); - } - { - // the positive control. - const toml::value v{1, 2, 3, 4, 5}; - BOOST_TEST(3 == toml::find(v, 2)); - } - - // ----------------------------------------------------------------------- - // non-const reference version - { - // value is not an array - toml::value v(true); - BOOST_CHECK_THROW(toml::find(v, 0), toml::type_error); - } - { - // the value corresponding to the key is not the expected type - toml::value v{1, 2, 3, 4, 5}; - BOOST_CHECK_THROW(toml::find(v, 0), toml::type_error); - } - { - // the value corresponding to the key is not found - toml::value v{1, 2, 3, 4, 5}; - BOOST_CHECK_THROW(toml::find(v, 6), std::out_of_range); - } - { - // the positive control. - toml::value v{1, 2, 3, 4, 5}; - BOOST_TEST(3 == toml::find(v, 2)); - } - - // ----------------------------------------------------------------------- - // move version - { - // value is not an array - toml::value v(true); - BOOST_CHECK_THROW(toml::find(std::move(v), 0), toml::type_error); - } - { - // the value corresponding to the key is not the expected type - toml::value v{1, 2, 3, 4, 5}; - BOOST_CHECK_THROW(toml::find(std::move(v), 0), toml::type_error); - } - { - // the value corresponding to the key is not found - toml::value v{1, 2, 3, 4, 5}; - BOOST_CHECK_THROW(toml::find(std::move(v), 6), std::out_of_range); - } - { - // the positive control. - toml::value v{1, 2, 3, 4, 5}; - BOOST_TEST(3 == toml::find(std::move(v), 2)); - } -} - -BOOST_AUTO_TEST_CASE(test_find_recursive) -{ - // recursively search tables - { - toml::value v{ - {"a", { - {"b", { - {"c", { - {"d", 42} - }} - }} - }} - }; - BOOST_TEST(42 == toml::find(v, "a", "b", "c", "d")); - - // reference that can be used to modify the content - auto& num = toml::find(v, "a", "b", "c", "d"); - num = 54; - BOOST_TEST(54 == toml::find(v, "a", "b", "c", "d")); - - const std::string a("a"), b("b"), c("c"), d("d"); - auto& num2 = toml::find(v, a, b, c, d); - num2 = 42; - BOOST_TEST(42 == toml::find(v, a, b, c, d)); - - auto num3 = toml::find(v, a, "b", c, "d"); - BOOST_TEST(42 == num3); - - auto num4 = toml::find(std::move(v), a, b, c, d); - BOOST_TEST(42 == num4); - } - // recursively search arrays - { - toml::value v{ - toml::array{"array", "of", "string"}, - toml::array{toml::array{1, 2, 3}, toml::array{3.14, 2.71}} - }; - BOOST_TEST("array" == toml::find(v, 0, 0)); - BOOST_TEST("of" == toml::find(v, 0, 1)); - BOOST_TEST("string" == toml::find(v, 0, 2)); - - BOOST_TEST(1 == toml::find(v, 1, 0, 0)); - BOOST_TEST(2 == toml::find(v, 1, 0, 1)); - BOOST_TEST(3 == toml::find(v, 1, 0, 2)); - - BOOST_TEST(3.14 == toml::find(v, 1, 1, 0)); - BOOST_TEST(2.71 == toml::find(v, 1, 1, 1)); - - // reference that can be used to modify the content - auto& num = toml::find(v, 1, 0, 2); - num = 42; - BOOST_TEST( 1 == toml::find(v, 1, 0, 0)); - BOOST_TEST( 2 == toml::find(v, 1, 0, 1)); - BOOST_TEST(42 == toml::find(v, 1, 0, 2)); - - // move value - auto num2 = toml::find(std::move(v), 1, 0, 2); - BOOST_TEST(42 == num2); - } - // recursively search mixtures - { - toml::value v = toml::table{{"array", toml::array{ - toml::array{1, 2, 3}, - toml::array{ - toml::table{{"foo", "bar"}, {"baz", "qux"}}, - toml::table{{"pi", 3.14}, {"e", 2.71}} - }} - }}; - - BOOST_TEST(1 == toml::find(v, "array", 0, 0)); - BOOST_TEST(2 == toml::find(v, "array", 0, 1)); - BOOST_TEST(3 == toml::find(v, "array", 0, 2)); - - BOOST_TEST("bar" == toml::find(v, "array", 1, 0, "foo")); - BOOST_TEST("qux" == toml::find(v, "array", 1, 0, "baz")); - - BOOST_TEST(3.14 == toml::find(v, "array", 1, 1, "pi")); - BOOST_TEST(2.71 == toml::find(v, "array", 1, 1, "e")); - - const std::string ar("array"); - const auto ar_c = "array"; - - const std::string pi("pi"); - const auto pi_c = "pi"; - - BOOST_TEST(3.14 == toml::find(v, ar, 1, 1, "pi")); - BOOST_TEST(3.14 == toml::find(v, ar, 1, 1, pi)); - BOOST_TEST(3.14 == toml::find(v, ar, 1, 1, pi_c)); - - BOOST_TEST(3.14 == toml::find(v, ar_c, 1, 1, "pi")); - BOOST_TEST(3.14 == toml::find(v, ar_c, 1, 1, pi)); - BOOST_TEST(3.14 == toml::find(v, ar_c, 1, 1, pi_c)); - - BOOST_TEST(3.14 == toml::find(v, "array", 1, 1, pi)); - BOOST_TEST(3.14 == toml::find(v, "array", 1, 1, pi_c)); - } -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types) -{ - { - value_type v{{"key", true}}; - BOOST_TEST(true == toml::find(v, "key")); - - toml::find(v, "key") = false; - BOOST_TEST(false == toml::find(v, "key")); - - const auto moved = toml::find(std::move(v), "key"); - BOOST_TEST(false == moved); - } - { - value_type v{{"key", 42}}; - BOOST_TEST(toml::integer(42) == toml::find(v, "key")); - - toml::find(v, "key") = 54; - BOOST_TEST(toml::integer(54) == toml::find(v, "key")); - - const auto moved = toml::find(std::move(v), "key"); - BOOST_TEST(toml::integer(54) == moved); - } - { - value_type v{{"key", 3.14}}; - BOOST_TEST(toml::floating(3.14) == toml::find(v, "key")); - - toml::find(v, "key") = 2.71; - BOOST_TEST(toml::floating(2.71) == toml::find(v, "key")); - - const auto moved = toml::find(std::move(v), "key"); - BOOST_TEST(toml::floating(2.71) == moved); - } - { - value_type v{{"key", "foo"}}; - BOOST_TEST(toml::string("foo", toml::string_t::basic) == - toml::find(v, "key")); - - toml::find(v, "key").str += "bar"; - BOOST_TEST(toml::string("foobar", toml::string_t::basic) == - toml::find(v, "key")); - - const auto moved = toml::find(std::move(v), "key"); - BOOST_TEST(toml::string("foobar", toml::string_t::basic) == moved); - } - { - value_type v{{"key", value_type("foo", toml::string_t::literal)}}; - BOOST_TEST(toml::string("foo", toml::string_t::literal) == - toml::find(v, "key")); - - toml::find(v, "key").str += "bar"; - BOOST_TEST(toml::string("foobar", toml::string_t::literal) == - toml::find(v, "key")); - - const auto moved = toml::find(std::move(v), "key"); - BOOST_TEST(toml::string("foobar", toml::string_t::literal) == moved); - } - { - toml::local_date d(2018, toml::month_t::Apr, 22); - value_type v{{"key", d}}; - BOOST_CHECK(d == toml::find(v, "key")); - - toml::find(v, "key").year = 2017; - d.year = 2017; - BOOST_CHECK(d == toml::find(v, "key")); - - const auto moved = toml::find(std::move(v), "key"); - BOOST_CHECK(d == moved); - } - { - toml::local_time t(12, 30, 45); - value_type v{{"key", t}}; - BOOST_CHECK(t == toml::find(v, "key")); - - toml::find(v, "key").hour = 9; - t.hour = 9; - BOOST_CHECK(t == toml::find(v, "key")); - - const auto moved = toml::find(std::move(v), "key"); - BOOST_CHECK(t == moved); - } - { - toml::local_datetime dt(toml::local_date(2018, toml::month_t::Apr, 22), - toml::local_time(12, 30, 45)); - value_type v{{"key", dt}}; - BOOST_CHECK(dt == toml::find(v, "key")); - - toml::find(v, "key").date.year = 2017; - dt.date.year = 2017; - BOOST_CHECK(dt == toml::find(v, "key")); - - const auto moved = toml::find(std::move(v), "key"); - BOOST_CHECK(dt == moved); - } - { - toml::offset_datetime dt(toml::local_datetime( - toml::local_date(2018, toml::month_t::Apr, 22), - toml::local_time(12, 30, 45)), toml::time_offset(9, 0)); - value_type v{{"key", dt}}; - BOOST_CHECK(dt == toml::find(v, "key")); - - toml::find(v, "key").date.year = 2017; - dt.date.year = 2017; - BOOST_CHECK(dt == toml::find(v, "key")); - - const auto moved = toml::find(std::move(v), "key"); - BOOST_CHECK(dt == moved); - } - { - typename value_type::array_type vec; - vec.push_back(value_type(42)); - vec.push_back(value_type(54)); - value_type v{{"key", vec}}; - - const bool result1 = (vec == toml::find(v, "key")); - BOOST_CHECK(result1); - - toml::find(v, "key").push_back(value_type(123)); - vec.push_back(value_type(123)); - - const bool result2 = (vec == toml::find(v, "key")); - BOOST_CHECK(result2); - - const auto moved = toml::find(std::move(v), "key"); - const bool result3 = (vec == moved); - BOOST_CHECK(result3); - } - { - typename value_type::table_type tab; - tab["key1"] = value_type(42); - tab["key2"] = value_type(3.14); - value_type v{{"key", tab}}; - const bool result1 = (tab == toml::find(v, "key")); - BOOST_CHECK(result1); - - toml::find(v, "key")["key3"] = value_type(123); - tab["key3"] = value_type(123); - const bool result2 = (tab == toml::find(v, "key")); - BOOST_CHECK(result2); - - const auto moved = toml::find(std::move(v), "key"); - const bool result3 = (tab == moved); - BOOST_CHECK(result3); - } - { - value_type v1(42); - value_type v{{"key", v1}}; - BOOST_CHECK(v1 == toml::find(v, "key")); - - value_type v2(54); - toml::find(v, "key") = v2; - BOOST_CHECK(v2 == toml::find(v, "key")); - - const auto moved = toml::find(std::move(v), "key"); - BOOST_CHECK(v2 == moved); - } -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_integer_type, value_type, test_value_types) -{ - { - value_type v{{"key", 42}}; - BOOST_TEST(int(42) == toml::find(v, "key")); - BOOST_TEST(short(42) == toml::find(v, "key")); - BOOST_TEST(char(42) == toml::find(v, "key")); - BOOST_TEST(unsigned(42) == toml::find(v, "key")); - BOOST_TEST(long(42) == toml::find(v, "key")); - BOOST_TEST(std::int64_t(42) == toml::find(v, "key")); - BOOST_TEST(std::uint64_t(42) == toml::find(v, "key")); - BOOST_TEST(std::int16_t(42) == toml::find(v, "key")); - BOOST_TEST(std::uint16_t(42) == toml::find(v, "key")); - BOOST_TEST(std::uint16_t(42) == toml::find(std::move(v), "key")); - } -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_floating_type, value_type, test_value_types) -{ - { - value_type v{{"key", 3.14}}; - const double ref(3.14); - BOOST_TEST(static_cast(ref) == toml::find(v, "key")); - BOOST_TEST( ref == toml::find(v, "key")); - BOOST_TEST(static_cast(ref) == toml::find(v, "key")); - BOOST_TEST(static_cast(ref) == toml::find(std::move(v), "key")); - } -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_string_type, value_type, test_value_types) -{ - { - value_type v{{"key", toml::string("foo", toml::string_t::basic)}}; - BOOST_TEST("foo" == toml::find(v, "key")); - toml::find(v, "key") += "bar"; - BOOST_TEST("foobar" == toml::find(v, "key")); - } - { - value_type v{{"key", toml::string("foo", toml::string_t::literal)}}; - BOOST_TEST("foo" == toml::find(v, "key")); - toml::find(v, "key") += "bar"; - BOOST_TEST("foobar" == toml::find(v, "key")); - } - { - value_type v{{"key", toml::string("foo", toml::string_t::literal)}}; - const auto moved = toml::find(std::move(v), "key"); - BOOST_TEST("foo" == moved); - } - -#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L - { - value_type v{{"key", toml::string("foo", toml::string_t::basic)}}; - BOOST_TEST("foo" == toml::find(v, "key")); - } - { - value_type v{{"key", toml::string("foo", toml::string_t::literal)}}; - BOOST_TEST("foo" == toml::find(v, "key")); - } -#endif -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_array, value_type, test_value_types) -{ - value_type v{{"key", {42, 54, 69, 72}}}; - - const std::vector vec = toml::find>(v, "key"); - const std::list lst = toml::find>(v, "key"); - const std::deque deq = toml::find>(v, "key"); - - BOOST_TEST(42 == vec.at(0)); - BOOST_TEST(54 == vec.at(1)); - BOOST_TEST(69 == vec.at(2)); - BOOST_TEST(72 == vec.at(3)); - - std::list::const_iterator iter = lst.begin(); - BOOST_TEST(static_cast(42) == *(iter++)); - BOOST_TEST(static_cast(54) == *(iter++)); - BOOST_TEST(static_cast(69) == *(iter++)); - BOOST_TEST(static_cast(72) == *(iter++)); - - BOOST_TEST(static_cast(42) == deq.at(0)); - BOOST_TEST(static_cast(54) == deq.at(1)); - BOOST_TEST(static_cast(69) == deq.at(2)); - BOOST_TEST(static_cast(72) == deq.at(3)); - - std::array ary = toml::find>(v, "key"); - BOOST_TEST(42 == ary.at(0)); - BOOST_TEST(54 == ary.at(1)); - BOOST_TEST(69 == ary.at(2)); - BOOST_TEST(72 == ary.at(3)); - - std::tuple tpl = - toml::find>(v, "key"); - BOOST_TEST( 42 == std::get<0>(tpl)); - BOOST_TEST(static_cast(54) == std::get<1>(tpl)); - BOOST_TEST(static_cast(69) == std::get<2>(tpl)); - BOOST_TEST(static_cast(72) == std::get<3>(tpl)); - - value_type p{{"key", {3.14, 2.71}}}; - std::pair pr = toml::find >(p, "key"); - BOOST_TEST(3.14 == pr.first); - BOOST_TEST(2.71 == pr.second); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_move_toml_array, value_type, test_value_types) -{ - value_type v1{{"key", {42, 54, 69, 72}}}; - value_type v2{{"key", {42, 54, 69, 72}}}; - value_type v3{{"key", {42, 54, 69, 72}}}; - value_type v4{{"key", {42, 54, 69, 72}}}; - value_type v5{{"key", {42, 54, 69, 72}}}; - - const std::vector vec = toml::find>(std::move(v1), "key"); - const std::list lst = toml::find>(std::move(v2), "key"); - const std::deque deq = toml::find>(std::move(v3), "key"); - - BOOST_TEST(42 == vec.at(0)); - BOOST_TEST(54 == vec.at(1)); - BOOST_TEST(69 == vec.at(2)); - BOOST_TEST(72 == vec.at(3)); - - std::list::const_iterator iter = lst.begin(); - BOOST_TEST(static_cast(42) == *(iter++)); - BOOST_TEST(static_cast(54) == *(iter++)); - BOOST_TEST(static_cast(69) == *(iter++)); - BOOST_TEST(static_cast(72) == *(iter++)); - - BOOST_TEST(static_cast(42) == deq.at(0)); - BOOST_TEST(static_cast(54) == deq.at(1)); - BOOST_TEST(static_cast(69) == deq.at(2)); - BOOST_TEST(static_cast(72) == deq.at(3)); - - std::array ary = toml::find>(std::move(v4), "key"); - BOOST_TEST(42 == ary.at(0)); - BOOST_TEST(54 == ary.at(1)); - BOOST_TEST(69 == ary.at(2)); - BOOST_TEST(72 == ary.at(3)); - - std::tuple tpl = - toml::find>(std::move(v5), "key"); - BOOST_TEST( 42 == std::get<0>(tpl)); - BOOST_TEST(static_cast(54) == std::get<1>(tpl)); - BOOST_TEST(static_cast(69) == std::get<2>(tpl)); - BOOST_TEST(static_cast(72) == std::get<3>(tpl)); - - value_type p{{"key", {3.14, 2.71}}}; - std::pair pr = toml::find >(std::move(p), "key"); - BOOST_TEST(3.14 == pr.first); - BOOST_TEST(2.71 == pr.second); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_array_of_array, value_type, test_value_types) -{ - value_type v1{42, 54, 69, 72}; - value_type v2{"foo", "bar", "baz"}; - value_type v{{"key", {v1, v2}}}; - - std::pair, std::vector> p = - toml::find, std::vector>>(v, "key"); - - BOOST_TEST(p.first.at(0) == 42); - BOOST_TEST(p.first.at(1) == 54); - BOOST_TEST(p.first.at(2) == 69); - BOOST_TEST(p.first.at(3) == 72); - - BOOST_TEST(p.second.at(0) == "foo"); - BOOST_TEST(p.second.at(1) == "bar"); - BOOST_TEST(p.second.at(2) == "baz"); - - std::tuple, std::vector> t = - toml::find, std::vector>>(v, "key"); - - BOOST_TEST(std::get<0>(t).at(0) == 42); - BOOST_TEST(std::get<0>(t).at(1) == 54); - BOOST_TEST(std::get<0>(t).at(2) == 69); - BOOST_TEST(std::get<0>(t).at(3) == 72); - - BOOST_TEST(std::get<1>(t).at(0) == "foo"); - BOOST_TEST(std::get<1>(t).at(1) == "bar"); - BOOST_TEST(std::get<1>(t).at(2) == "baz"); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_move_toml_array_of_array, value_type, test_value_types) -{ - value_type a1{42, 54, 69, 72}; - value_type a2{"foo", "bar", "baz"}; - value_type v1{{"key", {a1, a2}}}; - value_type v2{{"key", {a1, a2}}}; - - std::pair, std::vector> p = - toml::find, std::vector>>(std::move(v1), "key"); - - BOOST_TEST(p.first.at(0) == 42); - BOOST_TEST(p.first.at(1) == 54); - BOOST_TEST(p.first.at(2) == 69); - BOOST_TEST(p.first.at(3) == 72); - - BOOST_TEST(p.second.at(0) == "foo"); - BOOST_TEST(p.second.at(1) == "bar"); - BOOST_TEST(p.second.at(2) == "baz"); - - std::tuple, std::vector> t = - toml::find, std::vector>>(std::move(v2), "key"); - - BOOST_TEST(std::get<0>(t).at(0) == 42); - BOOST_TEST(std::get<0>(t).at(1) == 54); - BOOST_TEST(std::get<0>(t).at(2) == 69); - BOOST_TEST(std::get<0>(t).at(3) == 72); - - BOOST_TEST(std::get<1>(t).at(0) == "foo"); - BOOST_TEST(std::get<1>(t).at(1) == "bar"); - BOOST_TEST(std::get<1>(t).at(2) == "baz"); -} - - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_table, value_type, test_value_types) -{ - { - value_type v1{{"key", { - {"key1", 1}, {"key2", 2}, {"key3", 3}, {"key4", 4} - }}}; - const auto v = toml::find>(v1, "key"); - BOOST_TEST(v.at("key1") == 1); - BOOST_TEST(v.at("key2") == 2); - BOOST_TEST(v.at("key3") == 3); - BOOST_TEST(v.at("key4") == 4); - } - { - value_type v1{{"key", { - {"key1", 1}, {"key2", 2}, {"key3", 3}, {"key4", 4} - }}}; - const auto v = toml::find>(std::move(v1), "key"); - BOOST_TEST(v.at("key1") == 1); - BOOST_TEST(v.at("key2") == 2); - BOOST_TEST(v.at("key3") == 3); - BOOST_TEST(v.at("key4") == 4); - } -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_date, value_type, test_value_types) -{ - { - value_type v1{{"key", toml::local_date{2018, toml::month_t::Apr, 1}}}; - const auto date = std::chrono::system_clock::to_time_t( - toml::find(v1, "key")); - - std::tm t; - t.tm_year = 2018 - 1900; - t.tm_mon = 4 - 1; - t.tm_mday = 1; - t.tm_hour = 0; - t.tm_min = 0; - t.tm_sec = 0; - t.tm_isdst = -1; - const auto c = std::mktime(&t); - BOOST_TEST(c == date); - } - { - value_type v1{{"key", toml::local_date{2018, toml::month_t::Apr, 1}}}; - const auto date = std::chrono::system_clock::to_time_t( - toml::find(std::move(v1), "key")); - - std::tm t; - t.tm_year = 2018 - 1900; - t.tm_mon = 4 - 1; - t.tm_mday = 1; - t.tm_hour = 0; - t.tm_min = 0; - t.tm_sec = 0; - t.tm_isdst = -1; - const auto c = std::mktime(&t); - BOOST_TEST(c == date); - } -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_time, value_type, test_value_types) -{ - { - value_type v1{{"key", toml::local_time{12, 30, 45}}}; - const auto time = toml::find(v1, "key"); - BOOST_CHECK(time == std::chrono::hours(12) + - std::chrono::minutes(30) + std::chrono::seconds(45)); - } - { - value_type v1{{"key", toml::local_time{12, 30, 45}}}; - const auto time = toml::find(std::move(v1), "key"); - BOOST_CHECK(time == std::chrono::hours(12) + - std::chrono::minutes(30) + std::chrono::seconds(45)); - } -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_datetime, value_type, test_value_types) -{ - { - value_type v1{{"key", toml::local_datetime( - toml::local_date{2018, toml::month_t::Apr, 1}, - toml::local_time{12, 30, 45})}}; - - const auto date = std::chrono::system_clock::to_time_t( - toml::find(v1, "key")); - std::tm t; - t.tm_year = 2018 - 1900; - t.tm_mon = 4 - 1; - t.tm_mday = 1; - t.tm_hour = 12; - t.tm_min = 30; - t.tm_sec = 45; - t.tm_isdst = -1; - const auto c = std::mktime(&t); - BOOST_TEST(c == date); - } - { - value_type v1{{"key", toml::local_datetime( - toml::local_date{2018, toml::month_t::Apr, 1}, - toml::local_time{12, 30, 45})}}; - - const auto date = std::chrono::system_clock::to_time_t( - toml::find(std::move(v1), "key")); - std::tm t; - t.tm_year = 2018 - 1900; - t.tm_mon = 4 - 1; - t.tm_mday = 1; - t.tm_hour = 12; - t.tm_min = 30; - t.tm_sec = 45; - t.tm_isdst = -1; - const auto c = std::mktime(&t); - BOOST_TEST(c == date); - } -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_offset_datetime, value_type, test_value_types) -{ - { - value_type v1{{"key", toml::offset_datetime( - toml::local_date{2018, toml::month_t::Apr, 1}, - toml::local_time{12, 30, 0}, - toml::time_offset{9, 0})}}; - // 2018-04-01T12:30:00+09:00 - // == 2018-04-01T03:30:00Z - - const auto date = toml::find(v1, "key"); - const auto timet = std::chrono::system_clock::to_time_t(date); - - // get time_t as gmtime (2018-04-01T03:30:00Z) - const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe! - BOOST_CHECK(tmp); - const auto tm = *tmp; - BOOST_TEST(tm.tm_year + 1900 == 2018); - BOOST_TEST(tm.tm_mon + 1 == 4); - BOOST_TEST(tm.tm_mday == 1); - BOOST_TEST(tm.tm_hour == 3); - BOOST_TEST(tm.tm_min == 30); - BOOST_TEST(tm.tm_sec == 0); - } - - { - value_type v1{{"key", toml::offset_datetime( - toml::local_date{2018, toml::month_t::Apr, 1}, - toml::local_time{12, 30, 0}, - toml::time_offset{-8, 0})}}; - // 2018-04-01T12:30:00-08:00 - // == 2018-04-01T20:30:00Z - - const auto date = toml::find(v1, "key"); - const auto timet = std::chrono::system_clock::to_time_t(date); - - // get time_t as gmtime (2018-04-01T03:30:00Z) - const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe! - BOOST_CHECK(tmp); - const auto tm = *tmp; - BOOST_TEST(tm.tm_year + 1900 == 2018); - BOOST_TEST(tm.tm_mon + 1 == 4); - BOOST_TEST(tm.tm_mday == 1); - BOOST_TEST(tm.tm_hour == 20); - BOOST_TEST(tm.tm_min == 30); - BOOST_TEST(tm.tm_sec == 0); - } - - { - value_type v1{{"key", toml::offset_datetime( - toml::local_date{2018, toml::month_t::Apr, 1}, - toml::local_time{12, 30, 0}, - toml::time_offset{-8, 0})}}; - // 2018-04-01T12:30:00-08:00 - // == 2018-04-01T20:30:00Z - - const auto date = toml::find(std::move(v1), "key"); - const auto timet = std::chrono::system_clock::to_time_t(date); - - // get time_t as gmtime (2018-04-01T03:30:00Z) - const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe! - BOOST_CHECK(tmp); - const auto tm = *tmp; - BOOST_TEST(tm.tm_year + 1900 == 2018); - BOOST_TEST(tm.tm_mon + 1 == 4); - BOOST_TEST(tm.tm_mday == 1); - BOOST_TEST(tm.tm_hour == 20); - BOOST_TEST(tm.tm_min == 30); - BOOST_TEST(tm.tm_sec == 0); - } -} - diff --git a/lib/toml/tests/test_find_or.cpp b/lib/toml/tests/test_find_or.cpp deleted file mode 100644 index b0f786d..0000000 --- a/lib/toml/tests/test_find_or.cpp +++ /dev/null @@ -1,541 +0,0 @@ -#define BOOST_TEST_MODULE "test_find_or" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L -#include -#endif - -using test_value_types = std::tuple< - toml::basic_value, - toml::basic_value, - toml::basic_value, - toml::basic_value ->; - -namespace test -{ -template -std::basic_ostream& -operator<<(std::basic_ostream& os, const std::vector& v) -{ - os << "[ "; - for(const auto& i : v) {os << i << ' ';} - os << ']'; - return os; -} -template -std::basic_ostream& -operator<<(std::basic_ostream& os, const std::deque& v) -{ - os << "[ "; - for(const auto& i : v) {os << i << ' ';} - os << ']'; - return os; -} -template -std::basic_ostream& -operator<<(std::basic_ostream& os, const std::list& v) -{ - os << "[ "; - for(const auto& i : v) {os << i << ' ';} - os << ']'; - return os; -} -template -std::basic_ostream& -operator<<(std::basic_ostream& os, - const std::map& v) -{ - os << "[ "; - for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";} - os << ']'; - return os; -} -template -std::basic_ostream& -operator<<(std::basic_ostream& os, - const std::unordered_map& v) -{ - os << "[ "; - for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";} - os << ']'; - return os; -} -} // test - -#define TOML11_TEST_FIND_OR_EXACT(toml_type, init_expr, opt_expr)\ - { \ - using namespace test; \ - const toml::toml_type init init_expr ; \ - const toml::toml_type opt opt_expr ; \ - const value_type v{{"key", init}}; \ - BOOST_TEST(init != opt); \ - BOOST_TEST(init == toml::find_or(v, "key", opt)); \ - } \ - /**/ - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_exact, value_type, test_value_types) -{ - TOML11_TEST_FIND_OR_EXACT(boolean, ( true), (false)) - TOML11_TEST_FIND_OR_EXACT(integer, ( 42), ( 54)) - TOML11_TEST_FIND_OR_EXACT(floating, ( 3.14), ( 2.71)) - TOML11_TEST_FIND_OR_EXACT(string, ("foo"), ("bar")) - TOML11_TEST_FIND_OR_EXACT(local_time, (12, 30, 45), (6, 0, 30)) - TOML11_TEST_FIND_OR_EXACT(local_date, (2019, toml::month_t::Apr, 1), - (1999, toml::month_t::Jan, 2)) - TOML11_TEST_FIND_OR_EXACT(local_datetime, - (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)), - (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30)) - ) - TOML11_TEST_FIND_OR_EXACT(offset_datetime, - (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)), - (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0)) - ) - { - const typename value_type::array_type init{1,2,3,4,5}; - const typename value_type::array_type opt {6,7,8,9,10}; - const value_type v{{"key", init}}; - BOOST_TEST(init != opt); - BOOST_TEST(init == toml::find_or(v, "key", opt)); - } - { - const typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}}; - const typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}}; - const value_type v{{"key", init}}; - BOOST_TEST(init != opt); - BOOST_TEST(init == toml::find_or(v, "key", opt)); - } -} -#undef TOML11_TEST_FIND_OR_EXACT - -#define TOML11_TEST_FIND_OR_MOVE(toml_type, init_expr, opt_expr) \ - { \ - using namespace test; \ - const toml::toml_type init init_expr ; \ - toml::toml_type opt opt_expr ; \ - value_type v{{"key", init}}; \ - BOOST_TEST(init != opt); \ - const auto moved = toml::find_or(std::move(v), "key", std::move(opt));\ - BOOST_TEST(init == moved); \ - } \ - /**/ - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_move, value_type, test_value_types) -{ - TOML11_TEST_FIND_OR_MOVE(boolean, ( true), (false)) - TOML11_TEST_FIND_OR_MOVE(integer, ( 42), ( 54)) - TOML11_TEST_FIND_OR_MOVE(floating, ( 3.14), ( 2.71)) - TOML11_TEST_FIND_OR_MOVE(string, ("foo"), ("bar")) - TOML11_TEST_FIND_OR_MOVE(local_time, (12, 30, 45), (6, 0, 30)) - TOML11_TEST_FIND_OR_MOVE(local_date, (2019, toml::month_t::Apr, 1), - (1999, toml::month_t::Jan, 2)) - TOML11_TEST_FIND_OR_MOVE(local_datetime, - (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)), - (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30)) - ) - TOML11_TEST_FIND_OR_MOVE(offset_datetime, - (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)), - (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0)) - ) - { - typename value_type::array_type init{1,2,3,4,5}; - typename value_type::array_type opt {6,7,8,9,10}; - value_type v{{"key", init}}; - BOOST_TEST(init != opt); - const auto moved = toml::find_or(std::move(v), "key", std::move(opt)); - BOOST_TEST(init == moved); - } - { - typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}}; - typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}}; - value_type v{{"key", init}}; - BOOST_TEST(init != opt); - const auto moved = toml::find_or(std::move(v), "key", std::move(opt)); - BOOST_TEST(init == moved); - } -} -#undef TOML11_TEST_FIND_OR_MOVE - - -#define TOML11_TEST_FIND_OR_MODIFY(toml_type, init_expr, opt_expr)\ - { \ - using namespace test; \ - const toml::toml_type init init_expr ; \ - toml::toml_type opt1 opt_expr ; \ - toml::toml_type opt2 opt_expr ; \ - value_type v{{"key", init}}; \ - BOOST_TEST(init != opt1); \ - toml::find_or(v, "key", opt2) = opt1; \ - BOOST_TEST(opt1 == toml::find(v, "key"));\ - } \ - /**/ -BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_modify, value_type, test_value_types) -{ - TOML11_TEST_FIND_OR_MODIFY(boolean, ( true), (false)) - TOML11_TEST_FIND_OR_MODIFY(integer, ( 42), ( 54)) - TOML11_TEST_FIND_OR_MODIFY(floating, ( 3.14), ( 2.71)) - TOML11_TEST_FIND_OR_MODIFY(string, ("foo"), ("bar")) - TOML11_TEST_FIND_OR_MODIFY(local_time, (12, 30, 45), (6, 0, 30)) - TOML11_TEST_FIND_OR_MODIFY(local_date, (2019, toml::month_t::Apr, 1), - (1999, toml::month_t::Jan, 2)) - TOML11_TEST_FIND_OR_MODIFY(local_datetime, - (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)), - (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30)) - ) - TOML11_TEST_FIND_OR_MODIFY(offset_datetime, - (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)), - (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0)) - ) - { - typename value_type::array_type init{1,2,3,4,5}; - typename value_type::array_type opt1{6,7,8,9,10}; - typename value_type::array_type opt2{6,7,8,9,10}; - BOOST_TEST(init != opt1); - value_type v{{"key", init}}; - toml::find_or(v, "key", opt2) = opt1; - BOOST_TEST(opt1 == toml::find(v, "key")); - } - { - typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}}; - typename value_type::table_type opt1{{"key1", 54}, {"key2", "bar"}}; - typename value_type::table_type opt2{{"key1", 54}, {"key2", "bar"}}; - value_type v{{"key", init}}; - BOOST_TEST(init != opt1); - toml::find_or(v, "key", opt2) = opt1; - BOOST_TEST(opt1 == toml::find(v, "key")); - } -} -#undef TOML11_TEST_FIND_OR_MODIFY - -#define TOML11_TEST_FIND_OR_FALLBACK(init_type, opt_type) \ - { \ - using namespace test; \ - value_type v(init_type); \ - BOOST_TEST(opt_type == toml::find_or(v, "key", opt_type));\ - } \ - /**/ - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_fallback, value_type, test_value_types) -{ - const toml::boolean boolean (true); - const toml::integer integer (42); - const toml::floating floating (3.14); - const toml::string string ("foo"); - const toml::local_time local_time (12, 30, 45); - const toml::local_date local_date (2019, toml::month_t::Apr, 1); - const toml::local_datetime local_datetime ( - toml::local_date(2019, toml::month_t::Apr, 1), - toml::local_time(12, 30, 45)); - const toml::offset_datetime offset_datetime( - toml::local_date(2019, toml::month_t::Apr, 1), - toml::local_time(12, 30, 45), toml::time_offset( 9, 0)); - - using array_type = typename value_type::array_type; - using table_type = typename value_type::table_type; - const array_type array{1, 2, 3, 4, 5}; - const table_type table{{"key1", 42}, {"key2", "foo"}}; - - TOML11_TEST_FIND_OR_FALLBACK(boolean, integer ); - TOML11_TEST_FIND_OR_FALLBACK(boolean, floating ); - TOML11_TEST_FIND_OR_FALLBACK(boolean, string ); - TOML11_TEST_FIND_OR_FALLBACK(boolean, local_time ); - TOML11_TEST_FIND_OR_FALLBACK(boolean, local_date ); - TOML11_TEST_FIND_OR_FALLBACK(boolean, local_datetime ); - TOML11_TEST_FIND_OR_FALLBACK(boolean, offset_datetime); - TOML11_TEST_FIND_OR_FALLBACK(boolean, array ); - TOML11_TEST_FIND_OR_FALLBACK(boolean, table ); - - TOML11_TEST_FIND_OR_FALLBACK(integer, boolean ); - TOML11_TEST_FIND_OR_FALLBACK(integer, floating ); - TOML11_TEST_FIND_OR_FALLBACK(integer, string ); - TOML11_TEST_FIND_OR_FALLBACK(integer, local_time ); - TOML11_TEST_FIND_OR_FALLBACK(integer, local_date ); - TOML11_TEST_FIND_OR_FALLBACK(integer, local_datetime ); - TOML11_TEST_FIND_OR_FALLBACK(integer, offset_datetime); - TOML11_TEST_FIND_OR_FALLBACK(integer, array ); - TOML11_TEST_FIND_OR_FALLBACK(integer, table ); - - TOML11_TEST_FIND_OR_FALLBACK(floating, boolean ); - TOML11_TEST_FIND_OR_FALLBACK(floating, integer ); - TOML11_TEST_FIND_OR_FALLBACK(floating, string ); - TOML11_TEST_FIND_OR_FALLBACK(floating, local_time ); - TOML11_TEST_FIND_OR_FALLBACK(floating, local_date ); - TOML11_TEST_FIND_OR_FALLBACK(floating, local_datetime ); - TOML11_TEST_FIND_OR_FALLBACK(floating, offset_datetime); - TOML11_TEST_FIND_OR_FALLBACK(floating, array ); - TOML11_TEST_FIND_OR_FALLBACK(floating, table ); - - TOML11_TEST_FIND_OR_FALLBACK(string, boolean ); - TOML11_TEST_FIND_OR_FALLBACK(string, integer ); - TOML11_TEST_FIND_OR_FALLBACK(string, floating ); - TOML11_TEST_FIND_OR_FALLBACK(string, local_time ); - TOML11_TEST_FIND_OR_FALLBACK(string, local_date ); - TOML11_TEST_FIND_OR_FALLBACK(string, local_datetime ); - TOML11_TEST_FIND_OR_FALLBACK(string, offset_datetime); - TOML11_TEST_FIND_OR_FALLBACK(string, array ); - TOML11_TEST_FIND_OR_FALLBACK(string, table ); - - TOML11_TEST_FIND_OR_FALLBACK(local_time, boolean ); - TOML11_TEST_FIND_OR_FALLBACK(local_time, integer ); - TOML11_TEST_FIND_OR_FALLBACK(local_time, floating ); - TOML11_TEST_FIND_OR_FALLBACK(local_time, string ); - TOML11_TEST_FIND_OR_FALLBACK(local_time, local_date ); - TOML11_TEST_FIND_OR_FALLBACK(local_time, local_datetime ); - TOML11_TEST_FIND_OR_FALLBACK(local_time, offset_datetime); - TOML11_TEST_FIND_OR_FALLBACK(local_time, array ); - TOML11_TEST_FIND_OR_FALLBACK(local_time, table ); - - TOML11_TEST_FIND_OR_FALLBACK(local_date, boolean ); - TOML11_TEST_FIND_OR_FALLBACK(local_date, integer ); - TOML11_TEST_FIND_OR_FALLBACK(local_date, floating ); - TOML11_TEST_FIND_OR_FALLBACK(local_date, string ); - TOML11_TEST_FIND_OR_FALLBACK(local_date, local_time ); - TOML11_TEST_FIND_OR_FALLBACK(local_date, local_datetime ); - TOML11_TEST_FIND_OR_FALLBACK(local_date, offset_datetime); - TOML11_TEST_FIND_OR_FALLBACK(local_date, array ); - TOML11_TEST_FIND_OR_FALLBACK(local_date, table ); - - TOML11_TEST_FIND_OR_FALLBACK(local_datetime, boolean ); - TOML11_TEST_FIND_OR_FALLBACK(local_datetime, integer ); - TOML11_TEST_FIND_OR_FALLBACK(local_datetime, floating ); - TOML11_TEST_FIND_OR_FALLBACK(local_datetime, string ); - TOML11_TEST_FIND_OR_FALLBACK(local_datetime, local_time ); - TOML11_TEST_FIND_OR_FALLBACK(local_datetime, local_date ); - TOML11_TEST_FIND_OR_FALLBACK(local_datetime, offset_datetime); - TOML11_TEST_FIND_OR_FALLBACK(local_datetime, array ); - TOML11_TEST_FIND_OR_FALLBACK(local_datetime, table ); - - TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, boolean ); - TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, integer ); - TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, floating ); - TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, string ); - TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, local_time ); - TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, local_date ); - TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, local_datetime ); - TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, array ); - TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, table ); - - TOML11_TEST_FIND_OR_FALLBACK(array, boolean ); - TOML11_TEST_FIND_OR_FALLBACK(array, integer ); - TOML11_TEST_FIND_OR_FALLBACK(array, floating ); - TOML11_TEST_FIND_OR_FALLBACK(array, string ); - TOML11_TEST_FIND_OR_FALLBACK(array, local_time ); - TOML11_TEST_FIND_OR_FALLBACK(array, local_date ); - TOML11_TEST_FIND_OR_FALLBACK(array, local_datetime ); - TOML11_TEST_FIND_OR_FALLBACK(array, offset_datetime); - TOML11_TEST_FIND_OR_FALLBACK(array, table ); - - TOML11_TEST_FIND_OR_FALLBACK(table, boolean ); - TOML11_TEST_FIND_OR_FALLBACK(table, integer ); - TOML11_TEST_FIND_OR_FALLBACK(table, floating ); - TOML11_TEST_FIND_OR_FALLBACK(table, string ); - TOML11_TEST_FIND_OR_FALLBACK(table, local_time ); - TOML11_TEST_FIND_OR_FALLBACK(table, local_date ); - TOML11_TEST_FIND_OR_FALLBACK(table, local_datetime ); - TOML11_TEST_FIND_OR_FALLBACK(table, offset_datetime); - TOML11_TEST_FIND_OR_FALLBACK(table, array ); -} -#undef TOML11_TEST_FIND_OR_FALLBACK - -BOOST_AUTO_TEST_CASE(test_find_or_integer) -{ - { - toml::value v{{"num", 42}}; - BOOST_TEST(42u == toml::find_or(v, "num", 0u)); - BOOST_TEST(0u == toml::find_or(v, "foo", 0u)); - } - { - toml::value v{{"num", 42}}; - const auto moved = toml::find_or(std::move(v), "num", 0u); - BOOST_TEST(42u == moved); - } - { - toml::value v{{"num", 42}}; - const auto moved = toml::find_or(std::move(v), "foo", 0u); - BOOST_TEST(0u == moved); - } -} - -BOOST_AUTO_TEST_CASE(test_find_or_floating) -{ - { - toml::value v1{{"key", 42}}; - toml::value v2{{"key", 3.14}}; - BOOST_TEST(2.71f == toml::find_or(v1, "key", 2.71f)); - const double ref(3.14); - BOOST_TEST(static_cast(ref) == toml::find_or(v2, "key", 2.71f)); - } - { - toml::value v1{{"key", 42}}; - toml::value v2{{"key", 3.14}}; - const auto moved1 = toml::find_or(std::move(v1), "key", 2.71f); - const auto moved2 = toml::find_or(std::move(v2), "key", 2.71f); - BOOST_TEST(2.71f == moved1); - const double ref(3.14); - BOOST_TEST(static_cast(ref) == moved2); - } -} - -BOOST_AUTO_TEST_CASE(test_find_or_string) -{ - { - toml::value v1 = toml::table{{"key", "foobar"}}; - toml::value v2 = toml::table{{"key", 42}}; - - std::string s1("bazqux"); - const std::string s2("bazqux"); - - BOOST_TEST("foobar" == toml::find_or(v1, "key", s1)); - BOOST_TEST("bazqux" == toml::find_or(v2, "key", s1)); - - std::string& v1r = toml::find_or(v1, "key", s1); - std::string& s1r = toml::find_or(v2, "key", s1); - - BOOST_TEST("foobar" == v1r); - BOOST_TEST("bazqux" == s1r); - - BOOST_TEST("foobar" == toml::find_or(v1, "key", s2)); - BOOST_TEST("bazqux" == toml::find_or(v2, "key", s2)); - - BOOST_TEST("foobar" == toml::find_or(std::move(v1), "key", std::move(s1))); - s1 = "bazqux"; // restoring moved value - BOOST_TEST("bazqux" == toml::find_or(std::move(v2), "key", std::move(s1))); - } - { - toml::value v1 = toml::table{{"key", "foobar"}}; - toml::value v2 = toml::table{{"key", 42}}; - - std::string s1("bazqux"); - - const auto moved1 = toml::find_or(std::move(v1), "key", s1); - const auto moved2 = toml::find_or(std::move(v2), "key", s1); - - BOOST_TEST("foobar" == moved1); - BOOST_TEST("bazqux" == moved2); - } - { - toml::value v1 = toml::table{{"key", "foobar"}}; - toml::value v2 = toml::table{{"key", 42}}; - - std::string s1("bazqux"); - std::string s2("bazqux"); - - const auto moved1 = toml::find_or(std::move(v1), "key", std::move(s1)); - const auto moved2 = toml::find_or(std::move(v2), "key", std::move(s2)); - - BOOST_TEST("foobar" == moved1); - BOOST_TEST("bazqux" == moved2); - } - - // string literal - { - toml::value v1 = toml::table{{"key", "foobar"}}; - toml::value v2 = toml::table{{"key",42}}; - - BOOST_TEST("foobar" == toml::find_or(v1, "key", "bazqux")); - BOOST_TEST("bazqux" == toml::find_or(v2, "key", "bazqux")); - - const char* lit = "bazqux"; - BOOST_TEST("foobar" == toml::find_or(v1, "key", lit)); - BOOST_TEST("bazqux" == toml::find_or(v2, "key", lit)); - } - { - toml::value v1 = toml::table{{"key", "foobar"}}; - toml::value v2 = toml::table{{"key",42}}; - - const auto moved1 = toml::find_or(std::move(v1), "key", "bazqux"); - const auto moved2 = toml::find_or(std::move(v2), "key", "bazqux"); - - BOOST_TEST("foobar" == moved1); - BOOST_TEST("bazqux" == moved2); - } - { - toml::value v1 = toml::table{{"key", "foobar"}}; - toml::value v2 = toml::table{{"key",42}}; - - const char* lit = "bazqux"; - const auto moved1 = toml::find_or(std::move(v1), "key", lit); - const auto moved2 = toml::find_or(std::move(v2), "key", lit); - - BOOST_TEST("foobar" == moved1); - BOOST_TEST("bazqux" == moved2); - } - -} - -BOOST_AUTO_TEST_CASE(test_find_or_map) -{ - using map_type = std::map; - { - const toml::value v1{ - {"key", {{"key", "value"}}} - }; - - const auto key = toml::find_or(v1, "key", map_type{}); - const auto key2 = toml::find_or(v1, "key2", map_type{}); - - BOOST_TEST(!key.empty()); - BOOST_TEST(key2.empty()); - - BOOST_TEST(key.size() == 1u); - BOOST_TEST(key.at("key") == "value"); - } - { - toml::value v1{ - {"key", {{"key", "value"}}} - }; - - const auto key = toml::find_or(v1, "key", map_type{}); - const auto key2 = toml::find_or(v1, "key2", map_type{}); - - BOOST_TEST(!key.empty()); - BOOST_TEST(key2.empty()); - - BOOST_TEST(key.size() == 1u); - BOOST_TEST(key.at("key") == "value"); - } - - { - toml::value v1{ - {"key", {{"key", "value"}}} - }; - toml::value v2(v1); - - const auto key = toml::find_or(std::move(v1), "key", map_type{}); - const auto key2 = toml::find_or(std::move(v2), "key2", map_type{}); - - BOOST_TEST(!key.empty()); - BOOST_TEST(key2.empty()); - - BOOST_TEST(key.size() == 1u); - BOOST_TEST(key.at("key") == "value"); - } - { - toml::value v1{ - {"key", {{"key", "value"}}} - }; - toml::value v2(v1); - - const auto key = toml::find_or(std::move(v1), "key", map_type{}); - const auto key2 = toml::find_or(std::move(v2), "key2", map_type{}); - - BOOST_TEST(!key.empty()); - BOOST_TEST(key2.empty()); - - BOOST_TEST(key.size() == 1u); - BOOST_TEST(key.at("key") == "value"); - } -} diff --git a/lib/toml/tests/test_find_or_recursive.cpp b/lib/toml/tests/test_find_or_recursive.cpp deleted file mode 100644 index 364112a..0000000 --- a/lib/toml/tests/test_find_or_recursive.cpp +++ /dev/null @@ -1,401 +0,0 @@ -#define BOOST_TEST_MODULE "test_find_or_recursive" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L -#include -#endif - -using test_value_types = std::tuple< - toml::basic_value, - toml::basic_value, - toml::basic_value, - toml::basic_value ->; - -namespace test -{ -template -std::basic_ostream& -operator<<(std::basic_ostream& os, const std::vector& v) -{ - os << "[ "; - for(const auto& i : v) {os << i << ' ';} - os << ']'; - return os; -} -template -std::basic_ostream& -operator<<(std::basic_ostream& os, const std::deque& v) -{ - os << "[ "; - for(const auto& i : v) {os << i << ' ';} - os << ']'; - return os; -} -template -std::basic_ostream& -operator<<(std::basic_ostream& os, const std::list& v) -{ - os << "[ "; - for(const auto& i : v) {os << i << ' ';} - os << ']'; - return os; -} -template -std::basic_ostream& -operator<<(std::basic_ostream& os, - const std::map& v) -{ - os << "[ "; - for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";} - os << ']'; - return os; -} -template -std::basic_ostream& -operator<<(std::basic_ostream& os, - const std::unordered_map& v) -{ - os << "[ "; - for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";} - os << ']'; - return os; -} -} // test - -#define TOML11_TEST_FIND_OR_EXACT(toml_type, init_expr, opt_expr) \ - { \ - using namespace test; \ - const toml::toml_type init init_expr ; \ - const toml::toml_type opt opt_expr ; \ - const value_type v{{"key1", value_type{{"key2", init}} }};\ - BOOST_TEST(init != opt); \ - BOOST_TEST(init == toml::find_or(v, "key1", "key2", opt));\ - } \ - /**/ - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_exact, value_type, test_value_types) -{ - TOML11_TEST_FIND_OR_EXACT(boolean, ( true), (false)) - TOML11_TEST_FIND_OR_EXACT(integer, ( 42), ( 54)) - TOML11_TEST_FIND_OR_EXACT(floating, ( 3.14), ( 2.71)) - TOML11_TEST_FIND_OR_EXACT(string, ("foo"), ("bar")) - TOML11_TEST_FIND_OR_EXACT(local_time, (12, 30, 45), (6, 0, 30)) - TOML11_TEST_FIND_OR_EXACT(local_date, (2019, toml::month_t::Apr, 1), - (1999, toml::month_t::Jan, 2)) - TOML11_TEST_FIND_OR_EXACT(local_datetime, - (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)), - (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30)) - ) - TOML11_TEST_FIND_OR_EXACT(offset_datetime, - (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)), - (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0)) - ) - { - const typename value_type::array_type init{1,2,3,4,5}; - const typename value_type::array_type opt {6,7,8,9,10}; - const value_type v{{"key", init}}; - BOOST_TEST(init != opt); - BOOST_TEST(init == toml::find_or(v, "key", opt)); - } - { - const typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}}; - const typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}}; - const value_type v{{"key", init}}; - BOOST_TEST(init != opt); - BOOST_TEST(init == toml::find_or(v, "key", opt)); - } -} -#undef TOML11_TEST_FIND_OR_EXACT - -#define TOML11_TEST_FIND_OR_MOVE(toml_type, init_expr, opt_expr) \ - { \ - using namespace test; \ - const toml::toml_type init init_expr ; \ - toml::toml_type opt opt_expr ; \ - value_type v{{"key1", value_type{{"key2", init}} }}; \ - BOOST_TEST(init != opt); \ - const auto moved = toml::find_or(std::move(v), "key1", "key2", std::move(opt));\ - BOOST_TEST(init == moved); \ - } \ - /**/ - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_move, value_type, test_value_types) -{ - TOML11_TEST_FIND_OR_MOVE(boolean, ( true), (false)) - TOML11_TEST_FIND_OR_MOVE(integer, ( 42), ( 54)) - TOML11_TEST_FIND_OR_MOVE(floating, ( 3.14), ( 2.71)) - TOML11_TEST_FIND_OR_MOVE(string, ("foo"), ("bar")) - TOML11_TEST_FIND_OR_MOVE(local_time, (12, 30, 45), (6, 0, 30)) - TOML11_TEST_FIND_OR_MOVE(local_date, (2019, toml::month_t::Apr, 1), - (1999, toml::month_t::Jan, 2)) - TOML11_TEST_FIND_OR_MOVE(local_datetime, - (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)), - (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30)) - ) - TOML11_TEST_FIND_OR_MOVE(offset_datetime, - (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)), - (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0)) - ) - { - typename value_type::array_type init{1,2,3,4,5}; - typename value_type::array_type opt {6,7,8,9,10}; - value_type v{{"key", init}}; - BOOST_TEST(init != opt); - const auto moved = toml::find_or(std::move(v), "key", std::move(opt)); - BOOST_TEST(init == moved); - } - { - typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}}; - typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}}; - value_type v{{"key", init}}; - BOOST_TEST(init != opt); - const auto moved = toml::find_or(std::move(v), "key", std::move(opt)); - BOOST_TEST(init == moved); - } -} -#undef TOML11_TEST_FIND_OR_MOVE - - -#define TOML11_TEST_FIND_OR_MODIFY(toml_type, init_expr, opt_expr)\ - { \ - using namespace test; \ - const toml::toml_type init init_expr ; \ - toml::toml_type opt1 opt_expr ; \ - toml::toml_type opt2 opt_expr ; \ - value_type v{{"key1", value_type{{"key2", init}} }}; \ - BOOST_TEST(init != opt1); \ - toml::find_or(v, "key1", "key2", opt2) = opt1; \ - BOOST_TEST(opt1 == toml::find(v, "key1", "key2"));\ - } \ - /**/ -BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_modify, value_type, test_value_types) -{ - TOML11_TEST_FIND_OR_MODIFY(boolean, ( true), (false)) - TOML11_TEST_FIND_OR_MODIFY(integer, ( 42), ( 54)) - TOML11_TEST_FIND_OR_MODIFY(floating, ( 3.14), ( 2.71)) - TOML11_TEST_FIND_OR_MODIFY(string, ("foo"), ("bar")) - TOML11_TEST_FIND_OR_MODIFY(local_time, (12, 30, 45), (6, 0, 30)) - TOML11_TEST_FIND_OR_MODIFY(local_date, (2019, toml::month_t::Apr, 1), - (1999, toml::month_t::Jan, 2)) - TOML11_TEST_FIND_OR_MODIFY(local_datetime, - (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)), - (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30)) - ) - TOML11_TEST_FIND_OR_MODIFY(offset_datetime, - (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)), - (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0)) - ) - { - typename value_type::array_type init{1,2,3,4,5}; - typename value_type::array_type opt1{6,7,8,9,10}; - typename value_type::array_type opt2{6,7,8,9,10}; - BOOST_TEST(init != opt1); - value_type v{{"key", init}}; - toml::find_or(v, "key", opt2) = opt1; - BOOST_TEST(opt1 == toml::find(v, "key")); - } - { - typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}}; - typename value_type::table_type opt1{{"key1", 54}, {"key2", "bar"}}; - typename value_type::table_type opt2{{"key1", 54}, {"key2", "bar"}}; - value_type v{{"key", init}}; - BOOST_TEST(init != opt1); - toml::find_or(v, "key", opt2) = opt1; - BOOST_TEST(opt1 == toml::find(v, "key")); - } -} -#undef TOML11_TEST_FIND_OR_MODIFY - -#define TOML11_TEST_FIND_OR_FALLBACK(init_type, opt_type) \ - { \ - using namespace test; \ - value_type v1{{"key1", value_type{{"key3", "foo"}}}}; \ - BOOST_TEST(opt_type == toml::find_or(v1, "key1", "key2", opt_type));\ - value_type v2{{"key1", "foo"}}; \ - BOOST_TEST(opt_type == toml::find_or(v2, "key1", "key3", opt_type));\ - } \ - /**/ - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_fallback, value_type, test_value_types) -{ - const toml::boolean boolean (true); - const toml::integer integer (42); - const toml::floating floating (3.14); - const toml::string string ("foo"); - const toml::local_time local_time (12, 30, 45); - const toml::local_date local_date (2019, toml::month_t::Apr, 1); - const toml::local_datetime local_datetime ( - toml::local_date(2019, toml::month_t::Apr, 1), - toml::local_time(12, 30, 45)); - const toml::offset_datetime offset_datetime( - toml::local_date(2019, toml::month_t::Apr, 1), - toml::local_time(12, 30, 45), toml::time_offset( 9, 0)); - - using array_type = typename value_type::array_type; - using table_type = typename value_type::table_type; - const array_type array{1, 2, 3, 4, 5}; - const table_type table{{"key1", 42}, {"key2", "foo"}}; - - TOML11_TEST_FIND_OR_FALLBACK(boolean, integer ); - TOML11_TEST_FIND_OR_FALLBACK(boolean, floating ); - TOML11_TEST_FIND_OR_FALLBACK(boolean, string ); - TOML11_TEST_FIND_OR_FALLBACK(boolean, local_time ); - TOML11_TEST_FIND_OR_FALLBACK(boolean, local_date ); - TOML11_TEST_FIND_OR_FALLBACK(boolean, local_datetime ); - TOML11_TEST_FIND_OR_FALLBACK(boolean, offset_datetime); - TOML11_TEST_FIND_OR_FALLBACK(boolean, array ); - TOML11_TEST_FIND_OR_FALLBACK(boolean, table ); - - TOML11_TEST_FIND_OR_FALLBACK(integer, boolean ); - TOML11_TEST_FIND_OR_FALLBACK(integer, floating ); - TOML11_TEST_FIND_OR_FALLBACK(integer, string ); - TOML11_TEST_FIND_OR_FALLBACK(integer, local_time ); - TOML11_TEST_FIND_OR_FALLBACK(integer, local_date ); - TOML11_TEST_FIND_OR_FALLBACK(integer, local_datetime ); - TOML11_TEST_FIND_OR_FALLBACK(integer, offset_datetime); - TOML11_TEST_FIND_OR_FALLBACK(integer, array ); - TOML11_TEST_FIND_OR_FALLBACK(integer, table ); - - TOML11_TEST_FIND_OR_FALLBACK(floating, boolean ); - TOML11_TEST_FIND_OR_FALLBACK(floating, integer ); - TOML11_TEST_FIND_OR_FALLBACK(floating, string ); - TOML11_TEST_FIND_OR_FALLBACK(floating, local_time ); - TOML11_TEST_FIND_OR_FALLBACK(floating, local_date ); - TOML11_TEST_FIND_OR_FALLBACK(floating, local_datetime ); - TOML11_TEST_FIND_OR_FALLBACK(floating, offset_datetime); - TOML11_TEST_FIND_OR_FALLBACK(floating, array ); - TOML11_TEST_FIND_OR_FALLBACK(floating, table ); - - TOML11_TEST_FIND_OR_FALLBACK(string, boolean ); - TOML11_TEST_FIND_OR_FALLBACK(string, integer ); - TOML11_TEST_FIND_OR_FALLBACK(string, floating ); - TOML11_TEST_FIND_OR_FALLBACK(string, local_time ); - TOML11_TEST_FIND_OR_FALLBACK(string, local_date ); - TOML11_TEST_FIND_OR_FALLBACK(string, local_datetime ); - TOML11_TEST_FIND_OR_FALLBACK(string, offset_datetime); - TOML11_TEST_FIND_OR_FALLBACK(string, array ); - TOML11_TEST_FIND_OR_FALLBACK(string, table ); - - TOML11_TEST_FIND_OR_FALLBACK(local_time, boolean ); - TOML11_TEST_FIND_OR_FALLBACK(local_time, integer ); - TOML11_TEST_FIND_OR_FALLBACK(local_time, floating ); - TOML11_TEST_FIND_OR_FALLBACK(local_time, string ); - TOML11_TEST_FIND_OR_FALLBACK(local_time, local_date ); - TOML11_TEST_FIND_OR_FALLBACK(local_time, local_datetime ); - TOML11_TEST_FIND_OR_FALLBACK(local_time, offset_datetime); - TOML11_TEST_FIND_OR_FALLBACK(local_time, array ); - TOML11_TEST_FIND_OR_FALLBACK(local_time, table ); - - TOML11_TEST_FIND_OR_FALLBACK(local_date, boolean ); - TOML11_TEST_FIND_OR_FALLBACK(local_date, integer ); - TOML11_TEST_FIND_OR_FALLBACK(local_date, floating ); - TOML11_TEST_FIND_OR_FALLBACK(local_date, string ); - TOML11_TEST_FIND_OR_FALLBACK(local_date, local_time ); - TOML11_TEST_FIND_OR_FALLBACK(local_date, local_datetime ); - TOML11_TEST_FIND_OR_FALLBACK(local_date, offset_datetime); - TOML11_TEST_FIND_OR_FALLBACK(local_date, array ); - TOML11_TEST_FIND_OR_FALLBACK(local_date, table ); - - TOML11_TEST_FIND_OR_FALLBACK(local_datetime, boolean ); - TOML11_TEST_FIND_OR_FALLBACK(local_datetime, integer ); - TOML11_TEST_FIND_OR_FALLBACK(local_datetime, floating ); - TOML11_TEST_FIND_OR_FALLBACK(local_datetime, string ); - TOML11_TEST_FIND_OR_FALLBACK(local_datetime, local_time ); - TOML11_TEST_FIND_OR_FALLBACK(local_datetime, local_date ); - TOML11_TEST_FIND_OR_FALLBACK(local_datetime, offset_datetime); - TOML11_TEST_FIND_OR_FALLBACK(local_datetime, array ); - TOML11_TEST_FIND_OR_FALLBACK(local_datetime, table ); - - TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, boolean ); - TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, integer ); - TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, floating ); - TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, string ); - TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, local_time ); - TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, local_date ); - TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, local_datetime ); - TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, array ); - TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, table ); - - TOML11_TEST_FIND_OR_FALLBACK(array, boolean ); - TOML11_TEST_FIND_OR_FALLBACK(array, integer ); - TOML11_TEST_FIND_OR_FALLBACK(array, floating ); - TOML11_TEST_FIND_OR_FALLBACK(array, string ); - TOML11_TEST_FIND_OR_FALLBACK(array, local_time ); - TOML11_TEST_FIND_OR_FALLBACK(array, local_date ); - TOML11_TEST_FIND_OR_FALLBACK(array, local_datetime ); - TOML11_TEST_FIND_OR_FALLBACK(array, offset_datetime); - TOML11_TEST_FIND_OR_FALLBACK(array, table ); - - TOML11_TEST_FIND_OR_FALLBACK(table, boolean ); - TOML11_TEST_FIND_OR_FALLBACK(table, integer ); - TOML11_TEST_FIND_OR_FALLBACK(table, floating ); - TOML11_TEST_FIND_OR_FALLBACK(table, string ); - TOML11_TEST_FIND_OR_FALLBACK(table, local_time ); - TOML11_TEST_FIND_OR_FALLBACK(table, local_date ); - TOML11_TEST_FIND_OR_FALLBACK(table, local_datetime ); - TOML11_TEST_FIND_OR_FALLBACK(table, offset_datetime); - TOML11_TEST_FIND_OR_FALLBACK(table, array ); -} -#undef TOML11_TEST_FIND_OR_FALLBACK - -struct move_only_type -{ - explicit move_only_type(const std::string& n): name_(n) {} - - void from_toml(const toml::value& v) - { - this->name_ = toml::find(v, "name"); - return; - } - - move_only_type(): name_("default"){} - ~move_only_type() = default; - move_only_type(move_only_type&&) = default; - move_only_type& operator=(move_only_type&&) = default; - move_only_type(const move_only_type&) = delete; - move_only_type& operator=(const move_only_type&) = delete; - - bool operator==(const move_only_type& other) const noexcept {return this->name_ == other.name_;} - bool operator!=(const move_only_type& other) const noexcept {return this->name_ != other.name_;} - bool operator< (const move_only_type& other) const noexcept {return this->name_ < other.name_;} - bool operator<=(const move_only_type& other) const noexcept {return this->name_ <= other.name_;} - bool operator> (const move_only_type& other) const noexcept {return this->name_ > other.name_;} - bool operator>=(const move_only_type& other) const noexcept {return this->name_ >= other.name_;} - - std::string name_; -}; - -std::ostream& operator<<(std::ostream& os, const move_only_type& mot) -{ - os << mot.name_; - return os; -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_move_only, value_type, test_value_types) -{ - const move_only_type ref("reference"); - move_only_type opt("optional"); - { - const value_type v{{"key1", value_type{{"key2", value_type{{"name", "reference"}} }} }}; - BOOST_TEST(ref == toml::find_or(v, "key1", "key2", std::move(opt))); - } -} - - - - - diff --git a/lib/toml/tests/test_format_error.cpp b/lib/toml/tests/test_format_error.cpp deleted file mode 100644 index df558da..0000000 --- a/lib/toml/tests/test_format_error.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#define BOOST_TEST_MODULE "test_format_error" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include - -// to check it successfully compiles. it does not check the formatted string. - -BOOST_AUTO_TEST_CASE(test_1_value) -{ - toml::value val(42); - - { - const std::string pretty_error = - toml::format_error("[error] test error", val, "this is a value"); - std::cout << pretty_error << std::endl; - } - - { - const std::string pretty_error = - toml::format_error("[error] test error", val, "this is a value", - {"this is a hint"}); - std::cout << pretty_error << std::endl; - } -} - -BOOST_AUTO_TEST_CASE(test_2_values) -{ - toml::value v1(42); - toml::value v2(3.14); - { - const std::string pretty_error = - toml::format_error("[error] test error with two values", - v1, "this is the answer", - v2, "this is the pi"); - std::cout << pretty_error << std::endl; - } - - { - const std::string pretty_error = - toml::format_error("[error] test error with two values", - v1, "this is the answer", - v2, "this is the pi", - {"hint"}); - std::cout << pretty_error << std::endl; - } -} - -BOOST_AUTO_TEST_CASE(test_3_values) -{ - toml::value v1(42); - toml::value v2(3.14); - toml::value v3("foo"); - { - const std::string pretty_error = - toml::format_error("[error] test error with two values", - v1, "this is the answer", - v2, "this is the pi", - v3, "this is a meta-syntactic variable"); - std::cout << pretty_error << std::endl; - } - - { - const std::string pretty_error = - toml::format_error("[error] test error with two values", - v1, "this is the answer", - v2, "this is the pi", - v3, "this is a meta-syntactic variable", - {"hint 1", "hint 2"}); - std::cout << pretty_error << std::endl; - } -} diff --git a/lib/toml/tests/test_get.cpp b/lib/toml/tests/test_get.cpp deleted file mode 100644 index a0dd315..0000000 --- a/lib/toml/tests/test_get.cpp +++ /dev/null @@ -1,509 +0,0 @@ -#define BOOST_TEST_MODULE "test_get" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L -#include -#endif - -using test_value_types = std::tuple< - toml::basic_value, - toml::basic_value, - toml::basic_value, - toml::basic_value ->; - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types) -{ - { - value_type v(true); - BOOST_TEST(true == toml::get(v)); - - toml::get(v) = false; - BOOST_TEST(false == toml::get(v)); - - toml::boolean x = toml::get(std::move(v)); - BOOST_TEST(false == x); - } - { - value_type v(42); - BOOST_TEST(toml::integer(42) == toml::get(v)); - - toml::get(v) = 54; - BOOST_TEST(toml::integer(54) == toml::get(v)); - - toml::integer x = toml::get(std::move(v)); - BOOST_TEST(toml::integer(54) == x); - } - { - value_type v(3.14); - BOOST_TEST(toml::floating(3.14) == toml::get(v)); - - toml::get(v) = 2.71; - BOOST_TEST(toml::floating(2.71) == toml::get(v)); - - toml::floating x = toml::get(std::move(v)); - BOOST_TEST(toml::floating(2.71) == x); - } - { - value_type v("foo"); - BOOST_TEST(toml::string("foo", toml::string_t::basic) == - toml::get(v)); - - toml::get(v).str += "bar"; - BOOST_TEST(toml::string("foobar", toml::string_t::basic) == - toml::get(v)); - - toml::string x = toml::get(std::move(v)); - BOOST_TEST(toml::string("foobar") == x); - } - { - value_type v("foo", toml::string_t::literal); - BOOST_TEST(toml::string("foo", toml::string_t::literal) == - toml::get(v)); - - toml::get(v).str += "bar"; - BOOST_TEST(toml::string("foobar", toml::string_t::literal) == - toml::get(v)); - - toml::string x = toml::get(std::move(v)); - BOOST_TEST(toml::string("foobar", toml::string_t::literal) == x); - } - { - toml::local_date d(2018, toml::month_t::Apr, 22); - value_type v(d); - BOOST_TEST(d == toml::get(v)); - - toml::get(v).year = 2017; - d.year = 2017; - BOOST_TEST(d == toml::get(v)); - - toml::local_date x = toml::get(std::move(v)); - BOOST_TEST(d == x); - } - { - toml::local_time t(12, 30, 45); - value_type v(t); - BOOST_TEST(t == toml::get(v)); - - toml::get(v).hour = 9; - t.hour = 9; - BOOST_TEST(t == toml::get(v)); - - toml::local_time x = toml::get(std::move(v)); - BOOST_TEST(t == x); - } - { - toml::local_datetime dt(toml::local_date(2018, toml::month_t::Apr, 22), - toml::local_time(12, 30, 45)); - value_type v(dt); - BOOST_TEST(dt == toml::get(v)); - - toml::get(v).date.year = 2017; - dt.date.year = 2017; - BOOST_TEST(dt == toml::get(v)); - - toml::local_datetime x = toml::get(std::move(v)); - BOOST_TEST(dt == x); - } - { - toml::offset_datetime dt(toml::local_datetime( - toml::local_date(2018, toml::month_t::Apr, 22), - toml::local_time(12, 30, 45)), toml::time_offset(9, 0)); - value_type v(dt); - BOOST_TEST(dt == toml::get(v)); - - toml::get(v).date.year = 2017; - dt.date.year = 2017; - BOOST_TEST(dt == toml::get(v)); - - toml::offset_datetime x = toml::get(std::move(v)); - BOOST_TEST(dt == x); - } - { - using array_type = typename value_type::array_type; - array_type vec; - vec.push_back(value_type(42)); - vec.push_back(value_type(54)); - value_type v(vec); - BOOST_TEST(vec == toml::get(v)); - - toml::get(v).push_back(value_type(123)); - vec.push_back(value_type(123)); - BOOST_TEST(vec == toml::get(v)); - - array_type x = toml::get(std::move(v)); - BOOST_TEST(vec == x); - } - { - using table_type = typename value_type::table_type; - table_type tab; - tab["key1"] = value_type(42); - tab["key2"] = value_type(3.14); - value_type v(tab); - BOOST_TEST(tab == toml::get(v)); - - toml::get(v)["key3"] = value_type(123); - tab["key3"] = value_type(123); - BOOST_TEST(tab == toml::get(v)); - - table_type x = toml::get(std::move(v)); - BOOST_TEST(tab == x); - } - { - value_type v1(42); - BOOST_TEST(v1 == toml::get(v1)); - - value_type v2(54); - toml::get(v1) = v2; - BOOST_TEST(v2 == toml::get(v1)); - - value_type x = toml::get(std::move(v1)); - BOOST_TEST(v2 == x); - } -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_integer_type, value_type, test_value_types) -{ - { - value_type v(42); - BOOST_TEST(int(42) == toml::get(v)); - BOOST_TEST(short(42) == toml::get(v)); - BOOST_TEST(char(42) == toml::get(v)); - BOOST_TEST(unsigned(42) == toml::get(v)); - BOOST_TEST(long(42) == toml::get(v)); - BOOST_TEST(std::int64_t(42) == toml::get(v)); - BOOST_TEST(std::uint64_t(42) == toml::get(v)); - BOOST_TEST(std::int16_t(42) == toml::get(v)); - BOOST_TEST(std::uint16_t(42) == toml::get(v)); - - BOOST_TEST(std::uint16_t(42) == toml::get(std::move(v))); - } -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_floating_type, value_type, test_value_types) -{ - { - value_type v(3.14); - const double ref(3.14); - BOOST_TEST(static_cast(ref) == toml::get(v)); - BOOST_TEST( ref == toml::get(v)); - BOOST_TEST(static_cast(ref) == toml::get(v)); - BOOST_TEST(static_cast(ref) == toml::get(std::move(v))); - } -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_string_type, value_type, test_value_types) -{ - { - value_type v("foo", toml::string_t::basic); - BOOST_TEST("foo" == toml::get(v)); - toml::get(v) += "bar"; - BOOST_TEST("foobar" == toml::get(v)); - - const auto x = toml::get(std::move(v)); - BOOST_TEST("foobar" == x); - } - { - value_type v("foo", toml::string_t::literal); - BOOST_TEST("foo" == toml::get(v)); - toml::get(v) += "bar"; - BOOST_TEST("foobar" == toml::get(v)); - - const auto x = toml::get(std::move(v)); - BOOST_TEST("foobar" == x); - } - -#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L - { - value_type v("foo", toml::string_t::basic); - BOOST_TEST("foo" == toml::get(v)); - } - { - value_type v("foo", toml::string_t::literal); - BOOST_TEST("foo" == toml::get(v)); - } -#endif -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array, value_type, test_value_types) -{ - { - const value_type v{42, 54, 69, 72}; - - const std::vector vec = toml::get>(v); - const std::list lst = toml::get>(v); - const std::deque deq = toml::get>(v); - - BOOST_TEST(42 == vec.at(0)); - BOOST_TEST(54 == vec.at(1)); - BOOST_TEST(69 == vec.at(2)); - BOOST_TEST(72 == vec.at(3)); - - std::list::const_iterator iter = lst.begin(); - BOOST_TEST(static_cast(42) == *(iter++)); - BOOST_TEST(static_cast(54) == *(iter++)); - BOOST_TEST(static_cast(69) == *(iter++)); - BOOST_TEST(static_cast(72) == *(iter++)); - - BOOST_TEST(static_cast(42) == deq.at(0)); - BOOST_TEST(static_cast(54) == deq.at(1)); - BOOST_TEST(static_cast(69) == deq.at(2)); - BOOST_TEST(static_cast(72) == deq.at(3)); - - std::array ary = toml::get>(v); - BOOST_TEST(42 == ary.at(0)); - BOOST_TEST(54 == ary.at(1)); - BOOST_TEST(69 == ary.at(2)); - BOOST_TEST(72 == ary.at(3)); - - std::tuple tpl = - toml::get>(v); - BOOST_TEST( 42 == std::get<0>(tpl)); - BOOST_TEST(static_cast(54) == std::get<1>(tpl)); - BOOST_TEST(static_cast(69) == std::get<2>(tpl)); - BOOST_TEST(static_cast(72) == std::get<3>(tpl)); - - const value_type p{3.14, 2.71}; - std::pair pr = toml::get >(p); - BOOST_TEST(3.14 == pr.first); - BOOST_TEST(2.71 == pr.second); - } - - { - value_type v{42, 54, 69, 72}; - const std::vector vec = toml::get>(std::move(v)); - BOOST_TEST(42 == vec.at(0)); - BOOST_TEST(54 == vec.at(1)); - BOOST_TEST(69 == vec.at(2)); - BOOST_TEST(72 == vec.at(3)); - } - { - value_type v{42, 54, 69, 72}; - const std::deque deq = toml::get>(std::move(v)); - BOOST_TEST(42 == deq.at(0)); - BOOST_TEST(54 == deq.at(1)); - BOOST_TEST(69 == deq.at(2)); - BOOST_TEST(72 == deq.at(3)); - } - { - value_type v{42, 54, 69, 72}; - const std::list lst = toml::get>(std::move(v)); - std::list::const_iterator iter = lst.begin(); - BOOST_TEST(42 == *(iter++)); - BOOST_TEST(54 == *(iter++)); - BOOST_TEST(69 == *(iter++)); - BOOST_TEST(72 == *(iter++)); - } - { - value_type v{42, 54, 69, 72}; - std::array ary = toml::get>(std::move(v)); - BOOST_TEST(42 == ary.at(0)); - BOOST_TEST(54 == ary.at(1)); - BOOST_TEST(69 == ary.at(2)); - BOOST_TEST(72 == ary.at(3)); - } - { - value_type v{42, 54, 69, 72}; - std::tuple tpl = - toml::get>(std::move(v)); - BOOST_TEST( 42 == std::get<0>(tpl)); - BOOST_TEST(static_cast(54) == std::get<1>(tpl)); - BOOST_TEST(static_cast(69) == std::get<2>(tpl)); - BOOST_TEST(static_cast(72) == std::get<3>(tpl)); - } -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array_of_array, value_type, test_value_types) -{ - { - const value_type v1{42, 54, 69, 72}; - const value_type v2{"foo", "bar", "baz"}; - const value_type v{v1, v2}; - - std::pair, std::vector> p = - toml::get, std::vector>>(v); - - BOOST_TEST(p.first.size() == 4u); - BOOST_TEST(p.first.at(0) == 42); - BOOST_TEST(p.first.at(1) == 54); - BOOST_TEST(p.first.at(2) == 69); - BOOST_TEST(p.first.at(3) == 72); - - BOOST_TEST(p.second.size() == 3u); - BOOST_TEST(p.second.at(0) == "foo"); - BOOST_TEST(p.second.at(1) == "bar"); - BOOST_TEST(p.second.at(2) == "baz"); - - std::tuple, std::vector> t = - toml::get, std::vector>>(v); - - BOOST_TEST(std::get<0>(t).at(0) == 42); - BOOST_TEST(std::get<0>(t).at(1) == 54); - BOOST_TEST(std::get<0>(t).at(2) == 69); - BOOST_TEST(std::get<0>(t).at(3) == 72); - - BOOST_TEST(std::get<1>(t).at(0) == "foo"); - BOOST_TEST(std::get<1>(t).at(1) == "bar"); - BOOST_TEST(std::get<1>(t).at(2) == "baz"); - } - { - const value_type v1{42, 54, 69, 72}; - const value_type v2{"foo", "bar", "baz"}; - value_type v{v1, v2}; - - std::pair, std::vector> p = - toml::get, std::vector>>(std::move(v)); - - BOOST_TEST(p.first.size() == 4u); - BOOST_TEST(p.first.at(0) == 42); - BOOST_TEST(p.first.at(1) == 54); - BOOST_TEST(p.first.at(2) == 69); - BOOST_TEST(p.first.at(3) == 72); - - BOOST_TEST(p.second.size() == 3u); - BOOST_TEST(p.second.at(0) == "foo"); - BOOST_TEST(p.second.at(1) == "bar"); - BOOST_TEST(p.second.at(2) == "baz"); - } -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_table, value_type, test_value_types) -{ - { - const value_type v1{ - {"key1", 1}, - {"key2", 2}, - {"key3", 3}, - {"key4", 4} - }; - - const auto v = toml::get>(v1); - BOOST_TEST(v.at("key1") == 1); - BOOST_TEST(v.at("key2") == 2); - BOOST_TEST(v.at("key3") == 3); - BOOST_TEST(v.at("key4") == 4); - } - { - value_type v1{ - {"key1", 1}, - {"key2", 2}, - {"key3", 3}, - {"key4", 4} - }; - const auto v = toml::get>(std::move(v1)); - BOOST_TEST(v.at("key1") == 1); - BOOST_TEST(v.at("key2") == 2); - BOOST_TEST(v.at("key3") == 3); - BOOST_TEST(v.at("key4") == 4); - } - -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_local_date, value_type, test_value_types) -{ - value_type v1(toml::local_date{2018, toml::month_t::Apr, 1}); - const auto date = std::chrono::system_clock::to_time_t( - toml::get(v1)); - - std::tm t; - t.tm_year = 2018 - 1900; - t.tm_mon = 4 - 1; - t.tm_mday = 1; - t.tm_hour = 0; - t.tm_min = 0; - t.tm_sec = 0; - t.tm_isdst = -1; - const auto c = std::mktime(&t); - BOOST_TEST(c == date); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_local_time, value_type, test_value_types) -{ - value_type v1(toml::local_time{12, 30, 45}); - const auto time = toml::get(v1); - const bool result = time == std::chrono::hours(12) + - std::chrono::minutes(30) + - std::chrono::seconds(45); - BOOST_TEST(result); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_local_datetime, value_type, test_value_types) -{ - value_type v1(toml::local_datetime( - toml::local_date{2018, toml::month_t::Apr, 1}, - toml::local_time{12, 30, 45})); - - const auto date = std::chrono::system_clock::to_time_t( - toml::get(v1)); - std::tm t; - t.tm_year = 2018 - 1900; - t.tm_mon = 4 - 1; - t.tm_mday = 1; - t.tm_hour = 12; - t.tm_min = 30; - t.tm_sec = 45; - t.tm_isdst = -1; - const auto c = std::mktime(&t); - BOOST_TEST(c == date); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_offset_datetime, value_type, test_value_types) -{ - { - value_type v1(toml::offset_datetime( - toml::local_date{2018, toml::month_t::Apr, 1}, - toml::local_time{12, 30, 0}, - toml::time_offset{9, 0})); - // 2018-04-01T12:30:00+09:00 - // == 2018-04-01T03:30:00Z - - const auto date = toml::get(v1); - const auto timet = std::chrono::system_clock::to_time_t(date); - - // get time_t as gmtime (2018-04-01T03:30:00Z) - const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe! - BOOST_TEST(tmp); - const auto tm = *tmp; - BOOST_TEST(tm.tm_year + 1900 == 2018); - BOOST_TEST(tm.tm_mon + 1 == 4); - BOOST_TEST(tm.tm_mday == 1); - BOOST_TEST(tm.tm_hour == 3); - BOOST_TEST(tm.tm_min == 30); - BOOST_TEST(tm.tm_sec == 0); - } - - { - value_type v1(toml::offset_datetime( - toml::local_date{2018, toml::month_t::Apr, 1}, - toml::local_time{12, 30, 0}, - toml::time_offset{-8, 0})); - // 2018-04-01T12:30:00-08:00 - // == 2018-04-01T20:30:00Z - - const auto date = toml::get(v1); - const auto timet = std::chrono::system_clock::to_time_t(date); - - // get time_t as gmtime (2018-04-01T03:30:00Z) - const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe! - BOOST_TEST(tmp); - const auto tm = *tmp; - BOOST_TEST(tm.tm_year + 1900 == 2018); - BOOST_TEST(tm.tm_mon + 1 == 4); - BOOST_TEST(tm.tm_mday == 1); - BOOST_TEST(tm.tm_hour == 20); - BOOST_TEST(tm.tm_min == 30); - BOOST_TEST(tm.tm_sec == 0); - } -} - diff --git a/lib/toml/tests/test_get_or.cpp b/lib/toml/tests/test_get_or.cpp deleted file mode 100644 index 081b966..0000000 --- a/lib/toml/tests/test_get_or.cpp +++ /dev/null @@ -1,452 +0,0 @@ -#define BOOST_TEST_MODULE "test_get_or" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L -#include -#endif - -using test_value_types = std::tuple< - toml::basic_value, - toml::basic_value, - toml::basic_value, - toml::basic_value ->; - -namespace test -{ -// to compare result values in BOOST_TEST(). -// -// BOOST_TEST outputs the expected and actual values. Thus it includes the -// output stream operator inside. To compile it, we need operator< -std::basic_ostream& -operator<<(std::basic_ostream& os, const std::vector& v) -{ - os << "[ "; - for(const auto& i : v) {os << i << ' ';} - os << ']'; - return os; -} -template -std::basic_ostream& -operator<<(std::basic_ostream& os, const std::deque& v) -{ - os << "[ "; - for(const auto& i : v) {os << i << ' ';} - os << ']'; - return os; -} -template -std::basic_ostream& -operator<<(std::basic_ostream& os, const std::list& v) -{ - os << "[ "; - for(const auto& i : v) {os << i << ' ';} - os << ']'; - return os; -} -template -std::basic_ostream& -operator<<(std::basic_ostream& os, - const std::map& v) -{ - os << "[ "; - for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";} - os << ']'; - return os; -} -template -std::basic_ostream& -operator<<(std::basic_ostream& os, - const std::unordered_map& v) -{ - os << "[ "; - for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";} - os << ']'; - return os; -} -} // test - -#define TOML11_TEST_GET_OR_EXACT(toml_type, init_expr, opt_expr)\ - { \ - using namespace test; \ - const toml::toml_type init init_expr ; \ - const toml::toml_type opt opt_expr ; \ - const value_type v(init); \ - BOOST_TEST(init != opt); \ - BOOST_TEST(init == toml::get_or(v, opt)); \ - } \ - /**/ - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_or_exact, value_type, test_value_types) -{ - TOML11_TEST_GET_OR_EXACT(boolean, ( true), (false)) - TOML11_TEST_GET_OR_EXACT(integer, ( 42), ( 54)) - TOML11_TEST_GET_OR_EXACT(floating, ( 3.14), ( 2.71)) - TOML11_TEST_GET_OR_EXACT(string, ("foo"), ("bar")) - TOML11_TEST_GET_OR_EXACT(local_time, (12, 30, 45), (6, 0, 30)) - TOML11_TEST_GET_OR_EXACT(local_date, (2019, toml::month_t::Apr, 1), - (1999, toml::month_t::Jan, 2)) - TOML11_TEST_GET_OR_EXACT(local_datetime, - (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)), - (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30)) - ) - TOML11_TEST_GET_OR_EXACT(offset_datetime, - (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)), - (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0)) - ) - { - const typename value_type::array_type init{1,2,3,4,5}; - const typename value_type::array_type opt {6,7,8,9,10}; - const value_type v(init); - BOOST_TEST(init != opt); - BOOST_TEST(init == toml::get_or(v, opt)); - } - { - const typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}}; - const typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}}; - const value_type v(init); - BOOST_TEST(init != opt); - BOOST_TEST(init == toml::get_or(v, opt)); - } -} -#undef TOML11_TEST_GET_OR_EXACT - -#define TOML11_TEST_GET_OR_MOVE_EXACT(toml_type, init_expr, opt_expr)\ - { \ - using namespace test; \ - const toml::toml_type init init_expr ; \ - toml::toml_type opt opt_expr ; \ - value_type v(init); \ - BOOST_TEST(init != opt); \ - const auto opt_ = toml::get_or(std::move(v), std::move(opt));\ - BOOST_TEST(init == opt_); \ - } \ - /**/ - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_or_move, value_type, test_value_types) -{ - TOML11_TEST_GET_OR_MOVE_EXACT(boolean, ( true), (false)) - TOML11_TEST_GET_OR_MOVE_EXACT(integer, ( 42), ( 54)) - TOML11_TEST_GET_OR_MOVE_EXACT(floating, ( 3.14), ( 2.71)) - TOML11_TEST_GET_OR_MOVE_EXACT(string, ("foo"), ("bar")) - TOML11_TEST_GET_OR_MOVE_EXACT(local_time, (12, 30, 45), (6, 0, 30)) - TOML11_TEST_GET_OR_MOVE_EXACT(local_date, (2019, toml::month_t::Apr, 1), - (1999, toml::month_t::Jan, 2)) - TOML11_TEST_GET_OR_MOVE_EXACT(local_datetime, - (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)), - (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30)) - ) - TOML11_TEST_GET_OR_MOVE_EXACT(offset_datetime, - (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)), - (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0)) - ) - { - const typename value_type::array_type init{1,2,3,4,5}; - typename value_type::array_type opt {6,7,8,9,10}; - value_type v(init); - BOOST_TEST(init != opt); - const auto opt_ = toml::get_or(std::move(v), std::move(opt)); - BOOST_TEST(init == opt_); - } - { - const typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}}; - typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}}; - value_type v(init); - BOOST_TEST(init != opt); - const auto opt_ = toml::get_or(std::move(v), std::move(opt)); - BOOST_TEST(init == opt_); - } -} -#undef TOML11_TEST_GET_OR_MOVE_EXACT - - -#define TOML11_TEST_GET_OR_MODIFY(toml_type, init_expr, opt_expr)\ - { \ - using namespace test; \ - const toml::toml_type init init_expr ; \ - toml::toml_type opt1 opt_expr ; \ - toml::toml_type opt2 opt_expr ; \ - value_type v(init); \ - BOOST_TEST(init != opt1); \ - toml::get_or(v, opt2) = opt1; \ - BOOST_TEST(opt1 == toml::get(v)); \ - } \ - /**/ -BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_or_modify, value_type, test_value_types) -{ - TOML11_TEST_GET_OR_MODIFY(boolean, ( true), (false)) - TOML11_TEST_GET_OR_MODIFY(integer, ( 42), ( 54)) - TOML11_TEST_GET_OR_MODIFY(floating, ( 3.14), ( 2.71)) - TOML11_TEST_GET_OR_MODIFY(string, ("foo"), ("bar")) - TOML11_TEST_GET_OR_MODIFY(local_time, (12, 30, 45), (6, 0, 30)) - TOML11_TEST_GET_OR_MODIFY(local_date, (2019, toml::month_t::Apr, 1), - (1999, toml::month_t::Jan, 2)) - TOML11_TEST_GET_OR_MODIFY(local_datetime, - (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)), - (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30)) - ) - TOML11_TEST_GET_OR_MODIFY(offset_datetime, - (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)), - (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0)) - ) - { - typename value_type::array_type init{1,2,3,4,5}; - typename value_type::array_type opt1{6,7,8,9,10}; - typename value_type::array_type opt2{6,7,8,9,10}; - BOOST_TEST(init != opt1); - value_type v(init); - toml::get_or(v, opt2) = opt1; - BOOST_TEST(opt1 == toml::get(v)); - } - { - typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}}; - typename value_type::table_type opt1{{"key1", 54}, {"key2", "bar"}}; - typename value_type::table_type opt2{{"key1", 54}, {"key2", "bar"}}; - value_type v(init); - BOOST_TEST(init != opt1); - toml::get_or(v, opt2) = opt1; - BOOST_TEST(opt1 == toml::get(v)); - } -} -#undef TOML11_TEST_GET_OR_MODIFY - -#define TOML11_TEST_GET_OR_FALLBACK(init_type, opt_type) \ - { \ - using namespace test; \ - value_type v(init_type); \ - BOOST_TEST(opt_type == toml::get_or(v, opt_type));\ - } \ - /**/ - -BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_or_fallback, value_type, test_value_types) -{ - const toml::boolean boolean (true); - const toml::integer integer (42); - const toml::floating floating (3.14); - const toml::string string ("foo"); - const toml::local_time local_time (12, 30, 45); - const toml::local_date local_date (2019, toml::month_t::Apr, 1); - const toml::local_datetime local_datetime ( - toml::local_date(2019, toml::month_t::Apr, 1), - toml::local_time(12, 30, 45)); - const toml::offset_datetime offset_datetime( - toml::local_date(2019, toml::month_t::Apr, 1), - toml::local_time(12, 30, 45), toml::time_offset( 9, 0)); - - using array_type = typename value_type::array_type; - using table_type = typename value_type::table_type; - const array_type array{1, 2, 3, 4, 5}; - const table_type table{{"key1", 42}, {"key2", "foo"}}; - - TOML11_TEST_GET_OR_FALLBACK(boolean, integer ); - TOML11_TEST_GET_OR_FALLBACK(boolean, floating ); - TOML11_TEST_GET_OR_FALLBACK(boolean, string ); - TOML11_TEST_GET_OR_FALLBACK(boolean, local_time ); - TOML11_TEST_GET_OR_FALLBACK(boolean, local_date ); - TOML11_TEST_GET_OR_FALLBACK(boolean, local_datetime ); - TOML11_TEST_GET_OR_FALLBACK(boolean, offset_datetime); - TOML11_TEST_GET_OR_FALLBACK(boolean, array ); - TOML11_TEST_GET_OR_FALLBACK(boolean, table ); - - TOML11_TEST_GET_OR_FALLBACK(integer, boolean ); - TOML11_TEST_GET_OR_FALLBACK(integer, floating ); - TOML11_TEST_GET_OR_FALLBACK(integer, string ); - TOML11_TEST_GET_OR_FALLBACK(integer, local_time ); - TOML11_TEST_GET_OR_FALLBACK(integer, local_date ); - TOML11_TEST_GET_OR_FALLBACK(integer, local_datetime ); - TOML11_TEST_GET_OR_FALLBACK(integer, offset_datetime); - TOML11_TEST_GET_OR_FALLBACK(integer, array ); - TOML11_TEST_GET_OR_FALLBACK(integer, table ); - - TOML11_TEST_GET_OR_FALLBACK(floating, boolean ); - TOML11_TEST_GET_OR_FALLBACK(floating, integer ); - TOML11_TEST_GET_OR_FALLBACK(floating, string ); - TOML11_TEST_GET_OR_FALLBACK(floating, local_time ); - TOML11_TEST_GET_OR_FALLBACK(floating, local_date ); - TOML11_TEST_GET_OR_FALLBACK(floating, local_datetime ); - TOML11_TEST_GET_OR_FALLBACK(floating, offset_datetime); - TOML11_TEST_GET_OR_FALLBACK(floating, array ); - TOML11_TEST_GET_OR_FALLBACK(floating, table ); - - TOML11_TEST_GET_OR_FALLBACK(string, boolean ); - TOML11_TEST_GET_OR_FALLBACK(string, integer ); - TOML11_TEST_GET_OR_FALLBACK(string, floating ); - TOML11_TEST_GET_OR_FALLBACK(string, local_time ); - TOML11_TEST_GET_OR_FALLBACK(string, local_date ); - TOML11_TEST_GET_OR_FALLBACK(string, local_datetime ); - TOML11_TEST_GET_OR_FALLBACK(string, offset_datetime); - TOML11_TEST_GET_OR_FALLBACK(string, array ); - TOML11_TEST_GET_OR_FALLBACK(string, table ); - - TOML11_TEST_GET_OR_FALLBACK(local_time, boolean ); - TOML11_TEST_GET_OR_FALLBACK(local_time, integer ); - TOML11_TEST_GET_OR_FALLBACK(local_time, floating ); - TOML11_TEST_GET_OR_FALLBACK(local_time, string ); - TOML11_TEST_GET_OR_FALLBACK(local_time, local_date ); - TOML11_TEST_GET_OR_FALLBACK(local_time, local_datetime ); - TOML11_TEST_GET_OR_FALLBACK(local_time, offset_datetime); - TOML11_TEST_GET_OR_FALLBACK(local_time, array ); - TOML11_TEST_GET_OR_FALLBACK(local_time, table ); - - TOML11_TEST_GET_OR_FALLBACK(local_date, boolean ); - TOML11_TEST_GET_OR_FALLBACK(local_date, integer ); - TOML11_TEST_GET_OR_FALLBACK(local_date, floating ); - TOML11_TEST_GET_OR_FALLBACK(local_date, string ); - TOML11_TEST_GET_OR_FALLBACK(local_date, local_time ); - TOML11_TEST_GET_OR_FALLBACK(local_date, local_datetime ); - TOML11_TEST_GET_OR_FALLBACK(local_date, offset_datetime); - TOML11_TEST_GET_OR_FALLBACK(local_date, array ); - TOML11_TEST_GET_OR_FALLBACK(local_date, table ); - - TOML11_TEST_GET_OR_FALLBACK(local_datetime, boolean ); - TOML11_TEST_GET_OR_FALLBACK(local_datetime, integer ); - TOML11_TEST_GET_OR_FALLBACK(local_datetime, floating ); - TOML11_TEST_GET_OR_FALLBACK(local_datetime, string ); - TOML11_TEST_GET_OR_FALLBACK(local_datetime, local_time ); - TOML11_TEST_GET_OR_FALLBACK(local_datetime, local_date ); - TOML11_TEST_GET_OR_FALLBACK(local_datetime, offset_datetime); - TOML11_TEST_GET_OR_FALLBACK(local_datetime, array ); - TOML11_TEST_GET_OR_FALLBACK(local_datetime, table ); - - TOML11_TEST_GET_OR_FALLBACK(offset_datetime, boolean ); - TOML11_TEST_GET_OR_FALLBACK(offset_datetime, integer ); - TOML11_TEST_GET_OR_FALLBACK(offset_datetime, floating ); - TOML11_TEST_GET_OR_FALLBACK(offset_datetime, string ); - TOML11_TEST_GET_OR_FALLBACK(offset_datetime, local_time ); - TOML11_TEST_GET_OR_FALLBACK(offset_datetime, local_date ); - TOML11_TEST_GET_OR_FALLBACK(offset_datetime, local_datetime ); - TOML11_TEST_GET_OR_FALLBACK(offset_datetime, array ); - TOML11_TEST_GET_OR_FALLBACK(offset_datetime, table ); - - TOML11_TEST_GET_OR_FALLBACK(array, boolean ); - TOML11_TEST_GET_OR_FALLBACK(array, integer ); - TOML11_TEST_GET_OR_FALLBACK(array, floating ); - TOML11_TEST_GET_OR_FALLBACK(array, string ); - TOML11_TEST_GET_OR_FALLBACK(array, local_time ); - TOML11_TEST_GET_OR_FALLBACK(array, local_date ); - TOML11_TEST_GET_OR_FALLBACK(array, local_datetime ); - TOML11_TEST_GET_OR_FALLBACK(array, offset_datetime); - TOML11_TEST_GET_OR_FALLBACK(array, table ); - - TOML11_TEST_GET_OR_FALLBACK(table, boolean ); - TOML11_TEST_GET_OR_FALLBACK(table, integer ); - TOML11_TEST_GET_OR_FALLBACK(table, floating ); - TOML11_TEST_GET_OR_FALLBACK(table, string ); - TOML11_TEST_GET_OR_FALLBACK(table, local_time ); - TOML11_TEST_GET_OR_FALLBACK(table, local_date ); - TOML11_TEST_GET_OR_FALLBACK(table, local_datetime ); - TOML11_TEST_GET_OR_FALLBACK(table, offset_datetime); - TOML11_TEST_GET_OR_FALLBACK(table, array ); -} -#undef TOML11_TEST_GET_OR_FALLBACK - -BOOST_AUTO_TEST_CASE(test_get_or_integer) -{ - { - toml::value v1(42); - toml::value v2(3.14); - BOOST_TEST(42u == toml::get_or(v1, 0u)); - BOOST_TEST(0u == toml::get_or(v2, 0u)); - } - { - toml::value v1(42); - toml::value v2(3.14); - BOOST_TEST(42u == toml::get_or(std::move(v1), 0u)); - BOOST_TEST(0u == toml::get_or(std::move(v2), 0u)); - } - -} - -BOOST_AUTO_TEST_CASE(test_get_or_floating) -{ - { - toml::value v1(42); - toml::value v2(3.14); - BOOST_TEST(2.71f == toml::get_or(v1, 2.71f)); - BOOST_TEST(static_cast(v2.as_floating()) == toml::get_or(v2, 2.71f)); - } - { - toml::value v1(42); - toml::value v2(3.14); - BOOST_TEST(2.71f == toml::get_or(std::move(v1), 2.71f)); - BOOST_TEST(static_cast(3.14) == toml::get_or(std::move(v2), 2.71f)); - } -} - -BOOST_AUTO_TEST_CASE(test_get_or_string) -{ - { - toml::value v1("foobar"); - toml::value v2(42); - - std::string s1("bazqux"); - const std::string s2("bazqux"); - - BOOST_TEST("foobar" == toml::get_or(v1, s1)); - BOOST_TEST("bazqux" == toml::get_or(v2, s1)); - - std::string& v1r = toml::get_or(v1, s1); - std::string& s1r = toml::get_or(v2, s1); - - BOOST_TEST("foobar" == v1r); - BOOST_TEST("bazqux" == s1r); - - BOOST_TEST("foobar" == toml::get_or(v1, s2)); - BOOST_TEST("bazqux" == toml::get_or(v2, s2)); - - BOOST_TEST("foobar" == toml::get_or(v1, std::move(s1))); - BOOST_TEST("bazqux" == toml::get_or(v2, std::move(s1))); - } - { - toml::value v1("foobar"); - toml::value v2(42); - - std::string s1("bazqux"); - const std::string s2("bazqux"); - - BOOST_TEST("foobar" == toml::get_or(std::move(v1), s1)); - BOOST_TEST("bazqux" == toml::get_or(std::move(v2), s1)); - } - { - toml::value v1("foobar"); - toml::value v2(42); - - BOOST_TEST("foobar" == toml::get_or(v1, "bazqux")); - BOOST_TEST("bazqux" == toml::get_or(v2, "bazqux")); - - const char* lit = "bazqux"; - BOOST_TEST("foobar" == toml::get_or(v1, lit)); - BOOST_TEST("bazqux" == toml::get_or(v2, lit)); - } - { - toml::value v1("foobar"); - toml::value v2(42); - - BOOST_TEST("foobar" == toml::get_or(std::move(v1), "bazqux")); - BOOST_TEST("bazqux" == toml::get_or(std::move(v2), "bazqux")); - } - { - toml::value v1("foobar"); - toml::value v2(42); - - const char* lit = "bazqux"; - BOOST_TEST("foobar" == toml::get_or(v1, lit)); - BOOST_TEST("bazqux" == toml::get_or(v2, lit)); - } - -} diff --git a/lib/toml/tests/test_lex_aux.hpp b/lib/toml/tests/test_lex_aux.hpp deleted file mode 100644 index 77f2a9b..0000000 --- a/lib/toml/tests/test_lex_aux.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#include -#include -#include - -#define TOML11_TEST_LEX_ACCEPT(lxr, tkn, expct) \ -do { \ - const std::string token (tkn); \ - const std::string expected(expct); \ - toml::detail::location loc("test", token); \ - const auto result = lxr::invoke(loc); \ - BOOST_TEST(result.is_ok()); \ - if(result.is_ok()){ \ - const auto region = result.unwrap(); \ - BOOST_TEST(region.str() == expected); \ - BOOST_TEST(region.str().size() == expected.size()); \ - BOOST_TEST(static_cast(std::distance( \ - loc.begin(), loc.iter())) == region.size()); \ - } else { \ - std::cerr << "lexer failed with input `"; \ - std::cerr << token << "`. expected `" << expected << "`\n"; \ - std::cerr << "reason: " << result.unwrap_err() << '\n'; \ - } \ -} while(false); \ -/**/ - -#define TOML11_TEST_LEX_REJECT(lxr, tkn) \ -do { \ - const std::string token (tkn); \ - toml::detail::location loc("test", token); \ - const auto result = lxr::invoke(loc); \ - BOOST_TEST(result.is_err()); \ - const bool loc_same = (loc.begin() == loc.iter()); \ - BOOST_TEST(loc_same); \ -} while(false); /**/ diff --git a/lib/toml/tests/test_lex_boolean.cpp b/lib/toml/tests/test_lex_boolean.cpp deleted file mode 100644 index c2e43a8..0000000 --- a/lib/toml/tests/test_lex_boolean.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#define BOOST_TEST_MODULE "test_lex_boolean" -#include -#include -#include "test_lex_aux.hpp" - -using namespace toml; -using namespace detail; - -BOOST_AUTO_TEST_CASE(test_correct) -{ - TOML11_TEST_LEX_ACCEPT(lex_boolean, "true", "true"); - TOML11_TEST_LEX_ACCEPT(lex_boolean, "false", "false"); - TOML11_TEST_LEX_ACCEPT(lex_boolean, "true # trailing", "true"); - TOML11_TEST_LEX_ACCEPT(lex_boolean, "false # trailing", "false"); -} - -BOOST_AUTO_TEST_CASE(test_invalid) -{ - TOML11_TEST_LEX_REJECT(lex_boolean, "TRUE"); - TOML11_TEST_LEX_REJECT(lex_boolean, "FALSE"); - TOML11_TEST_LEX_REJECT(lex_boolean, "True"); - TOML11_TEST_LEX_REJECT(lex_boolean, "False"); -} diff --git a/lib/toml/tests/test_lex_datetime.cpp b/lib/toml/tests/test_lex_datetime.cpp deleted file mode 100644 index a790eeb..0000000 --- a/lib/toml/tests/test_lex_datetime.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#define BOOST_TEST_MODULE "test_lex_datetime" -#include -#include -#include "test_lex_aux.hpp" - -using namespace toml; -using namespace detail; - -BOOST_AUTO_TEST_CASE(test_offset_datetime) -{ - TOML11_TEST_LEX_ACCEPT(lex_offset_date_time, - "1979-05-27T07:32:00Z", - "1979-05-27T07:32:00Z"); - TOML11_TEST_LEX_ACCEPT(lex_offset_date_time, - "1979-05-27T07:32:00-07:00", - "1979-05-27T07:32:00-07:00"); - TOML11_TEST_LEX_ACCEPT(lex_offset_date_time, - "1979-05-27T07:32:00.999999-07:00", - "1979-05-27T07:32:00.999999-07:00"); - - TOML11_TEST_LEX_ACCEPT(lex_offset_date_time, - "1979-05-27 07:32:00Z", - "1979-05-27 07:32:00Z"); - TOML11_TEST_LEX_ACCEPT(lex_offset_date_time, - "1979-05-27 07:32:00-07:00", - "1979-05-27 07:32:00-07:00"); - TOML11_TEST_LEX_ACCEPT(lex_offset_date_time, - "1979-05-27 07:32:00.999999-07:00", - "1979-05-27 07:32:00.999999-07:00"); -} - -BOOST_AUTO_TEST_CASE(test_local_datetime) -{ - TOML11_TEST_LEX_ACCEPT(lex_local_date_time, - "1979-05-27T07:32:00", - "1979-05-27T07:32:00"); - TOML11_TEST_LEX_ACCEPT(lex_local_date_time, - "1979-05-27T07:32:00.999999", - "1979-05-27T07:32:00.999999"); - - TOML11_TEST_LEX_ACCEPT(lex_local_date_time, - "1979-05-27 07:32:00", - "1979-05-27 07:32:00"); - TOML11_TEST_LEX_ACCEPT(lex_local_date_time, - "1979-05-27 07:32:00.999999", - "1979-05-27 07:32:00.999999"); -} - -BOOST_AUTO_TEST_CASE(test_local_date) -{ - TOML11_TEST_LEX_ACCEPT(lex_local_date, "1979-05-27", "1979-05-27"); -} -BOOST_AUTO_TEST_CASE(test_local_time) -{ - TOML11_TEST_LEX_ACCEPT(lex_local_time, "07:32:00", "07:32:00"); - TOML11_TEST_LEX_ACCEPT(lex_local_time, "07:32:00.999999", "07:32:00.999999"); -} diff --git a/lib/toml/tests/test_lex_floating.cpp b/lib/toml/tests/test_lex_floating.cpp deleted file mode 100644 index 9c5c809..0000000 --- a/lib/toml/tests/test_lex_floating.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#define BOOST_TEST_MODULE "test_lex_floating" -#include -#include -#include -#include "test_lex_aux.hpp" - -using namespace toml; -using namespace detail; - -BOOST_AUTO_TEST_CASE(test_fractional_valid) -{ - TOML11_TEST_LEX_ACCEPT(lex_float, "1.0", "1.0" ); - TOML11_TEST_LEX_ACCEPT(lex_float, "0.1", "0.1" ); - TOML11_TEST_LEX_ACCEPT(lex_float, "0.001", "0.001" ); - TOML11_TEST_LEX_ACCEPT(lex_float, "0.100", "0.100" ); - TOML11_TEST_LEX_ACCEPT(lex_float, "+3.14", "+3.14" ); - TOML11_TEST_LEX_ACCEPT(lex_float, "-3.14", "-3.14" ); - TOML11_TEST_LEX_ACCEPT(lex_float, "3.1415_9265_3589", "3.1415_9265_3589" ); - TOML11_TEST_LEX_ACCEPT(lex_float, "+3.1415_9265_3589", "+3.1415_9265_3589"); - TOML11_TEST_LEX_ACCEPT(lex_float, "-3.1415_9265_3589", "-3.1415_9265_3589"); - TOML11_TEST_LEX_ACCEPT(lex_float, "123_456.789", "123_456.789" ); - TOML11_TEST_LEX_ACCEPT(lex_float, "+123_456.789", "+123_456.789" ); - TOML11_TEST_LEX_ACCEPT(lex_float, "-123_456.789", "-123_456.789" ); -} - -BOOST_AUTO_TEST_CASE(test_fractional_invalid) -{ - TOML11_TEST_LEX_REJECT(lex_float, "0."); - TOML11_TEST_LEX_REJECT(lex_float, ".0"); - TOML11_TEST_LEX_REJECT(lex_float, "01.0"); - TOML11_TEST_LEX_REJECT(lex_float, "3,14"); - TOML11_TEST_LEX_REJECT(lex_float, "+-1.0"); - TOML11_TEST_LEX_REJECT(lex_float, "1._0"); -} - -BOOST_AUTO_TEST_CASE(test_exponential_valid) -{ - TOML11_TEST_LEX_ACCEPT(lex_float, "1e10", "1e10"); - TOML11_TEST_LEX_ACCEPT(lex_float, "1e+10", "1e+10"); - TOML11_TEST_LEX_ACCEPT(lex_float, "1e-10", "1e-10"); - TOML11_TEST_LEX_ACCEPT(lex_float, "+1e10", "+1e10"); - TOML11_TEST_LEX_ACCEPT(lex_float, "+1e+10", "+1e+10"); - TOML11_TEST_LEX_ACCEPT(lex_float, "+1e-10", "+1e-10"); - TOML11_TEST_LEX_ACCEPT(lex_float, "-1e10", "-1e10"); - TOML11_TEST_LEX_ACCEPT(lex_float, "-1e+10", "-1e+10"); - TOML11_TEST_LEX_ACCEPT(lex_float, "-1e-10", "-1e-10"); - TOML11_TEST_LEX_ACCEPT(lex_float, "123e-10", "123e-10"); - TOML11_TEST_LEX_ACCEPT(lex_float, "1E10", "1E10"); - TOML11_TEST_LEX_ACCEPT(lex_float, "1E+10", "1E+10"); - TOML11_TEST_LEX_ACCEPT(lex_float, "1E-10", "1E-10"); - TOML11_TEST_LEX_ACCEPT(lex_float, "123E-10", "123E-10"); - TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-10", "1_2_3E-10"); - TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-1_0", "1_2_3E-1_0"); - -#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES - BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part"); - // toml-lang/toml master permits leading 0s in exp part (unreleased) - TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-01", "1_2_3E-01"); - TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-0_1", "1_2_3E-0_1"); -#endif -} - -BOOST_AUTO_TEST_CASE(test_exponential_invalid) -{ - // accept partially - TOML11_TEST_LEX_ACCEPT(lex_float, "1e1E0", "1e1"); - TOML11_TEST_LEX_ACCEPT(lex_float, "1E1e0", "1E1"); -} - -BOOST_AUTO_TEST_CASE(test_both_valid) -{ - TOML11_TEST_LEX_ACCEPT(lex_float, "6.02e23", "6.02e23"); - TOML11_TEST_LEX_ACCEPT(lex_float, "6.02e+23", "6.02e+23"); - TOML11_TEST_LEX_ACCEPT(lex_float, "1.112_650_06e-17", "1.112_650_06e-17"); - -#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES - BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part"); - // toml-lang/toml master permits leading 0s in exp part (unreleased) - TOML11_TEST_LEX_ACCEPT(lex_float, "1.0e-07", "1.0e-07"); -#endif -} - -BOOST_AUTO_TEST_CASE(test_both_invalid) -{ - TOML11_TEST_LEX_REJECT(lex_float, "01e1.0"); - // accept partially - TOML11_TEST_LEX_ACCEPT(lex_float, "1e1.0", "1e1"); - -#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES - BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part"); - // toml-lang/toml master permits leading 0s in exp part (unreleased) - TOML11_TEST_LEX_ACCEPT(lex_float, "1.0e_01", "1.0"); - TOML11_TEST_LEX_ACCEPT(lex_float, "1.0e0__1", "1.0e0"); -#endif -} - -BOOST_AUTO_TEST_CASE(test_special_floating_point) -{ - TOML11_TEST_LEX_ACCEPT(lex_float, "inf", "inf"); - TOML11_TEST_LEX_ACCEPT(lex_float, "+inf", "+inf"); - TOML11_TEST_LEX_ACCEPT(lex_float, "-inf", "-inf"); - - TOML11_TEST_LEX_ACCEPT(lex_float, "nan", "nan"); - TOML11_TEST_LEX_ACCEPT(lex_float, "+nan", "+nan"); - TOML11_TEST_LEX_ACCEPT(lex_float, "-nan", "-nan"); -} diff --git a/lib/toml/tests/test_lex_integer.cpp b/lib/toml/tests/test_lex_integer.cpp deleted file mode 100644 index bb6dbb7..0000000 --- a/lib/toml/tests/test_lex_integer.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#define BOOST_TEST_MODULE "test_lex_integer" -#include -#include -#include "test_lex_aux.hpp" - -using namespace toml; -using namespace detail; - -BOOST_AUTO_TEST_CASE(test_decimal_correct) -{ - TOML11_TEST_LEX_ACCEPT(lex_integer, "1234", "1234" ); - TOML11_TEST_LEX_ACCEPT(lex_integer, "+1234", "+1234" ); - TOML11_TEST_LEX_ACCEPT(lex_integer, "-1234", "-1234" ); - TOML11_TEST_LEX_ACCEPT(lex_integer, "0", "0" ); - TOML11_TEST_LEX_ACCEPT(lex_integer, "1_2_3_4", "1_2_3_4" ); - TOML11_TEST_LEX_ACCEPT(lex_integer, "+1_2_3_4", "+1_2_3_4" ); - TOML11_TEST_LEX_ACCEPT(lex_integer, "-1_2_3_4", "-1_2_3_4" ); - TOML11_TEST_LEX_ACCEPT(lex_integer, "123_456_789", "123_456_789"); -} - -BOOST_AUTO_TEST_CASE(test_decimal_invalid) -{ - TOML11_TEST_LEX_ACCEPT(lex_integer, "123+45", "123"); - TOML11_TEST_LEX_ACCEPT(lex_integer, "123-45", "123"); - TOML11_TEST_LEX_ACCEPT(lex_integer, "01234", "0"); - TOML11_TEST_LEX_ACCEPT(lex_integer, "123__45", "123"); - - TOML11_TEST_LEX_REJECT(lex_integer, "_1234"); -} - -BOOST_AUTO_TEST_CASE(test_hex_correct) -{ - TOML11_TEST_LEX_ACCEPT(lex_integer, "0xDEADBEEF", "0xDEADBEEF" ); - TOML11_TEST_LEX_ACCEPT(lex_integer, "0xdeadbeef", "0xdeadbeef" ); - TOML11_TEST_LEX_ACCEPT(lex_integer, "0xDEADbeef", "0xDEADbeef" ); - TOML11_TEST_LEX_ACCEPT(lex_integer, "0xDEAD_BEEF", "0xDEAD_BEEF"); - TOML11_TEST_LEX_ACCEPT(lex_integer, "0xdead_beef", "0xdead_beef"); - TOML11_TEST_LEX_ACCEPT(lex_integer, "0xdead_BEEF", "0xdead_BEEF"); - - TOML11_TEST_LEX_ACCEPT(lex_integer, "0xFF", "0xFF" ); - TOML11_TEST_LEX_ACCEPT(lex_integer, "0x00FF", "0x00FF" ); - TOML11_TEST_LEX_ACCEPT(lex_integer, "0x0000FF", "0x0000FF"); -} - -BOOST_AUTO_TEST_CASE(test_hex_invalid) -{ - TOML11_TEST_LEX_ACCEPT(lex_integer, "0xAPPLE", "0xA"); - TOML11_TEST_LEX_ACCEPT(lex_integer, "0xDEAD+BEEF", "0xDEAD"); - TOML11_TEST_LEX_ACCEPT(lex_integer, "0xDEAD__BEEF", "0xDEAD"); - - TOML11_TEST_LEX_REJECT(lex_hex_int, "0x_DEADBEEF"); - TOML11_TEST_LEX_REJECT(lex_hex_int, "0x+DEADBEEF"); - TOML11_TEST_LEX_REJECT(lex_hex_int, "-0xFF" ); - TOML11_TEST_LEX_REJECT(lex_hex_int, "-0x00FF" ); - - TOML11_TEST_LEX_ACCEPT(lex_integer, "0x_DEADBEEF", "0" ); - TOML11_TEST_LEX_ACCEPT(lex_integer, "0x+DEADBEEF", "0" ); - TOML11_TEST_LEX_ACCEPT(lex_integer, "-0xFF" , "-0" ); - TOML11_TEST_LEX_ACCEPT(lex_integer, "-0x00FF" , "-0" ); -} - -BOOST_AUTO_TEST_CASE(test_oct_correct) -{ - TOML11_TEST_LEX_ACCEPT(lex_integer, "0o777", "0o777" ); - TOML11_TEST_LEX_ACCEPT(lex_integer, "0o7_7_7", "0o7_7_7"); - TOML11_TEST_LEX_ACCEPT(lex_integer, "0o007", "0o007" ); - -} - -BOOST_AUTO_TEST_CASE(test_oct_invalid) -{ - TOML11_TEST_LEX_ACCEPT(lex_integer, "0o77+7", "0o77"); - TOML11_TEST_LEX_ACCEPT(lex_integer, "0o1__0", "0o1"); - - TOML11_TEST_LEX_REJECT(lex_oct_int, "0o800" ); - TOML11_TEST_LEX_REJECT(lex_oct_int, "-0o777"); - TOML11_TEST_LEX_REJECT(lex_oct_int, "0o+777"); - TOML11_TEST_LEX_REJECT(lex_oct_int, "0o_10" ); - - TOML11_TEST_LEX_ACCEPT(lex_integer, "0o800", "0"); - TOML11_TEST_LEX_ACCEPT(lex_integer, "-0o777", "-0"); - TOML11_TEST_LEX_ACCEPT(lex_integer, "0o+777", "0"); - TOML11_TEST_LEX_ACCEPT(lex_integer, "0o_10", "0"); -} - -BOOST_AUTO_TEST_CASE(test_bin_correct) -{ - TOML11_TEST_LEX_ACCEPT(lex_integer, "0b10000", "0b10000" ); - TOML11_TEST_LEX_ACCEPT(lex_integer, "0b010000", "0b010000" ); - TOML11_TEST_LEX_ACCEPT(lex_integer, "0b01_00_00", "0b01_00_00"); - TOML11_TEST_LEX_ACCEPT(lex_integer, "0b111111", "0b111111" ); -} - -BOOST_AUTO_TEST_CASE(test_bin_invalid) -{ - TOML11_TEST_LEX_ACCEPT(lex_bin_int, "0b11__11", "0b11"); - TOML11_TEST_LEX_ACCEPT(lex_bin_int, "0b11+11" , "0b11"); - - TOML11_TEST_LEX_REJECT(lex_bin_int, "-0b10000"); - TOML11_TEST_LEX_REJECT(lex_bin_int, "0b_1111" ); -} diff --git a/lib/toml/tests/test_lex_key_comment.cpp b/lib/toml/tests/test_lex_key_comment.cpp deleted file mode 100644 index 0921bd6..0000000 --- a/lib/toml/tests/test_lex_key_comment.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#define BOOST_TEST_MODULE "lex_key_comment_test" -#include -#include -#include "test_lex_aux.hpp" - -using namespace toml; -using namespace detail; - -BOOST_AUTO_TEST_CASE(test_bare_key) -{ - TOML11_TEST_LEX_ACCEPT(lex_key, "barekey", "barekey"); - TOML11_TEST_LEX_ACCEPT(lex_key, "bare-key", "bare-key"); - TOML11_TEST_LEX_ACCEPT(lex_key, "bare_key", "bare_key"); - TOML11_TEST_LEX_ACCEPT(lex_key, "1234", "1234"); -} - -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, "\"character encoding\"", "\"character encoding\""); - - // UTF-8 codepoint of characters that looks like "key" written upside down - TOML11_TEST_LEX_ACCEPT(lex_key, "\"\xCA\x8E\xC7\x9D\xCA\x9E\"", - "\"\xCA\x8E\xC7\x9D\xCA\x9E\""); - - TOML11_TEST_LEX_ACCEPT(lex_key, "'key2'", "'key2'"); - TOML11_TEST_LEX_ACCEPT(lex_key, "'quoted \"value\"'", "'quoted \"value\"'"); -} - -BOOST_AUTO_TEST_CASE(test_dotted_key) -{ - TOML11_TEST_LEX_ACCEPT(lex_key, "physical.color", "physical.color"); - TOML11_TEST_LEX_ACCEPT(lex_key, "physical.shape", "physical.shape"); - TOML11_TEST_LEX_ACCEPT(lex_key, "x.y", "x.y"); - TOML11_TEST_LEX_ACCEPT(lex_key, "x . y", "x . y"); - TOML11_TEST_LEX_ACCEPT(lex_key, "x.y.z", "x.y.z"); - TOML11_TEST_LEX_ACCEPT(lex_key, "x. y .z", "x. y .z"); - TOML11_TEST_LEX_ACCEPT(lex_key, "x .y. z", "x .y. z"); - TOML11_TEST_LEX_ACCEPT(lex_key, "x . y . z", "x . y . z"); - TOML11_TEST_LEX_ACCEPT(lex_key, "x.y.z.w", "x.y.z.w"); - TOML11_TEST_LEX_ACCEPT(lex_key, "x. y .z. w", "x. y .z. w"); - TOML11_TEST_LEX_ACCEPT(lex_key, "x . y . z . w", "x . y . z . w"); - TOML11_TEST_LEX_ACCEPT(lex_key, "site.\"google.com\"", "site.\"google.com\""); -} - -BOOST_AUTO_TEST_CASE(test_comment) -{ - TOML11_TEST_LEX_ACCEPT(lex_comment, "# hoge", "# hoge"); - TOML11_TEST_LEX_ACCEPT(lex_comment, "# \n", "# "); - TOML11_TEST_LEX_ACCEPT(lex_comment, "# \r\n", "# "); - TOML11_TEST_LEX_ACCEPT(lex_comment, "# # \n", "# # "); -} diff --git a/lib/toml/tests/test_lex_string.cpp b/lib/toml/tests/test_lex_string.cpp deleted file mode 100644 index 643ab31..0000000 --- a/lib/toml/tests/test_lex_string.cpp +++ /dev/null @@ -1,108 +0,0 @@ -#define BOOST_TEST_MODULE "test_lex_string" -#include -#include -#include "test_lex_aux.hpp" - -using namespace toml; -using namespace detail; - -BOOST_AUTO_TEST_CASE(test_string) -{ - TOML11_TEST_LEX_ACCEPT(lex_string, - "\"The quick brown fox jumps over the lazy dog\"", - "\"The quick brown fox jumps over the lazy dog\""); - TOML11_TEST_LEX_ACCEPT(lex_string, - "\'The quick brown fox jumps over the lazy dog\'", - "\'The quick brown fox jumps over the lazy dog\'"); - TOML11_TEST_LEX_ACCEPT(lex_ml_basic_string, - "\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\"", - "\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\""); - TOML11_TEST_LEX_ACCEPT(lex_ml_literal_string, - "'''The quick brown fox \njumps over the lazy dog'''", - "'''The quick brown fox \njumps over the lazy dog'''"); -} - -BOOST_AUTO_TEST_CASE(test_basic_string) -{ - TOML11_TEST_LEX_ACCEPT(lex_string, - "\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"", - "\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\""); - TOML11_TEST_LEX_ACCEPT(lex_string, - "\"192.168.1.1\"", - "\"192.168.1.1\""); - - TOML11_TEST_LEX_ACCEPT(lex_string, - "\"\xE4\xB8\xAD\xE5\x9B\xBD\"", // UTF-8 string (means "China" in - "\"\xE4\xB8\xAD\xE5\x9B\xBD\""); // Chinese characters) - - TOML11_TEST_LEX_ACCEPT(lex_string, - "\"You'll hate me after this - #\"", - "\"You'll hate me after this - #\""); - TOML11_TEST_LEX_ACCEPT(lex_string, - "\" And when \\\"'s are in the string, along with # \\\"\"", - "\" And when \\\"'s are in the string, along with # \\\"\""); -} - -BOOST_AUTO_TEST_CASE(test_ml_basic_string) -{ - TOML11_TEST_LEX_ACCEPT(lex_string, - "\"\"\"\nThe quick brown \\\n\n fox jumps over \\\n the lazy dog.\"\"\"", - "\"\"\"\nThe quick brown \\\n\n fox jumps over \\\n the lazy dog.\"\"\""); - TOML11_TEST_LEX_ACCEPT(lex_string, - "\"\"\"\\\n The quick brown \\\n\n fox jumps over \\\n the lazy dog.\\\n \"\"\"", - "\"\"\"\\\n The quick brown \\\n\n fox jumps over \\\n the lazy dog.\\\n \"\"\""); - - TOML11_TEST_LEX_ACCEPT(lex_string, - "\"\"\"Here are two quotation marks: \"\". Simple enough.\"\"\"", - "\"\"\"Here are two quotation marks: \"\". Simple enough.\"\"\""); - - TOML11_TEST_LEX_ACCEPT(lex_string, - "\"\"\"Here are three quotation marks: \"\"\\\".\"\"\"", - "\"\"\"Here are three quotation marks: \"\"\\\".\"\"\""); - - TOML11_TEST_LEX_ACCEPT(lex_string, - "\"\"\"Here are fifteen quotation marks: \"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\".\"\"\"", - "\"\"\"Here are fifteen quotation marks: \"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\".\"\"\""); - - TOML11_TEST_LEX_ACCEPT(lex_string, - "\"\"\"\"This,\" she said, \"is just a pointless statement.\"\"\"\"", - "\"\"\"\"This,\" she said, \"is just a pointless statement.\"\"\"\""); -} - -BOOST_AUTO_TEST_CASE(test_literal_string) -{ - TOML11_TEST_LEX_ACCEPT(lex_string, - "'C:\\Users\\nodejs\\templates'", - "'C:\\Users\\nodejs\\templates'"); - TOML11_TEST_LEX_ACCEPT(lex_string, - "'\\\\ServerX\\admin$\\system32\\'", - "'\\\\ServerX\\admin$\\system32\\'"); - TOML11_TEST_LEX_ACCEPT(lex_string, - "'Tom \"Dubs\" Preston-Werner'", - "'Tom \"Dubs\" Preston-Werner'"); - TOML11_TEST_LEX_ACCEPT(lex_string, - "'<\\i\\c*\\s*>'", - "'<\\i\\c*\\s*>'"); -} - -BOOST_AUTO_TEST_CASE(test_ml_literal_string) -{ - TOML11_TEST_LEX_ACCEPT(lex_string, - "'''I [dw]on't need \\d{2} apples'''", - "'''I [dw]on't need \\d{2} apples'''"); - TOML11_TEST_LEX_ACCEPT(lex_string, - "'''\nThe first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n'''", - "'''\nThe first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n'''"); - - TOML11_TEST_LEX_ACCEPT(lex_string, - "''''That's still pointless', she said.'''", - "''''That's still pointless', she said.'''"); - - TOML11_TEST_LEX_ACCEPT(lex_string, - "'''Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".'''", - "'''Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".'''"); - - TOML11_TEST_LEX_ACCEPT(lex_string, - "''''This,' she said, 'is just a pointless statement.''''", - "''''This,' she said, 'is just a pointless statement.''''"); -} diff --git a/lib/toml/tests/test_literals.cpp b/lib/toml/tests/test_literals.cpp deleted file mode 100644 index 5aaf928..0000000 --- a/lib/toml/tests/test_literals.cpp +++ /dev/null @@ -1,340 +0,0 @@ -#define BOOST_TEST_MODULE "test_literals" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include - -BOOST_AUTO_TEST_CASE(test_file_as_literal) -{ - 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(v1)); - BOOST_TEST(!toml::get(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(v1) == 123456); - BOOST_TEST(toml::get(v2) == 2); - BOOST_TEST(toml::get(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(v1) == 3.1415, boost::test_tools::tolerance(0.00001)); - BOOST_TEST(toml::get(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(v1) == "foo"); - BOOST_TEST(toml::get(v2) == "foo"); - BOOST_TEST(toml::get(v3) == "foo"); - BOOST_TEST(toml::get(v4) == "foo"); - } - { - { - const toml::value v1 = R"([1,2,3])"_toml; - BOOST_TEST(v1.is_array()); - const bool result = (toml::get>(v1) == std::vector{1,2,3}); - BOOST_TEST(result); - } - { - const toml::value v2 = R"([1,])"_toml; - BOOST_TEST(v2.is_array()); - const bool result = (toml::get>(v2) == std::vector{1}); - BOOST_TEST(result); - } - { - const toml::value v3 = R"([[1,]])"_toml; - BOOST_TEST(v3.is_array()); - const bool result = (toml::get>(toml::get(v3).front()) == std::vector{1}); - BOOST_TEST(result); - } - { - const toml::value v4 = R"([[1],])"_toml; - BOOST_TEST(v4.is_array()); - const bool result = (toml::get>(toml::get(v4).front()) == std::vector{1}); - BOOST_TEST(result); - } - } - { - const toml::value v1 = R"({a = 42})"_toml; - - BOOST_TEST(v1.is_table()); - const bool result = toml::get>(v1) == - std::map{{"a", 42}}; - BOOST_TEST(result); - } - { - const toml::value v1 = "1979-05-27"_toml; - - BOOST_TEST(v1.is_local_date()); - BOOST_TEST(toml::get(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(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(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(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 v = u8R"( - 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 = u8R"( - 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 = u8R"( - [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 = u8R"( - [[array_of_tables]] - )"_toml; - - BOOST_TEST(r == v); - } -} - -BOOST_AUTO_TEST_CASE(test_value_as_u8_literal) -{ - using namespace toml::literals::toml_literals; - - { - const toml::value v1 = u8"true"_toml; - const toml::value v2 = u8"false"_toml; - - BOOST_TEST(v1.is_boolean()); - BOOST_TEST(v2.is_boolean()); - BOOST_TEST(toml::get(v1)); - BOOST_TEST(!toml::get(v2)); - } - { - const toml::value v1 = u8"123_456"_toml; - const toml::value v2 = u8"0b0010"_toml; - const toml::value v3 = u8"0xDEADBEEF"_toml; - - BOOST_TEST(v1.is_integer()); - BOOST_TEST(v2.is_integer()); - BOOST_TEST(v3.is_integer()); - BOOST_TEST(toml::get(v1) == 123456); - BOOST_TEST(toml::get(v2) == 2); - BOOST_TEST(toml::get(v3) == 0xDEADBEEF); - } - { - const toml::value v1 = u8"3.1415"_toml; - const toml::value v2 = u8"6.02e+23"_toml; - - BOOST_TEST(v1.is_floating()); - BOOST_TEST(v2.is_floating()); - BOOST_TEST(toml::get(v1) == 3.1415, boost::test_tools::tolerance(0.00001)); - BOOST_TEST(toml::get(v2) == 6.02e23, boost::test_tools::tolerance(0.0001)); - } - { - const toml::value v1 = u8R"("foo")"_toml; - const toml::value v2 = u8R"('foo')"_toml; - const toml::value v3 = u8R"("""foo""")"_toml; - const toml::value v4 = u8R"('''foo''')"_toml; - const toml::value v5 = u8R"("ひらがな")"_toml; - - BOOST_TEST(v1.is_string()); - BOOST_TEST(v2.is_string()); - BOOST_TEST(v3.is_string()); - BOOST_TEST(v4.is_string()); - BOOST_TEST(v5.is_string()); - BOOST_TEST(toml::get(v1) == "foo"); - BOOST_TEST(toml::get(v2) == "foo"); - BOOST_TEST(toml::get(v3) == "foo"); - BOOST_TEST(toml::get(v4) == "foo"); - BOOST_TEST(toml::get(v5) == "\xE3\x81\xB2\xE3\x82\x89\xE3\x81\x8C\xE3\x81\xAA"); - } - { - { - const toml::value v1 = u8R"([1,2,3])"_toml; - BOOST_TEST(v1.is_array()); - const bool result = (toml::get>(v1) == std::vector{1,2,3}); - BOOST_TEST(result); - } - { - const toml::value v2 = u8R"([1,])"_toml; - BOOST_TEST(v2.is_array()); - const bool result = (toml::get>(v2) == std::vector{1}); - BOOST_TEST(result); - } - { - const toml::value v3 = u8R"([[1,]])"_toml; - BOOST_TEST(v3.is_array()); - const bool result = (toml::get>(toml::get(v3).front()) == std::vector{1}); - BOOST_TEST(result); - } - { - const toml::value v4 = u8R"([[1],])"_toml; - BOOST_TEST(v4.is_array()); - const bool result = (toml::get>(toml::get(v4).front()) == std::vector{1}); - BOOST_TEST(result); - } - } - { - const toml::value v1 = u8R"({a = 42})"_toml; - - BOOST_TEST(v1.is_table()); - const bool result = toml::get>(v1) == - std::map{{"a", 42}}; - BOOST_TEST(result); - } - { - const toml::value v1 = u8"1979-05-27"_toml; - - BOOST_TEST(v1.is_local_date()); - BOOST_TEST(toml::get(v1) == - toml::local_date(1979, toml::month_t::May, 27)); - } - { - const toml::value v1 = u8"12:00:00"_toml; - - BOOST_TEST(v1.is_local_time()); - const bool result = toml::get(v1) == std::chrono::hours(12); - BOOST_TEST(result); - } - { - const toml::value v1 = u8"1979-05-27T07:32:00"_toml; - BOOST_TEST(v1.is_local_datetime()); - BOOST_TEST(toml::get(v1) == - toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), - toml::local_time(7, 32, 0))); - } - { - const toml::value v1 = u8"1979-05-27T07:32:00Z"_toml; - BOOST_TEST(v1.is_offset_datetime()); - BOOST_TEST(toml::get(v1) == - toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), - toml::local_time(7, 32, 0), toml::time_offset(0, 0))); - } -} diff --git a/lib/toml/tests/test_multiple_translation_unit_1.cpp b/lib/toml/tests/test_multiple_translation_unit_1.cpp deleted file mode 100644 index 08a4f98..0000000 --- a/lib/toml/tests/test_multiple_translation_unit_1.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include - -int read_a(const toml::table&); - -int main() -{ - const std::string content("a = 0"); - std::istringstream iss(content); - const auto data = toml::parse(iss, "test_multiple_translation_unit.toml"); - return read_a(toml::get(data)); -} diff --git a/lib/toml/tests/test_multiple_translation_unit_2.cpp b/lib/toml/tests/test_multiple_translation_unit_2.cpp deleted file mode 100644 index 2a4cc32..0000000 --- a/lib/toml/tests/test_multiple_translation_unit_2.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include - -int read_a(const toml::table& t) -{ - return toml::get(t.at("a")); -} diff --git a/lib/toml/tests/test_parse_array.cpp b/lib/toml/tests/test_parse_array.cpp deleted file mode 100644 index a75a6f1..0000000 --- a/lib/toml/tests/test_parse_array.cpp +++ /dev/null @@ -1,293 +0,0 @@ -#define BOOST_TEST_MODULE "parse_array_test" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include "test_parse_aux.hpp" - -using namespace toml; -using namespace detail; - -BOOST_AUTO_TEST_CASE(test_oneline_array) -{ - TOML11_TEST_PARSE_EQUAL(parse_array, "[]", array()); - { - array a(5); - a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); - a[3] = toml::value(1); a[4] = toml::value(5); - TOML11_TEST_PARSE_EQUAL(parse_array, "[3,1,4,1,5]", a); - } - { - array a(3); - a[0] = toml::value("foo"); a[1] = toml::value("bar"); - a[2] = toml::value("baz"); - TOML11_TEST_PARSE_EQUAL(parse_array, "[\"foo\", \"bar\", \"baz\"]", a); - } - { - array a(5); - a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); - a[3] = toml::value(1); a[4] = toml::value(5); - TOML11_TEST_PARSE_EQUAL(parse_array, "[3,1,4,1,5,]", a); - } - { - array a(3); - a[0] = toml::value("foo"); a[1] = toml::value("bar"); - a[2] = toml::value("baz"); - TOML11_TEST_PARSE_EQUAL(parse_array, "[\"foo\", \"bar\", \"baz\",]", a); - } -} - -BOOST_AUTO_TEST_CASE(test_oneline_array_value) -{ - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[]", toml::value(array())); - { - array a(5); - a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); - a[3] = toml::value(1); a[4] = toml::value(5); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[3,1,4,1,5]", toml::value(a)); - } - { - array a(3); - a[0] = toml::value("foo"); a[1] = toml::value("bar"); - a[2] = toml::value("baz"); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\", \"bar\", \"baz\"]", toml::value(a)); - } - { - array a(5); - a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); - a[3] = toml::value(1); a[4] = toml::value(5); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[3,1,4,1,5,]", toml::value(a)); - } - { - array a(3); - a[0] = toml::value("foo"); a[1] = toml::value("bar"); - a[2] = toml::value("baz"); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\", \"bar\", \"baz\",]", toml::value(a)); - } -} - -BOOST_AUTO_TEST_CASE(test_multiline_array) -{ - TOML11_TEST_PARSE_EQUAL(parse_array>, "[\n#comment\n]", typename basic_value< discard_comments>::array_type()); - TOML11_TEST_PARSE_EQUAL(parse_array>, "[\n#comment\n]", typename basic_value::array_type()); - - { - typename basic_value::array_type a(5); - a[0] = basic_value(3); - a[1] = basic_value(1); - a[2] = basic_value(4); - a[3] = basic_value(1); - a[4] = basic_value(5); - TOML11_TEST_PARSE_EQUAL(parse_array>, "[3,\n1,\n4,\n1,\n5]", a); - } - { - typename basic_value::array_type a(5); - a[0] = basic_value(3); - a[1] = basic_value(1); - a[2] = basic_value(4); - a[3] = basic_value(1); - a[4] = basic_value(5); - TOML11_TEST_PARSE_EQUAL(parse_array>, "[3,\n1,\n4,\n1,\n5]", a); - } - - { - typename basic_value::array_type a(5); - a[0] = basic_value(3); - a[1] = basic_value(1); - a[2] = basic_value(4); - a[3] = basic_value(1); - a[4] = basic_value(5); - TOML11_TEST_PARSE_EQUAL(parse_array>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5 #comment\n]", a); - } - { - typename basic_value::array_type a(5); - a[0] = basic_value(3, {"comment"}); - a[1] = basic_value(1, {"comment"}); - a[2] = basic_value(4, {"comment"}); - a[3] = basic_value(1, {"comment"}); - a[4] = basic_value(5, {"comment"}); - TOML11_TEST_PARSE_EQUAL(parse_array>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5 #comment\n]", a); - } - - - { - typename basic_value::array_type a(3); - a[0] = basic_value("foo"); - a[1] = basic_value("bar"); - a[2] = basic_value("baz"); - TOML11_TEST_PARSE_EQUAL(parse_array>, "[\"foo\",\n\"bar\",\n\"baz\"]", a); - } - { - typename basic_value::array_type a(3); - a[0] = basic_value("foo"); - a[1] = basic_value("bar"); - a[2] = basic_value("baz"); - TOML11_TEST_PARSE_EQUAL(parse_array>, "[\"foo\",\n\"bar\",\n\"baz\"]", a); - } - - { - typename basic_value::array_type a(3); - a[0] = basic_value("foo"); - a[1] = basic_value("b#r"); - a[2] = basic_value("b#z"); - TOML11_TEST_PARSE_EQUAL(parse_array>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", a); - } - { - typename basic_value::array_type a(3); - a[0] = basic_value("foo", {"comment"}); - a[1] = basic_value("b#r", {"comment"}); - a[2] = basic_value("b#z", {"comment"}); - TOML11_TEST_PARSE_EQUAL(parse_array>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", a); - } -} - -BOOST_AUTO_TEST_CASE(test_multiline_array_value) -{ - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, "[\n#comment\n]", basic_value< discard_comments>(typename basic_value< discard_comments>::array_type())); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, "[\n#comment\n]", basic_value(typename basic_value::array_type())); - - { - typename basic_value::array_type a(5); - a[0] = basic_value(3); - a[1] = basic_value(1); - a[2] = basic_value(4); - a[3] = basic_value(1); - a[4] = basic_value(5); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, "[3,\n1,\n4,\n1,\n5]", basic_value(a)); - } - { - typename basic_value::array_type a(5); - a[0] = basic_value(3); - a[1] = basic_value(1); - a[2] = basic_value(4); - a[3] = basic_value(1); - a[4] = basic_value(5); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, "[3,\n1,\n4,\n1,\n5]", basic_value(a)); - } - - { - typename basic_value::array_type a(5); - a[0] = basic_value(3); - a[1] = basic_value(1); - a[2] = basic_value(4); - a[3] = basic_value(1); - a[4] = basic_value(5); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5 #comment\n]", basic_value(a)); - } - { - typename basic_value::array_type a(5); - a[0] = basic_value(3, {"comment"}); - a[1] = basic_value(1, {"comment"}); - a[2] = basic_value(4, {"comment"}); - a[3] = basic_value(1, {"comment"}); - a[4] = basic_value(5, {"comment"}); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5 #comment\n]", basic_value(a)); - } - - - { - typename basic_value::array_type a(3); - a[0] = basic_value("foo"); - a[1] = basic_value("bar"); - a[2] = basic_value("baz"); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, "[\"foo\",\n\"bar\",\n\"baz\"]", basic_value(a)); - } - { - typename basic_value::array_type a(3); - a[0] = basic_value("foo"); - a[1] = basic_value("bar"); - a[2] = basic_value("baz"); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, "[\"foo\",\n\"bar\",\n\"baz\"]", basic_value(a)); - } - - { - typename basic_value::array_type a(3); - a[0] = basic_value("foo"); - a[1] = basic_value("b#r"); - a[2] = basic_value("b#z"); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", basic_value(a)); - } - { - typename basic_value::array_type a(3); - a[0] = basic_value("foo", {"comment"}); - a[1] = basic_value("b#r", {"comment"}); - a[2] = basic_value("b#z", {"comment"}); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", basic_value(a)); - } - -} - -BOOST_AUTO_TEST_CASE(test_heterogeneous_array) -{ -#ifndef TOML11_USE_UNRELEASED_TOML_FEATURES - BOOST_TEST_MESSAGE("In strict TOML v0.5.0, heterogeneous arrays are not allowed."); -#else - { - array a(5); - a[0] = toml::value("foo"); - a[1] = toml::value(3.14); - a[2] = toml::value(42); - a[3] = toml::value{toml::value("array"), toml::value("of"), toml::value("hetero-array"), toml::value(1)}; - a[4] = toml::value{{"key", "value"}}; - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\", 3.14, 42, [\"array\", \"of\", \"hetero-array\", 1], {key = \"value\"}]", toml::value(a)); - } - { - array a(5); - a[0] = toml::value("foo"); - a[1] = toml::value(3.14); - a[2] = toml::value(42); - a[3] = toml::value{toml::value("array"), toml::value("of"), toml::value("hetero-array"), toml::value(1)}; - a[4] = toml::value{{"key", "value"}}; - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\",\n 3.14,\n 42,\n [\"array\", \"of\", \"hetero-array\", 1],\n {key = \"value\"},\n]", toml::value(a)); - } - { - array a(5); - a[0] = toml::value("foo"); - a[1] = toml::value(3.14); - a[2] = toml::value(42); - a[3] = toml::value{toml::value("array"), toml::value("of"), toml::value("hetero-array"), toml::value(1)}; - a[4] = toml::value{{"key", "value"}}; - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\",#comment\n 3.14,#comment\n 42,#comment\n [\"array\", \"of\", \"hetero-array\", 1],#comment\n {key = \"value\"},#comment\n]#comment", toml::value(a)); - } - { - array a(5); - a[0] = toml::value("foo"); - a[1] = toml::value(3.14); - a[2] = toml::value(42); - a[3] = toml::value{toml::value("array"), toml::value("of"), toml::value("hetero-array"), toml::value(1)}; - a[4] = toml::value{{"key", "value"}}; - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\",\n 3.14,\n 42,\n [\"array\",\n \"of\",\n \"hetero-array\",\n 1],\n {key = \"value\"},\n]", toml::value(a)); - } -#endif -} - -BOOST_AUTO_TEST_CASE(test_comments_after_comma) -{ - { - typename basic_value::array_type a(3); - a[0] = basic_value("foo"); - a[1] = basic_value("bar"); - a[2] = basic_value("baz"); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, - "[ \"foo\" # comment\n" - ", \"bar\" # comment\n" - ", \"baz\" # comment\n" - "]", basic_value(a)); - } - - { - typename basic_value::array_type a(3); - a[0] = basic_value("foo", {" comment"}); - a[1] = basic_value("bar", {" comment"}); - a[2] = basic_value("baz", {" comment"}); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value>, - "[ \"foo\" # comment\n" - ", \"bar\" # comment\n" - ", \"baz\" # comment\n" - "]", basic_value(a)); - } - -} diff --git a/lib/toml/tests/test_parse_aux.hpp b/lib/toml/tests/test_parse_aux.hpp deleted file mode 100644 index b9fd07c..0000000 --- a/lib/toml/tests/test_parse_aux.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include -#include -#include - -// some of the parsers returns not only a value but also a region. -#define TOML11_TEST_PARSE_EQUAL(psr, tkn, expct) \ -do { \ - const std::string token(tkn); \ - toml::detail::location loc("test", token); \ - const auto result = psr(loc); \ - BOOST_TEST(result.is_ok()); \ - if(result.is_ok()){ \ - BOOST_TEST(result.unwrap().first == expct); \ - } else { \ - std::cerr << "parser " << #psr << " failed with input `"; \ - std::cerr << token << "`.\n"; \ - std::cerr << "reason: " << result.unwrap_err() << '\n'; \ - } \ -} while(false); \ -/**/ - -#define TOML11_TEST_PARSE_EQUAL_VALUE(psr, tkn, expct) \ -do { \ - const std::string token(tkn); \ - toml::detail::location loc("test", token); \ - const auto result = psr(loc); \ - BOOST_TEST(result.is_ok()); \ - if(result.is_ok()){ \ - BOOST_TEST(result.unwrap() == expct); \ - } else { \ - std::cerr << "parse_value failed with input `"; \ - std::cerr << token << "`.\n"; \ - std::cerr << "reason: " << result.unwrap_err() << '\n'; \ - } \ -} while(false); \ -/**/ diff --git a/lib/toml/tests/test_parse_boolean.cpp b/lib/toml/tests/test_parse_boolean.cpp deleted file mode 100644 index 068aaa4..0000000 --- a/lib/toml/tests/test_parse_boolean.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#define BOOST_TEST_MODULE "test_parse_boolean" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include "test_parse_aux.hpp" - -using namespace toml; -using namespace detail; - -BOOST_AUTO_TEST_CASE(test_boolean) -{ - TOML11_TEST_PARSE_EQUAL(parse_boolean, "true", true); - TOML11_TEST_PARSE_EQUAL(parse_boolean, "false", false); -} - -BOOST_AUTO_TEST_CASE(test_boolean_value) -{ - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "true", toml::value( true)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "false", toml::value(false)); -} diff --git a/lib/toml/tests/test_parse_datetime.cpp b/lib/toml/tests/test_parse_datetime.cpp deleted file mode 100644 index e7247b0..0000000 --- a/lib/toml/tests/test_parse_datetime.cpp +++ /dev/null @@ -1,251 +0,0 @@ -#define BOOST_TEST_MODULE "parse_datetime_test" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include "test_parse_aux.hpp" - -using namespace toml; -using namespace detail; - -BOOST_AUTO_TEST_CASE(test_time) -{ - TOML11_TEST_PARSE_EQUAL(parse_local_time, "07:32:00", toml::local_time(7, 32, 0)); - TOML11_TEST_PARSE_EQUAL(parse_local_time, "07:32:00.99", toml::local_time(7, 32, 0, 990, 0)); - TOML11_TEST_PARSE_EQUAL(parse_local_time, "07:32:00.999", toml::local_time(7, 32, 0, 999, 0)); - TOML11_TEST_PARSE_EQUAL(parse_local_time, "07:32:00.999999", toml::local_time(7, 32, 0, 999, 999)); - - - TOML11_TEST_PARSE_EQUAL(parse_local_time, "00:00:00.000000", toml::local_time( 0, 0, 0, 0, 0)); - TOML11_TEST_PARSE_EQUAL(parse_local_time, "23:59:59.999999", toml::local_time(23, 59, 59, 999, 999)); - TOML11_TEST_PARSE_EQUAL(parse_local_time, "23:59:60.999999", toml::local_time(23, 59, 60, 999, 999)); // leap second -} - -BOOST_AUTO_TEST_CASE(test_time_value) -{ - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "07:32:00", toml::value(toml::local_time(7, 32, 0))); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "07:32:00.99", toml::value(toml::local_time(7, 32, 0, 990, 0))); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "07:32:00.999", toml::value(toml::local_time(7, 32, 0, 999, 0))); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "07:32:00.999999", toml::value(toml::local_time(7, 32, 0, 999, 999))); - - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "00:00:00.000000", toml::value(toml::local_time( 0, 0, 0, 0, 0))); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "23:59:59.999999", toml::value(toml::local_time(23, 59, 59, 999, 999))); - - std::istringstream stream1(std::string("invalid-datetime = 24:00:00")); - std::istringstream stream2(std::string("invalid-datetime = 00:60:00")); - std::istringstream stream3(std::string("invalid-datetime = 00:00:61")); - BOOST_CHECK_THROW(toml::parse(stream1), toml::syntax_error); - BOOST_CHECK_THROW(toml::parse(stream2), toml::syntax_error); - BOOST_CHECK_THROW(toml::parse(stream3), toml::syntax_error); -} - -BOOST_AUTO_TEST_CASE(test_date) -{ - TOML11_TEST_PARSE_EQUAL(parse_local_date, "1979-05-27", toml::local_date(1979, toml::month_t::May, 27)); - - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-01-01", toml::local_date(2000, toml::month_t::Jan, 1)); - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-01-31", toml::local_date(2000, toml::month_t::Jan, 31)); - std::istringstream stream1_1(std::string("invalid-datetime = 2000-01-00")); - std::istringstream stream1_2(std::string("invalid-datetime = 2000-01-32")); - BOOST_CHECK_THROW(toml::parse(stream1_1), toml::syntax_error); - BOOST_CHECK_THROW(toml::parse(stream1_2), toml::syntax_error); - - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-02-01", toml::local_date(2000, toml::month_t::Feb, 1)); - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-02-29", toml::local_date(2000, toml::month_t::Feb, 29)); - std::istringstream stream2_1(std::string("invalid-datetime = 2000-02-00")); - std::istringstream stream2_2(std::string("invalid-datetime = 2000-02-30")); - BOOST_CHECK_THROW(toml::parse(stream2_1), toml::syntax_error); - BOOST_CHECK_THROW(toml::parse(stream2_2), toml::syntax_error); - - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2001-02-28", toml::local_date(2001, toml::month_t::Feb, 28)); - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2004-02-29", toml::local_date(2004, toml::month_t::Feb, 29)); - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2100-02-28", toml::local_date(2100, toml::month_t::Feb, 28)); - std::istringstream stream2_3(std::string("invalid-datetime = 2001-02-29")); - std::istringstream stream2_4(std::string("invalid-datetime = 2004-02-30")); - std::istringstream stream2_5(std::string("invalid-datetime = 2100-02-29")); - BOOST_CHECK_THROW(toml::parse(stream2_3), toml::syntax_error); - BOOST_CHECK_THROW(toml::parse(stream2_4), toml::syntax_error); - BOOST_CHECK_THROW(toml::parse(stream2_5), toml::syntax_error); - - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-03-01", toml::local_date(2000, toml::month_t::Mar, 1)); - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-03-31", toml::local_date(2000, toml::month_t::Mar, 31)); - std::istringstream stream3_1(std::string("invalid-datetime = 2000-03-00")); - std::istringstream stream3_2(std::string("invalid-datetime = 2000-03-32")); - BOOST_CHECK_THROW(toml::parse(stream3_1), toml::syntax_error); - BOOST_CHECK_THROW(toml::parse(stream3_2), toml::syntax_error); - - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-04-01", toml::local_date(2000, toml::month_t::Apr, 1)); - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-04-30", toml::local_date(2000, toml::month_t::Apr, 30)); - std::istringstream stream4_1(std::string("invalid-datetime = 2000-04-00")); - std::istringstream stream4_2(std::string("invalid-datetime = 2000-04-31")); - BOOST_CHECK_THROW(toml::parse(stream4_1), toml::syntax_error); - BOOST_CHECK_THROW(toml::parse(stream4_2), toml::syntax_error); - - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-05-01", toml::local_date(2000, toml::month_t::May, 1)); - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-05-31", toml::local_date(2000, toml::month_t::May, 31)); - std::istringstream stream5_1(std::string("invalid-datetime = 2000-05-00")); - std::istringstream stream5_2(std::string("invalid-datetime = 2000-05-32")); - BOOST_CHECK_THROW(toml::parse(stream5_1), toml::syntax_error); - BOOST_CHECK_THROW(toml::parse(stream5_2), toml::syntax_error); - - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-06-01", toml::local_date(2000, toml::month_t::Jun, 1)); - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-06-30", toml::local_date(2000, toml::month_t::Jun, 30)); - std::istringstream stream6_1(std::string("invalid-datetime = 2000-06-00")); - std::istringstream stream6_2(std::string("invalid-datetime = 2000-06-31")); - BOOST_CHECK_THROW(toml::parse(stream6_1), toml::syntax_error); - BOOST_CHECK_THROW(toml::parse(stream6_2), toml::syntax_error); - - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-07-01", toml::local_date(2000, toml::month_t::Jul, 1)); - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-07-31", toml::local_date(2000, toml::month_t::Jul, 31)); - std::istringstream stream7_1(std::string("invalid-datetime = 2000-07-00")); - std::istringstream stream7_2(std::string("invalid-datetime = 2000-07-32")); - BOOST_CHECK_THROW(toml::parse(stream7_1), toml::syntax_error); - BOOST_CHECK_THROW(toml::parse(stream7_2), toml::syntax_error); - - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-08-01", toml::local_date(2000, toml::month_t::Aug, 1)); - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-08-31", toml::local_date(2000, toml::month_t::Aug, 31)); - std::istringstream stream8_1(std::string("invalid-datetime = 2000-08-00")); - std::istringstream stream8_2(std::string("invalid-datetime = 2000-08-32")); - BOOST_CHECK_THROW(toml::parse(stream8_1), toml::syntax_error); - BOOST_CHECK_THROW(toml::parse(stream8_2), toml::syntax_error); - - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-09-01", toml::local_date(2000, toml::month_t::Sep, 1)); - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-09-30", toml::local_date(2000, toml::month_t::Sep, 30)); - std::istringstream stream9_1(std::string("invalid-datetime = 2000-09-00")); - std::istringstream stream9_2(std::string("invalid-datetime = 2000-09-31")); - BOOST_CHECK_THROW(toml::parse(stream9_1), toml::syntax_error); - BOOST_CHECK_THROW(toml::parse(stream9_2), toml::syntax_error); - - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-10-01", toml::local_date(2000, toml::month_t::Oct, 1)); - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-10-31", toml::local_date(2000, toml::month_t::Oct, 31)); - std::istringstream stream10_1(std::string("invalid-datetime = 2000-10-00")); - std::istringstream stream10_2(std::string("invalid-datetime = 2000-10-32")); - BOOST_CHECK_THROW(toml::parse(stream10_1), toml::syntax_error); - BOOST_CHECK_THROW(toml::parse(stream10_2), toml::syntax_error); - - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-11-01", toml::local_date(2000, toml::month_t::Nov, 1)); - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-11-30", toml::local_date(2000, toml::month_t::Nov, 30)); - std::istringstream stream11_1(std::string("invalid-datetime = 2000-11-00")); - std::istringstream stream11_2(std::string("invalid-datetime = 2000-11-31")); - BOOST_CHECK_THROW(toml::parse(stream11_1), toml::syntax_error); - BOOST_CHECK_THROW(toml::parse(stream11_2), toml::syntax_error); - - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-12-01", toml::local_date(2000, toml::month_t::Dec, 1)); - TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-12-31", toml::local_date(2000, toml::month_t::Dec, 31)); - std::istringstream stream12_1(std::string("invalid-datetime = 2000-12-00")); - std::istringstream stream12_2(std::string("invalid-datetime = 2000-12-32")); - BOOST_CHECK_THROW(toml::parse(stream12_1), toml::syntax_error); - BOOST_CHECK_THROW(toml::parse(stream12_2), toml::syntax_error); - - std::istringstream stream13_1(std::string("invalid-datetime = 2000-13-01")); - BOOST_CHECK_THROW(toml::parse(stream13_1), toml::syntax_error); - std::istringstream stream0_1(std::string("invalid-datetime = 2000-00-01")); - BOOST_CHECK_THROW(toml::parse(stream0_1), toml::syntax_error); -} - -BOOST_AUTO_TEST_CASE(test_date_value) -{ - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27", value(toml::local_date(1979, toml::month_t::May, 27))); -} - -BOOST_AUTO_TEST_CASE(test_datetime) -{ - TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27T07:32:00", - toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0))); - TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27T07:32:00.99", - toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0))); - TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27T07:32:00.999999", - toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999))); - - TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27t07:32:00", - toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0))); - TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27t07:32:00.99", - toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0))); - TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27t07:32:00.999999", - toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999))); - - TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27 07:32:00", - toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0))); - TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27 07:32:00.99", - toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0))); - TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27 07:32:00.999999", - toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999))); -} - -BOOST_AUTO_TEST_CASE(test_datetime_value) -{ - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00", - toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0)))); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00.99", - toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0)))); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00.999999", - toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999)))); - - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27t07:32:00", - toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0)))); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27t07:32:00.99", - toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0)))); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27t07:32:00.999999", - toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999)))); - - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27 07:32:00", - toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0)))); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27 07:32:00.99", - toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0)))); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27 07:32:00.999999", - toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999)))); -} - -BOOST_AUTO_TEST_CASE(test_offset_datetime) -{ - TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00Z", - toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), - toml::local_time(7, 32, 0), toml::time_offset(0, 0))); - TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00.99Z", - toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), - toml::local_time(7, 32, 0, 990, 0), toml::time_offset(0, 0))); - TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00.999999Z", - toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), - toml::local_time(7, 32, 0, 999, 999), toml::time_offset(0, 0))); - - TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00+09:00", - toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), - toml::local_time(7, 32, 0), toml::time_offset(9, 0))); - TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00.99+09:00", - toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), - toml::local_time(7, 32, 0, 990, 0), toml::time_offset(9, 0))); - TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00.999999+09:00", - toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), - toml::local_time(7, 32, 0, 999, 999), toml::time_offset(9, 0))); - - std::istringstream stream1(std::string("invalid-datetime = 2000-01-01T00:00:00+24:00")); - std::istringstream stream2(std::string("invalid-datetime = 2000-01-01T00:00:00+00:60")); - BOOST_CHECK_THROW(toml::parse(stream1), toml::syntax_error); - BOOST_CHECK_THROW(toml::parse(stream2), toml::syntax_error); -} - -BOOST_AUTO_TEST_CASE(test_offset_datetime_value) -{ - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00Z", - toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), - toml::local_time(7, 32, 0), toml::time_offset(0, 0)))); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00.99Z", - toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), - toml::local_time(7, 32, 0, 990, 0), toml::time_offset(0, 0)))); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00.999999Z", - toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), - toml::local_time(7, 32, 0, 999, 999), toml::time_offset(0, 0)))); - - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00+09:00", - toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), - toml::local_time(7, 32, 0), toml::time_offset(9, 0)))); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00.99+09:00", - toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), - toml::local_time(7, 32, 0, 990, 0), toml::time_offset(9, 0)))); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00.999999+09:00", - toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), - toml::local_time(7, 32, 0, 999, 999), toml::time_offset(9, 0)))); -} diff --git a/lib/toml/tests/test_parse_file.cpp b/lib/toml/tests/test_parse_file.cpp deleted file mode 100644 index c2d3610..0000000 --- a/lib/toml/tests/test_parse_file.cpp +++ /dev/null @@ -1,961 +0,0 @@ -#define BOOST_TEST_MODULE "test_parse_file" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include -#include -#include -#include - -BOOST_AUTO_TEST_CASE(test_example) -{ - const auto data = toml::parse("toml/tests/example.toml"); - - BOOST_TEST(toml::find(data, "title") == "TOML Example"); - const auto& owner = toml::find(data, "owner"); - { - BOOST_TEST(toml::find(owner, "name") == "Tom Preston-Werner"); - BOOST_TEST(toml::find(owner, "organization") == "GitHub"); - BOOST_TEST(toml::find(owner, "bio") == - "GitHub Cofounder & CEO\nLikes tater tots and beer."); - BOOST_TEST(toml::find(owner, "dob") == - toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), - toml::local_time(7, 32, 0), toml::time_offset(0, 0))); - } - - const auto& database = toml::find(data, "database"); - { - BOOST_TEST(toml::find(database, "server") == "192.168.1.1"); - const std::vector expected_ports{8001, 8001, 8002}; - BOOST_CHECK(toml::find>(database, "ports") == expected_ports); - BOOST_TEST(toml::find(database, "connection_max") == 5000); - BOOST_TEST(toml::find(database, "enabled") == true); - } - - const auto& servers = toml::find(data, "servers"); - { - toml::table alpha = toml::find(servers, "alpha"); - BOOST_TEST(toml::get(alpha.at("ip")) == "10.0.0.1"); - BOOST_TEST(toml::get(alpha.at("dc")) == "eqdc10"); - - toml::table beta = toml::find(servers, "beta"); - BOOST_TEST(toml::get(beta.at("ip")) == "10.0.0.2"); - BOOST_TEST(toml::get(beta.at("dc")) == "eqdc10"); - BOOST_TEST(toml::get(beta.at("country")) == "\xE4\xB8\xAD\xE5\x9B\xBD"); - } - - const auto& clients = toml::find(data, "clients"); - { - toml::array clients_data = toml::find(clients, "data"); - - std::vector expected_name{"gamma", "delta"}; - BOOST_CHECK(toml::get>(clients_data.at(0)) == expected_name); - - std::vector expected_number{1, 2}; - BOOST_CHECK(toml::get>(clients_data.at(1)) == expected_number); - - std::vector expected_hosts{"alpha", "omega"}; - BOOST_CHECK(toml::find>(clients, "hosts") == expected_hosts); - } - - std::vector products = - toml::find>(data, "products"); - { - BOOST_TEST(toml::get(products.at(0).at("name")) == "Hammer"); - BOOST_TEST(toml::get(products.at(0).at("sku")) == 738594937); - - BOOST_TEST(toml::get(products.at(1).at("name")) == "Nail"); - BOOST_TEST(toml::get(products.at(1).at("sku")) == 284758393); - BOOST_TEST(toml::get(products.at(1).at("color")) == "gray"); - } -} - -BOOST_AUTO_TEST_CASE(test_example_stream) -{ - std::ifstream ifs("toml/tests/example.toml", std::ios::binary); - const auto data = toml::parse(ifs); - - BOOST_TEST(toml::find(data, "title") == "TOML Example"); - const auto& owner = toml::find(data, "owner"); - { - BOOST_TEST(toml::find(owner, "name") == "Tom Preston-Werner"); - BOOST_TEST(toml::find(owner, "organization") == "GitHub"); - BOOST_TEST(toml::find(owner, "bio") == - "GitHub Cofounder & CEO\nLikes tater tots and beer."); - BOOST_TEST(toml::find(owner, "dob") == - toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), - toml::local_time(7, 32, 0), toml::time_offset(0, 0))); - } - - const auto& database = toml::find(data, "database"); - { - BOOST_TEST(toml::find(database, "server") == "192.168.1.1"); - const std::vector expected_ports{8001, 8001, 8002}; - BOOST_CHECK(toml::find>(database, "ports") == expected_ports); - BOOST_TEST(toml::find(database, "connection_max") == 5000); - BOOST_TEST(toml::find(database, "enabled") == true); - } - - const auto& servers = toml::find(data, "servers"); - { - toml::table alpha = toml::find(servers, "alpha"); - BOOST_TEST(toml::get(alpha.at("ip")) == "10.0.0.1"); - BOOST_TEST(toml::get(alpha.at("dc")) == "eqdc10"); - - toml::table beta = toml::find(servers, "beta"); - BOOST_TEST(toml::get(beta.at("ip")) == "10.0.0.2"); - BOOST_TEST(toml::get(beta.at("dc")) == "eqdc10"); - BOOST_TEST(toml::get(beta.at("country")) == "\xE4\xB8\xAD\xE5\x9B\xBD"); - } - - const auto& clients = toml::find(data, "clients"); - { - toml::array clients_data = toml::find(clients, "data"); - std::vector expected_name{"gamma", "delta"}; - BOOST_CHECK(toml::get>(clients_data.at(0)) == expected_name); - - std::vector expected_number{1, 2}; - BOOST_CHECK(toml::get>(clients_data.at(1)) == expected_number); - - std::vector expected_hosts{"alpha", "omega"}; - BOOST_CHECK(toml::find>(clients, "hosts") == expected_hosts); - } - - std::vector products = - toml::find>(data, "products"); - { - BOOST_TEST(toml::get(products.at(0).at("name")) == - "Hammer"); - BOOST_TEST(toml::get(products.at(0).at("sku")) == - 738594937); - - BOOST_TEST(toml::get(products.at(1).at("name")) == - "Nail"); - BOOST_TEST(toml::get(products.at(1).at("sku")) == - 284758393); - BOOST_TEST(toml::get(products.at(1).at("color")) == - "gray"); - } -} - -BOOST_AUTO_TEST_CASE(test_fruit) -{ - const auto data = toml::parse("toml/tests/fruit.toml"); - const auto blah = toml::find(toml::find(data, "fruit"), "blah"); - BOOST_TEST(toml::find(blah.at(0), "name") == "apple"); - BOOST_TEST(toml::find(blah.at(1), "name") == "banana"); - { - const auto physical = toml::find(blah.at(0), "physical"); - BOOST_TEST(toml::find(physical, "color") == "red"); - BOOST_TEST(toml::find(physical, "shape") == "round"); - } - { - const auto physical = toml::find(blah.at(1), "physical"); - BOOST_TEST(toml::find(physical, "color") == "yellow"); - BOOST_TEST(toml::find(physical, "shape") == "bent"); - } -} - -BOOST_AUTO_TEST_CASE(test_hard_example) -{ - const auto data = toml::parse("toml/tests/hard_example.toml"); - const auto the = toml::find(data, "the"); - BOOST_TEST(toml::find(the, "test_string") == - "You'll hate me after this - #"); - - const auto hard = toml::find(the, "hard"); - const std::vector expected_the_hard_test_array{"] ", " # "}; - BOOST_CHECK(toml::find>(hard, "test_array") == - expected_the_hard_test_array); - const std::vector expected_the_hard_test_array2{ - "Test #11 ]proved that", "Experiment #9 was a success"}; - BOOST_CHECK(toml::find>(hard, "test_array2") == - expected_the_hard_test_array2); - BOOST_TEST(toml::find(hard, "another_test_string") == - " Same thing, but with a string #"); - BOOST_TEST(toml::find(hard, "harder_test_string") == - " And when \"'s are in the string, along with # \""); - - const auto bit = toml::find(hard, "bit#"); - BOOST_TEST(toml::find(bit, "what?") == - "You don't think some user won't do that?"); - const std::vector expected_multi_line_array{"]"}; - BOOST_CHECK(toml::find>(bit, "multi_line_array") == - expected_multi_line_array); -} -BOOST_AUTO_TEST_CASE(test_hard_example_comment) -{ - const auto data = toml::parse("toml/tests/hard_example.toml"); - const auto the = toml::find(data, "the"); - BOOST_TEST(toml::find(the, "test_string") == - "You'll hate me after this - #"); - - const auto hard = toml::find(the, "hard"); - const std::vector expected_the_hard_test_array{"] ", " # "}; - BOOST_CHECK(toml::find>(hard, "test_array") == - expected_the_hard_test_array); - const std::vector expected_the_hard_test_array2{ - "Test #11 ]proved that", "Experiment #9 was a success"}; - BOOST_CHECK(toml::find>(hard, "test_array2") == - expected_the_hard_test_array2); - BOOST_TEST(toml::find(hard, "another_test_string") == - " Same thing, but with a string #"); - BOOST_TEST(toml::find(hard, "harder_test_string") == - " And when \"'s are in the string, along with # \""); - - const auto bit = toml::find(hard, "bit#"); - BOOST_TEST(toml::find(bit, "what?") == - "You don't think some user won't do that?"); - const std::vector expected_multi_line_array{"]"}; - BOOST_CHECK(toml::find>(bit, "multi_line_array") == - expected_multi_line_array); -} - - -BOOST_AUTO_TEST_CASE(test_example_preserve_comment) -{ - const auto data = toml::parse("toml/tests/example.toml"); - - BOOST_TEST(toml::find(data, "title") == "TOML Example"); - const auto& owner = toml::find(data, "owner"); - { - BOOST_TEST(toml::find(owner, "name") == "Tom Preston-Werner"); - BOOST_TEST(toml::find(owner, "organization") == "GitHub"); - BOOST_TEST(toml::find(owner, "bio") == - "GitHub Cofounder & CEO\nLikes tater tots and beer."); - BOOST_TEST(toml::find(owner, "dob") == - toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), - toml::local_time(7, 32, 0), toml::time_offset(0, 0))); - BOOST_TEST(toml::find(owner, "dob").comments().at(0) == - " First class dates? Why not?"); - } - - const auto& database = toml::find(data, "database"); - { - BOOST_TEST(toml::find(database, "server") == "192.168.1.1"); - const std::vector expected_ports{8001, 8001, 8002}; - BOOST_CHECK(toml::find>(database, "ports") == expected_ports); - BOOST_TEST(toml::find(database, "connection_max") == 5000); - BOOST_TEST(toml::find(database, "enabled") == true); - } - - const auto& servers = toml::find(data, "servers"); - { - const auto& alpha = toml::find(servers, "alpha"); - BOOST_TEST(alpha.comments().at(0) == - " You can indent as you please. Tabs or spaces. TOML don't care."); - BOOST_TEST(toml::find(alpha, "ip") == "10.0.0.1"); - BOOST_TEST(toml::find(alpha, "dc") == "eqdc10"); - - const auto& beta = toml::find(servers, "beta"); - BOOST_TEST(toml::find(beta, "ip") == "10.0.0.2"); - BOOST_TEST(toml::find(beta, "dc") == "eqdc10"); - BOOST_TEST(toml::find(beta, "country") == - "\xE4\xB8\xAD\xE5\x9B\xBD"); - BOOST_TEST(toml::find(beta, "country").comments().at(0) == - " This should be parsed as UTF-8"); - } - - const auto& clients = toml::find(data, "clients"); - { - BOOST_TEST(toml::find(clients, "data").comments().at(0) == - " just an update to make sure parsers support it"); - - - toml::array clients_data = toml::find(clients, "data"); - std::vector expected_name{"gamma", "delta"}; - BOOST_CHECK(toml::get>(clients_data.at(0)) == - expected_name); - std::vector expected_number{1, 2}; - BOOST_CHECK(toml::get>(clients_data.at(1)) == - expected_number); - std::vector expected_hosts{"alpha", "omega"}; - BOOST_CHECK(toml::find>(clients, "hosts") == - expected_hosts); - - BOOST_TEST(toml::find(clients, "hosts").comments().at(0) == - " Line breaks are OK when inside arrays"); - } - - std::vector products = - toml::find>(data, "products"); - { - BOOST_TEST(toml::get(products.at(0).at("name")) == - "Hammer"); - BOOST_TEST(toml::get(products.at(0).at("sku")) == - 738594937); - - BOOST_TEST(toml::get(products.at(1).at("name")) == - "Nail"); - BOOST_TEST(toml::get(products.at(1).at("sku")) == - 284758393); - BOOST_TEST(toml::get(products.at(1).at("color")) == - "gray"); - } -} - -BOOST_AUTO_TEST_CASE(test_example_preserve_stdmap_stddeque) -{ - const auto data = toml::parse("toml/tests/example.toml"); - - static_assert(std::is_same::type> - >::value, ""); - static_assert(std::is_same::type> - >::value, ""); - - BOOST_TEST(toml::find(data, "title") == "TOML Example"); - const auto& owner = toml::find(data, "owner"); - { - BOOST_TEST(toml::find(owner, "name") == "Tom Preston-Werner"); - BOOST_TEST(toml::find(owner, "organization") == "GitHub"); - BOOST_TEST(toml::find(owner, "bio") == - "GitHub Cofounder & CEO\nLikes tater tots and beer."); - BOOST_TEST(toml::find(owner, "dob") == - toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), - toml::local_time(7, 32, 0), toml::time_offset(0, 0))); - BOOST_TEST(toml::find(owner, "dob").comments().at(0) == - " First class dates? Why not?"); - } - - const auto& database = toml::find(data, "database"); - { - BOOST_TEST(toml::find(database, "server") == "192.168.1.1"); - const std::vector expected_ports{8001, 8001, 8002}; - BOOST_CHECK(toml::find>(database, "ports") == expected_ports); - BOOST_TEST(toml::find(database, "connection_max") == 5000); - BOOST_TEST(toml::find(database, "enabled") == true); - } - - const auto& servers = toml::find(data, "servers"); - { - const auto& alpha = toml::find(servers, "alpha"); - BOOST_TEST(alpha.comments().at(0) == - " You can indent as you please. Tabs or spaces. TOML don't care."); - BOOST_TEST(toml::find(alpha, "ip") == "10.0.0.1"); - BOOST_TEST(toml::find(alpha, "dc") == "eqdc10"); - - const auto& beta = toml::find(servers, "beta"); - BOOST_TEST(toml::find(beta, "ip") == "10.0.0.2"); - BOOST_TEST(toml::find(beta, "dc") == "eqdc10"); - BOOST_TEST(toml::find(beta, "country") == - "\xE4\xB8\xAD\xE5\x9B\xBD"); - BOOST_TEST(toml::find(beta, "country").comments().at(0) == - " This should be parsed as UTF-8"); - } - - const auto& clients = toml::find(data, "clients"); - { - BOOST_TEST(toml::find(clients, "data").comments().at(0) == - " just an update to make sure parsers support it"); - - - toml::array clients_data = toml::find(clients, "data"); - std::vector expected_name{"gamma", "delta"}; - BOOST_CHECK(toml::get>(clients_data.at(0)) == - expected_name); - std::vector expected_number{1, 2}; - BOOST_CHECK(toml::get>(clients_data.at(1)) == - expected_number); - std::vector expected_hosts{"alpha", "omega"}; - BOOST_CHECK(toml::find>(clients, "hosts") == - expected_hosts); - - BOOST_TEST(toml::find(clients, "hosts").comments().at(0) == - " Line breaks are OK when inside arrays"); - } - - std::vector products = - toml::find>(data, "products"); - { - BOOST_TEST(toml::get(products.at(0).at("name")) == - "Hammer"); - BOOST_TEST(toml::get(products.at(0).at("sku")) == - 738594937); - - BOOST_TEST(toml::get(products.at(1).at("name")) == - "Nail"); - BOOST_TEST(toml::get(products.at(1).at("sku")) == - 284758393); - BOOST_TEST(toml::get(products.at(1).at("color")) == - "gray"); - } -} - -// --------------------------------------------------------------------------- -// after here, the test codes generate the content of a file. - -BOOST_AUTO_TEST_CASE(test_file_with_BOM) -{ - { - const std::string table( - "\xEF\xBB\xBF" // BOM - "key = \"value\"\n" - "[table]\n" - "key = \"value\"\n" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, "test_file_with_BOM.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - { - const std::string table( - "\xEF\xBB\xBF" // BOM - "key = \"value\"\n" - "[table]\n" - "key = \"value\"\n" - ); - { - std::ofstream ofs("tmp.toml"); - ofs << table; - } - const auto data = toml::parse("tmp.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - { - const std::string table( - "\xEF\xBB\xBF" // BOM - "key = \"value\"\r\n" - "[table]\r\n" - "key = \"value\"\r\n" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, "test_file_with_BOM_CRLF.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - { - const std::string table( - "\xEF\xBB\xBF" // BOM - "key = \"value\"\r\n" - "[table]\r\n" - "key = \"value\"\r\n" - ); - { - // with text-mode, "\n" is converted to "\r\n" and the resulting - // value will be "\r\r\n". To avoid the additional "\r", use binary - // mode. - std::ofstream ofs("tmp.toml", std::ios_base::binary); - ofs.write(table.data(), static_cast(table.size())); - } - const auto data = toml::parse("tmp.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } -} - -BOOST_AUTO_TEST_CASE(test_file_without_newline_at_the_end_of_file) -{ - { - const std::string table( - "key = \"value\"\n" - "[table]\n" - "key = \"value\"" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_file_without_newline_at_the_end_of_file.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - { - const std::string table( - "key = \"value\"\r\n" - "[table]\r\n" - "key = \"value\"" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_file_without_newline_at_the_end_of_file_CRLF.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - - { - const std::string table( - "key = \"value\"\n" - "[table]\n" - "key = \"value\" # comment" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_file_without_newline_at_the_end_of_file_comment.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - { - const std::string table( - "key = \"value\"\r\n" - "[table]\r\n" - "key = \"value\" # comment" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_file_without_newline_at_the_end_of_file_comment.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - - { - const std::string table( - "key = \"value\"\n" - "[table]\n" - "key = \"value\" \t" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_file_without_newline_at_the_end_of_file_ws.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - { - const std::string table( - "key = \"value\"\r\n" - "[table]\r\n" - "key = \"value\" \t" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_file_without_newline_at_the_end_of_file_ws.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } -} - - -BOOST_AUTO_TEST_CASE(test_files_end_with_comment) -{ - // comment w/o newline - { - const std::string table( - "key = \"value\"\n" - "[table]\n" - "key = \"value\"\n" - "# comment" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_comment.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - { - const std::string table( - "key = \"value\"\n" - "[table]\n" - "key = \"value\"\n" - "# comment\n" - "# one more comment" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_comment.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - - // comment w/ newline - - { - const std::string table( - "key = \"value\"\n" - "[table]\n" - "key = \"value\"\n" - "# comment\n" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_comment.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - { - const std::string table( - "key = \"value\"\n" - "[table]\n" - "key = \"value\"\n" - "# comment\n" - "# one more comment\n" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_comment.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - - // CRLF version - - { - const std::string table( - "key = \"value\"\r\n" - "[table]\r\n" - "key = \"value\"\r\n" - "# comment" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_comment.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - { - const std::string table( - "key = \"value\"\r\n" - "[table]\r\n" - "key = \"value\"\r\n" - "# comment\r\n" - "# one more comment" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_comment.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - { - const std::string table( - "key = \"value\"\r\n" - "[table]\r\n" - "key = \"value\"\r\n" - "# comment\r\n" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_comment.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - { - const std::string table( - "key = \"value\"\r\n" - "[table]\r\n" - "key = \"value\"\r\n" - "# comment\r\n" - "# one more comment\r\n" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_comment.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } -} - - -BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines) -{ - { - const std::string table( - "key = \"value\"\n" - "[table]\n" - "key = \"value\"\n" - "\n" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_newline.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - { - const std::string table( - "key = \"value\"\n" - "[table]\n" - "key = \"value\"\n" - "\n" - "\n" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_newline.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - - // with whitespaces - - { - const std::string table( - "key = \"value\"\n" - "[table]\n" - "key = \"value\"\n" - " \n" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_newline.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - { - const std::string table( - "key = \"value\"\n" - "[table]\n" - "key = \"value\"\n" - " \n" - " \n" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_newline.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - { - const std::string table( - "key = \"value\"\n" - "[table]\n" - "key = \"value\"\n" - "\n" - " \n" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_newline.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - { - const std::string table( - "key = \"value\"\n" - "[table]\n" - "key = \"value\"\n" - " \n" - "\n" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_newline.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - - // with whitespaces but no newline - { - const std::string table( - "key = \"value\"\n" - "[table]\n" - "key = \"value\"\n" - " " - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_newline.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(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(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - - - // CRLF - - { - const std::string table( - "key = \"value\"\r\n" - "[table]\r\n" - "key = \"value\"\r\n" - "\r\n" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_newline.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - { - const std::string table( - "key = \"value\"\r\n" - "[table]\r\n" - "key = \"value\"\r\n" - "\r\n" - "\r\n" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_newline.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - - // with whitespaces - - { - const std::string table( - "key = \"value\"\r\n" - "[table]\r\n" - "key = \"value\"\r\n" - " \r\n" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_newline.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - { - const std::string table( - "key = \"value\"\r\n" - "[table]\r\n" - "key = \"value\"\r\n" - "\r\n" - " \r\n" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_newline.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - { - const std::string table( - "key = \"value\"\r\n" - "[table]\r\n" - "key = \"value\"\r\n" - " \r\n" - "\r\n" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_newline.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - { - const std::string table( - "key = \"value\"\r\n" - "[table]\r\n" - "key = \"value\"\r\n" - " \r\n" - " \r\n" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_newline.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } - { - const std::string table( - "key = \"value\"\r\n" - "[table]\r\n" - "key = \"value\"\r\n" - " " - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_with_newline.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } -} - -BOOST_AUTO_TEST_CASE(test_file_ends_without_lf) -{ - { - const std::string table( - "key = \"value\"\n" - "[table]\n" - "key = \"value\"" - ); - std::istringstream iss(table); - const auto data = toml::parse(iss, - "test_files_end_without_lf.toml"); - - BOOST_TEST(toml::find(data, "key") == "value"); - BOOST_TEST(toml::find(toml::find(data, "table"), "key") == "value"); - } -} - -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 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 -} diff --git a/lib/toml/tests/test_parse_floating.cpp b/lib/toml/tests/test_parse_floating.cpp deleted file mode 100644 index 8ddcb90..0000000 --- a/lib/toml/tests/test_parse_floating.cpp +++ /dev/null @@ -1,178 +0,0 @@ -#define BOOST_TEST_MODULE "parse_floating_test" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include -#include "test_parse_aux.hpp" - -using namespace toml; -using namespace detail; - -BOOST_AUTO_TEST_CASE(test_fractional) -{ - TOML11_TEST_PARSE_EQUAL(parse_floating, "1.0", 1.0); - TOML11_TEST_PARSE_EQUAL(parse_floating, "0.1", 0.1); - TOML11_TEST_PARSE_EQUAL(parse_floating, "0.001", 0.001); - TOML11_TEST_PARSE_EQUAL(parse_floating, "0.100", 0.1); - TOML11_TEST_PARSE_EQUAL(parse_floating, "+3.14", 3.14); - TOML11_TEST_PARSE_EQUAL(parse_floating, "-3.14", -3.14); - TOML11_TEST_PARSE_EQUAL(parse_floating, "3.1415_9265_3589", 3.141592653589); - TOML11_TEST_PARSE_EQUAL(parse_floating, "+3.1415_9265_3589", 3.141592653589); - TOML11_TEST_PARSE_EQUAL(parse_floating, "-3.1415_9265_3589", -3.141592653589); - TOML11_TEST_PARSE_EQUAL(parse_floating, "123_456.789", 123456.789); - TOML11_TEST_PARSE_EQUAL(parse_floating, "+123_456.789", 123456.789); - TOML11_TEST_PARSE_EQUAL(parse_floating, "-123_456.789", -123456.789); - TOML11_TEST_PARSE_EQUAL(parse_floating, "+0.0", 0.0); - TOML11_TEST_PARSE_EQUAL(parse_floating, "-0.0", -0.0); -} - -BOOST_AUTO_TEST_CASE(test_fractional_value) -{ - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1.0", value( 1.0)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0.1", value( 0.1)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0.001", value( 0.001)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0.100", value( 0.1)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+3.14", value( 3.14)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-3.14", value(-3.14)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "3.1415_9265_3589", value( 3.141592653589)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+3.1415_9265_3589", value( 3.141592653589)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-3.1415_9265_3589", value(-3.141592653589)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "123_456.789", value( 123456.789)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+123_456.789", value( 123456.789)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-123_456.789", value(-123456.789)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+0.0", value( 0.0)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-0.0", value(-0.0)); -} - -BOOST_AUTO_TEST_CASE(test_exponential) -{ - TOML11_TEST_PARSE_EQUAL(parse_floating, "1e10", 1e10); - TOML11_TEST_PARSE_EQUAL(parse_floating, "1e+10", 1e10); - TOML11_TEST_PARSE_EQUAL(parse_floating, "1e-10", 1e-10); - TOML11_TEST_PARSE_EQUAL(parse_floating, "+1e10", 1e10); - TOML11_TEST_PARSE_EQUAL(parse_floating, "+1e+10", 1e10); - TOML11_TEST_PARSE_EQUAL(parse_floating, "+1e-10", 1e-10); - TOML11_TEST_PARSE_EQUAL(parse_floating, "-1e10", -1e10); - TOML11_TEST_PARSE_EQUAL(parse_floating, "-1e+10", -1e10); - TOML11_TEST_PARSE_EQUAL(parse_floating, "-1e-10", -1e-10); - TOML11_TEST_PARSE_EQUAL(parse_floating, "123e-10", 123e-10); - TOML11_TEST_PARSE_EQUAL(parse_floating, "1E10", 1e10); - TOML11_TEST_PARSE_EQUAL(parse_floating, "1E+10", 1e10); - TOML11_TEST_PARSE_EQUAL(parse_floating, "1E-10", 1e-10); - TOML11_TEST_PARSE_EQUAL(parse_floating, "123E-10", 123e-10); - TOML11_TEST_PARSE_EQUAL(parse_floating, "1_2_3E-10", 123e-10); - TOML11_TEST_PARSE_EQUAL(parse_floating, "1_2_3E-1_0", 123e-10); - TOML11_TEST_PARSE_EQUAL(parse_floating, "+0e0", 0.0); - TOML11_TEST_PARSE_EQUAL(parse_floating, "-0e0", -0.0); - -#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES - BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part"); - // toml-lang/toml master permits leading 0s in exp part (unreleased) - TOML11_TEST_PARSE_EQUAL(parse_floating, "1_2_3E-01", 123e-1); - TOML11_TEST_PARSE_EQUAL(parse_floating, "1_2_3E-0_1", 123e-1); -#endif -} - -BOOST_AUTO_TEST_CASE(test_exponential_value) -{ - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1e10", value(1e10)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1e+10", value(1e10)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1e-10", value(1e-10)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1e10", value(1e10)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1e+10", value(1e10)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1e-10", value(1e-10)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1e10", value(-1e10)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1e+10", value(-1e10)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1e-10", value(-1e-10)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "123e-10", value(123e-10)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1E10", value(1e10)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1E+10", value(1e10)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1E-10", value(1e-10)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "123E-10", value(123e-10)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1_2_3E-10", value(123e-10)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1_2_3E-1_0", value(123e-10)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+0e0", value( 0.0)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-0e0", value(-0.0)); - -#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES - BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part"); - // toml-lang/toml master permits leading 0s in exp part (unreleased) - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1_2_3E-01", value(123e-1)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1_2_3E-0_1", value(123e-1)); -#endif -} -BOOST_AUTO_TEST_CASE(test_fe) -{ - TOML11_TEST_PARSE_EQUAL(parse_floating, "6.02e23", 6.02e23); - TOML11_TEST_PARSE_EQUAL(parse_floating, "6.02e+23", 6.02e23); - TOML11_TEST_PARSE_EQUAL(parse_floating, "1.112_650_06e-17", 1.11265006e-17); -} -BOOST_AUTO_TEST_CASE(test_fe_vaule) -{ - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "6.02e23", value(6.02e23)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "6.02e+23", value(6.02e23)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1.112_650_06e-17", value(1.11265006e-17)); - -#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES - BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part"); - // toml-lang/toml master permits leading 0s in exp part (unreleased) - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "3.141_5e-01", value(3.1415e-1)); -#endif -} - -BOOST_AUTO_TEST_CASE(test_inf) -{ - { - const std::string token("inf"); - toml::detail::location loc("test", token); - const auto r = parse_floating(loc); - BOOST_CHECK(r.is_ok()); - BOOST_CHECK(std::isinf(r.unwrap().first)); - BOOST_CHECK(r.unwrap().first > 0.0); - } - { - const std::string token("+inf"); - toml::detail::location loc("test", token); - const auto r = parse_floating(loc); - BOOST_CHECK(r.is_ok()); - BOOST_CHECK(std::isinf(r.unwrap().first)); - BOOST_CHECK(r.unwrap().first > 0.0); - } - { - const std::string token("-inf"); - toml::detail::location loc("test", token); - const auto r = parse_floating(loc); - BOOST_CHECK(r.is_ok()); - BOOST_CHECK(std::isinf(r.unwrap().first)); - BOOST_CHECK(r.unwrap().first < 0.0); - } -} - -BOOST_AUTO_TEST_CASE(test_nan) -{ - { - const std::string token("nan"); - toml::detail::location loc("test", token); - const auto r = parse_floating(loc); - BOOST_CHECK(r.is_ok()); - BOOST_CHECK(std::isnan(r.unwrap().first)); - } - { - const std::string token("+nan"); - toml::detail::location loc("test", token); - const auto r = parse_floating(loc); - BOOST_CHECK(r.is_ok()); - BOOST_CHECK(std::isnan(r.unwrap().first)); - } - { - const std::string token("-nan"); - toml::detail::location loc("test", token); - const auto r = parse_floating(loc); - BOOST_CHECK(r.is_ok()); - BOOST_CHECK(std::isnan(r.unwrap().first)); - } -} diff --git a/lib/toml/tests/test_parse_inline_table.cpp b/lib/toml/tests/test_parse_inline_table.cpp deleted file mode 100644 index 5fa99c1..0000000 --- a/lib/toml/tests/test_parse_inline_table.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#define BOOST_TEST_MODULE "parse_inline_table_test" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include "test_parse_aux.hpp" - -using namespace toml; -using namespace detail; - -BOOST_AUTO_TEST_CASE(test_inline_table) -{ - TOML11_TEST_PARSE_EQUAL(parse_inline_table, "{}", table()); - { - table t; - t["foo"] = toml::value(42); - t["bar"] = toml::value("baz"); - TOML11_TEST_PARSE_EQUAL(parse_inline_table, "{foo = 42, bar = \"baz\"}", t); - } - { - table t; - table t_sub; - t_sub["name"] = toml::value("pug"); - t["type"] = toml::value(t_sub); - TOML11_TEST_PARSE_EQUAL(parse_inline_table, "{type.name = \"pug\"}", t); - } -} - -BOOST_AUTO_TEST_CASE(test_inline_table_value) -{ - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "{}", value(table())); - { - table t; - t["foo"] = toml::value(42); - t["bar"] = toml::value("baz"); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "{foo = 42, bar = \"baz\"}", value(t)); - } - { - table t; - table t_sub; - t_sub["name"] = toml::value("pug"); - t["type"] = toml::value(t_sub); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "{type.name = \"pug\"}", value(t)); - } -} - -BOOST_AUTO_TEST_CASE(test_inline_table_immutability) -{ - { - std::istringstream stream(std::string( - "a = {b = 1}\n" - "a.c = 2\n")); - BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error); - } - { - std::istringstream stream(std::string( - "a = {b = {c = 1}}\n" - "a.b.d = 2\n")); - BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error); - } -} diff --git a/lib/toml/tests/test_parse_integer.cpp b/lib/toml/tests/test_parse_integer.cpp deleted file mode 100644 index f6547bb..0000000 --- a/lib/toml/tests/test_parse_integer.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#define BOOST_TEST_MODULE "parse_integer_test" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include "test_parse_aux.hpp" - -using namespace toml; -using namespace detail; - -BOOST_AUTO_TEST_CASE(test_decimal) -{ - TOML11_TEST_PARSE_EQUAL(parse_integer, "1234", 1234); - TOML11_TEST_PARSE_EQUAL(parse_integer, "+1234", 1234); - TOML11_TEST_PARSE_EQUAL(parse_integer, "-1234", -1234); - TOML11_TEST_PARSE_EQUAL(parse_integer, "0", 0); - TOML11_TEST_PARSE_EQUAL(parse_integer, "1_2_3_4", 1234); - TOML11_TEST_PARSE_EQUAL(parse_integer, "+1_2_3_4", +1234); - TOML11_TEST_PARSE_EQUAL(parse_integer, "-1_2_3_4", -1234); - TOML11_TEST_PARSE_EQUAL(parse_integer, "123_456_789", 123456789); -} - -BOOST_AUTO_TEST_CASE(test_decimal_value) -{ - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1234", toml::value( 1234)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1234", toml::value( 1234)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1234", toml::value( -1234)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0", toml::value( 0)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1_2_3_4", toml::value( 1234)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1_2_3_4", toml::value( +1234)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1_2_3_4", toml::value( -1234)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "123_456_789", toml::value(123456789)); -} - -BOOST_AUTO_TEST_CASE(test_hex) -{ - TOML11_TEST_PARSE_EQUAL(parse_integer, "0xDEADBEEF", 0xDEADBEEF); - TOML11_TEST_PARSE_EQUAL(parse_integer, "0xdeadbeef", 0xDEADBEEF); - TOML11_TEST_PARSE_EQUAL(parse_integer, "0xDEADbeef", 0xDEADBEEF); - TOML11_TEST_PARSE_EQUAL(parse_integer, "0xDEAD_BEEF", 0xDEADBEEF); - TOML11_TEST_PARSE_EQUAL(parse_integer, "0xdead_beef", 0xDEADBEEF); - TOML11_TEST_PARSE_EQUAL(parse_integer, "0xdead_BEEF", 0xDEADBEEF); - TOML11_TEST_PARSE_EQUAL(parse_integer, "0xFF", 0xFF); - TOML11_TEST_PARSE_EQUAL(parse_integer, "0x00FF", 0xFF); - TOML11_TEST_PARSE_EQUAL(parse_integer, "0x0000FF", 0xFF); -} - -BOOST_AUTO_TEST_CASE(test_hex_value) -{ - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xDEADBEEF", value(0xDEADBEEF)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xdeadbeef", value(0xDEADBEEF)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xDEADbeef", value(0xDEADBEEF)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xDEAD_BEEF", value(0xDEADBEEF)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xdead_beef", value(0xDEADBEEF)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xdead_BEEF", value(0xDEADBEEF)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xFF", value(0xFF)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0x00FF", value(0xFF)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0x0000FF", value(0xFF)); -} - -BOOST_AUTO_TEST_CASE(test_oct) -{ - TOML11_TEST_PARSE_EQUAL(parse_integer, "0o777", 64*7+8*7+7); - TOML11_TEST_PARSE_EQUAL(parse_integer, "0o7_7_7", 64*7+8*7+7); - TOML11_TEST_PARSE_EQUAL(parse_integer, "0o007", 7); -} - -BOOST_AUTO_TEST_CASE(test_oct_value) -{ - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0o777", value(64*7+8*7+7)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0o7_7_7", value(64*7+8*7+7)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0o007", value(7)); -} - -BOOST_AUTO_TEST_CASE(test_bin) -{ - TOML11_TEST_PARSE_EQUAL(parse_integer, "0b10000", 16); - TOML11_TEST_PARSE_EQUAL(parse_integer, "0b010000", 16); - TOML11_TEST_PARSE_EQUAL(parse_integer, "0b01_00_00", 16); - TOML11_TEST_PARSE_EQUAL(parse_integer, "0b111111", 63); -} - -BOOST_AUTO_TEST_CASE(test_bin_value) -{ - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b10000", value(16)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b010000", value(16)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b01_00_00", value(16)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b111111", value(63)); -} diff --git a/lib/toml/tests/test_parse_key.cpp b/lib/toml/tests/test_parse_key.cpp deleted file mode 100644 index f05c26b..0000000 --- a/lib/toml/tests/test_parse_key.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#define BOOST_TEST_MODULE "parse_key_test" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include "test_parse_aux.hpp" - -using namespace toml; -using namespace detail; - -BOOST_AUTO_TEST_CASE(test_bare_key) -{ - TOML11_TEST_PARSE_EQUAL(parse_key, "barekey", std::vector(1, "barekey")); - TOML11_TEST_PARSE_EQUAL(parse_key, "bare-key", std::vector(1, "bare-key")); - TOML11_TEST_PARSE_EQUAL(parse_key, "bare_key", std::vector(1, "bare_key")); - TOML11_TEST_PARSE_EQUAL(parse_key, "1234", std::vector(1, "1234")); -} - -BOOST_AUTO_TEST_CASE(test_quoted_key) -{ - TOML11_TEST_PARSE_EQUAL(parse_key, "\"127.0.0.1\"", std::vector(1, "127.0.0.1" )); - TOML11_TEST_PARSE_EQUAL(parse_key, "\"character encoding\"", std::vector(1, "character encoding")); -#if defined(_MSC_VER) || defined(__INTEL_COMPILER) - TOML11_TEST_PARSE_EQUAL(parse_key, "\"\xCA\x8E\xC7\x9D\xCA\x9E\"", std::vector(1, "\xCA\x8E\xC7\x9D\xCA\x9E")); -#else - TOML11_TEST_PARSE_EQUAL(parse_key, "\"ʎǝʞ\"", std::vector(1, "ʎǝʞ" )); -#endif - TOML11_TEST_PARSE_EQUAL(parse_key, "'key2'", std::vector(1, "key2" )); - TOML11_TEST_PARSE_EQUAL(parse_key, "'quoted \"value\"'", std::vector(1, "quoted \"value\"" )); -} - -BOOST_AUTO_TEST_CASE(test_dotted_key) -{ - { - std::vector keys(2); - keys[0] = "physical"; - keys[1] = "color"; - TOML11_TEST_PARSE_EQUAL(parse_key, "physical.color", keys); - } - { - std::vector keys(2); - keys[0] = "physical"; - keys[1] = "shape"; - TOML11_TEST_PARSE_EQUAL(parse_key, "physical.shape", keys); - } - { - std::vector keys(4); - keys[0] = "x"; - keys[1] = "y"; - keys[2] = "z"; - keys[3] = "w"; - TOML11_TEST_PARSE_EQUAL(parse_key, "x.y.z.w", keys); - } - { - std::vector keys(2); - keys[0] = "site"; - keys[1] = "google.com"; - TOML11_TEST_PARSE_EQUAL(parse_key, "site.\"google.com\"", keys); - } -} diff --git a/lib/toml/tests/test_parse_string.cpp b/lib/toml/tests/test_parse_string.cpp deleted file mode 100644 index df4b787..0000000 --- a/lib/toml/tests/test_parse_string.cpp +++ /dev/null @@ -1,237 +0,0 @@ -#define BOOST_TEST_MODULE "parse_string_test" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include "test_parse_aux.hpp" - -using namespace toml; -using namespace detail; - -BOOST_AUTO_TEST_CASE(test_string) -{ - TOML11_TEST_PARSE_EQUAL(parse_string, - "\"The quick brown fox jumps over the lazy dog\"", - string("The quick brown fox jumps over the lazy dog", string_t::basic)); - TOML11_TEST_PARSE_EQUAL(parse_string, - "\'The quick brown fox jumps over the lazy dog\'", - string("The quick brown fox jumps over the lazy dog", string_t::literal)); - TOML11_TEST_PARSE_EQUAL(parse_string, - "\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\"", - string("The quick brown fox jumps over the lazy dog", string_t::basic)); - TOML11_TEST_PARSE_EQUAL(parse_string, - "'''The quick brown fox \njumps over the lazy dog'''", - string("The quick brown fox \njumps over the lazy dog", string_t::literal)); -} - -BOOST_AUTO_TEST_CASE(test_string_value) -{ - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "\"The quick brown fox jumps over the lazy dog\"", - toml::value("The quick brown fox jumps over the lazy dog", string_t::basic)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "\'The quick brown fox jumps over the lazy dog\'", - toml::value("The quick brown fox jumps over the lazy dog", string_t::literal)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\"", - toml::value("The quick brown fox jumps over the lazy dog", string_t::basic)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "'''The quick brown fox \njumps over the lazy dog'''", - toml::value("The quick brown fox \njumps over the lazy dog", string_t::literal)); -} - - -BOOST_AUTO_TEST_CASE(test_basic_string) -{ - TOML11_TEST_PARSE_EQUAL(parse_string, - "\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"", - string("GitHub Cofounder & CEO\nLikes tater tots and beer.", string_t::basic)); - TOML11_TEST_PARSE_EQUAL(parse_string, - "\"192.168.1.1\"", - string("192.168.1.1", string_t::basic)); - -#if defined(_MSC_VER) || defined(__INTEL_COMPILER) - TOML11_TEST_PARSE_EQUAL(parse_string, - "\"\xE4\xB8\xAD\xE5\x9B\xBD\"", - string("\xE4\xB8\xAD\xE5\x9B\xBD", string_t::basic)); -#else - TOML11_TEST_PARSE_EQUAL(parse_string, - "\"中国\"", - string("中国", string_t::basic)); -#endif - - TOML11_TEST_PARSE_EQUAL(parse_string, - "\"You'll hate me after this - #\"", - string("You'll hate me after this - #", string_t::basic)); - TOML11_TEST_PARSE_EQUAL(parse_string, - "\" And when \\\"'s are in the along with # \\\"\"", - string(" And when \"'s are in the along with # \"", string_t::basic)); - TOML11_TEST_PARSE_EQUAL(parse_string, - "\"Here are fifteen apostrophes: '''''''''''''''\"", - string("Here are fifteen apostrophes: '''''''''''''''", string_t::basic)); -} - -BOOST_AUTO_TEST_CASE(test_basic_string_value) -{ - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"", - value("GitHub Cofounder & CEO\nLikes tater tots and beer.", string_t::basic)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "\"192.168.1.1\"", - value("192.168.1.1", string_t::basic)); -#if defined(_MSC_VER) || defined(__INTEL_COMPILER) - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "\"\xE4\xB8\xAD\xE5\x9B\xBD\"", - value("\xE4\xB8\xAD\xE5\x9B\xBD", string_t::basic)); -#else - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "\"中国\"", - value("中国", string_t::basic)); -#endif - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "\"You'll hate me after this - #\"", - value("You'll hate me after this - #", string_t::basic)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "\" And when \\\"'s are in the along with # \\\"\"", - value(" And when \"'s are in the along with # \"", string_t::basic)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "\"Here are fifteen apostrophes: '''''''''''''''\"", - value("Here are fifteen apostrophes: '''''''''''''''", string_t::basic)); -} - -BOOST_AUTO_TEST_CASE(test_ml_basic_string) -{ - TOML11_TEST_PARSE_EQUAL(parse_string, - "\"\"\"\nThe quick brown \\\n\n fox jumps over \\\n the lazy dog.\"\"\"", - string("The quick brown fox jumps over the lazy dog.", string_t::basic)); - TOML11_TEST_PARSE_EQUAL(parse_string, - "\"\"\"\\\n The quick brown \\\n\n fox jumps over \\\n the lazy dog.\\\n \"\"\"", - string("The quick brown fox jumps over the lazy dog.", string_t::basic)); - TOML11_TEST_PARSE_EQUAL(parse_string, - "\"\"\"Here are two quotation marks: \"\". Simple enough.\"\"\"", - string("Here are two quotation marks: \"\". Simple enough.", string_t::basic)); - TOML11_TEST_PARSE_EQUAL(parse_string, - "\"\"\"Here are three quotation marks: \"\"\\\".\"\"\"", - string("Here are three quotation marks: \"\"\".", string_t::basic)); - TOML11_TEST_PARSE_EQUAL(parse_string, - "\"\"\"Here are fifteen quotation marks: \"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\".\"\"\"", - string("Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".", string_t::basic)); - TOML11_TEST_PARSE_EQUAL(parse_string, - "\"\"\"\"This,\" she said, \"is just a pointless statement.\"\"\"\"", - string("\"This,\" she said, \"is just a pointless statement.\"", string_t::basic)); -} - -BOOST_AUTO_TEST_CASE(test_ml_basic_string_value) -{ - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "\"\"\"\nThe quick brown \\\n\n fox jumps over \\\n the lazy dog.\"\"\"", - value("The quick brown fox jumps over the lazy dog.", string_t::basic)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "\"\"\"\\\n The quick brown \\\n\n fox jumps over \\\n the lazy dog.\\\n \"\"\"", - value("The quick brown fox jumps over the lazy dog.", string_t::basic)); - - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "\"\"\"Here are two quotation marks: \"\". Simple enough.\"\"\"", - value("Here are two quotation marks: \"\". Simple enough.", string_t::basic)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "\"\"\"Here are three quotation marks: \"\"\\\".\"\"\"", - value("Here are three quotation marks: \"\"\".", string_t::basic)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "\"\"\"Here are fifteen quotation marks: \"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\".\"\"\"", - value("Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".", string_t::basic)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "\"\"\"\"This,\" she said, \"is just a pointless statement.\"\"\"\"", - value("\"This,\" she said, \"is just a pointless statement.\"", string_t::basic)); -} - -BOOST_AUTO_TEST_CASE(test_literal_string) -{ - TOML11_TEST_PARSE_EQUAL(parse_string, - "'C:\\Users\\nodejs\\templates'", - string("C:\\Users\\nodejs\\templates", string_t::literal)); - TOML11_TEST_PARSE_EQUAL(parse_string, - "'\\\\ServerX\\admin$\\system32\\'", - string("\\\\ServerX\\admin$\\system32\\", string_t::literal)); - TOML11_TEST_PARSE_EQUAL(parse_string, - "'Tom \"Dubs\" Preston-Werner'", - string("Tom \"Dubs\" Preston-Werner", string_t::literal)); - TOML11_TEST_PARSE_EQUAL(parse_string, - "'<\\i\\c*\\s*>'", - string("<\\i\\c*\\s*>", string_t::literal)); -} - -BOOST_AUTO_TEST_CASE(test_literal_string_value) -{ - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "'C:\\Users\\nodejs\\templates'", - value("C:\\Users\\nodejs\\templates", string_t::literal)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "'\\\\ServerX\\admin$\\system32\\'", - value("\\\\ServerX\\admin$\\system32\\", string_t::literal)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "'Tom \"Dubs\" Preston-Werner'", - value("Tom \"Dubs\" Preston-Werner", string_t::literal)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "'<\\i\\c*\\s*>'", - value("<\\i\\c*\\s*>", string_t::literal)); -} - -BOOST_AUTO_TEST_CASE(test_ml_literal_string) -{ - TOML11_TEST_PARSE_EQUAL(parse_string, - "'''I [dw]on't need \\d{2} apples'''", - string("I [dw]on't need \\d{2} apples", string_t::literal)); - TOML11_TEST_PARSE_EQUAL(parse_string, - "'''\nThe first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n'''", - string("The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n", string_t::literal)); - TOML11_TEST_PARSE_EQUAL(parse_string, - "''''That's still pointless', she said.'''", - string("'That's still pointless', she said.", string_t::literal)); - TOML11_TEST_PARSE_EQUAL(parse_string, - "'''Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".'''", - string("Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".", string_t::literal)); - TOML11_TEST_PARSE_EQUAL(parse_string, - "''''This,' she said, 'is just a pointless statement.''''", - string("'This,' she said, 'is just a pointless statement.'", string_t::literal)); -} - -BOOST_AUTO_TEST_CASE(test_ml_literal_string_value) -{ - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "'''I [dw]on't need \\d{2} apples'''", - value("I [dw]on't need \\d{2} apples", string_t::literal)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "'''\nThe first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n'''", - value("The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n", string_t::literal)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "''''That's still pointless', she said.'''", - value("'That's still pointless', she said.", string_t::literal)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "'''Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".'''", - value("Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".", string_t::literal)); - TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, - "''''This,' she said, 'is just a pointless statement.''''", - value("'This,' she said, 'is just a pointless statement.'", string_t::literal)); -} - -BOOST_AUTO_TEST_CASE(test_unicode_escape_sequence) -{ -#if defined(_MSC_VER) || defined(__INTEL_COMPILER) - TOML11_TEST_PARSE_EQUAL(parse_string, - "\"\\u03B1\\u03B2\\u03B3\"", - string("\xCE\xB1\xCE\xB2\xCE\xB3", string_t::basic)); - TOML11_TEST_PARSE_EQUAL(parse_string, - "\"\\U0001D7AA\"", - string("\xF0\x9D\x9E\xAA", string_t::basic)); -#else - TOML11_TEST_PARSE_EQUAL(parse_string, - "\"\\u03B1\\u03B2\\u03B3\"", - string("αβγ", string_t::basic)); - TOML11_TEST_PARSE_EQUAL(parse_string, - "\"\\U0001D7AA\"", - string("𝞪", string_t::basic)); -#endif -} diff --git a/lib/toml/tests/test_parse_table.cpp b/lib/toml/tests/test_parse_table.cpp deleted file mode 100644 index cb5baee..0000000 --- a/lib/toml/tests/test_parse_table.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#define BOOST_TEST_MODULE "parse_table_test" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include -#include "test_parse_aux.hpp" - -using namespace toml; -using namespace detail; - -BOOST_AUTO_TEST_CASE(test_normal_table) -{ - std::string table( - "key1 = \"value\"\n" - "key2 = 42\n" - "key3 = 3.14\n" - ); - location loc("test", table); - - const auto result = toml::detail::parse_ml_table(loc); - BOOST_TEST(result.is_ok()); - const auto data = result.unwrap(); - - BOOST_TEST(toml::get(data.at("key1")) == "value"); - BOOST_TEST(toml::get(data.at("key2")) == 42); - BOOST_TEST(toml::get(data.at("key3")) == 3.14); -} - -BOOST_AUTO_TEST_CASE(test_nested_table) -{ - std::string table( - "a.b = \"value\"\n" - "a.c.d = 42\n" - ); - location loc("test", table); - - const auto result = toml::detail::parse_ml_table(loc); - BOOST_TEST(result.is_ok()); - const auto data = result.unwrap(); - - const auto a = toml::get(data.at("a")); - const auto c = toml::get(a.at("c")); - - BOOST_TEST(toml::get(a.at("b")) == "value"); - BOOST_TEST(toml::get(c.at("d")) == 42); -} diff --git a/lib/toml/tests/test_parse_table_key.cpp b/lib/toml/tests/test_parse_table_key.cpp deleted file mode 100644 index 47df434..0000000 --- a/lib/toml/tests/test_parse_table_key.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#define BOOST_TEST_MODULE "parse_table_key_test" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include "test_parse_aux.hpp" - -using namespace toml; -using namespace detail; - -BOOST_AUTO_TEST_CASE(test_table_bare_key) -{ - TOML11_TEST_PARSE_EQUAL(parse_table_key, "[barekey]", std::vector(1, "barekey")); - TOML11_TEST_PARSE_EQUAL(parse_table_key, "[bare-key]", std::vector(1, "bare-key")); - TOML11_TEST_PARSE_EQUAL(parse_table_key, "[bare_key]", std::vector(1, "bare_key")); - TOML11_TEST_PARSE_EQUAL(parse_table_key, "[1234]", std::vector(1, "1234")); -} - -BOOST_AUTO_TEST_CASE(test_table_quoted_key) -{ - TOML11_TEST_PARSE_EQUAL(parse_table_key, "[\"127.0.0.1\"]", std::vector(1, "127.0.0.1" )); - TOML11_TEST_PARSE_EQUAL(parse_table_key, "[\"character encoding\"]", std::vector(1, "character encoding")); - TOML11_TEST_PARSE_EQUAL(parse_table_key, "[\"ʎǝʞ\"]", std::vector(1, "ʎǝʞ" )); - TOML11_TEST_PARSE_EQUAL(parse_table_key, "['key2']", std::vector(1, "key2" )); - TOML11_TEST_PARSE_EQUAL(parse_table_key, "['quoted \"value\"']", std::vector(1, "quoted \"value\"" )); -} - -BOOST_AUTO_TEST_CASE(test_table_dotted_key) -{ - { - std::vector keys(2); - keys[0] = "physical"; - keys[1] = "color"; - TOML11_TEST_PARSE_EQUAL(parse_table_key, "[physical.color]", keys); - } - { - std::vector keys(2); - keys[0] = "physical"; - keys[1] = "shape"; - TOML11_TEST_PARSE_EQUAL(parse_table_key, "[physical.shape]", keys); - } - { - std::vector keys(4); - keys[0] = "x"; - keys[1] = "y"; - keys[2] = "z"; - keys[3] = "w"; - TOML11_TEST_PARSE_EQUAL(parse_table_key, "[x.y.z.w]", keys); - TOML11_TEST_PARSE_EQUAL(parse_table_key, "[x . y . z . w]", keys); - TOML11_TEST_PARSE_EQUAL(parse_table_key, "[x. y .z. w]", keys); - TOML11_TEST_PARSE_EQUAL(parse_table_key, "[x .y. z .w]", keys); - TOML11_TEST_PARSE_EQUAL(parse_table_key, "[ x. y .z . w ]", keys); - TOML11_TEST_PARSE_EQUAL(parse_table_key, "[ x . y . z . w ]", keys); - } - { - std::vector keys(2); - keys[0] = "site"; - keys[1] = "google.com"; - TOML11_TEST_PARSE_EQUAL(parse_table_key, "[site.\"google.com\"]", keys); - } -} - -BOOST_AUTO_TEST_CASE(test_array_of_table_bare_key) -{ - TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[barekey]]", std::vector(1, "barekey")); - TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[bare-key]]", std::vector(1, "bare-key")); - TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[bare_key]]", std::vector(1, "bare_key")); - TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[1234]]", std::vector(1, "1234")); -} - -BOOST_AUTO_TEST_CASE(test_array_of_table_quoted_key) -{ - TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[\"127.0.0.1\"]]", std::vector(1, "127.0.0.1" )); - TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[\"character encoding\"]]", std::vector(1, "character encoding")); - TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[\"ʎǝʞ\"]]", std::vector(1, "ʎǝʞ" )); - TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[['key2']]", std::vector(1, "key2" )); - TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[['quoted \"value\"']]", std::vector(1, "quoted \"value\"" )); -} - -BOOST_AUTO_TEST_CASE(test_array_of_table_dotted_key) -{ - { - std::vector keys(2); - keys[0] = "physical"; - keys[1] = "color"; - TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[physical.color]]", keys); - } - { - std::vector keys(2); - keys[0] = "physical"; - keys[1] = "shape"; - TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[physical.shape]]", keys); - } - { - std::vector keys(4); - keys[0] = "x"; - keys[1] = "y"; - keys[2] = "z"; - keys[3] = "w"; - TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[x.y.z.w]]", keys); - TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[x . y . z . w]]", keys); - TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[x. y .z. w]]", keys); - TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[x .y. z .w]]", keys); - TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[ x. y .z . w ]]", keys); - TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[ x . y . z . w ]]", keys); - - } - { - std::vector keys(2); - keys[0] = "site"; - keys[1] = "google.com"; - TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[site.\"google.com\"]]", keys); - } -} diff --git a/lib/toml/tests/test_parse_unicode.cpp b/lib/toml/tests/test_parse_unicode.cpp deleted file mode 100644 index e3797a6..0000000 --- a/lib/toml/tests/test_parse_unicode.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#define BOOST_TEST_MODULE "test_parse_unicode" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include -#include - -BOOST_AUTO_TEST_CASE(test_hard_example_unicode) -{ - const auto data = toml::parse("toml/tests/hard_example_unicode.toml"); - - const auto the = toml::find(data, "the"); - BOOST_TEST(toml::get(the.at("test_string")) == - std::string("\xC3\x9D\xC3\xB4\xC3\xBA\x27\xE2\x84\x93\xE2\x84\x93\x20\xCE\xBB\xC3\xA1\xC6\xAD\xC3\xA8\x20\xE2\x82\xA5\xC3\xA8\x20\xC3\xA1\xC6\x92\xC6\xAD\xC3\xA8\xC5\x99\x20\xC6\xAD\xCE\xBB\xC3\xAF\xC6\xA8\x20\x2D\x20\x23")); - - const auto hard = toml::get(the.at("hard")); - const std::vector expected_the_hard_test_array{"] ", " # "}; - BOOST_CHECK(toml::get>(hard.at("test_array")) == - expected_the_hard_test_array); - const std::vector expected_the_hard_test_array2{ - std::string("\x54\xC3\xA8\xC6\xA8\xC6\xAD\x20\x23\x31\x31\x20\x5D\xC6\xA5\xC5\x99\xC3\xB4\xC6\xB2\xC3\xA8\xCE\xB4\x20\xC6\xAD\xCE\xBB\xC3\xA1\xC6\xAD"), - std::string("\xC3\x89\xD0\xB6\xC6\xA5\xC3\xA8\xC5\x99\xC3\xAF\xE2\x82\xA5\xC3\xA8\xC3\xB1\xC6\xAD\x20\x23\x39\x20\xCF\x89\xC3\xA1\xC6\xA8\x20\xC3\xA1\x20\xC6\xA8\xC3\xBA\xC3\xA7\xC3\xA7\xC3\xA8\xC6\xA8\xC6\xA8") - }; - BOOST_CHECK(toml::get>(hard.at("test_array2")) == - expected_the_hard_test_array2); - BOOST_TEST(toml::get(hard.at("another_test_string")) == - std::string("\xC2\xA7\xC3\xA1\xE2\x82\xA5\xC3\xA8\x20\xC6\xAD\xCE\xBB\xC3\xAF\xC3\xB1\xCF\xB1\x2C\x20\xCE\xB2\xC3\xBA\xC6\xAD\x20\xCF\x89\xC3\xAF\xC6\xAD\xCE\xBB\x20\xC3\xA1\x20\xC6\xA8\xC6\xAD\xC5\x99\xC3\xAF\xC3\xB1\xCF\xB1\x20\x23")); - BOOST_TEST(toml::get(hard.at("harder_test_string")) == - std::string("\x20\xC3\x82\xC3\xB1\xCE\xB4\x20\xCF\x89\xCE\xBB\xC3\xA8\xC3\xB1\x20\x22\x27\xC6\xA8\x20\xC3\xA1\xC5\x99\xC3\xA8\x20\xC3\xAF\xC3\xB1\x20\xC6\xAD\xCE\xBB\xC3\xA8\x20\xC6\xA8\xC6\xAD\xC5\x99\xC3\xAF\xC3\xB1\xCF\xB1\x2C\x20\xC3\xA1\xE2\x84\x93\xC3\xB4\xC3\xB1\xCF\xB1\x20\xCF\x89\xC3\xAF\xC6\xAD\xCE\xBB\x20\x23\x20\x22")); -// - const auto bit = toml::get(hard.at(std::string("\xCE\xB2\xC3\xAF\xC6\xAD\x23"))); - BOOST_TEST(toml::get(bit.at(std::string("\xCF\x89\xCE\xBB\xC3\xA1\xC6\xAD\x3F"))) == - std::string("\xC3\x9D\xC3\xB4\xC3\xBA\x20\xCE\xB4\xC3\xB4\xC3\xB1\x27\xC6\xAD\x20\xC6\xAD\xCE\xBB\xC3\xAF\xC3\xB1\xC6\x99\x20\xC6\xA8\xC3\xB4\xE2\x82\xA5\xC3\xA8\x20\xC3\xBA\xC6\xA8\xC3\xA8\xC5\x99\x20\xCF\x89\xC3\xB4\xC3\xB1\x27\xC6\xAD\x20\xCE\xB4\xC3\xB4\x20\xC6\xAD\xCE\xBB\xC3\xA1\xC6\xAD\x3F")); - const std::vector expected_multi_line_array{"]"}; - BOOST_CHECK(toml::get>(bit.at("multi_line_array")) == - expected_multi_line_array); -} diff --git a/lib/toml/tests/test_result.cpp b/lib/toml/tests/test_result.cpp deleted file mode 100644 index d693bd6..0000000 --- a/lib/toml/tests/test_result.cpp +++ /dev/null @@ -1,441 +0,0 @@ -#define BOOST_TEST_MODULE "test_result" -#include -#include -#include - -BOOST_AUTO_TEST_CASE(test_construct) -{ - { - auto s = toml::ok(42); - toml::result result(s); - BOOST_TEST(!!result); - BOOST_TEST(result.is_ok()); - BOOST_TEST(!result.is_err()); - BOOST_TEST(result.unwrap() == 42); - } - { - const auto s = toml::ok(42); - toml::result result(s); - BOOST_TEST(!!result); - BOOST_TEST(result.is_ok()); - BOOST_TEST(!result.is_err()); - BOOST_TEST(result.unwrap() == 42); - } - { - toml::result result(toml::ok(42)); - BOOST_TEST(!!result); - BOOST_TEST(result.is_ok()); - BOOST_TEST(!result.is_err()); - BOOST_TEST(result.unwrap() == 42); - } - - { - auto f = toml::err("foobar"); - toml::result result(f); - BOOST_TEST(!result); - BOOST_TEST(!result.is_ok()); - BOOST_TEST(result.is_err()); - BOOST_TEST(result.unwrap_err() == "foobar"); - } - { - const auto f = toml::err("foobar"); - toml::result result(f); - BOOST_TEST(!result); - BOOST_TEST(!result.is_ok()); - BOOST_TEST(result.is_err()); - BOOST_TEST(result.unwrap_err() == "foobar"); - } - { - toml::result result(toml::err("foobar")); - BOOST_TEST(!result); - BOOST_TEST(!result.is_ok()); - BOOST_TEST(result.is_err()); - BOOST_TEST(result.unwrap_err() == "foobar"); - } -} - -BOOST_AUTO_TEST_CASE(test_assignment) -{ - { - toml::result result(toml::err("foobar")); - result = toml::ok(42); - BOOST_TEST(!!result); - BOOST_TEST(result.is_ok()); - BOOST_TEST(!result.is_err()); - BOOST_TEST(result.unwrap() == 42); - } - { - toml::result result(toml::err("foobar")); - auto s = toml::ok(42); - result = s; - BOOST_TEST(!!result); - BOOST_TEST(result.is_ok()); - BOOST_TEST(!result.is_err()); - BOOST_TEST(result.unwrap() == 42); - } - { - toml::result result(toml::err("foobar")); - const auto s = toml::ok(42); - result = s; - BOOST_TEST(!!result); - BOOST_TEST(result.is_ok()); - BOOST_TEST(!result.is_err()); - BOOST_TEST(result.unwrap() == 42); - } - { - toml::result result(toml::err("foobar")); - result = toml::err("hoge"); - BOOST_TEST(!result); - BOOST_TEST(!result.is_ok()); - BOOST_TEST(result.is_err()); - BOOST_TEST(result.unwrap_err() == "hoge"); - } - { - toml::result result(toml::err("foobar")); - auto f = toml::err("hoge"); - result = f; - BOOST_TEST(!result); - BOOST_TEST(!result.is_ok()); - BOOST_TEST(result.is_err()); - BOOST_TEST(result.unwrap_err() == "hoge"); - } - { - toml::result result(toml::err("foobar")); - const auto f = toml::err("hoge"); - result = f; - BOOST_TEST(!result); - BOOST_TEST(!result.is_ok()); - BOOST_TEST(result.is_err()); - BOOST_TEST(result.unwrap_err() == "hoge"); - } -} - -BOOST_AUTO_TEST_CASE(test_map) -{ - { - const toml::result result(toml::ok(42)); - const auto mapped = result.map( - [](const int i) -> int { - return i * 2; - }); - - BOOST_TEST(!!mapped); - BOOST_TEST(mapped.is_ok()); - BOOST_TEST(!mapped.is_err()); - BOOST_TEST(mapped.unwrap() == 42 * 2); - } - { - toml::result, std::string> - result(toml::ok(std::unique_ptr(new int(42)))); - const auto mapped = std::move(result).map( - [](std::unique_ptr i) -> int { - return *i; - }); - - BOOST_TEST(!!mapped); - BOOST_TEST(mapped.is_ok()); - BOOST_TEST(!mapped.is_err()); - BOOST_TEST(mapped.unwrap() == 42); - } - { - const toml::result result(toml::err("hoge")); - const auto mapped = result.map( - [](const int i) -> int { - return i * 2; - }); - - BOOST_TEST(!mapped); - BOOST_TEST(!mapped.is_ok()); - BOOST_TEST(mapped.is_err()); - BOOST_TEST(mapped.unwrap_err() == "hoge"); - } - { - toml::result, std::string> - result(toml::err("hoge")); - const auto mapped = std::move(result).map( - [](std::unique_ptr i) -> int { - return *i; - }); - - BOOST_TEST(!mapped); - BOOST_TEST(!mapped.is_ok()); - BOOST_TEST(mapped.is_err()); - BOOST_TEST(mapped.unwrap_err() == "hoge"); - } -} - -BOOST_AUTO_TEST_CASE(test_map_err) -{ - { - const toml::result result(toml::ok(42)); - const auto mapped = result.map_err( - [](const std::string s) -> std::string { - return s + s; - }); - - BOOST_TEST(!!mapped); - BOOST_TEST(mapped.is_ok()); - BOOST_TEST(!mapped.is_err()); - BOOST_TEST(mapped.unwrap() == 42); - } - { - toml::result, std::string> - result(toml::ok(std::unique_ptr(new int(42)))); - const auto mapped = std::move(result).map_err( - [](const std::string s) -> std::string { - return s + s; - }); - - BOOST_TEST(!!mapped); - BOOST_TEST(mapped.is_ok()); - BOOST_TEST(!mapped.is_err()); - BOOST_TEST(*(mapped.unwrap()) == 42); - } - { - const toml::result result(toml::err("hoge")); - const auto mapped = result.map_err( - [](const std::string s) -> std::string { - return s + s; - }); - BOOST_TEST(!mapped); - BOOST_TEST(!mapped.is_ok()); - BOOST_TEST(mapped.is_err()); - BOOST_TEST(mapped.unwrap_err() == "hogehoge"); - } - { - toml::result> - result(toml::err(std::unique_ptr(new std::string("hoge")))); - const auto mapped = std::move(result).map_err( - [](std::unique_ptr p) -> std::string { - return *p; - }); - - BOOST_TEST(!mapped); - BOOST_TEST(!mapped.is_ok()); - BOOST_TEST(mapped.is_err()); - BOOST_TEST(mapped.unwrap_err() == "hoge"); - } -} - -BOOST_AUTO_TEST_CASE(test_map_or_else) -{ - { - const toml::result result(toml::ok(42)); - const auto mapped = result.map_or_else( - [](const int i) -> int { - return i * 2; - }, 54); - - BOOST_TEST(mapped == 42 * 2); - } - { - toml::result, std::string> - result(toml::ok(std::unique_ptr(new int(42)))); - const auto mapped = std::move(result).map_or_else( - [](std::unique_ptr i) -> int { - return *i; - }, 54); - - BOOST_TEST(mapped == 42); - } - { - const toml::result result(toml::err("hoge")); - const auto mapped = result.map_or_else( - [](const int i) -> int { - return i * 2; - }, 54); - - BOOST_TEST(mapped == 54); - } - { - toml::result, std::string> - result(toml::err("hoge")); - const auto mapped = std::move(result).map_or_else( - [](std::unique_ptr i) -> int { - return *i; - }, 54); - - BOOST_TEST(mapped == 54); - } -} - -BOOST_AUTO_TEST_CASE(test_map_err_or_else) -{ - { - const toml::result result(toml::ok(42)); - const auto mapped = result.map_err_or_else( - [](const std::string i) -> std::string { - return i + i; - }, "foobar"); - - BOOST_TEST(mapped == "foobar"); - } - { - toml::result, std::string> - result(toml::ok(std::unique_ptr(new int(42)))); - const auto mapped = std::move(result).map_err_or_else( - [](const std::string i) -> std::string { - return i + i; - }, "foobar"); - - BOOST_TEST(mapped == "foobar"); - } - { - const toml::result result(toml::err("hoge")); - const auto mapped = result.map_err_or_else( - [](const std::string i) -> std::string { - return i + i; - }, "foobar"); - - BOOST_TEST(mapped == "hogehoge"); - } - { - toml::result, std::string> - result(toml::err("hoge")); - const auto mapped = result.map_err_or_else( - [](const std::string i) -> std::string { - return i + i; - }, "foobar"); - - BOOST_TEST(mapped == "hogehoge"); - } -} - - -BOOST_AUTO_TEST_CASE(test_and_then) -{ - { - const toml::result result(toml::ok(42)); - const auto mapped = result.and_then( - [](const int i) -> toml::result { - return toml::ok(i * 2); - }); - - BOOST_TEST(!!mapped); - BOOST_TEST(mapped.is_ok()); - BOOST_TEST(!mapped.is_err()); - BOOST_TEST(mapped.unwrap() == 42 * 2); - } - { - toml::result, std::string> - result(toml::ok(std::unique_ptr(new int(42)))); - const auto mapped = std::move(result).and_then( - [](std::unique_ptr i) -> toml::result { - return toml::ok(*i); - }); - - BOOST_TEST(!!mapped); - BOOST_TEST(mapped.is_ok()); - BOOST_TEST(!mapped.is_err()); - BOOST_TEST(mapped.unwrap() == 42); - } - { - const toml::result result(toml::err("hoge")); - const auto mapped = result.and_then( - [](const int i) -> toml::result { - return toml::ok(i * 2); - }); - - BOOST_TEST(!mapped); - BOOST_TEST(!mapped.is_ok()); - BOOST_TEST(mapped.is_err()); - BOOST_TEST(mapped.unwrap_err() == "hoge"); - } - { - toml::result, std::string> - result(toml::err("hoge")); - const auto mapped = std::move(result).and_then( - [](std::unique_ptr i) -> toml::result { - return toml::ok(*i); - }); - - BOOST_TEST(!mapped); - BOOST_TEST(!mapped.is_ok()); - BOOST_TEST(mapped.is_err()); - BOOST_TEST(mapped.unwrap_err() == "hoge"); - } -} - -BOOST_AUTO_TEST_CASE(test_or_else) -{ - { - const toml::result result(toml::ok(42)); - const auto mapped = result.or_else( - [](const std::string& s) -> toml::result { - return toml::err(s + s); - }); - - BOOST_TEST(!!mapped); - BOOST_TEST(mapped.is_ok()); - BOOST_TEST(!mapped.is_err()); - BOOST_TEST(mapped.unwrap() == 42); - } - { - toml::result, std::string> - result(toml::ok(std::unique_ptr(new int(42)))); - const auto mapped = std::move(result).or_else( - [](const std::string& s) -> toml::result, std::string> { - return toml::err(s + s); - }); - - BOOST_TEST(!!mapped); - BOOST_TEST(mapped.is_ok()); - BOOST_TEST(!mapped.is_err()); - BOOST_TEST(*mapped.unwrap() == 42); - } - { - const toml::result result(toml::err("hoge")); - const auto mapped = result.or_else( - [](const std::string& s) -> toml::result { - return toml::err(s + s); - }); - - BOOST_TEST(!mapped); - BOOST_TEST(!mapped.is_ok()); - BOOST_TEST(mapped.is_err()); - BOOST_TEST(mapped.unwrap_err() == "hogehoge"); - } - { - toml::result, std::string> - result(toml::err("hoge")); - const auto mapped = std::move(result).or_else( - [](const std::string& s) -> toml::result, std::string> { - return toml::err(s + s); - }); - - BOOST_TEST(!mapped); - BOOST_TEST(!mapped.is_ok()); - BOOST_TEST(mapped.is_err()); - BOOST_TEST(mapped.unwrap_err() == "hogehoge"); - } -} - -BOOST_AUTO_TEST_CASE(test_and_or_other) -{ - { - const toml::result r1(toml::ok(42)); - const toml::result r2(toml::err("foo")); - - BOOST_TEST(r1 == r1.or_other(r2)); - BOOST_TEST(r2 == r1.and_other(r2)); - BOOST_TEST(42 == r1.or_other(r2).unwrap()); - BOOST_TEST("foo" == r1.and_other(r2).unwrap_err()); - } - { - auto r1_gen = []() -> toml::result { - return toml::ok(42); - }; - auto r2_gen = []() -> toml::result { - return toml::err("foo"); - }; - const auto r3 = r1_gen(); - const auto r4 = r2_gen(); - - BOOST_TEST(r3 == r1_gen().or_other (r2_gen())); - BOOST_TEST(r4 == r1_gen().and_other(r2_gen())); - BOOST_TEST(42 == r1_gen().or_other (r2_gen()).unwrap()); - BOOST_TEST("foo" == r1_gen().and_other(r2_gen()).unwrap_err()); - } -} - - diff --git a/lib/toml/tests/test_serialize_file.cpp b/lib/toml/tests/test_serialize_file.cpp deleted file mode 100644 index 7e1d8e1..0000000 --- a/lib/toml/tests/test_serialize_file.cpp +++ /dev/null @@ -1,363 +0,0 @@ -#define BOOST_TEST_MODULE "test_serialize_file" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include -#include -#include -#include -#include - -template class Table, - template class Array> -bool has_comment_inside(const toml::basic_value& v) -{ - if(!v.comments().empty()) - { - return false; - } - // v itself does not have a comment. - if(v.is_array()) - { - for(const auto& x : v.as_array()) - { - if(has_comment_inside(x)) - { - return false; - } - } - } - if(v.is_table()) - { - for(const auto& x : v.as_table()) - { - if(has_comment_inside(x.second)) - { - return false; - } - } - } - return true; -} - -BOOST_AUTO_TEST_CASE(test_example) -{ - const auto data = toml::parse("toml/tests/example.toml"); - { - std::ofstream ofs("tmp1.toml"); - ofs << std::setw(80) << data; - } - - auto serialized = toml::parse("tmp1.toml"); - { - auto& owner = toml::find(serialized, "owner"); - auto& bio = toml::find(owner, "bio"); - const auto CR = std::find(bio.begin(), bio.end(), '\r'); - if(CR != bio.end()) - { - bio.erase(CR); - } - } - BOOST_TEST(data == serialized); -} - -BOOST_AUTO_TEST_CASE(test_example_map_dq) -{ - const auto data = toml::parse( - "toml/tests/example.toml"); - { - std::ofstream ofs("tmp1_map_dq.toml"); - ofs << std::setw(80) << data; - } - - auto serialized = toml::parse( - "tmp1_map_dq.toml"); - { - auto& owner = toml::find(serialized, "owner"); - auto& bio = toml::find(owner, "bio"); - const auto CR = std::find(bio.begin(), bio.end(), '\r'); - if(CR != bio.end()) - { - bio.erase(CR); - } - } - BOOST_TEST(data == serialized); -} - -BOOST_AUTO_TEST_CASE(test_example_with_comment) -{ - const auto data = toml::parse("toml/tests/example.toml"); - { - std::ofstream ofs("tmp1_com.toml"); - ofs << std::setw(80) << data; - } - - auto serialized = toml::parse("tmp1_com.toml"); - { - auto& owner = toml::find(serialized, "owner"); - auto& bio = toml::find(owner, "bio"); - const auto CR = std::find(bio.begin(), bio.end(), '\r'); - if(CR != bio.end()) - { - bio.erase(CR); - } - } - BOOST_TEST(data == serialized); - { - std::ofstream ofs("tmp1_com1.toml"); - ofs << std::setw(80) << serialized; - } -} - -BOOST_AUTO_TEST_CASE(test_example_with_comment_nocomment) -{ - { - const auto data = toml::parse("toml/tests/example.toml"); - { - std::ofstream ofs("tmp1_com_nocomment.toml"); - ofs << std::setw(80) << toml::nocomment << data; - } - const auto serialized = toml::parse("tmp1_com_nocomment.toml"); - // check no comment exist - BOOST_TEST(!has_comment_inside(serialized)); - } - { - const auto data_nocomment = toml::parse("toml/tests/example.toml"); - auto serialized = toml::parse("tmp1_com_nocomment.toml"); - { - auto& owner = toml::find(serialized, "owner"); - auto& bio = toml::find(owner, "bio"); - const auto CR = std::find(bio.begin(), bio.end(), '\r'); - if(CR != bio.end()) - { - bio.erase(CR); - } - } - // check collectly serialized - BOOST_TEST(data_nocomment == serialized); - } -} - -BOOST_AUTO_TEST_CASE(test_example_with_comment_map_dq) -{ - const auto data = toml::parse( - "toml/tests/example.toml"); - { - std::ofstream ofs("tmp1_com_map_dq.toml"); - ofs << std::setw(80) << data; - } - - auto serialized = toml::parse( - "tmp1_com_map_dq.toml"); - { - auto& owner = toml::find(serialized, "owner"); - auto& bio = toml::find(owner, "bio"); - const auto CR = std::find(bio.begin(), bio.end(), '\r'); - if(CR != bio.end()) - { - bio.erase(CR); - } - } - BOOST_TEST(data == serialized); - { - std::ofstream ofs("tmp1_com1_map_dq.toml"); - ofs << std::setw(80) << serialized; - } -} - -BOOST_AUTO_TEST_CASE(test_example_with_comment_map_dq_nocomment) -{ - { - const auto data = toml::parse("toml/tests/example.toml"); - { - std::ofstream ofs("tmp1_com_map_dq_nocomment.toml"); - ofs << std::setw(80) << toml::nocomment << data; - } - const auto serialized = toml::parse("tmp1_com_map_dq_nocomment.toml"); - BOOST_TEST(!has_comment_inside(serialized)); - } - { - const auto data_nocomment = toml::parse("toml/tests/example.toml"); - auto serialized = toml::parse("tmp1_com_map_dq_nocomment.toml"); - { - auto& owner = toml::find(serialized, "owner"); - auto& bio = toml::find(owner, "bio"); - const auto CR = std::find(bio.begin(), bio.end(), '\r'); - if(CR != bio.end()) - { - bio.erase(CR); - } - } - BOOST_TEST(data_nocomment == serialized); - } -} - -BOOST_AUTO_TEST_CASE(test_fruit) -{ - const auto data = toml::parse("toml/tests/fruit.toml"); - { - std::ofstream ofs("tmp2.toml"); - ofs << std::setw(80) << data; - } - const auto serialized = toml::parse("tmp2.toml"); - BOOST_TEST(data == serialized); -} - -BOOST_AUTO_TEST_CASE(test_fruit_map_dq) -{ - const auto data = toml::parse( - "toml/tests/fruit.toml"); - { - std::ofstream ofs("tmp2.toml"); - ofs << std::setw(80) << data; - } - const auto serialized = toml::parse( - "tmp2.toml"); - BOOST_TEST(data == serialized); -} - -BOOST_AUTO_TEST_CASE(test_fruit_with_comments) -{ - const auto data = toml::parse("toml/tests/fruit.toml"); - { - std::ofstream ofs("tmp2_com.toml"); - ofs << std::setw(80) << data; - } - const auto serialized = toml::parse("tmp2_com.toml"); - BOOST_TEST(data == serialized); -} - -BOOST_AUTO_TEST_CASE(test_fruit_with_comments_map_dq) -{ - const auto data = toml::parse( - "toml/tests/fruit.toml"); - { - std::ofstream ofs("tmp2_com.toml"); - ofs << std::setw(80) << data; - } - const auto serialized = toml::parse("tmp2_com.toml"); - BOOST_TEST(data == serialized); -} - -BOOST_AUTO_TEST_CASE(test_hard_example) -{ - const auto data = toml::parse("toml/tests/hard_example.toml"); - { - std::ofstream ofs("tmp3.toml"); - ofs << std::setw(80) << data; - } - const auto serialized = toml::parse("tmp3.toml"); - BOOST_TEST(data == serialized); -} - -BOOST_AUTO_TEST_CASE(test_hard_example_map_dq) -{ - const auto data = toml::parse( - "toml/tests/hard_example.toml"); - { - std::ofstream ofs("tmp3.toml"); - ofs << std::setw(80) << data; - } - const auto serialized = toml::parse( - "tmp3.toml"); - BOOST_TEST(data == serialized); -} - -BOOST_AUTO_TEST_CASE(test_hard_example_with_comment) -{ - const auto data = toml::parse( - "toml/tests/hard_example.toml"); - { - std::ofstream ofs("tmp3_com.toml"); - ofs << std::setw(80) << data; - } - const auto serialized = toml::parse( - "tmp3_com.toml"); - { - std::ofstream ofs("tmp3_com1.toml"); - ofs << std::setw(80) << serialized; - } - BOOST_TEST(data == serialized); -} - -BOOST_AUTO_TEST_CASE(test_format_key) -{ - { - const toml::key key("normal_bare-key"); - BOOST_TEST("normal_bare-key" == toml::format_key(key)); - } - { - const toml::key key("key.include.dots"); - BOOST_TEST("\"key.include.dots\"" == toml::format_key(key)); - } - { - const toml::key key("key-include-unicode-\xE3\x81\x82"); - BOOST_TEST("\"key-include-unicode-\xE3\x81\x82\"" == toml::format_key(key)); - } - { - const toml::key key("special-chars-\\-\"-\b-\f-\r-\n-\t"); - BOOST_TEST("\"special-chars-\\\\-\\\"-\\b-\\f-\\r-\\n-\\t\"" == toml::format_key(key)); - } -} - -// In toml11, an implicitly-defined value does not have any comments. -// So, in the following file, -// ```toml -// # comment -// [[array-of-tables]] -// foo = "bar" -// ``` -// The array named "array-of-tables" does not have the comment, but the first -// element of the array has. That means that, the above file is equivalent to -// the following. -// ```toml -// array-of-tables = [ -// # comment -// {foo = "bar"}, -// ] -// ``` -// If the array itself has a comment (value_has_comment_ == true), we should try -// to make it inline. -// ```toml -// # comment about array -// array-of-tables = [ -// # comment about table element -// {foo = "bar"} -// ] -// ``` -// If it is formatted as a multiline table, the two comments becomes -// indistinguishable. -// ```toml -// # comment about array -// # comment about table element -// [[array-of-tables]] -// foo = "bar" -// ``` -// So we need to try to make it inline, and it force-inlines regardless -// of the line width limit. -// It may fail if the element of a table has comment. In that case, -// the array-of-tables will be formatted as a multiline table. -BOOST_AUTO_TEST_CASE(test_distinguish_comment) -{ - const std::string str = R"(# comment about array itself -array_of_table = [ - # comment about the first element (table) - {key = "value"}, -])"; - std::istringstream iss(str); - const auto data = toml::parse(iss); - const auto serialized = toml::format(data, /*width = */ 0); - - std::istringstream reparse(serialized); - const auto parsed = toml::parse(reparse); - - BOOST_TEST(parsed.at("array_of_table").comments().size() == 1u); - BOOST_TEST(parsed.at("array_of_table").comments().front() == " comment about array itself"); - BOOST_TEST(parsed.at("array_of_table").at(0).comments().size() == 1u); - BOOST_TEST(parsed.at("array_of_table").at(0).comments().front() == " comment about the first element (table)"); -} diff --git a/lib/toml/tests/test_string.cpp b/lib/toml/tests/test_string.cpp deleted file mode 100644 index 444fc63..0000000 --- a/lib/toml/tests/test_string.cpp +++ /dev/null @@ -1,154 +0,0 @@ -#define BOOST_TEST_MODULE "test_string" -#include -#include - -BOOST_AUTO_TEST_CASE(test_basic_string) -{ - { - const toml::string str("basic string"); - std::ostringstream oss; - oss << str; - BOOST_TEST(oss.str() == "\"basic string\""); - } - { - const std::string s1 ("basic string"); - const toml::string str(s1); - std::ostringstream oss; - oss << str; - BOOST_TEST(oss.str() == "\"basic string\""); - } - { - const toml::string str("basic string", toml::string_t::basic); - std::ostringstream oss; - oss << str; - BOOST_TEST(oss.str() == "\"basic string\""); - } - { - const std::string s1 ("basic string"); - const toml::string str(s1, toml::string_t::basic); - std::ostringstream oss; - oss << str; - BOOST_TEST(oss.str() == "\"basic string\""); - } -} - -BOOST_AUTO_TEST_CASE(test_basic_ml_string) -{ - { - const toml::string str("basic\nstring"); - std::ostringstream oss1; - oss1 << str; - std::ostringstream oss2; - oss2 << "\"\"\"\nbasic\nstring\\\n\"\"\""; - BOOST_TEST(oss1.str() == oss2.str()); - } - { - const std::string s1 ("basic\nstring"); - const toml::string str(s1); - std::ostringstream oss1; - oss1 << str; - std::ostringstream oss2; - oss2 << "\"\"\"\nbasic\nstring\\\n\"\"\""; - BOOST_TEST(oss1.str() == oss2.str()); - } - { - const toml::string str("basic\nstring", toml::string_t::basic); - std::ostringstream oss1; - oss1 << str; - std::ostringstream oss2; - oss2 << "\"\"\"\nbasic\nstring\\\n\"\"\""; - BOOST_TEST(oss1.str() == oss2.str()); - - } - { - const std::string s1 ("basic\nstring"); - const toml::string str(s1, toml::string_t::basic); - std::ostringstream oss1; - oss1 << str; - std::ostringstream oss2; - oss2 << "\"\"\"\nbasic\nstring\\\n\"\"\""; - BOOST_TEST(oss1.str() == oss2.str()); - } -} - - -BOOST_AUTO_TEST_CASE(test_literal_string) -{ - { - const toml::string str("literal string", toml::string_t::literal); - std::ostringstream oss; - oss << str; - BOOST_TEST(oss.str() == "'literal string'"); - } - { - const std::string s1 ("literal string"); - const toml::string str(s1, toml::string_t::literal); - std::ostringstream oss; - oss << str; - BOOST_TEST(oss.str() == "'literal string'"); - } -} - -BOOST_AUTO_TEST_CASE(test_literal_ml_string) -{ - { - const toml::string str("literal\nstring", toml::string_t::literal); - std::ostringstream oss1; - oss1 << str; - std::ostringstream oss2; - oss2 << "'''\nliteral\nstring'''"; - BOOST_TEST(oss1.str() == oss2.str()); - - } - { - const std::string s1 ("literal\nstring"); - const toml::string str(s1, toml::string_t::literal); - std::ostringstream oss1; - oss1 << str; - std::ostringstream oss2; - oss2 << "'''\nliteral\nstring'''"; - BOOST_TEST(oss1.str() == oss2.str()); - } -} - -BOOST_AUTO_TEST_CASE(test_string_add_assign) -{ - // string literal - { - toml::string str("foo"); - str += "bar"; - BOOST_TEST(str.str == "foobar"); - } - // std::string - { - toml::string str("foo"); - std::string str2("bar"); - str += str2; - BOOST_TEST(str.str == "foobar"); - } - // toml::string - { - toml::string str("foo"); - toml::string str2("bar"); - str += str2; - BOOST_TEST(str.str == "foobar"); - } -#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L - // std::string_view - { - toml::string str("foo"); - str += std::string_view("bar"); - BOOST_TEST(str == "foobar"); - } -#endif - // std::string += toml::string - { - std::string str("foo"); - toml::string str2("bar"); - str += str2; - BOOST_TEST(str == "foobar"); - } - - -} - diff --git a/lib/toml/tests/test_traits.cpp b/lib/toml/tests/test_traits.cpp deleted file mode 100644 index 63b8a14..0000000 --- a/lib/toml/tests/test_traits.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#define BOOST_TEST_MODULE "test_traits" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct dummy_type{}; - -template -struct dummy_container -{ - typedef T value_type; - typedef value_type* pointer; - typedef value_type& reference; - typedef value_type const* const_pointer; - typedef value_type const& const_reference; - typedef pointer iterator; - typedef const_pointer const_iterator; -}; - -typedef std::array std_array_type; -typedef std::map std_map_type; -typedef std::unordered_map std_unordered_map_type; - -BOOST_AUTO_TEST_CASE(test_has_xxx) -{ - BOOST_TEST(toml::detail::has_iterator>::value); - BOOST_TEST(toml::detail::has_iterator>::value); - BOOST_TEST(toml::detail::has_iterator>::value); - BOOST_TEST(toml::detail::has_iterator>::value); - BOOST_TEST(toml::detail::has_iterator>::value); - BOOST_TEST(toml::detail::has_iterator>::value); - BOOST_TEST(toml::detail::has_iterator::value); - BOOST_TEST(toml::detail::has_iterator::value); - BOOST_TEST(toml::detail::has_iterator::value); - BOOST_TEST(toml::detail::has_iterator>::value); - - BOOST_TEST(toml::detail::has_value_type>::value); - BOOST_TEST(toml::detail::has_value_type>::value); - BOOST_TEST(toml::detail::has_value_type>::value); - BOOST_TEST(toml::detail::has_value_type>::value); - BOOST_TEST(toml::detail::has_value_type::value); - BOOST_TEST(toml::detail::has_value_type>::value); - BOOST_TEST(toml::detail::has_value_type>::value); - BOOST_TEST(toml::detail::has_value_type::value); - BOOST_TEST(toml::detail::has_value_type::value); - BOOST_TEST(toml::detail::has_value_type>::value); - - BOOST_TEST(toml::detail::has_key_type::value); - BOOST_TEST(toml::detail::has_key_type::value); - BOOST_TEST(toml::detail::has_mapped_type::value); - BOOST_TEST(toml::detail::has_mapped_type::value); -} - -BOOST_AUTO_TEST_CASE(test_is_xxx) -{ - BOOST_TEST(toml::detail::is_container>::value); - BOOST_TEST(toml::detail::is_container>::value); - BOOST_TEST(toml::detail::is_container>::value); - BOOST_TEST(toml::detail::is_container>::value); - BOOST_TEST(toml::detail::is_container::value); - BOOST_TEST(toml::detail::is_container>::value); - BOOST_TEST(toml::detail::is_container>::value); - BOOST_TEST(toml::detail::is_container>::value); - - BOOST_TEST(!toml::detail::is_container::value); - BOOST_TEST(!toml::detail::is_container::value); - - BOOST_TEST(toml::detail::is_map::value); - BOOST_TEST(toml::detail::is_map::value); -} diff --git a/lib/toml/tests/test_utility.cpp b/lib/toml/tests/test_utility.cpp deleted file mode 100644 index 6919399..0000000 --- a/lib/toml/tests/test_utility.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#define BOOST_TEST_MODULE "test_acceptor" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include -#include - -BOOST_AUTO_TEST_CASE(test_try_reserve) -{ - { - // since BOOST_TEST is a macro, it cannot handle commas correctly. - // When toml::detail::has_reserve_method>::value - // is passed to a macro, C preprocessor considers - // toml::detail::has_reserve_method>::value as the second argument. We need an alias to avoid - // this problem. - using reservable_type = std::vector ; - using nonreservable_type = std::array; - BOOST_TEST( toml::detail::has_reserve_method::value); - BOOST_TEST(!toml::detail::has_reserve_method::value); - } - { - std::vector v; - toml::try_reserve(v, 100); - BOOST_TEST(v.capacity() == 100u); - } -} - -BOOST_AUTO_TEST_CASE(test_concat_to_string) -{ - const std::string cat = toml::concat_to_string("foo", "bar", 42); - BOOST_TEST(cat == "foobar42"); -} - -BOOST_AUTO_TEST_CASE(test_from_string) -{ - { - const std::string str("123"); - BOOST_TEST(toml::from_string(str, 0) == 123); - } - { - const std::string str("01"); - BOOST_TEST(toml::from_string(str, 0) == 1); - } -} diff --git a/lib/toml/tests/test_value.cpp b/lib/toml/tests/test_value.cpp deleted file mode 100644 index 099d502..0000000 --- a/lib/toml/tests/test_value.cpp +++ /dev/null @@ -1,1019 +0,0 @@ -#define BOOST_TEST_MODULE "test_value" -#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST -#include -#else -#define BOOST_TEST_NO_LIB -#include -#endif -#include -#include -#include - -#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L -#include -#endif - - -BOOST_AUTO_TEST_CASE(test_value_boolean) -{ - toml::value v1(true); - toml::value v2(false); - - BOOST_TEST(v1.type() == toml::value_t::boolean); - BOOST_TEST(v2.type() == toml::value_t::boolean); - BOOST_TEST(v1.is(toml::value_t::boolean)); - BOOST_TEST(v2.is(toml::value_t::boolean)); - BOOST_TEST(v1.is()); - BOOST_TEST(v2.is()); - BOOST_TEST(v1.is_boolean()); - BOOST_TEST(v2.is_boolean()); - - BOOST_TEST(v1.cast() == true); - BOOST_TEST(v2.cast() == false); - BOOST_TEST(v1.as_boolean() == true); - BOOST_TEST(v2.as_boolean() == false); - BOOST_TEST(v1.as_boolean(std::nothrow) == true); - BOOST_TEST(v2.as_boolean(std::nothrow) == false); - - v1 = false; - v2 = true; - - BOOST_TEST(v1.type() == toml::value_t::boolean); - BOOST_TEST(v2.type() == toml::value_t::boolean); - BOOST_TEST(v1.is(toml::value_t::boolean)); - BOOST_TEST(v2.is(toml::value_t::boolean)); - BOOST_TEST(v1.is()); - BOOST_TEST(v2.is()); - BOOST_TEST(v1.is_boolean()); - BOOST_TEST(v2.is_boolean()); - - BOOST_TEST(v1.cast() == false); - BOOST_TEST(v2.cast() == true); - BOOST_TEST(v1.as_boolean() == false); - BOOST_TEST(v2.as_boolean() == true); - - toml::value v3(v1); - toml::value v4(v2); - BOOST_TEST(v3 == v1); - BOOST_TEST(v4 == v2); - - BOOST_TEST(v3.type() == toml::value_t::boolean); - BOOST_TEST(v4.type() == toml::value_t::boolean); - BOOST_TEST(v3.is(toml::value_t::boolean)); - BOOST_TEST(v4.is(toml::value_t::boolean)); - BOOST_TEST(v3.is()); - BOOST_TEST(v4.is()); - BOOST_TEST(v3.is_boolean()); - BOOST_TEST(v4.is_boolean()); - - BOOST_TEST(v3.cast() == false); - BOOST_TEST(v4.cast() == true); - BOOST_TEST(v3.as_boolean() == false); - BOOST_TEST(v4.as_boolean() == true); - - toml::value v5(std::move(v1)); - toml::value v6(std::move(v2)); - - BOOST_TEST(v5.type() == toml::value_t::boolean); - BOOST_TEST(v6.type() == toml::value_t::boolean); - BOOST_TEST(v5.is(toml::value_t::boolean)); - BOOST_TEST(v6.is(toml::value_t::boolean)); - BOOST_TEST(v5.is()); - BOOST_TEST(v6.is()); - BOOST_TEST(v3.is_boolean()); - BOOST_TEST(v4.is_boolean()); - - BOOST_TEST(v5.cast() == false); - BOOST_TEST(v6.cast() == true); - BOOST_TEST(v5.as_boolean() == false); - BOOST_TEST(v6.as_boolean() == true); - - v1 = 42; - v2 = 3.14; - - BOOST_TEST(v1.type() == toml::value_t::integer); - BOOST_TEST(v2.type() == toml::value_t::floating); - BOOST_TEST(v1.is(toml::value_t::integer)); - BOOST_TEST(v2.is(toml::value_t::floating)); - BOOST_TEST(v1.is()); - BOOST_TEST(v2.is()); - BOOST_TEST(v1.is_integer()); - BOOST_TEST(v2.is_floating()); - - BOOST_TEST(v1.cast() == 42); - BOOST_TEST(v2.cast() == 3.14); - BOOST_TEST(v1.as_integer() == 42); - BOOST_TEST(v2.as_floating() == 3.14); -} - -BOOST_AUTO_TEST_CASE(test_value_integer) -{ - toml::value v1(-42); - toml::value v2(42u); - - BOOST_TEST(v1.type() == toml::value_t::integer); - BOOST_TEST(v2.type() == toml::value_t::integer); - BOOST_TEST(v1.is(toml::value_t::integer)); - BOOST_TEST(v2.is(toml::value_t::integer)); - BOOST_TEST(v1.is()); - BOOST_TEST(v2.is()); - BOOST_TEST(v1.is_integer()); - BOOST_TEST(v2.is_integer()); - - BOOST_TEST(v1.cast() == -42); - BOOST_TEST(v2.cast() == 42u); - BOOST_TEST(v1.as_integer() == -42); - BOOST_TEST(v2.as_integer() == 42u); - BOOST_TEST(v1.as_integer(std::nothrow) == -42); - BOOST_TEST(v2.as_integer(std::nothrow) == 42u); - - v1 = 54; - v2 = -54; - - BOOST_TEST(v1.type() == toml::value_t::integer); - BOOST_TEST(v2.type() == toml::value_t::integer); - BOOST_TEST(v1.is(toml::value_t::integer)); - BOOST_TEST(v2.is(toml::value_t::integer)); - BOOST_TEST(v1.is()); - BOOST_TEST(v2.is()); - BOOST_TEST(v1.is_integer()); - BOOST_TEST(v2.is_integer()); - - BOOST_TEST(v1.cast() == 54); - BOOST_TEST(v2.cast() == -54); - BOOST_TEST(v1.as_integer() == 54); - BOOST_TEST(v2.as_integer() == -54); - - toml::value v3(v1); - toml::value v4(v2); - BOOST_TEST(v3 == v1); - BOOST_TEST(v4 == v2); - - BOOST_TEST(v3.type() == toml::value_t::integer); - BOOST_TEST(v4.type() == toml::value_t::integer); - BOOST_TEST(v3.is(toml::value_t::integer)); - BOOST_TEST(v4.is(toml::value_t::integer)); - BOOST_TEST(v3.is()); - BOOST_TEST(v4.is()); - BOOST_TEST(v3.is_integer()); - BOOST_TEST(v4.is_integer()); - - BOOST_TEST(v3.cast() == 54); - BOOST_TEST(v4.cast() == -54); - BOOST_TEST(v3.as_integer() == 54); - BOOST_TEST(v4.as_integer() == -54); - - toml::value v5(std::move(v1)); - toml::value v6(std::move(v2)); - - BOOST_TEST(v5.type() == toml::value_t::integer); - BOOST_TEST(v6.type() == toml::value_t::integer); - BOOST_TEST(v5.is(toml::value_t::integer)); - BOOST_TEST(v6.is(toml::value_t::integer)); - BOOST_TEST(v5.is()); - BOOST_TEST(v6.is()); - BOOST_TEST(v5.is_integer()); - BOOST_TEST(v6.is_integer()); - - BOOST_TEST(v5.cast() == 54); - BOOST_TEST(v6.cast() == -54); - BOOST_TEST(v5.as_integer() == 54); - BOOST_TEST(v6.as_integer() == -54); - - v1 = true; - v2 = false; - - BOOST_TEST(v1.type() == toml::value_t::boolean); - BOOST_TEST(v2.type() == toml::value_t::boolean); - BOOST_TEST(v1.is(toml::value_t::boolean)); - BOOST_TEST(v2.is(toml::value_t::boolean)); - BOOST_TEST(v1.is()); - BOOST_TEST(v2.is()); - BOOST_TEST(v1.is_boolean()); - BOOST_TEST(v2.is_boolean()); - - BOOST_TEST(v1.cast() == true); - BOOST_TEST(v2.cast() == false); - BOOST_TEST(v1.as_boolean() == true); - BOOST_TEST(v2.as_boolean() == false); -} - -BOOST_AUTO_TEST_CASE(test_value_float) -{ - toml::value v1(3.14); - toml::value v2(3.14f); - - BOOST_TEST(v1.type() == toml::value_t::floating); - BOOST_TEST(v2.type() == toml::value_t::floating); - BOOST_TEST(v1.is(toml::value_t::floating)); - BOOST_TEST(v2.is(toml::value_t::floating)); - BOOST_TEST(v1.is()); - BOOST_TEST(v2.is()); - BOOST_TEST(v1.is_floating()); - BOOST_TEST(v2.is_floating()); - - BOOST_TEST(v1.cast() == 3.14); - BOOST_TEST(v2.cast() == 3.14, - boost::test_tools::tolerance(1e-2)); - BOOST_TEST(v1.as_floating() == 3.14); - BOOST_TEST(v2.as_floating() == 3.14, - boost::test_tools::tolerance(1e-2)); - BOOST_TEST(v1.as_floating(std::nothrow) == 3.14); - BOOST_TEST(v2.as_floating(std::nothrow) == 3.14, - boost::test_tools::tolerance(1e-2)); - - v1 = 2.718f; - v2 = 2.718; - - BOOST_TEST(v1.type() == toml::value_t::floating); - BOOST_TEST(v2.type() == toml::value_t::floating); - BOOST_TEST(v1.is(toml::value_t::floating)); - BOOST_TEST(v2.is(toml::value_t::floating)); - BOOST_TEST(v1.is()); - BOOST_TEST(v2.is()); - BOOST_TEST(v1.is_floating()); - BOOST_TEST(v2.is_floating()); - - BOOST_TEST(v1.cast() == 2.718, - boost::test_tools::tolerance(1e-3)); - BOOST_TEST(v2.cast() == 2.718); - BOOST_TEST(v1.as_floating() == 2.718, - boost::test_tools::tolerance(1e-3)); - BOOST_TEST(v2.as_floating() == 2.718); - - toml::value v3(v1); - toml::value v4(v2); - BOOST_TEST(v3 == v1); - BOOST_TEST(v4 == v2); - - BOOST_TEST(v3.type() == toml::value_t::floating); - BOOST_TEST(v4.type() == toml::value_t::floating); - BOOST_TEST(v3.is(toml::value_t::floating)); - BOOST_TEST(v4.is(toml::value_t::floating)); - BOOST_TEST(v3.is()); - BOOST_TEST(v4.is()); - BOOST_TEST(v3.is_floating()); - BOOST_TEST(v4.is_floating()); - - BOOST_TEST(v3.cast() == 2.718, - boost::test_tools::tolerance(1e-3)); - BOOST_TEST(v4.cast() == 2.718); - BOOST_TEST(v3.as_floating() == 2.718, - boost::test_tools::tolerance(1e-3)); - BOOST_TEST(v4.as_floating() == 2.718); - - toml::value v5(std::move(v1)); - toml::value v6(std::move(v2)); - - BOOST_TEST(v5.type() == toml::value_t::floating); - BOOST_TEST(v6.type() == toml::value_t::floating); - BOOST_TEST(v5.is(toml::value_t::floating)); - BOOST_TEST(v6.is(toml::value_t::floating)); - BOOST_TEST(v5.is()); - BOOST_TEST(v6.is()); - BOOST_TEST(v5.is_floating()); - BOOST_TEST(v6.is_floating()); - - BOOST_TEST(v5.cast() == 2.718, - boost::test_tools::tolerance(1e-3)); - BOOST_TEST(v6.cast() == 2.718); - BOOST_TEST(v5.as_floating() == 2.718, - boost::test_tools::tolerance(1e-3)); - BOOST_TEST(v6.as_floating() == 2.718); - - v1 = true; - v2 = false; - - BOOST_TEST(v1.type() == toml::value_t::boolean); - BOOST_TEST(v2.type() == toml::value_t::boolean); - BOOST_TEST(v1.is(toml::value_t::boolean)); - BOOST_TEST(v2.is(toml::value_t::boolean)); - BOOST_TEST(v1.is()); - BOOST_TEST(v2.is()); - BOOST_TEST(v1.is_boolean()); - BOOST_TEST(v2.is_boolean()); - - BOOST_TEST(v1.cast() == true); - BOOST_TEST(v2.cast() == false); - BOOST_TEST(v1.as_boolean() == true); - BOOST_TEST(v2.as_boolean() == false); -} - -BOOST_AUTO_TEST_CASE(test_value_string) -{ - toml::value v1(std::string("foo")); - toml::value v2(std::string("foo"), toml::string_t::literal); - toml::value v3("foo"); - - BOOST_TEST(v1.type() == toml::value_t::string); - BOOST_TEST(v2.type() == toml::value_t::string); - BOOST_TEST(v3.type() == toml::value_t::string); - BOOST_TEST(v1.is(toml::value_t::string)); - BOOST_TEST(v2.is(toml::value_t::string)); - BOOST_TEST(v3.is(toml::value_t::string)); - BOOST_TEST(v1.is()); - BOOST_TEST(v2.is()); - BOOST_TEST(v3.is()); - BOOST_TEST(v1.is_string()); - BOOST_TEST(v2.is_string()); - BOOST_TEST(v3.is_string()); - - BOOST_TEST(v1.cast() == "foo"); - BOOST_TEST(v2.cast() == "foo"); - BOOST_TEST(v3.cast() == "foo"); - BOOST_TEST(v1.as_string() == "foo"); - BOOST_TEST(v2.as_string() == "foo"); - BOOST_TEST(v3.as_string() == "foo"); - BOOST_TEST(v1.as_string(std::nothrow) == "foo"); - BOOST_TEST(v2.as_string(std::nothrow) == "foo"); - BOOST_TEST(v3.as_string(std::nothrow) == "foo"); - - v1 = "bar"; - v2 = "bar"; - v3 = "bar"; - - BOOST_TEST(v1.type() == toml::value_t::string); - BOOST_TEST(v2.type() == toml::value_t::string); - BOOST_TEST(v3.type() == toml::value_t::string); - BOOST_TEST(v1.is(toml::value_t::string)); - BOOST_TEST(v2.is(toml::value_t::string)); - BOOST_TEST(v3.is(toml::value_t::string)); - BOOST_TEST(v1.is_string()); - BOOST_TEST(v2.is_string()); - BOOST_TEST(v3.is_string()); - - BOOST_TEST(v1.cast() == "bar"); - BOOST_TEST(v2.cast() == "bar"); - BOOST_TEST(v3.cast() == "bar"); - BOOST_TEST(v1.as_string() == "bar"); - BOOST_TEST(v2.as_string() == "bar"); - BOOST_TEST(v3.as_string() == "bar"); - - - toml::value v4(v1); - toml::value v5(v2); - toml::value v6(v3); - BOOST_TEST(v4 == v1); - BOOST_TEST(v5 == v2); - BOOST_TEST(v6 == v3); - - BOOST_TEST(v4.type() == toml::value_t::string); - BOOST_TEST(v5.type() == toml::value_t::string); - BOOST_TEST(v6.type() == toml::value_t::string); - BOOST_TEST(v4.is(toml::value_t::string)); - BOOST_TEST(v5.is(toml::value_t::string)); - BOOST_TEST(v6.is(toml::value_t::string)); - BOOST_TEST(v4.is()); - BOOST_TEST(v5.is()); - BOOST_TEST(v6.is()); - BOOST_TEST(v4.is_string()); - BOOST_TEST(v5.is_string()); - BOOST_TEST(v6.is_string()); - - BOOST_TEST(v4.cast() == "bar"); - BOOST_TEST(v5.cast() == "bar"); - BOOST_TEST(v6.cast() == "bar"); - BOOST_TEST(v4.as_string() == "bar"); - BOOST_TEST(v5.as_string() == "bar"); - BOOST_TEST(v6.as_string() == "bar"); - - - v4.cast().str.at(2) = 'z'; - v5.cast().str.at(2) = 'z'; - v6.cast().str.at(2) = 'z'; - - BOOST_TEST(v4.type() == toml::value_t::string); - BOOST_TEST(v5.type() == toml::value_t::string); - BOOST_TEST(v6.type() == toml::value_t::string); - BOOST_TEST(v4.is(toml::value_t::string)); - BOOST_TEST(v5.is(toml::value_t::string)); - BOOST_TEST(v6.is(toml::value_t::string)); - BOOST_TEST(v4.is()); - BOOST_TEST(v5.is()); - BOOST_TEST(v6.is()); - BOOST_TEST(v4.is_string()); - BOOST_TEST(v5.is_string()); - BOOST_TEST(v6.is_string()); - - BOOST_TEST(v4.as_string() == "baz"); - BOOST_TEST(v5.as_string() == "baz"); - BOOST_TEST(v6.as_string() == "baz"); - - v1 = true; - v2 = true; - v3 = true; - - BOOST_TEST(v1.type() == toml::value_t::boolean); - BOOST_TEST(v2.type() == toml::value_t::boolean); - BOOST_TEST(v3.type() == toml::value_t::boolean); - BOOST_TEST(v1.is(toml::value_t::boolean)); - BOOST_TEST(v2.is(toml::value_t::boolean)); - BOOST_TEST(v3.is(toml::value_t::boolean)); - BOOST_TEST(v1.is()); - BOOST_TEST(v2.is()); - BOOST_TEST(v3.is()); - BOOST_TEST(v1.is_boolean()); - BOOST_TEST(v2.is_boolean()); - BOOST_TEST(v3.is_boolean()); - - BOOST_TEST(v1.cast() == true); - BOOST_TEST(v2.cast() == true); - BOOST_TEST(v3.cast() == true); - BOOST_TEST(v1.as_boolean() == true); - BOOST_TEST(v2.as_boolean() == true); - BOOST_TEST(v3.as_boolean() == true); - -#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L - std::string_view sv = "foo"; - - toml::value v7(sv); - toml::value v8(sv, toml::string_t::literal); - - BOOST_TEST(v7.type() == toml::value_t::string); - BOOST_TEST(v8.type() == toml::value_t::string); - BOOST_TEST(v7.is(toml::value_t::string)); - BOOST_TEST(v8.is(toml::value_t::string)); - BOOST_TEST(v7.is()); - BOOST_TEST(v8.is()); - BOOST_TEST(v7.is_string()); - BOOST_TEST(v8.is_string()); - - BOOST_TEST(v7.cast() == "foo"); - BOOST_TEST(v8.cast() == "foo"); -#endif -} - -BOOST_AUTO_TEST_CASE(test_value_local_date) -{ - toml::value v1(toml::local_date(2018, toml::month_t::Jan, 31)); - - BOOST_TEST(v1.type() == toml::value_t::local_date); - BOOST_TEST(v1.is(toml::value_t::local_date)); - BOOST_TEST(v1.is()); - BOOST_TEST(v1.is_local_date()); - - BOOST_TEST(v1.cast() == - toml::local_date(2018, toml::month_t::Jan, 31)); - BOOST_TEST(v1.as_local_date() == - toml::local_date(2018, toml::month_t::Jan, 31)); - BOOST_TEST(v1.as_local_date(std::nothrow) == - toml::local_date(2018, toml::month_t::Jan, 31)); - - v1 = toml::local_date(2018, toml::month_t::Apr, 1); - - BOOST_TEST(v1.type() == toml::value_t::local_date); - BOOST_TEST(v1.is(toml::value_t::local_date)); - BOOST_TEST(v1.is()); - BOOST_TEST(v1.is_local_date()); - - BOOST_TEST(v1.cast() == - toml::local_date(2018, toml::month_t::Apr, 1)); - BOOST_TEST(v1.as_local_date() == - toml::local_date(2018, toml::month_t::Apr, 1)); - - toml::value v2(v1); - BOOST_TEST(v2 == v1); - - BOOST_TEST(v2.type() == toml::value_t::local_date); - BOOST_TEST(v2.is(toml::value_t::local_date)); - BOOST_TEST(v2.is()); - BOOST_TEST(v2.is_local_date()); - - BOOST_TEST(v2.cast() == - toml::local_date(2018, toml::month_t::Apr, 1)); - BOOST_TEST(v2.as_local_date() == - toml::local_date(2018, toml::month_t::Apr, 1)); - - v1 = true; - BOOST_TEST(v1.type() == toml::value_t::boolean); - BOOST_TEST(v1.is(toml::value_t::boolean)); - BOOST_TEST(v1.is()); - BOOST_TEST(v1.is_boolean()); - BOOST_TEST(v1.cast() == true); - BOOST_TEST(v1.as_boolean() == true); -} - -BOOST_AUTO_TEST_CASE(test_value_local_time) -{ - toml::value v1(toml::local_time(12, 30, 45)); - toml::value v2(std::chrono::hours(12) + std::chrono::minutes(30) + - std::chrono::seconds(45)); - - BOOST_TEST(v1.type() == toml::value_t::local_time); - BOOST_TEST(v2.type() == toml::value_t::local_time); - BOOST_TEST(v1.is(toml::value_t::local_time)); - BOOST_TEST(v2.is(toml::value_t::local_time)); - BOOST_TEST(v1.is()); - BOOST_TEST(v2.is()); - BOOST_TEST(v1.is_local_time()); - BOOST_TEST(v2.is_local_time()); - - BOOST_TEST(v1.cast() == - toml::local_time(12, 30, 45)); - BOOST_TEST(v1.as_local_time() == - toml::local_time(12, 30, 45)); - - BOOST_TEST(v2.cast() == - toml::local_time(12, 30, 45)); - BOOST_TEST(v2.as_local_time() == - toml::local_time(12, 30, 45)); - - BOOST_TEST(v1.cast() == - v2.cast()); - BOOST_TEST(v1.as_local_time() == - v2.as_local_time()); - BOOST_TEST(v1.as_local_time(std::nothrow) == - v2.as_local_time(std::nothrow)); - - v1 = toml::local_time(1, 30, 0, /*ms*/ 100, /*us*/ 0); - - BOOST_TEST(v1.type() == toml::value_t::local_time); - BOOST_TEST(v1.is(toml::value_t::local_time)); - BOOST_TEST(v1.is()); - BOOST_TEST(v1.is_local_time()); - BOOST_TEST(v1.cast() == - toml::local_time(1, 30, 0, 100, 0)); - BOOST_TEST(v1.as_local_time() == - toml::local_time(1, 30, 0, 100, 0)); - - toml::value v3(v1); - BOOST_TEST(v3 == v1); - - BOOST_TEST(v3.type() == toml::value_t::local_time); - BOOST_TEST(v3.is(toml::value_t::local_time)); - BOOST_TEST(v3.is()); - BOOST_TEST(v3.is_local_time()); - - BOOST_TEST(v3.cast() == - toml::local_time(1, 30, 0, 100, 0)); - BOOST_TEST(v3.as_local_time() == - toml::local_time(1, 30, 0, 100, 0)); - - v1 = true; - BOOST_TEST(v1.type() == toml::value_t::boolean); - BOOST_TEST(v1.is(toml::value_t::boolean)); - BOOST_TEST(v1.is()); - BOOST_TEST(v1.is_boolean()); - BOOST_TEST(v1.cast() == true); - BOOST_TEST(v1.as_boolean() == true); -} - -BOOST_AUTO_TEST_CASE(test_value_local_datetime) -{ - toml::value v1(toml::local_datetime( - toml::local_date(2018, toml::month_t::Jan, 31), - toml::local_time(12, 30, 45) - )); - - BOOST_TEST(v1.type() == toml::value_t::local_datetime); - BOOST_TEST(v1.is(toml::value_t::local_datetime)); - BOOST_TEST(v1.is()); - BOOST_TEST(v1.is_local_datetime()); - - BOOST_TEST(v1.cast() == - toml::local_datetime( - toml::local_date(2018, toml::month_t::Jan, 31), - toml::local_time(12, 30, 45))); - BOOST_TEST(v1.as_local_datetime() == - toml::local_datetime( - toml::local_date(2018, toml::month_t::Jan, 31), - toml::local_time(12, 30, 45))); - BOOST_TEST(v1.as_local_datetime(std::nothrow) == - toml::local_datetime( - toml::local_date(2018, toml::month_t::Jan, 31), - toml::local_time(12, 30, 45))); - - - v1 = toml::local_datetime( - toml::local_date(2018, toml::month_t::Apr, 1), - toml::local_time(1, 15, 30)); - - BOOST_TEST(v1.type() == toml::value_t::local_datetime); - BOOST_TEST(v1.is(toml::value_t::local_datetime)); - BOOST_TEST(v1.is()); - BOOST_TEST(v1.is_local_datetime()); - - BOOST_TEST(v1.cast() == - toml::local_datetime( - toml::local_date(2018, toml::month_t::Apr, 1), - toml::local_time(1, 15, 30))); - BOOST_TEST(v1.as_local_datetime() == - toml::local_datetime( - toml::local_date(2018, toml::month_t::Apr, 1), - toml::local_time(1, 15, 30))); - - toml::value v2(v1); - BOOST_TEST(v2 == v1); - - BOOST_TEST(v2.type() == toml::value_t::local_datetime); - BOOST_TEST(v2.is(toml::value_t::local_datetime)); - BOOST_TEST(v2.is()); - BOOST_TEST(v2.is_local_datetime()); - - BOOST_TEST(v2.cast() == - toml::local_datetime( - toml::local_date(2018, toml::month_t::Apr, 1), - toml::local_time(1, 15, 30))); - BOOST_TEST(v2.as_local_datetime() == - toml::local_datetime( - toml::local_date(2018, toml::month_t::Apr, 1), - toml::local_time(1, 15, 30))); - - - v1 = true; - BOOST_TEST(v1.type() == toml::value_t::boolean); - BOOST_TEST(v1.is(toml::value_t::boolean)); - BOOST_TEST(v1.is()); - BOOST_TEST(v1.is_boolean()); - BOOST_TEST(v1.cast() == true); - BOOST_TEST(v1.as_boolean() == true); -} - -BOOST_AUTO_TEST_CASE(test_value_offset_datetime) -{ - toml::value v1(toml::offset_datetime( - toml::local_date(2018, toml::month_t::Jan, 31), - toml::local_time(12, 30, 45), - toml::time_offset(9, 0) - )); - - BOOST_TEST(v1.type() == toml::value_t::offset_datetime); - BOOST_TEST(v1.is(toml::value_t::offset_datetime)); - BOOST_TEST(v1.is()); - BOOST_TEST(v1.is_offset_datetime()); - - BOOST_TEST(v1.cast() == - toml::offset_datetime( - toml::local_date(2018, toml::month_t::Jan, 31), - toml::local_time(12, 30, 45), - toml::time_offset(9, 0) - )); - BOOST_TEST(v1.as_offset_datetime() == - toml::offset_datetime( - toml::local_date(2018, toml::month_t::Jan, 31), - toml::local_time(12, 30, 45), - toml::time_offset(9, 0) - )); - BOOST_TEST(v1.as_offset_datetime(std::nothrow) == - toml::offset_datetime( - toml::local_date(2018, toml::month_t::Jan, 31), - toml::local_time(12, 30, 45), - toml::time_offset(9, 0) - )); - - - v1 = toml::offset_datetime( - toml::local_date(2018, toml::month_t::Apr, 1), - toml::local_time(1, 15, 30), - toml::time_offset(9, 0)); - - BOOST_TEST(v1.type() == toml::value_t::offset_datetime); - BOOST_TEST(v1.is(toml::value_t::offset_datetime)); - BOOST_TEST(v1.is()); - BOOST_TEST(v1.is_offset_datetime()); - - BOOST_TEST(v1.cast() == - toml::offset_datetime( - toml::local_date(2018, toml::month_t::Apr, 1), - toml::local_time(1, 15, 30), - toml::time_offset(9, 0))); - BOOST_TEST(v1.as_offset_datetime() == - toml::offset_datetime( - toml::local_date(2018, toml::month_t::Apr, 1), - toml::local_time(1, 15, 30), - toml::time_offset(9, 0))); - - - toml::value v2(v1); - BOOST_TEST(v2 == v1); - - BOOST_TEST(v2.type() == toml::value_t::offset_datetime); - BOOST_TEST(v2.is(toml::value_t::offset_datetime)); - BOOST_TEST(v2.is()); - BOOST_TEST(v2.is_offset_datetime()); - - BOOST_TEST(v2.cast() == - toml::offset_datetime( - toml::local_date(2018, toml::month_t::Apr, 1), - toml::local_time(1, 15, 30), - toml::time_offset(9, 0))); - BOOST_TEST(v2.as_offset_datetime() == - toml::offset_datetime( - toml::local_date(2018, toml::month_t::Apr, 1), - toml::local_time(1, 15, 30), - toml::time_offset(9, 0))); - - v1 = true; - BOOST_TEST(v1.type() == toml::value_t::boolean); - BOOST_TEST(v1.is(toml::value_t::boolean)); - BOOST_TEST(v1.is()); - BOOST_TEST(v1.is_boolean()); - BOOST_TEST(v1.cast() == true); - BOOST_TEST(v1.as_boolean() == true); -} - -BOOST_AUTO_TEST_CASE(test_value_array) -{ - std::vector v{1,2,3,4,5}; - toml::value v1(v); - toml::value v2{6,7,8,9,0}; - - BOOST_TEST(v1.type() == toml::value_t::array); - BOOST_TEST(v1.is(toml::value_t::array)); - BOOST_TEST(v1.is()); - BOOST_TEST(v1.is_array()); - - BOOST_TEST(v2.type() == toml::value_t::array); - BOOST_TEST(v2.is(toml::value_t::array)); - BOOST_TEST(v2.is()); - BOOST_TEST(v2.is_array()); - - BOOST_TEST(v1.cast().at(0).cast() == 1); - BOOST_TEST(v1.cast().at(1).cast() == 2); - BOOST_TEST(v1.cast().at(2).cast() == 3); - BOOST_TEST(v1.cast().at(3).cast() == 4); - BOOST_TEST(v1.cast().at(4).cast() == 5); - BOOST_TEST(v1.as_array().at(0).as_integer() == 1); - BOOST_TEST(v1.as_array().at(1).as_integer() == 2); - BOOST_TEST(v1.as_array().at(2).as_integer() == 3); - BOOST_TEST(v1.as_array().at(3).as_integer() == 4); - BOOST_TEST(v1.as_array().at(4).as_integer() == 5); - BOOST_TEST(v1.as_array(std::nothrow).at(0).as_integer() == 1); - BOOST_TEST(v1.as_array(std::nothrow).at(1).as_integer() == 2); - BOOST_TEST(v1.as_array(std::nothrow).at(2).as_integer() == 3); - BOOST_TEST(v1.as_array(std::nothrow).at(3).as_integer() == 4); - BOOST_TEST(v1.as_array(std::nothrow).at(4).as_integer() == 5); - - BOOST_TEST(v2.cast().at(0).cast() == 6); - BOOST_TEST(v2.cast().at(1).cast() == 7); - BOOST_TEST(v2.cast().at(2).cast() == 8); - BOOST_TEST(v2.cast().at(3).cast() == 9); - BOOST_TEST(v2.cast().at(4).cast() == 0); - - v1 = {6,7,8,9,0}; - v2 = v; - - BOOST_TEST(v1.type() == toml::value_t::array); - BOOST_TEST(v1.is(toml::value_t::array)); - BOOST_TEST(v1.is()); - BOOST_TEST(v1.is_array()); - - BOOST_TEST(v2.type() == toml::value_t::array); - BOOST_TEST(v2.is(toml::value_t::array)); - BOOST_TEST(v2.is()); - BOOST_TEST(v2.is_array()); - - BOOST_TEST(v1.cast().at(0).cast() == 6); - BOOST_TEST(v1.cast().at(1).cast() == 7); - BOOST_TEST(v1.cast().at(2).cast() == 8); - BOOST_TEST(v1.cast().at(3).cast() == 9); - BOOST_TEST(v1.cast().at(4).cast() == 0); - BOOST_TEST(v1.as_array().at(0).as_integer() == 6); - BOOST_TEST(v1.as_array().at(1).as_integer() == 7); - BOOST_TEST(v1.as_array().at(2).as_integer() == 8); - BOOST_TEST(v1.as_array().at(3).as_integer() == 9); - BOOST_TEST(v1.as_array().at(4).as_integer() == 0); - - - BOOST_TEST(v2.cast().at(0).cast() == 1); - BOOST_TEST(v2.cast().at(1).cast() == 2); - BOOST_TEST(v2.cast().at(2).cast() == 3); - BOOST_TEST(v2.cast().at(3).cast() == 4); - BOOST_TEST(v2.cast().at(4).cast() == 5); - BOOST_TEST(v2.as_array().at(0).as_integer() == 1); - BOOST_TEST(v2.as_array().at(1).as_integer() == 2); - BOOST_TEST(v2.as_array().at(2).as_integer() == 3); - BOOST_TEST(v2.as_array().at(3).as_integer() == 4); - BOOST_TEST(v2.as_array().at(4).as_integer() == 5); - - - toml::value v3(v1); - BOOST_TEST(v3 == v1); - - BOOST_TEST(v3.type() == toml::value_t::array); - BOOST_TEST(v3.is(toml::value_t::array)); - BOOST_TEST(v3.is()); - BOOST_TEST(v3.is_array()); - - BOOST_TEST(v3.cast().at(0).cast() == 6); - BOOST_TEST(v3.cast().at(1).cast() == 7); - BOOST_TEST(v3.cast().at(2).cast() == 8); - BOOST_TEST(v3.cast().at(3).cast() == 9); - BOOST_TEST(v3.cast().at(4).cast() == 0); - BOOST_TEST(v3.as_array().at(0).as_integer() == 6); - BOOST_TEST(v3.as_array().at(1).as_integer() == 7); - BOOST_TEST(v3.as_array().at(2).as_integer() == 8); - BOOST_TEST(v3.as_array().at(3).as_integer() == 9); - BOOST_TEST(v3.as_array().at(4).as_integer() == 0); - - - v1 = true; - BOOST_TEST(v1.type() == toml::value_t::boolean); - BOOST_TEST(v1.is(toml::value_t::boolean)); - BOOST_TEST(v1.is()); - BOOST_TEST(v1.is_boolean()); - BOOST_TEST(v1.cast() == true); - BOOST_TEST(v1.as_boolean() == true); -} - -BOOST_AUTO_TEST_CASE(test_value_table) -{ - toml::value v1{{"foo", 42}, {"bar", 3.14}, {"baz", "qux"}}; - - BOOST_TEST(v1.type() == toml::value_t::table); - BOOST_TEST(v1.is(toml::value_t::table)); - BOOST_TEST(v1.is()); - BOOST_TEST(v1.is_table()); - - BOOST_TEST(v1.cast().at("foo").cast() == 42); - BOOST_TEST(v1.cast().at("bar").cast() == 3.14); - BOOST_TEST(v1.cast().at("baz").cast().str == "qux"); - BOOST_TEST(v1.as_table().at("foo").as_integer() == 42); - BOOST_TEST(v1.as_table().at("bar").as_floating() == 3.14); - BOOST_TEST(v1.as_table().at("baz").as_string().str == "qux"); - BOOST_TEST(v1.as_table(std::nothrow).at("foo").as_integer() == 42); - BOOST_TEST(v1.as_table(std::nothrow).at("bar").as_floating() == 3.14); - BOOST_TEST(v1.as_table(std::nothrow).at("baz").as_string().str == "qux"); - - v1 = {{"foo", 2.71}, {"bar", 54}, {"baz", "quux"}}; - - BOOST_TEST(v1.type() == toml::value_t::table); - BOOST_TEST(v1.is(toml::value_t::table)); - BOOST_TEST(v1.is()); - BOOST_TEST(v1.is_table()); - - BOOST_TEST(v1.cast().at("foo").cast() == 2.71); - BOOST_TEST(v1.cast().at("bar").cast() == 54); - BOOST_TEST(v1.cast().at("baz").cast().str == "quux"); - BOOST_TEST(v1.as_table().at("foo").as_floating() == 2.71); - BOOST_TEST(v1.as_table().at("bar").as_integer() == 54); - BOOST_TEST(v1.as_table().at("baz").as_string().str == "quux"); - - v1 = toml::table{{"foo", 2.71}, {"bar", 54}, {"baz", "quux"}}; - - BOOST_TEST(v1.type() == toml::value_t::table); - BOOST_TEST(v1.is(toml::value_t::table)); - BOOST_TEST(v1.is()); - BOOST_TEST(v1.is_table()); - - BOOST_TEST(v1.cast().at("foo").cast() == 2.71); - BOOST_TEST(v1.cast().at("bar").cast() == 54); - BOOST_TEST(v1.cast().at("baz").cast().str == "quux"); - BOOST_TEST(v1.as_table().at("foo").as_floating() == 2.71); - BOOST_TEST(v1.as_table().at("bar").as_integer() == 54); - BOOST_TEST(v1.as_table().at("baz").as_string().str == "quux"); - - toml::value v3(v1); - BOOST_TEST(v3 == v1); - - BOOST_TEST(v3.type() == toml::value_t::table); - BOOST_TEST(v3.is(toml::value_t::table)); - BOOST_TEST(v3.is()); - BOOST_TEST(v3.is_table()); - - BOOST_TEST(v3.cast().at("foo").cast() == 2.71); - BOOST_TEST(v3.cast().at("bar").cast() == 54); - BOOST_TEST(v3.cast().at("baz").cast().str == "quux"); - BOOST_TEST(v3.as_table().at("foo").as_floating() == 2.71); - BOOST_TEST(v3.as_table().at("bar").as_integer() == 54); - BOOST_TEST(v3.as_table().at("baz").as_string().str == "quux"); - - - v1 = true; - BOOST_TEST(v1.type() == toml::value_t::boolean); - BOOST_TEST(v1.is(toml::value_t::boolean)); - BOOST_TEST(v1.is()); - BOOST_TEST(v1.is_boolean()); - BOOST_TEST(v1.cast() == true); - BOOST_TEST(v1.as_boolean() == true); -} - -BOOST_AUTO_TEST_CASE(test_value_empty) -{ - toml::value v1; - BOOST_TEST(v1.is_uninitialized()); - BOOST_TEST(v1.is(toml::value_t::empty)); - - BOOST_CHECK_THROW(v1.as_boolean(), toml::type_error); - BOOST_CHECK_THROW(v1.as_integer(), toml::type_error); - BOOST_CHECK_THROW(v1.as_floating(), toml::type_error); - BOOST_CHECK_THROW(v1.as_string(), toml::type_error); - BOOST_CHECK_THROW(v1.as_offset_datetime(), toml::type_error); - BOOST_CHECK_THROW(v1.as_local_datetime(), toml::type_error); - BOOST_CHECK_THROW(v1.as_local_date(), toml::type_error); - BOOST_CHECK_THROW(v1.as_local_time(), toml::type_error); - BOOST_CHECK_THROW(v1.as_array(), toml::type_error); - BOOST_CHECK_THROW(v1.as_table(), toml::type_error); -} - - -BOOST_AUTO_TEST_CASE(test_value_at) -{ - { - toml::value v1{{"foo", 42}, {"bar", 3.14}, {"baz", "qux"}}; - - BOOST_TEST(v1.at("foo").as_integer() == 42); - BOOST_TEST(v1.at("bar").as_floating() == 3.14); - BOOST_TEST(v1.at("baz").as_string() == "qux"); - - BOOST_CHECK_THROW(v1.at(0), toml::type_error); - BOOST_CHECK_THROW(v1.at("quux"), std::out_of_range); - } - - - { - toml::value v1{1,2,3,4,5}; - - BOOST_TEST(v1.at(0).as_integer() == 1); - BOOST_TEST(v1.at(1).as_integer() == 2); - BOOST_TEST(v1.at(2).as_integer() == 3); - BOOST_TEST(v1.at(3).as_integer() == 4); - BOOST_TEST(v1.at(4).as_integer() == 5); - - BOOST_CHECK_THROW(v1.at("foo"), toml::type_error); - BOOST_CHECK_THROW(v1.at(5), std::out_of_range); - } -} - -BOOST_AUTO_TEST_CASE(test_value_bracket) -{ - { - toml::value v1{{"foo", 42}, {"bar", 3.14}, {"baz", "qux"}}; - - BOOST_TEST(v1["foo"].as_integer() == 42); - BOOST_TEST(v1["bar"].as_floating() == 3.14); - BOOST_TEST(v1["baz"].as_string() == "qux"); - - v1["qux"] = 54; - BOOST_TEST(v1["qux"].as_integer() == 54); - } - { - toml::value v1; - v1["foo"] = 42; - - BOOST_TEST(v1.is_table()); - BOOST_TEST(v1["foo"].as_integer() == 42); - } - { - toml::value v1{1,2,3,4,5}; - - BOOST_TEST(v1[0].as_integer() == 1); - BOOST_TEST(v1[1].as_integer() == 2); - BOOST_TEST(v1[2].as_integer() == 3); - BOOST_TEST(v1[3].as_integer() == 4); - BOOST_TEST(v1[4].as_integer() == 5); - - BOOST_CHECK_THROW(v1["foo"], toml::type_error); - } -} - -BOOST_AUTO_TEST_CASE(test_value_map_methods) -{ - { - toml::value v1{{"foo", 42}, {"bar", 3.14}, {"baz", "qux"}}; - - BOOST_TEST(v1.count("foo") == 1u); - BOOST_TEST(v1.count("bar") == 1u); - BOOST_TEST(v1.count("baz") == 1u); - BOOST_TEST(v1.count("qux") == 0u); - - BOOST_TEST( v1.contains("foo")); - BOOST_TEST( v1.contains("bar")); - BOOST_TEST( v1.contains("baz")); - BOOST_TEST(!v1.contains("qux")); - - BOOST_TEST(v1.size() == 3); - - v1["qux"] = 54; - BOOST_TEST(v1.count("qux") == 1u); - BOOST_TEST(v1.contains("qux")); - BOOST_TEST(v1.size() == 4); - } - { - toml::value v1(42); - BOOST_CHECK_THROW(v1.size() , toml::type_error); - BOOST_CHECK_THROW(v1.count("k") , toml::type_error); - BOOST_CHECK_THROW(v1.contains("k"), toml::type_error); - } -} - -BOOST_AUTO_TEST_CASE(test_value_vector_methods) -{ - { - toml::value v1{1, 2, 3, 4, 5}; - - BOOST_TEST(v1.size() == 5); - - v1.push_back(6); - BOOST_TEST(v1.size() == 6); - - v1.emplace_back(6); - BOOST_TEST(v1.size() == 7); - } - { - toml::value v1(42); - BOOST_CHECK_THROW(v1.size(), toml::type_error); - BOOST_CHECK_THROW(v1.push_back(1), toml::type_error); - BOOST_CHECK_THROW(v1.emplace_back(1), toml::type_error); - } -} diff --git a/lib/toml/tests/test_windows.cpp b/lib/toml/tests/test_windows.cpp deleted file mode 100644 index b178a26..0000000 --- a/lib/toml/tests/test_windows.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include -#include - -int main() -{ - using namespace toml::literals::toml_literals; - const auto data = R"(windows = "defines min and max as a macro")"_toml; - - std::cout << toml::find(data, "windows") << std::endl; - return 0; -} diff --git a/lib/toml/toml.hpp b/lib/toml/toml.hpp deleted file mode 100644 index 6b0ca1e..0000000 --- a/lib/toml/toml.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2017 Toru Niina - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef TOML_FOR_MODERN_CPP -#define TOML_FOR_MODERN_CPP - -#define TOML11_VERSION_MAJOR 3 -#define TOML11_VERSION_MINOR 7 -#define TOML11_VERSION_PATCH 1 - -#include "toml/parser.hpp" -#include "toml/literal.hpp" -#include "toml/serializer.hpp" -#include "toml/get.hpp" -#include "toml/macros.hpp" - -#endif// TOML_FOR_MODERN_CPP diff --git a/lib/toml/toml/color.hpp b/lib/toml/toml/color.hpp deleted file mode 100644 index 4cb572c..0000000 --- a/lib/toml/toml/color.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef TOML11_COLOR_HPP -#define TOML11_COLOR_HPP -#include -#include - -#ifdef TOML11_COLORIZE_ERROR_MESSAGE -#define TOML11_ERROR_MESSAGE_COLORIZED true -#else -#define TOML11_ERROR_MESSAGE_COLORIZED false -#endif - -namespace toml -{ - -// put ANSI escape sequence to ostream -namespace color_ansi -{ -namespace detail -{ -inline int colorize_index() -{ - static const int index = std::ios_base::xalloc(); - return index; -} -} // detail - -inline std::ostream& colorize(std::ostream& os) -{ - // by default, it is zero. - os.iword(detail::colorize_index()) = 1; - return os; -} -inline std::ostream& nocolorize(std::ostream& os) -{ - os.iword(detail::colorize_index()) = 0; - return os; -} -inline std::ostream& reset (std::ostream& os) -{if(os.iword(detail::colorize_index()) == 1) {os << "\033[00m";} return os;} -inline std::ostream& bold (std::ostream& os) -{if(os.iword(detail::colorize_index()) == 1) {os << "\033[01m";} return os;} -inline std::ostream& grey (std::ostream& os) -{if(os.iword(detail::colorize_index()) == 1) {os << "\033[30m";} return os;} -inline std::ostream& red (std::ostream& os) -{if(os.iword(detail::colorize_index()) == 1) {os << "\033[31m";} return os;} -inline std::ostream& green (std::ostream& os) -{if(os.iword(detail::colorize_index()) == 1) {os << "\033[32m";} return os;} -inline std::ostream& yellow (std::ostream& os) -{if(os.iword(detail::colorize_index()) == 1) {os << "\033[33m";} return os;} -inline std::ostream& blue (std::ostream& os) -{if(os.iword(detail::colorize_index()) == 1) {os << "\033[34m";} return os;} -inline std::ostream& magenta(std::ostream& os) -{if(os.iword(detail::colorize_index()) == 1) {os << "\033[35m";} return os;} -inline std::ostream& cyan (std::ostream& os) -{if(os.iword(detail::colorize_index()) == 1) {os << "\033[36m";} return os;} -inline std::ostream& white (std::ostream& os) -{if(os.iword(detail::colorize_index()) == 1) {os << "\033[37m";} return os;} -} // color_ansi - -// ANSI escape sequence is the only and default colorization method currently -namespace color = color_ansi; - -} // toml -#endif// TOML11_COLOR_HPP diff --git a/lib/toml/toml/combinator.hpp b/lib/toml/toml/combinator.hpp deleted file mode 100644 index 33ecca1..0000000 --- a/lib/toml/toml/combinator.hpp +++ /dev/null @@ -1,306 +0,0 @@ -// Copyright Toru Niina 2017. -// Distributed under the MIT License. -#ifndef TOML11_COMBINATOR_HPP -#define TOML11_COMBINATOR_HPP -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "region.hpp" -#include "result.hpp" -#include "traits.hpp" -#include "utility.hpp" - -// they scans characters and returns region if it matches to the condition. -// when they fail, it does not change the location. -// in lexer.hpp, these are used. - -namespace toml -{ -namespace detail -{ - -// to output character as an error message. -inline std::string show_char(const char c) -{ - // It suppresses an error that occurs only in Debug mode of MSVC++ on Windows. - // I'm not completely sure but they check the value of char to be in the - // range [0, 256) and some of the COMPLETELY VALID utf-8 character sometimes - // has negative value (if char has sign). So here it re-interprets c as - // unsigned char through pointer. In general, converting pointer to a - // pointer that has different type cause UB, but `(signed|unsigned)?char` - // are one of the exceptions. Converting pointer only to char and std::byte - // (c++17) are valid. - if(std::isgraph(*reinterpret_cast(std::addressof(c)))) - { - return std::string(1, c); - } - else - { - std::array buf; - buf.fill('\0'); - const auto r = std::snprintf( - buf.data(), buf.size(), "0x%02x", static_cast(c) & 0xFF); - (void) r; // Unused variable warning - assert(r == static_cast(buf.size()) - 1); - return std::string(buf.data()); - } -} - -template -struct character -{ - static constexpr char target = C; - - static result - invoke(location& loc) - { - if(loc.iter() == loc.end()) {return none();} - const auto first = loc.iter(); - - const char c = *(loc.iter()); - if(c != target) - { - return none(); - } - loc.advance(); // update location - - return ok(region(loc, first, loc.iter())); - } -}; -template -constexpr char character::target; - -// closed interval [Low, Up]. both Low and Up are included. -template -struct in_range -{ - // assuming ascii part of UTF-8... - static_assert(Low <= Up, "lower bound should be less than upper bound."); - - static constexpr char upper = Up; - static constexpr char lower = Low; - - static result - invoke(location& loc) - { - if(loc.iter() == loc.end()) {return none();} - const auto first = loc.iter(); - - const char c = *(loc.iter()); - if(c < lower || upper < c) - { - return none(); - } - - loc.advance(); - return ok(region(loc, first, loc.iter())); - } -}; -template constexpr char in_range::upper; -template constexpr char in_range::lower; - -// keep iterator if `Combinator` matches. otherwise, increment `iter` by 1 char. -// for detecting invalid characters, like control sequences in toml string. -template -struct exclude -{ - static result - invoke(location& loc) - { - if(loc.iter() == loc.end()) {return none();} - auto first = loc.iter(); - - auto rslt = Combinator::invoke(loc); - if(rslt.is_ok()) - { - loc.reset(first); - return none(); - } - loc.reset(std::next(first)); // XXX maybe loc.advance() is okay but... - return ok(region(loc, first, loc.iter())); - } -}; - -// increment `iter`, if matches. otherwise, just return empty string. -template -struct maybe -{ - static result - invoke(location& loc) - { - const auto rslt = Combinator::invoke(loc); - if(rslt.is_ok()) - { - return rslt; - } - return ok(region(loc)); - } -}; - -template -struct sequence; - -template -struct sequence -{ - static result - invoke(location& loc) - { - const auto first = loc.iter(); - auto rslt = Head::invoke(loc); - if(rslt.is_err()) - { - loc.reset(first); - return none(); - } - return sequence::invoke(loc, std::move(rslt.unwrap()), first); - } - - // called from the above function only, recursively. - template - static result - invoke(location& loc, region reg, Iterator first) - { - const auto rslt = Head::invoke(loc); - if(rslt.is_err()) - { - loc.reset(first); - return none(); - } - reg += rslt.unwrap(); // concat regions - return sequence::invoke(loc, std::move(reg), first); - } -}; - -template -struct sequence -{ - // would be called from sequence::invoke only. - template - static result - invoke(location& loc, region reg, Iterator first) - { - const auto rslt = Head::invoke(loc); - if(rslt.is_err()) - { - loc.reset(first); - return none(); - } - reg += rslt.unwrap(); // concat regions - return ok(reg); - } -}; - -template -struct either; - -template -struct either -{ - static result - invoke(location& loc) - { - const auto rslt = Head::invoke(loc); - if(rslt.is_ok()) {return rslt;} - return either::invoke(loc); - } -}; -template -struct either -{ - static result - invoke(location& loc) - { - return Head::invoke(loc); - } -}; - -template -struct repeat; - -template struct exactly{}; -template struct at_least{}; -struct unlimited{}; - -template -struct repeat> -{ - static result - invoke(location& loc) - { - region retval(loc); - const auto first = loc.iter(); - for(std::size_t i=0; i -struct repeat> -{ - static result - invoke(location& loc) - { - region retval(loc); - - const auto first = loc.iter(); - for(std::size_t i=0; i -struct repeat -{ - static result - invoke(location& loc) - { - region retval(loc); - while(true) - { - auto rslt = T::invoke(loc); - if(rslt.is_err()) - { - return ok(std::move(retval)); - } - retval += rslt.unwrap(); - } - } -}; - -} // detail -} // toml -#endif// TOML11_COMBINATOR_HPP diff --git a/lib/toml/toml/comments.hpp b/lib/toml/toml/comments.hpp deleted file mode 100644 index ec25041..0000000 --- a/lib/toml/toml/comments.hpp +++ /dev/null @@ -1,472 +0,0 @@ -// Copyright Toru Niina 2019. -// Distributed under the MIT License. -#ifndef TOML11_COMMENTS_HPP -#define TOML11_COMMENTS_HPP -#include -#include -#include -#include -#include -#include -#include - -#ifdef TOML11_PRESERVE_COMMENTS_BY_DEFAULT -# define TOML11_DEFAULT_COMMENT_STRATEGY ::toml::preserve_comments -#else -# define TOML11_DEFAULT_COMMENT_STRATEGY ::toml::discard_comments -#endif - -// This file provides mainly two classes, `preserve_comments` and `discard_comments`. -// Those two are a container that have the same interface as `std::vector` -// but bahaves in the opposite way. `preserve_comments` is just the same as -// `std::vector` and each `std::string` corresponds to a comment line. -// Conversely, `discard_comments` discards all the strings and ignores everything -// assigned in it. `discard_comments` is always empty and you will encounter an -// error whenever you access to the element. -namespace toml -{ -struct discard_comments; // forward decl - -// use it in the following way -// -// const toml::basic_value data = -// toml::parse("example.toml"); -// -// the interface is almost the same as std::vector. -struct preserve_comments -{ - // `container_type` is not provided in discard_comments. - // do not use this inner-type in a generic code. - using container_type = std::vector; - - using size_type = container_type::size_type; - using difference_type = container_type::difference_type; - using value_type = container_type::value_type; - using reference = container_type::reference; - using const_reference = container_type::const_reference; - using pointer = container_type::pointer; - using const_pointer = container_type::const_pointer; - using iterator = container_type::iterator; - using const_iterator = container_type::const_iterator; - using reverse_iterator = container_type::reverse_iterator; - using const_reverse_iterator = container_type::const_reverse_iterator; - - preserve_comments() = default; - ~preserve_comments() = default; - preserve_comments(preserve_comments const&) = default; - preserve_comments(preserve_comments &&) = default; - preserve_comments& operator=(preserve_comments const&) = default; - preserve_comments& operator=(preserve_comments &&) = default; - - explicit preserve_comments(const std::vector& c): comments(c){} - explicit preserve_comments(std::vector&& c) - : comments(std::move(c)) - {} - preserve_comments& operator=(const std::vector& c) - { - comments = c; - return *this; - } - preserve_comments& operator=(std::vector&& c) - { - comments = std::move(c); - return *this; - } - - explicit preserve_comments(const discard_comments&) {} - - explicit preserve_comments(size_type n): comments(n) {} - preserve_comments(size_type n, const std::string& x): comments(n, x) {} - preserve_comments(std::initializer_list x): comments(x) {} - template - preserve_comments(InputIterator first, InputIterator last) - : comments(first, last) - {} - - template - void assign(InputIterator first, InputIterator last) {comments.assign(first, last);} - void assign(std::initializer_list ini) {comments.assign(ini);} - void assign(size_type n, const std::string& val) {comments.assign(n, val);} - - // Related to the issue #97. - // - // It is known that `std::vector::insert` and `std::vector::erase` in - // the standard library implementation included in GCC 4.8.5 takes - // `std::vector::iterator` instead of `std::vector::const_iterator`. - // Because of the const-correctness, we cannot convert a `const_iterator` to - // an `iterator`. It causes compilation error in GCC 4.8.5. -#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) && !defined(__clang__) -# if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) <= 40805 -# define TOML11_WORKAROUND_GCC_4_8_X_STANDARD_LIBRARY_IMPLEMENTATION -# endif -#endif - -#ifdef TOML11_WORKAROUND_GCC_4_8_X_STANDARD_LIBRARY_IMPLEMENTATION - iterator insert(iterator p, const std::string& x) - { - return comments.insert(p, x); - } - iterator insert(iterator p, std::string&& x) - { - return comments.insert(p, std::move(x)); - } - void insert(iterator p, size_type n, const std::string& x) - { - return comments.insert(p, n, x); - } - template - void insert(iterator p, InputIterator first, InputIterator last) - { - return comments.insert(p, first, last); - } - void insert(iterator p, std::initializer_list ini) - { - return comments.insert(p, ini); - } - - template - iterator emplace(iterator p, Ts&& ... args) - { - return comments.emplace(p, std::forward(args)...); - } - - iterator erase(iterator pos) {return comments.erase(pos);} - iterator erase(iterator first, iterator last) - { - return comments.erase(first, last); - } -#else - iterator insert(const_iterator p, const std::string& x) - { - return comments.insert(p, x); - } - iterator insert(const_iterator p, std::string&& x) - { - return comments.insert(p, std::move(x)); - } - iterator insert(const_iterator p, size_type n, const std::string& x) - { - return comments.insert(p, n, x); - } - template - iterator insert(const_iterator p, InputIterator first, InputIterator last) - { - return comments.insert(p, first, last); - } - iterator insert(const_iterator p, std::initializer_list ini) - { - return comments.insert(p, ini); - } - - template - iterator emplace(const_iterator p, Ts&& ... args) - { - return comments.emplace(p, std::forward(args)...); - } - - iterator erase(const_iterator pos) {return comments.erase(pos);} - iterator erase(const_iterator first, const_iterator last) - { - return comments.erase(first, last); - } -#endif - - void swap(preserve_comments& other) {comments.swap(other.comments);} - - void push_back(const std::string& v) {comments.push_back(v);} - void push_back(std::string&& v) {comments.push_back(std::move(v));} - void pop_back() {comments.pop_back();} - - template - void emplace_back(Ts&& ... args) {comments.emplace_back(std::forward(args)...);} - - void clear() {comments.clear();} - - size_type size() const noexcept {return comments.size();} - size_type max_size() const noexcept {return comments.max_size();} - size_type capacity() const noexcept {return comments.capacity();} - bool empty() const noexcept {return comments.empty();} - - void reserve(size_type n) {comments.reserve(n);} - void resize(size_type n) {comments.resize(n);} - void resize(size_type n, const std::string& c) {comments.resize(n, c);} - void shrink_to_fit() {comments.shrink_to_fit();} - - reference operator[](const size_type n) noexcept {return comments[n];} - const_reference operator[](const size_type n) const noexcept {return comments[n];} - reference at(const size_type n) {return comments.at(n);} - const_reference at(const size_type n) const {return comments.at(n);} - reference front() noexcept {return comments.front();} - const_reference front() const noexcept {return comments.front();} - reference back() noexcept {return comments.back();} - const_reference back() const noexcept {return comments.back();} - - pointer data() noexcept {return comments.data();} - const_pointer data() const noexcept {return comments.data();} - - iterator begin() noexcept {return comments.begin();} - iterator end() noexcept {return comments.end();} - const_iterator begin() const noexcept {return comments.begin();} - const_iterator end() const noexcept {return comments.end();} - const_iterator cbegin() const noexcept {return comments.cbegin();} - const_iterator cend() const noexcept {return comments.cend();} - - reverse_iterator rbegin() noexcept {return comments.rbegin();} - reverse_iterator rend() noexcept {return comments.rend();} - const_reverse_iterator rbegin() const noexcept {return comments.rbegin();} - const_reverse_iterator rend() const noexcept {return comments.rend();} - const_reverse_iterator crbegin() const noexcept {return comments.crbegin();} - const_reverse_iterator crend() const noexcept {return comments.crend();} - - friend bool operator==(const preserve_comments&, const preserve_comments&); - friend bool operator!=(const preserve_comments&, const preserve_comments&); - friend bool operator< (const preserve_comments&, const preserve_comments&); - friend bool operator<=(const preserve_comments&, const preserve_comments&); - friend bool operator> (const preserve_comments&, const preserve_comments&); - friend bool operator>=(const preserve_comments&, const preserve_comments&); - - friend void swap(preserve_comments&, std::vector&); - friend void swap(std::vector&, preserve_comments&); - - private: - - container_type comments; -}; - -inline bool operator==(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments == rhs.comments;} -inline bool operator!=(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments != rhs.comments;} -inline bool operator< (const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments < rhs.comments;} -inline bool operator<=(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments <= rhs.comments;} -inline bool operator> (const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments > rhs.comments;} -inline bool operator>=(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments >= rhs.comments;} - -inline void swap(preserve_comments& lhs, preserve_comments& rhs) -{ - lhs.swap(rhs); - return; -} -inline void swap(preserve_comments& lhs, std::vector& rhs) -{ - lhs.comments.swap(rhs); - return; -} -inline void swap(std::vector& lhs, preserve_comments& rhs) -{ - lhs.swap(rhs.comments); - return; -} - -template -std::basic_ostream& -operator<<(std::basic_ostream& os, const preserve_comments& com) -{ - for(const auto& c : com) - { - os << '#' << c << '\n'; - } - return os; -} - -namespace detail -{ - -// To provide the same interface with `preserve_comments`, `discard_comments` -// should have an iterator. But it does not contain anything, so we need to -// add an iterator that points nothing. -// -// It always points null, so DO NOT unwrap this iterator. It always crashes -// your program. -template -struct empty_iterator -{ - using value_type = T; - using reference_type = typename std::conditional::type; - using pointer_type = typename std::conditional::type; - using difference_type = std::ptrdiff_t; - using iterator_category = std::random_access_iterator_tag; - - empty_iterator() = default; - ~empty_iterator() = default; - empty_iterator(empty_iterator const&) = default; - empty_iterator(empty_iterator &&) = default; - empty_iterator& operator=(empty_iterator const&) = default; - empty_iterator& operator=(empty_iterator &&) = default; - - // DO NOT call these operators. - reference_type operator*() const noexcept {std::terminate();} - pointer_type operator->() const noexcept {return nullptr;} - reference_type operator[](difference_type) const noexcept {return this->operator*();} - - // These operators do nothing. - empty_iterator& operator++() noexcept {return *this;} - empty_iterator operator++(int) noexcept {return *this;} - empty_iterator& operator--() noexcept {return *this;} - empty_iterator operator--(int) noexcept {return *this;} - - empty_iterator& operator+=(difference_type) noexcept {return *this;} - empty_iterator& operator-=(difference_type) noexcept {return *this;} - - empty_iterator operator+(difference_type) const noexcept {return *this;} - empty_iterator operator-(difference_type) const noexcept {return *this;} -}; - -template -bool operator==(const empty_iterator&, const empty_iterator&) noexcept {return true;} -template -bool operator!=(const empty_iterator&, const empty_iterator&) noexcept {return false;} -template -bool operator< (const empty_iterator&, const empty_iterator&) noexcept {return false;} -template -bool operator<=(const empty_iterator&, const empty_iterator&) noexcept {return true;} -template -bool operator> (const empty_iterator&, const empty_iterator&) noexcept {return false;} -template -bool operator>=(const empty_iterator&, const empty_iterator&) noexcept {return true;} - -template -typename empty_iterator::difference_type -operator-(const empty_iterator&, const empty_iterator&) noexcept {return 0;} - -template -empty_iterator -operator+(typename empty_iterator::difference_type, const empty_iterator& rhs) noexcept {return rhs;} -template -empty_iterator -operator+(const empty_iterator& lhs, typename empty_iterator::difference_type) noexcept {return lhs;} - -} // detail - -// The default comment type. It discards all the comments. It requires only one -// byte to contain, so the memory footprint is smaller than preserve_comments. -// -// It just ignores `push_back`, `insert`, `erase`, and any other modifications. -// IT always returns size() == 0, the iterator taken by `begin()` is always the -// same as that of `end()`, and accessing through `operator[]` or iterators -// always causes a segmentation fault. DO NOT access to the element of this. -// -// Why this is chose as the default type is because the last version (2.x.y) -// does not contain any comments in a value. To minimize the impact on the -// efficiency, this is chosen as a default. -// -// To reduce the memory footprint, later we can try empty base optimization (EBO). -struct discard_comments -{ - using size_type = std::size_t; - using difference_type = std::ptrdiff_t; - using value_type = std::string; - using reference = std::string&; - using const_reference = std::string const&; - using pointer = std::string*; - using const_pointer = std::string const*; - using iterator = detail::empty_iterator; - using const_iterator = detail::empty_iterator; - using reverse_iterator = detail::empty_iterator; - using const_reverse_iterator = detail::empty_iterator; - - discard_comments() = default; - ~discard_comments() = default; - discard_comments(discard_comments const&) = default; - discard_comments(discard_comments &&) = default; - discard_comments& operator=(discard_comments const&) = default; - discard_comments& operator=(discard_comments &&) = default; - - explicit discard_comments(const std::vector&) noexcept {} - explicit discard_comments(std::vector&&) noexcept {} - discard_comments& operator=(const std::vector&) noexcept {return *this;} - discard_comments& operator=(std::vector&&) noexcept {return *this;} - - explicit discard_comments(const preserve_comments&) noexcept {} - - explicit discard_comments(size_type) noexcept {} - discard_comments(size_type, const std::string&) noexcept {} - discard_comments(std::initializer_list) noexcept {} - template - discard_comments(InputIterator, InputIterator) noexcept {} - - template - void assign(InputIterator, InputIterator) noexcept {} - void assign(std::initializer_list) noexcept {} - void assign(size_type, const std::string&) noexcept {} - - iterator insert(const_iterator, const std::string&) {return iterator{};} - iterator insert(const_iterator, std::string&&) {return iterator{};} - iterator insert(const_iterator, size_type, const std::string&) {return iterator{};} - template - iterator insert(const_iterator, InputIterator, InputIterator) {return iterator{};} - iterator insert(const_iterator, std::initializer_list) {return iterator{};} - - template - iterator emplace(const_iterator, Ts&& ...) {return iterator{};} - iterator erase(const_iterator) {return iterator{};} - iterator erase(const_iterator, const_iterator) {return iterator{};} - - void swap(discard_comments&) {return;} - - void push_back(const std::string&) {return;} - void push_back(std::string&& ) {return;} - void pop_back() {return;} - - template - void emplace_back(Ts&& ...) {return;} - - void clear() {return;} - - size_type size() const noexcept {return 0;} - size_type max_size() const noexcept {return 0;} - size_type capacity() const noexcept {return 0;} - bool empty() const noexcept {return true;} - - void reserve(size_type) {return;} - void resize(size_type) {return;} - void resize(size_type, const std::string&) {return;} - void shrink_to_fit() {return;} - - // DO NOT access to the element of this container. This container is always - // empty, so accessing through operator[], front/back, data causes address - // error. - - reference operator[](const size_type) noexcept {return *data();} - const_reference operator[](const size_type) const noexcept {return *data();} - reference at(const size_type) {throw std::out_of_range("toml::discard_comment is always empty.");} - const_reference at(const size_type) const {throw std::out_of_range("toml::discard_comment is always empty.");} - reference front() noexcept {return *data();} - const_reference front() const noexcept {return *data();} - reference back() noexcept {return *data();} - const_reference back() const noexcept {return *data();} - - pointer data() noexcept {return nullptr;} - const_pointer data() const noexcept {return nullptr;} - - iterator begin() noexcept {return iterator{};} - iterator end() noexcept {return iterator{};} - const_iterator begin() const noexcept {return const_iterator{};} - const_iterator end() const noexcept {return const_iterator{};} - const_iterator cbegin() const noexcept {return const_iterator{};} - const_iterator cend() const noexcept {return const_iterator{};} - - reverse_iterator rbegin() noexcept {return iterator{};} - reverse_iterator rend() noexcept {return iterator{};} - const_reverse_iterator rbegin() const noexcept {return const_iterator{};} - const_reverse_iterator rend() const noexcept {return const_iterator{};} - const_reverse_iterator crbegin() const noexcept {return const_iterator{};} - const_reverse_iterator crend() const noexcept {return const_iterator{};} -}; - -inline bool operator==(const discard_comments&, const discard_comments&) noexcept {return true;} -inline bool operator!=(const discard_comments&, const discard_comments&) noexcept {return false;} -inline bool operator< (const discard_comments&, const discard_comments&) noexcept {return false;} -inline bool operator<=(const discard_comments&, const discard_comments&) noexcept {return true;} -inline bool operator> (const discard_comments&, const discard_comments&) noexcept {return false;} -inline bool operator>=(const discard_comments&, const discard_comments&) noexcept {return true;} - -inline void swap(const discard_comments&, const discard_comments&) noexcept {return;} - -template -std::basic_ostream& -operator<<(std::basic_ostream& os, const discard_comments&) -{ - return os; -} - -} // toml11 -#endif// TOML11_COMMENTS_HPP diff --git a/lib/toml/toml/datetime.hpp b/lib/toml/toml/datetime.hpp deleted file mode 100644 index 36db1e1..0000000 --- a/lib/toml/toml/datetime.hpp +++ /dev/null @@ -1,631 +0,0 @@ -// Copyright Toru Niina 2017. -// Distributed under the MIT License. -#ifndef TOML11_DATETIME_HPP -#define TOML11_DATETIME_HPP -#include -#include -#include - -#include -#include -#include -#include -#include - -namespace toml -{ - -// To avoid non-threadsafe std::localtime. In C11 (not C++11!), localtime_s is -// provided in the absolutely same purpose, but C++11 is actually not compatible -// with C11. We need to dispatch the function depending on the OS. -namespace detail -{ -// TODO: find more sophisticated way to handle this -#if defined(_MSC_VER) -inline std::tm localtime_s(const std::time_t* src) -{ - std::tm dst; - const auto result = ::localtime_s(&dst, src); - if (result) { throw std::runtime_error("localtime_s failed."); } - return dst; -} -inline std::tm gmtime_s(const std::time_t* src) -{ - std::tm dst; - const auto result = ::gmtime_s(&dst, src); - if (result) { throw std::runtime_error("gmtime_s failed."); } - return dst; -} -#elif (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 1) || defined(_XOPEN_SOURCE) || defined(_BSD_SOURCE) || defined(_SVID_SOURCE) || defined(_POSIX_SOURCE) -inline std::tm localtime_s(const std::time_t* src) -{ - std::tm dst; - const auto result = ::localtime_r(src, &dst); - if (!result) { throw std::runtime_error("localtime_r failed."); } - return dst; -} -inline std::tm gmtime_s(const std::time_t* src) -{ - std::tm dst; - const auto result = ::gmtime_r(src, &dst); - if (!result) { throw std::runtime_error("gmtime_r failed."); } - return dst; -} -#else // fallback. not threadsafe -inline std::tm localtime_s(const std::time_t* src) -{ - const auto result = std::localtime(src); - if (!result) { throw std::runtime_error("localtime failed."); } - return *result; -} -inline std::tm gmtime_s(const std::time_t* src) -{ - const auto result = std::gmtime(src); - if (!result) { throw std::runtime_error("gmtime failed."); } - return *result; -} -#endif -} // detail - -enum class month_t : std::uint8_t -{ - Jan = 0, - Feb = 1, - Mar = 2, - Apr = 3, - May = 4, - Jun = 5, - Jul = 6, - Aug = 7, - Sep = 8, - Oct = 9, - Nov = 10, - Dec = 11 -}; - -struct local_date -{ - std::int16_t year; // A.D. (like, 2018) - std::uint8_t month; // [0, 11] - std::uint8_t day; // [1, 31] - - local_date(int y, month_t m, int d) - : year (static_cast(y)), - month(static_cast(m)), - day (static_cast(d)) - {} - - explicit local_date(const std::tm& t) - : year (static_cast(t.tm_year + 1900)), - month(static_cast(t.tm_mon)), - day (static_cast(t.tm_mday)) - {} - - explicit local_date(const std::chrono::system_clock::time_point& tp) - { - const auto t = std::chrono::system_clock::to_time_t(tp); - const auto time = detail::localtime_s(&t); - *this = local_date(time); - } - - explicit local_date(const std::time_t t) - : local_date(std::chrono::system_clock::from_time_t(t)) - {} - - operator std::chrono::system_clock::time_point() const - { - // std::mktime returns date as local time zone. no conversion needed - std::tm t; - t.tm_sec = 0; - t.tm_min = 0; - t.tm_hour = 0; - t.tm_mday = static_cast(this->day); - t.tm_mon = static_cast(this->month); - t.tm_year = static_cast(this->year) - 1900; - t.tm_wday = 0; // the value will be ignored - t.tm_yday = 0; // the value will be ignored - t.tm_isdst = -1; - return std::chrono::system_clock::from_time_t(std::mktime(&t)); - } - - operator std::time_t() const - { - return std::chrono::system_clock::to_time_t( - std::chrono::system_clock::time_point(*this)); - } - - local_date() = default; - ~local_date() = default; - local_date(local_date const&) = default; - local_date(local_date&&) = default; - local_date& operator=(local_date const&) = default; - local_date& operator=(local_date&&) = default; -}; - -inline bool operator==(const local_date& lhs, const local_date& rhs) -{ - return std::make_tuple(lhs.year, lhs.month, lhs.day) == - std::make_tuple(rhs.year, rhs.month, rhs.day); -} -inline bool operator!=(const local_date& lhs, const local_date& rhs) -{ - return !(lhs == rhs); -} -inline bool operator< (const local_date& lhs, const local_date& rhs) -{ - return std::make_tuple(lhs.year, lhs.month, lhs.day) < - std::make_tuple(rhs.year, rhs.month, rhs.day); -} -inline bool operator<=(const local_date& lhs, const local_date& rhs) -{ - return (lhs < rhs) || (lhs == rhs); -} -inline bool operator> (const local_date& lhs, const local_date& rhs) -{ - return !(lhs <= rhs); -} -inline bool operator>=(const local_date& lhs, const local_date& rhs) -{ - return !(lhs < rhs); -} - -template -std::basic_ostream& -operator<<(std::basic_ostream& os, const local_date& date) -{ - os << std::setfill('0') << std::setw(4) << static_cast(date.year ) << '-'; - os << std::setfill('0') << std::setw(2) << static_cast(date.month) + 1 << '-'; - os << std::setfill('0') << std::setw(2) << static_cast(date.day ) ; - return os; -} - -struct local_time -{ - std::uint8_t hour; // [0, 23] - std::uint8_t minute; // [0, 59] - std::uint8_t second; // [0, 60] - std::uint16_t millisecond; // [0, 999] - std::uint16_t microsecond; // [0, 999] - std::uint16_t nanosecond; // [0, 999] - - local_time(int h, int m, int s, - int ms = 0, int us = 0, int ns = 0) - : hour (static_cast(h)), - minute(static_cast(m)), - second(static_cast(s)), - millisecond(static_cast(ms)), - microsecond(static_cast(us)), - nanosecond (static_cast(ns)) - {} - - explicit local_time(const std::tm& t) - : hour (static_cast(t.tm_hour)), - minute(static_cast(t.tm_min)), - second(static_cast(t.tm_sec)), - millisecond(0), microsecond(0), nanosecond(0) - {} - - template - explicit local_time(const std::chrono::duration& t) - { - const auto h = std::chrono::duration_cast(t); - this->hour = static_cast(h.count()); - const auto t2 = t - h; - const auto m = std::chrono::duration_cast(t2); - this->minute = static_cast(m.count()); - const auto t3 = t2 - m; - const auto s = std::chrono::duration_cast(t3); - this->second = static_cast(s.count()); - const auto t4 = t3 - s; - const auto ms = std::chrono::duration_cast(t4); - this->millisecond = static_cast(ms.count()); - const auto t5 = t4 - ms; - const auto us = std::chrono::duration_cast(t5); - this->microsecond = static_cast(us.count()); - const auto t6 = t5 - us; - const auto ns = std::chrono::duration_cast(t6); - this->nanosecond = static_cast(ns.count()); - } - - operator std::chrono::nanoseconds() const - { - return std::chrono::nanoseconds (this->nanosecond) + - std::chrono::microseconds(this->microsecond) + - std::chrono::milliseconds(this->millisecond) + - std::chrono::seconds(this->second) + - std::chrono::minutes(this->minute) + - std::chrono::hours(this->hour); - } - - local_time() = default; - ~local_time() = default; - local_time(local_time const&) = default; - local_time(local_time&&) = default; - local_time& operator=(local_time const&) = default; - local_time& operator=(local_time&&) = default; -}; - -inline bool operator==(const local_time& lhs, const local_time& rhs) -{ - return std::make_tuple(lhs.hour, lhs.minute, lhs.second, lhs.millisecond, lhs.microsecond, lhs.nanosecond) == - std::make_tuple(rhs.hour, rhs.minute, rhs.second, rhs.millisecond, rhs.microsecond, rhs.nanosecond); -} -inline bool operator!=(const local_time& lhs, const local_time& rhs) -{ - return !(lhs == rhs); -} -inline bool operator< (const local_time& lhs, const local_time& rhs) -{ - return std::make_tuple(lhs.hour, lhs.minute, lhs.second, lhs.millisecond, lhs.microsecond, lhs.nanosecond) < - std::make_tuple(rhs.hour, rhs.minute, rhs.second, rhs.millisecond, rhs.microsecond, rhs.nanosecond); -} -inline bool operator<=(const local_time& lhs, const local_time& rhs) -{ - return (lhs < rhs) || (lhs == rhs); -} -inline bool operator> (const local_time& lhs, const local_time& rhs) -{ - return !(lhs <= rhs); -} -inline bool operator>=(const local_time& lhs, const local_time& rhs) -{ - return !(lhs < rhs); -} - -template -std::basic_ostream& -operator<<(std::basic_ostream& os, const local_time& time) -{ - os << std::setfill('0') << std::setw(2) << static_cast(time.hour ) << ':'; - os << std::setfill('0') << std::setw(2) << static_cast(time.minute) << ':'; - os << std::setfill('0') << std::setw(2) << static_cast(time.second); - if(time.millisecond != 0 || time.microsecond != 0 || time.nanosecond != 0) - { - os << '.'; - os << std::setfill('0') << std::setw(3) << static_cast(time.millisecond); - if(time.microsecond != 0 || time.nanosecond != 0) - { - os << std::setfill('0') << std::setw(3) << static_cast(time.microsecond); - if(time.nanosecond != 0) - { - os << std::setfill('0') << std::setw(3) << static_cast(time.nanosecond); - } - } - } - return os; -} - -struct time_offset -{ - std::int8_t hour; // [-12, 12] - std::int8_t minute; // [-59, 59] - - time_offset(int h, int m) - : hour (static_cast(h)), - minute(static_cast(m)) - {} - - operator std::chrono::minutes() const - { - return std::chrono::minutes(this->minute) + - std::chrono::hours(this->hour); - } - - time_offset() = default; - ~time_offset() = default; - time_offset(time_offset const&) = default; - time_offset(time_offset&&) = default; - time_offset& operator=(time_offset const&) = default; - time_offset& operator=(time_offset&&) = default; -}; - -inline bool operator==(const time_offset& lhs, const time_offset& rhs) -{ - return std::make_tuple(lhs.hour, lhs.minute) == - std::make_tuple(rhs.hour, rhs.minute); -} -inline bool operator!=(const time_offset& lhs, const time_offset& rhs) -{ - return !(lhs == rhs); -} -inline bool operator< (const time_offset& lhs, const time_offset& rhs) -{ - return std::make_tuple(lhs.hour, lhs.minute) < - std::make_tuple(rhs.hour, rhs.minute); -} -inline bool operator<=(const time_offset& lhs, const time_offset& rhs) -{ - return (lhs < rhs) || (lhs == rhs); -} -inline bool operator> (const time_offset& lhs, const time_offset& rhs) -{ - return !(lhs <= rhs); -} -inline bool operator>=(const time_offset& lhs, const time_offset& rhs) -{ - return !(lhs < rhs); -} - -template -std::basic_ostream& -operator<<(std::basic_ostream& os, const time_offset& offset) -{ - if(offset.hour == 0 && offset.minute == 0) - { - os << 'Z'; - return os; - } - int minute = static_cast(offset.hour) * 60 + offset.minute; - if(minute < 0){os << '-'; minute = std::abs(minute);} else {os << '+';} - os << std::setfill('0') << std::setw(2) << minute / 60 << ':'; - os << std::setfill('0') << std::setw(2) << minute % 60; - return os; -} - -struct local_datetime -{ - local_date date; - local_time time; - - local_datetime(local_date d, local_time t): date(d), time(t) {} - - explicit local_datetime(const std::tm& t): date(t), time(t){} - - explicit local_datetime(const std::chrono::system_clock::time_point& tp) - { - const auto t = std::chrono::system_clock::to_time_t(tp); - std::tm ltime = detail::localtime_s(&t); - - this->date = local_date(ltime); - this->time = local_time(ltime); - - // std::tm lacks subsecond information, so diff between tp and tm - // can be used to get millisecond & microsecond information. - const auto t_diff = tp - - std::chrono::system_clock::from_time_t(std::mktime(<ime)); - this->time.millisecond = static_cast( - std::chrono::duration_cast(t_diff).count()); - this->time.microsecond = static_cast( - std::chrono::duration_cast(t_diff).count()); - this->time.nanosecond = static_cast( - std::chrono::duration_cast(t_diff).count()); - } - - explicit local_datetime(const std::time_t t) - : local_datetime(std::chrono::system_clock::from_time_t(t)) - {} - - operator std::chrono::system_clock::time_point() const - { - using internal_duration = - typename std::chrono::system_clock::time_point::duration; - - // Normally DST begins at A.M. 3 or 4. If we re-use conversion operator - // of local_date and local_time independently, the conversion fails if - // it is the day when DST begins or ends. Since local_date considers the - // time is 00:00 A.M. and local_time does not consider DST because it - // does not have any date information. We need to consider both date and - // time information at the same time to convert it correctly. - - std::tm t; - t.tm_sec = static_cast(this->time.second); - t.tm_min = static_cast(this->time.minute); - t.tm_hour = static_cast(this->time.hour); - t.tm_mday = static_cast(this->date.day); - t.tm_mon = static_cast(this->date.month); - t.tm_year = static_cast(this->date.year) - 1900; - t.tm_wday = 0; // the value will be ignored - t.tm_yday = 0; // the value will be ignored - t.tm_isdst = -1; - - // std::mktime returns date as local time zone. no conversion needed - auto dt = std::chrono::system_clock::from_time_t(std::mktime(&t)); - dt += std::chrono::duration_cast( - std::chrono::milliseconds(this->time.millisecond) + - std::chrono::microseconds(this->time.microsecond) + - std::chrono::nanoseconds (this->time.nanosecond)); - return dt; - } - - operator std::time_t() const - { - return std::chrono::system_clock::to_time_t( - std::chrono::system_clock::time_point(*this)); - } - - local_datetime() = default; - ~local_datetime() = default; - local_datetime(local_datetime const&) = default; - local_datetime(local_datetime&&) = default; - local_datetime& operator=(local_datetime const&) = default; - local_datetime& operator=(local_datetime&&) = default; -}; - -inline bool operator==(const local_datetime& lhs, const local_datetime& rhs) -{ - return std::make_tuple(lhs.date, lhs.time) == - std::make_tuple(rhs.date, rhs.time); -} -inline bool operator!=(const local_datetime& lhs, const local_datetime& rhs) -{ - return !(lhs == rhs); -} -inline bool operator< (const local_datetime& lhs, const local_datetime& rhs) -{ - return std::make_tuple(lhs.date, lhs.time) < - std::make_tuple(rhs.date, rhs.time); -} -inline bool operator<=(const local_datetime& lhs, const local_datetime& rhs) -{ - return (lhs < rhs) || (lhs == rhs); -} -inline bool operator> (const local_datetime& lhs, const local_datetime& rhs) -{ - return !(lhs <= rhs); -} -inline bool operator>=(const local_datetime& lhs, const local_datetime& rhs) -{ - return !(lhs < rhs); -} - -template -std::basic_ostream& -operator<<(std::basic_ostream& os, const local_datetime& dt) -{ - os << dt.date << 'T' << dt.time; - return os; -} - -struct offset_datetime -{ - local_date date; - local_time time; - time_offset offset; - - offset_datetime(local_date d, local_time t, time_offset o) - : date(d), time(t), offset(o) - {} - offset_datetime(const local_datetime& dt, time_offset o) - : date(dt.date), time(dt.time), offset(o) - {} - explicit offset_datetime(const local_datetime& ld) - : date(ld.date), time(ld.time), offset(get_local_offset(nullptr)) - // use the current local timezone offset - {} - explicit offset_datetime(const std::chrono::system_clock::time_point& tp) - : offset(0, 0) // use gmtime - { - const auto timet = std::chrono::system_clock::to_time_t(tp); - const auto tm = detail::gmtime_s(&timet); - this->date = local_date(tm); - this->time = local_time(tm); - } - explicit offset_datetime(const std::time_t& t) - : offset(0, 0) // use gmtime - { - const auto tm = detail::gmtime_s(&t); - this->date = local_date(tm); - this->time = local_time(tm); - } - explicit offset_datetime(const std::tm& t) - : offset(0, 0) // assume gmtime - { - this->date = local_date(t); - this->time = local_time(t); - } - - operator std::chrono::system_clock::time_point() const - { - // get date-time - using internal_duration = - typename std::chrono::system_clock::time_point::duration; - - // first, convert it to local date-time information in the same way as - // local_datetime does. later we will use time_t to adjust time offset. - std::tm t; - t.tm_sec = static_cast(this->time.second); - t.tm_min = static_cast(this->time.minute); - t.tm_hour = static_cast(this->time.hour); - t.tm_mday = static_cast(this->date.day); - t.tm_mon = static_cast(this->date.month); - t.tm_year = static_cast(this->date.year) - 1900; - t.tm_wday = 0; // the value will be ignored - t.tm_yday = 0; // the value will be ignored - t.tm_isdst = -1; - const std::time_t tp_loc = std::mktime(std::addressof(t)); - - auto tp = std::chrono::system_clock::from_time_t(tp_loc); - tp += std::chrono::duration_cast( - std::chrono::milliseconds(this->time.millisecond) + - std::chrono::microseconds(this->time.microsecond) + - std::chrono::nanoseconds (this->time.nanosecond)); - - // Since mktime uses local time zone, it should be corrected. - // `12:00:00+09:00` means `03:00:00Z`. So mktime returns `03:00:00Z` if - // we are in `+09:00` timezone. To represent `12:00:00Z` there, we need - // to add `+09:00` to `03:00:00Z`. - // Here, it uses the time_t converted from date-time info to handle - // daylight saving time. - const auto ofs = get_local_offset(std::addressof(tp_loc)); - tp += std::chrono::hours (ofs.hour); - tp += std::chrono::minutes(ofs.minute); - - // We got `12:00:00Z` by correcting local timezone applied by mktime. - // Then we will apply the offset. Let's say `12:00:00-08:00` is given. - // And now, we have `12:00:00Z`. `12:00:00-08:00` means `20:00:00Z`. - // So we need to subtract the offset. - tp -= std::chrono::minutes(this->offset); - return tp; - } - - operator std::time_t() const - { - return std::chrono::system_clock::to_time_t( - std::chrono::system_clock::time_point(*this)); - } - - offset_datetime() = default; - ~offset_datetime() = default; - offset_datetime(offset_datetime const&) = default; - offset_datetime(offset_datetime&&) = default; - offset_datetime& operator=(offset_datetime const&) = default; - offset_datetime& operator=(offset_datetime&&) = default; - - private: - - static time_offset get_local_offset(const std::time_t* tp) - { - // get local timezone with the same date-time information as mktime - const auto t = detail::localtime_s(tp); - - std::array buf; - const auto result = std::strftime(buf.data(), 6, "%z", &t); // +hhmm\0 - if(result != 5) - { - throw std::runtime_error("toml::offset_datetime: cannot obtain " - "timezone information of current env"); - } - const int ofs = std::atoi(buf.data()); - const int ofs_h = ofs / 100; - const int ofs_m = ofs - (ofs_h * 100); - return time_offset(ofs_h, ofs_m); - } -}; - -inline bool operator==(const offset_datetime& lhs, const offset_datetime& rhs) -{ - return std::make_tuple(lhs.date, lhs.time, lhs.offset) == - std::make_tuple(rhs.date, rhs.time, rhs.offset); -} -inline bool operator!=(const offset_datetime& lhs, const offset_datetime& rhs) -{ - return !(lhs == rhs); -} -inline bool operator< (const offset_datetime& lhs, const offset_datetime& rhs) -{ - return std::make_tuple(lhs.date, lhs.time, lhs.offset) < - std::make_tuple(rhs.date, rhs.time, rhs.offset); -} -inline bool operator<=(const offset_datetime& lhs, const offset_datetime& rhs) -{ - return (lhs < rhs) || (lhs == rhs); -} -inline bool operator> (const offset_datetime& lhs, const offset_datetime& rhs) -{ - return !(lhs <= rhs); -} -inline bool operator>=(const offset_datetime& lhs, const offset_datetime& rhs) -{ - return !(lhs < rhs); -} - -template -std::basic_ostream& -operator<<(std::basic_ostream& os, const offset_datetime& dt) -{ - os << dt.date << 'T' << dt.time << dt.offset; - return os; -} - -}//toml -#endif// TOML11_DATETIME diff --git a/lib/toml/toml/exception.hpp b/lib/toml/toml/exception.hpp deleted file mode 100644 index c64651d..0000000 --- a/lib/toml/toml/exception.hpp +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright Toru Niina 2017. -// Distributed under the MIT License. -#ifndef TOML11_EXCEPTION_HPP -#define TOML11_EXCEPTION_HPP -#include -#include - -#include "source_location.hpp" - -namespace toml -{ - -struct exception : public std::exception -{ - public: - explicit exception(const source_location& loc): loc_(loc) {} - virtual ~exception() noexcept override = default; - virtual const char* what() const noexcept override {return "";} - virtual source_location const& location() const noexcept {return loc_;} - - protected: - source_location loc_; -}; - -struct syntax_error : public toml::exception -{ - public: - explicit syntax_error(const std::string& what_arg, const source_location& loc) - : exception(loc), what_(what_arg) - {} - virtual ~syntax_error() noexcept override = default; - virtual const char* what() const noexcept override {return what_.c_str();} - - protected: - std::string what_; -}; - -struct type_error : public toml::exception -{ - public: - explicit type_error(const std::string& what_arg, const source_location& loc) - : exception(loc), what_(what_arg) - {} - virtual ~type_error() noexcept override = default; - virtual const char* what() const noexcept override {return what_.c_str();} - - protected: - std::string what_; -}; - -struct internal_error : public toml::exception -{ - public: - explicit internal_error(const std::string& what_arg, const source_location& loc) - : exception(loc), what_(what_arg) - {} - virtual ~internal_error() noexcept override = default; - virtual const char* what() const noexcept override {return what_.c_str();} - - protected: - std::string what_; -}; - -} // toml -#endif // TOML_EXCEPTION diff --git a/lib/toml/toml/from.hpp b/lib/toml/toml/from.hpp deleted file mode 100644 index 10815ca..0000000 --- a/lib/toml/toml/from.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright Toru Niina 2019. -// Distributed under the MIT License. -#ifndef TOML11_FROM_HPP -#define TOML11_FROM_HPP - -namespace toml -{ - -template -struct from; -// { -// static T from_toml(const toml::value& v) -// { -// // User-defined conversions ... -// } -// }; - -} // toml -#endif // TOML11_FROM_HPP diff --git a/lib/toml/toml/get.hpp b/lib/toml/toml/get.hpp deleted file mode 100644 index 901790b..0000000 --- a/lib/toml/toml/get.hpp +++ /dev/null @@ -1,1119 +0,0 @@ -// Copyright Toru Niina 2017. -// Distributed under the MIT License. -#ifndef TOML11_GET_HPP -#define TOML11_GET_HPP -#include - -#include "from.hpp" -#include "result.hpp" -#include "value.hpp" - -namespace toml -{ - -// ============================================================================ -// exact toml::* type - -template class M, template class V> -detail::enable_if_t>::value, T> & -get(basic_value& v) -{ - return v.template cast>::value>(); -} - -template class M, template class V> -detail::enable_if_t>::value, T> const& -get(const basic_value& v) -{ - return v.template cast>::value>(); -} - -template class M, template class V> -detail::enable_if_t>::value, T> -get(basic_value&& v) -{ - return T(std::move(v).template cast>::value>()); -} - -// ============================================================================ -// T == toml::value; identity transformation. - -template class M, template class V> -inline detail::enable_if_t>::value, T>& -get(basic_value& v) -{ - return v; -} - -template class M, template class V> -inline detail::enable_if_t>::value, T> const& -get(const basic_value& v) -{ - return v; -} - -template class M, template class V> -inline detail::enable_if_t>::value, T> -get(basic_value&& v) -{ - return basic_value(std::move(v)); -} - -// ============================================================================ -// T == toml::basic_value; basic_value -> basic_value - -template class M, template class V> -inline detail::enable_if_t, - detail::negation>> - >::value, T> -get(const basic_value& v) -{ - return T(v); -} - -// ============================================================================ -// integer convertible from toml::Integer - -template class M, template class V> -inline detail::enable_if_t, // T is integral - detail::negation>, // but not bool - detail::negation< // but not toml::integer - detail::is_exact_toml_type>> - >::value, T> -get(const basic_value& v) -{ - return static_cast(v.as_integer()); -} - -// ============================================================================ -// floating point convertible from toml::Float - -template class M, template class V> -inline detail::enable_if_t, // T is floating_point - detail::negation< // but not toml::floating - detail::is_exact_toml_type>> - >::value, T> -get(const basic_value& v) -{ - return static_cast(v.as_floating()); -} - -// ============================================================================ -// std::string; toml uses its own toml::string, but it should be convertible to -// std::string seamlessly - -template class M, template class V> -inline detail::enable_if_t::value, std::string>& -get(basic_value& v) -{ - return v.as_string().str; -} - -template class M, template class V> -inline detail::enable_if_t::value, std::string> const& -get(const basic_value& v) -{ - return v.as_string().str; -} - -template class M, template class V> -inline detail::enable_if_t::value, std::string> -get(basic_value&& v) -{ - return std::string(std::move(v.as_string().str)); -} - -// ============================================================================ -// std::string_view - -#if defined(TOML11_USING_STRING_VIEW) && TOML11_USING_STRING_VIEW>0 -template class M, template class V> -inline detail::enable_if_t::value, std::string_view> -get(const basic_value& v) -{ - return std::string_view(v.as_string().str); -} -#endif - -// ============================================================================ -// std::chrono::duration from toml::local_time. - -template class M, template class V> -inline detail::enable_if_t::value, T> -get(const basic_value& v) -{ - return std::chrono::duration_cast( - std::chrono::nanoseconds(v.as_local_time())); -} - -// ============================================================================ -// std::chrono::system_clock::time_point from toml::datetime variants - -template class M, template class V> -inline detail::enable_if_t< - std::is_same::value, T> -get(const basic_value& v) -{ - switch(v.type()) - { - case value_t::local_date: - { - return std::chrono::system_clock::time_point(v.as_local_date()); - } - case value_t::local_datetime: - { - return std::chrono::system_clock::time_point(v.as_local_datetime()); - } - case value_t::offset_datetime: - { - return std::chrono::system_clock::time_point(v.as_offset_datetime()); - } - default: - { - throw type_error(detail::format_underline("toml::value: " - "bad_cast to std::chrono::system_clock::time_point", { - {v.location(), concat_to_string("the actual type is ", v.type())} - }), v.location()); - } - } -} - -// ============================================================================ -// forward declaration to use this recursively. ignore this and go ahead. - -// array-like type with push_back(value) method -template class M, template class V> -detail::enable_if_t, // T is a container - detail::has_push_back_method, // T::push_back(value) works - detail::negation< // but not toml::array - detail::is_exact_toml_type>> - >::value, T> -get(const basic_value&); - -// array-like type without push_back(value) method -template class M, template class V> -detail::enable_if_t, // T is a container - detail::negation>, // w/o push_back(...) - detail::negation>, // T does not have special conversion - detail::negation< // not toml::array - detail::is_exact_toml_type>> - >::value, T> -get(const basic_value&); - -// std::pair -template class M, template class V> -detail::enable_if_t::value, T> -get(const basic_value&); - -// std::tuple -template class M, template class V> -detail::enable_if_t::value, T> -get(const basic_value&); - -// map-like classes -template class M, template class V> -detail::enable_if_t, // T is map - detail::negation< // but not toml::table - detail::is_exact_toml_type>> - >::value, T> -get(const basic_value&); - -// T.from_toml(v) -template class M, template class V> -detail::enable_if_t>>, - detail::has_from_toml_method, // but has from_toml(toml::value) - std::is_default_constructible // and default constructible - >::value, T> -get(const basic_value&); - -// toml::from::from_toml(v) -template class M, template class V> -detail::enable_if_t::value, T> -get(const basic_value&); - -// T(const toml::value&) and T is not toml::basic_value, -// and it does not have `from` nor `from_toml`. -template class M, template class V> -detail::enable_if_t>, - std::is_constructible&>, - detail::negation>, - detail::negation> - >::value, T> -get(const basic_value&); - -// ============================================================================ -// array-like types; most likely STL container, like std::vector, etc. - -template class M, template class V> -detail::enable_if_t, // T is a container - detail::has_push_back_method, // container.push_back(elem) works - detail::negation< // but not toml::array - detail::is_exact_toml_type>> - >::value, T> -get(const basic_value& v) -{ - using value_type = typename T::value_type; - const auto& ary = v.as_array(); - - T container; - try_reserve(container, ary.size()); - - for(const auto& elem : ary) - { - container.push_back(get(elem)); - } - return container; -} - -// ============================================================================ -// std::forward_list does not have push_back, insert, or emplace. -// It has insert_after, emplace_after, push_front. - -template class M, template class V> -detail::enable_if_t::value, T> -get(const basic_value& v) -{ - using value_type = typename T::value_type; - T container; - for(const auto& elem : v.as_array()) - { - container.push_front(get(elem)); - } - container.reverse(); - return container; -} - -// ============================================================================ -// array-like types, without push_back(). most likely [std|boost]::array. - -template class M, template class V> -detail::enable_if_t, // T is a container - detail::negation>, // w/o push_back - detail::negation>, // T does not have special conversion - detail::negation< // T is not toml::array - detail::is_exact_toml_type>> - >::value, T> -get(const basic_value& v) -{ - using value_type = typename T::value_type; - const auto& ar = v.as_array(); - - T container; - if(ar.size() != container.size()) - { - throw std::out_of_range(detail::format_underline(concat_to_string( - "toml::get: specified container size is ", container.size(), - " but there are ", ar.size(), " elements in toml array."), { - {v.location(), "here"} - })); - } - for(std::size_t i=0; i(ar[i]); - } - return container; -} - -// ============================================================================ -// std::pair. - -template class M, template class V> -detail::enable_if_t::value, T> -get(const basic_value& v) -{ - using first_type = typename T::first_type; - using second_type = typename T::second_type; - - const auto& ar = v.as_array(); - if(ar.size() != 2) - { - throw std::out_of_range(detail::format_underline(concat_to_string( - "toml::get: specified std::pair but there are ", ar.size(), - " elements in toml array."), {{v.location(), "here"}})); - } - return std::make_pair(::toml::get(ar.at(0)), - ::toml::get(ar.at(1))); -} - -// ============================================================================ -// std::tuple. - -namespace detail -{ -template -T get_tuple_impl(const Array& a, index_sequence) -{ - return std::make_tuple( - ::toml::get::type>(a.at(I))...); -} -} // detail - -template class M, template class V> -detail::enable_if_t::value, T> -get(const basic_value& v) -{ - const auto& ar = v.as_array(); - if(ar.size() != std::tuple_size::value) - { - throw std::out_of_range(detail::format_underline(concat_to_string( - "toml::get: specified std::tuple with ", - std::tuple_size::value, " elements, but there are ", ar.size(), - " elements in toml array."), {{v.location(), "here"}})); - } - return detail::get_tuple_impl(ar, - detail::make_index_sequence::value>{}); -} - -// ============================================================================ -// map-like types; most likely STL map, like std::map or std::unordered_map. - -template class M, template class V> -detail::enable_if_t, // T is map - detail::negation< // but not toml::array - detail::is_exact_toml_type>> - >::value, T> -get(const basic_value& v) -{ - using key_type = typename T::key_type; - using mapped_type = typename T::mapped_type; - static_assert(std::is_convertible::value, - "toml::get only supports map type of which key_type is " - "convertible from std::string."); - T map; - for(const auto& kv : v.as_table()) - { - map.emplace(key_type(kv.first), get(kv.second)); - } - return map; -} - -// ============================================================================ -// user-defined, but compatible types. - -template class M, template class V> -detail::enable_if_t>>, - detail::has_from_toml_method, // but has from_toml(toml::value) memfn - std::is_default_constructible // and default constructible - >::value, T> -get(const basic_value& v) -{ - T ud; - ud.from_toml(v); - return ud; -} -template class M, template class V> -detail::enable_if_t::value, T> -get(const basic_value& v) -{ - return ::toml::from::from_toml(v); -} - -template class M, template class V> -detail::enable_if_t>, // T is not a toml::value - std::is_constructible&>, // T is constructible from toml::value - detail::negation>, // and T does not have T.from_toml(v); - detail::negation> // and T does not have toml::from{}; - >::value, T> -get(const basic_value& v) -{ - return T(v); -} - -// ============================================================================ -// find - -// ---------------------------------------------------------------------------- -// these overloads do not require to set T. and returns value itself. -template class M, template class V> -basic_value const& find(const basic_value& v, const key& ky) -{ - const auto& tab = v.as_table(); - if(tab.count(ky) == 0) - { - detail::throw_key_not_found_error(v, ky); - } - return tab.at(ky); -} -template class M, template class V> -basic_value& find(basic_value& v, const key& ky) -{ - auto& tab = v.as_table(); - if(tab.count(ky) == 0) - { - detail::throw_key_not_found_error(v, ky); - } - return tab.at(ky); -} -template class M, template class V> -basic_value find(basic_value&& v, const key& ky) -{ - typename basic_value::table_type tab = std::move(v).as_table(); - if(tab.count(ky) == 0) - { - detail::throw_key_not_found_error(v, ky); - } - return basic_value(std::move(tab.at(ky))); -} - -// ---------------------------------------------------------------------------- -// find(value, idx) -template class M, template class V> -basic_value const& -find(const basic_value& v, const std::size_t idx) -{ - const auto& ary = v.as_array(); - if(ary.size() <= idx) - { - throw std::out_of_range(detail::format_underline(concat_to_string( - "index ", idx, " is out of range"), {{v.location(), "in this array"}})); - } - return ary.at(idx); -} -template class M, template class V> -basic_value& find(basic_value& v, const std::size_t idx) -{ - auto& ary = v.as_array(); - if(ary.size() <= idx) - { - throw std::out_of_range(detail::format_underline(concat_to_string( - "index ", idx, " is out of range"), {{v.location(), "in this array"}})); - } - return ary.at(idx); -} -template class M, template class V> -basic_value find(basic_value&& v, const std::size_t idx) -{ - auto& ary = v.as_array(); - if(ary.size() <= idx) - { - throw std::out_of_range(detail::format_underline(concat_to_string( - "index ", idx, " is out of range"), {{v.location(), "in this array"}})); - } - return basic_value(std::move(ary.at(idx))); -} - -// ---------------------------------------------------------------------------- -// find(value, key); - -template class M, template class V> -decltype(::toml::get(std::declval const&>())) -find(const basic_value& v, const key& ky) -{ - const auto& tab = v.as_table(); - if(tab.count(ky) == 0) - { - detail::throw_key_not_found_error(v, ky); - } - return ::toml::get(tab.at(ky)); -} - -template class M, template class V> -decltype(::toml::get(std::declval&>())) -find(basic_value& v, const key& ky) -{ - auto& tab = v.as_table(); - if(tab.count(ky) == 0) - { - detail::throw_key_not_found_error(v, ky); - } - return ::toml::get(tab.at(ky)); -} - -template class M, template class V> -decltype(::toml::get(std::declval&&>())) -find(basic_value&& v, const key& ky) -{ - typename basic_value::table_type tab = std::move(v).as_table(); - if(tab.count(ky) == 0) - { - detail::throw_key_not_found_error(v, ky); - } - return ::toml::get(std::move(tab.at(ky))); -} - -// ---------------------------------------------------------------------------- -// find(value, idx) -template class M, template class V> -decltype(::toml::get(std::declval const&>())) -find(const basic_value& v, const std::size_t idx) -{ - const auto& ary = v.as_array(); - if(ary.size() <= idx) - { - throw std::out_of_range(detail::format_underline(concat_to_string( - "index ", idx, " is out of range"), {{v.location(), "in this array"}})); - } - return ::toml::get(ary.at(idx)); -} -template class M, template class V> -decltype(::toml::get(std::declval&>())) -find(basic_value& v, const std::size_t idx) -{ - auto& ary = v.as_array(); - if(ary.size() <= idx) - { - throw std::out_of_range(detail::format_underline(concat_to_string( - "index ", idx, " is out of range"), {{v.location(), "in this array"}})); - } - return ::toml::get(ary.at(idx)); -} -template class M, template class V> -decltype(::toml::get(std::declval&&>())) -find(basic_value&& v, const std::size_t idx) -{ - typename basic_value::array_type ary = std::move(v).as_array(); - if(ary.size() <= idx) - { - throw std::out_of_range(detail::format_underline(concat_to_string( - "index ", idx, " is out of range"), {{v.location(), "in this array"}})); - } - return ::toml::get(std::move(ary.at(idx))); -} - -// -------------------------------------------------------------------------- -// toml::find(toml::value, toml::key, Ts&& ... keys) - -namespace detail -{ -// It suppresses warnings by -Wsign-conversion. Let's say we have the following -// code. -// ```cpp -// const auto x = toml::find(data, "array", 0); -// ``` -// Here, the type of literal number `0` is `int`. `int` is a signed integer. -// `toml::find` takes `std::size_t` as an index. So it causes implicit sign -// conversion and `-Wsign-conversion` warns about it. Using `0u` instead of `0` -// suppresses the warning, but it makes user code messy. -// To suppress this warning, we need to be aware of type conversion caused -// by `toml::find(v, key1, key2, ... keys)`. But the thing is that the types of -// keys can be any combination of {string-like, size_t-like}. Of course we can't -// write down all the combinations. Thus we need to use some function that -// recognize the type of argument and cast it into `std::string` or -// `std::size_t` depending on the context. -// `key_cast` does the job. It has 2 overloads. One is invoked when the -// argument type is an integer and cast the argument into `std::size_t`. The -// other is invoked when the argument type is not an integer, possibly one of -// std::string, const char[N] or const char*, and construct std::string from -// the argument. -// `toml::find(v, k1, k2, ... ks)` uses `key_cast` before passing `ks` to -// `toml::find(v, k)` to suppress -Wsign-conversion. - -template -enable_if_t>, - negation, bool>>>::value, std::size_t> -key_cast(T&& v) noexcept -{ - return std::size_t(v); -} -template -enable_if_t>, - negation, bool>>>>::value, std::string> -key_cast(T&& v) noexcept -{ - return std::string(std::forward(v)); -} -} // detail - -template class M, template class V, - typename Key1, typename Key2, typename ... Keys> -const basic_value& -find(const basic_value& v, Key1&& k1, Key2&& k2, Keys&& ... keys) -{ - return ::toml::find(::toml::find(v, detail::key_cast(k1)), - detail::key_cast(k2), std::forward(keys)...); -} -template class M, template class V, - typename Key1, typename Key2, typename ... Keys> -basic_value& -find(basic_value& v, Key1&& k1, Key2&& k2, Keys&& ... keys) -{ - return ::toml::find(::toml::find(v, detail::key_cast(k1)), - detail::key_cast(k2), std::forward(keys)...); -} -template class M, template class V, - typename Key1, typename Key2, typename ... Keys> -basic_value -find(basic_value&& v, Key1&& k1, Key2&& k2, Keys&& ... keys) -{ - return ::toml::find(::toml::find(std::move(v), std::forward(k1)), - detail::key_cast(k2), std::forward(keys)...); -} - -template class M, template class V, - typename Key1, typename Key2, typename ... Keys> -decltype(::toml::get(std::declval&>())) -find(const basic_value& v, Key1&& k1, Key2&& k2, Keys&& ... keys) -{ - return ::toml::find(::toml::find(v, detail::key_cast(k1)), - detail::key_cast(k2), std::forward(keys)...); -} -template class M, template class V, - typename Key1, typename Key2, typename ... Keys> -decltype(::toml::get(std::declval&>())) -find(basic_value& v, Key1&& k1, Key2&& k2, Keys&& ... keys) -{ - return ::toml::find(::toml::find(v, detail::key_cast(k1)), - detail::key_cast(k2), std::forward(keys)...); -} -template class M, template class V, - typename Key1, typename Key2, typename ... Keys> -decltype(::toml::get(std::declval&&>())) -find(basic_value&& v, Key1&& k1, Key2&& k2, Keys&& ... keys) -{ - return ::toml::find(::toml::find(std::move(v), detail::key_cast(k1)), - detail::key_cast(k2), std::forward(keys)...); -} - -// ============================================================================ -// get_or(value, fallback) - -template class M, template class V> -basic_value const& -get_or(const basic_value& v, const basic_value&) -{ - return v; -} -template class M, template class V> -basic_value& -get_or(basic_value& v, basic_value&) -{ - return v; -} -template class M, template class V> -basic_value -get_or(basic_value&& v, basic_value&&) -{ - return v; -} - -// ---------------------------------------------------------------------------- -// specialization for the exact toml types (return type becomes lvalue ref) - -template class M, template class V> -detail::enable_if_t< - detail::is_exact_toml_type>::value, T> const& -get_or(const basic_value& v, const T& opt) -{ - try - { - return get>(v); - } - catch(...) - { - return opt; - } -} -template class M, template class V> -detail::enable_if_t< - detail::is_exact_toml_type>::value, T>& -get_or(basic_value& v, T& opt) -{ - try - { - return get>(v); - } - catch(...) - { - return opt; - } -} -template class M, template class V> -detail::enable_if_t, - basic_value>::value, detail::remove_cvref_t> -get_or(basic_value&& v, T&& opt) -{ - try - { - return get>(std::move(v)); - } - catch(...) - { - return detail::remove_cvref_t(std::forward(opt)); - } -} - -// ---------------------------------------------------------------------------- -// specialization for std::string (return type becomes lvalue ref) - -template class M, template class V> -detail::enable_if_t, std::string>::value, - std::string> const& -get_or(const basic_value& v, const T& opt) -{ - try - { - return v.as_string().str; - } - catch(...) - { - return opt; - } -} -template class M, template class V> -detail::enable_if_t::value, std::string>& -get_or(basic_value& v, T& opt) -{ - try - { - return v.as_string().str; - } - catch(...) - { - return opt; - } -} -template class M, template class V> -detail::enable_if_t< - std::is_same, std::string>::value, std::string> -get_or(basic_value&& v, T&& opt) -{ - try - { - return std::move(v.as_string().str); - } - catch(...) - { - return std::string(std::forward(opt)); - } -} - -// ---------------------------------------------------------------------------- -// specialization for string literal - -template class M, template class V> -detail::enable_if_t::type>::value, std::string> -get_or(const basic_value& v, T&& opt) -{ - try - { - return std::move(v.as_string().str); - } - catch(...) - { - return std::string(std::forward(opt)); - } -} - -// ---------------------------------------------------------------------------- -// others (require type conversion and return type cannot be lvalue reference) - -template class M, template class V> -detail::enable_if_t, - basic_value>>, - detail::negation>>, - detail::negation::type>> - >::value, detail::remove_cvref_t> -get_or(const basic_value& v, T&& opt) -{ - try - { - return get>(v); - } - catch(...) - { - return detail::remove_cvref_t(std::forward(opt)); - } -} - -// =========================================================================== -// find_or(value, key, fallback) - -template class M, template class V> -basic_value const& -find_or(const basic_value& v, const key& ky, - const basic_value& opt) -{ - if(!v.is_table()) {return opt;} - const auto& tab = v.as_table(); - if(tab.count(ky) == 0) {return opt;} - return tab.at(ky); -} - -template class M, template class V> -basic_value& -find_or(basic_value& v, const toml::key& ky, basic_value& opt) -{ - if(!v.is_table()) {return opt;} - auto& tab = v.as_table(); - if(tab.count(ky) == 0) {return opt;} - return tab.at(ky); -} - -template class M, template class V> -basic_value -find_or(basic_value&& v, const toml::key& ky, basic_value&& opt) -{ - if(!v.is_table()) {return opt;} - auto tab = std::move(v).as_table(); - if(tab.count(ky) == 0) {return opt;} - return basic_value(std::move(tab.at(ky))); -} - -// --------------------------------------------------------------------------- -// exact types (return type can be a reference) -template class M, template class V> -detail::enable_if_t< - detail::is_exact_toml_type>::value, T> const& -find_or(const basic_value& v, const key& ky, const T& opt) -{ - if(!v.is_table()) {return opt;} - const auto& tab = v.as_table(); - if(tab.count(ky) == 0) {return opt;} - return get_or(tab.at(ky), opt); -} - -template class M, template class V> -detail::enable_if_t< - detail::is_exact_toml_type>::value, T>& -find_or(basic_value& v, const toml::key& ky, T& opt) -{ - if(!v.is_table()) {return opt;} - auto& tab = v.as_table(); - if(tab.count(ky) == 0) {return opt;} - return get_or(tab.at(ky), opt); -} - -template class M, template class V> -detail::enable_if_t< - detail::is_exact_toml_type>::value, - detail::remove_cvref_t> -find_or(basic_value&& v, const toml::key& ky, T&& opt) -{ - if(!v.is_table()) {return std::forward(opt);} - auto tab = std::move(v).as_table(); - if(tab.count(ky) == 0) {return std::forward(opt);} - return get_or(std::move(tab.at(ky)), std::forward(opt)); -} - -// --------------------------------------------------------------------------- -// std::string (return type can be a reference) - -template class M, template class V> -detail::enable_if_t::value, std::string> const& -find_or(const basic_value& v, const key& ky, const T& opt) -{ - if(!v.is_table()) {return opt;} - const auto& tab = v.as_table(); - if(tab.count(ky) == 0) {return opt;} - return get_or(tab.at(ky), opt); -} -template class M, template class V> -detail::enable_if_t::value, std::string>& -find_or(basic_value& v, const toml::key& ky, T& opt) -{ - if(!v.is_table()) {return opt;} - auto& tab = v.as_table(); - if(tab.count(ky) == 0) {return opt;} - return get_or(tab.at(ky), opt); -} -template class M, template class V> -detail::enable_if_t::value, std::string> -find_or(basic_value&& v, const toml::key& ky, T&& opt) -{ - if(!v.is_table()) {return std::forward(opt);} - auto tab = std::move(v).as_table(); - if(tab.count(ky) == 0) {return std::forward(opt);} - return get_or(std::move(tab.at(ky)), std::forward(opt)); -} - -// --------------------------------------------------------------------------- -// string literal (deduced as std::string) -template class M, template class V> -detail::enable_if_t< - detail::is_string_literal::type>::value, - std::string> -find_or(const basic_value& v, const toml::key& ky, T&& opt) -{ - if(!v.is_table()) {return std::string(opt);} - const auto& tab = v.as_table(); - if(tab.count(ky) == 0) {return std::string(opt);} - return get_or(tab.at(ky), std::forward(opt)); -} - -// --------------------------------------------------------------------------- -// others (require type conversion and return type cannot be lvalue reference) -template class M, template class V> -detail::enable_if_t, basic_value>>, - // T is not std::string - detail::negation>>, - // T is not a string literal - detail::negation::type>> - >::value, detail::remove_cvref_t> -find_or(const basic_value& v, const toml::key& ky, T&& opt) -{ - if(!v.is_table()) {return std::forward(opt);} - const auto& tab = v.as_table(); - if(tab.count(ky) == 0) {return std::forward(opt);} - return get_or(tab.at(ky), std::forward(opt)); -} - -// --------------------------------------------------------------------------- -// recursive find-or with type deduction (find_or(value, keys, opt)) - -template 1), std::nullptr_t> = nullptr> - // here we need to add SFINAE in the template parameter to avoid - // infinite recursion in type deduction on gcc -auto find_or(Value&& v, const toml::key& ky, Ks&& ... keys) - -> decltype(find_or(std::forward(v), ky, detail::last_one(std::forward(keys)...))) -{ - if(!v.is_table()) - { - return detail::last_one(std::forward(keys)...); - } - auto&& tab = std::forward(v).as_table(); - if(tab.count(ky) == 0) - { - return detail::last_one(std::forward(keys)...); - } - return find_or(std::forward(tab).at(ky), std::forward(keys)...); -} - -// --------------------------------------------------------------------------- -// recursive find_or with explicit type specialization, find_or(value, keys...) - -template 1), std::nullptr_t> = nullptr> - // here we need to add SFINAE in the template parameter to avoid - // infinite recursion in type deduction on gcc -auto find_or(Value&& v, const toml::key& ky, Ks&& ... keys) - -> decltype(find_or(std::forward(v), ky, detail::last_one(std::forward(keys)...))) -{ - if(!v.is_table()) - { - return detail::last_one(std::forward(keys)...); - } - auto&& tab = std::forward(v).as_table(); - if(tab.count(ky) == 0) - { - return detail::last_one(std::forward(keys)...); - } - return find_or(std::forward(tab).at(ky), std::forward(keys)...); -} - -// ============================================================================ -// expect - -template class M, template class V> -result expect(const basic_value& v) noexcept -{ - try - { - return ok(get(v)); - } - catch(const std::exception& e) - { - return err(e.what()); - } -} -template class M, template class V> -result -expect(const basic_value& v, const toml::key& k) noexcept -{ - try - { - return ok(find(v, k)); - } - catch(const std::exception& e) - { - return err(e.what()); - } -} - -} // toml -#endif// TOML11_GET diff --git a/lib/toml/toml/into.hpp b/lib/toml/toml/into.hpp deleted file mode 100644 index 7449556..0000000 --- a/lib/toml/toml/into.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright Toru Niina 2019. -// Distributed under the MIT License. -#ifndef TOML11_INTO_HPP -#define TOML11_INTO_HPP - -namespace toml -{ - -template -struct into; -// { -// static toml::value into_toml(const T& user_defined_type) -// { -// // User-defined conversions ... -// } -// }; - -} // toml -#endif // TOML11_INTO_HPP diff --git a/lib/toml/toml/lexer.hpp b/lib/toml/toml/lexer.hpp deleted file mode 100644 index ea5050b..0000000 --- a/lib/toml/toml/lexer.hpp +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright Toru Niina 2017. -// Distributed under the MIT License. -#ifndef TOML11_LEXER_HPP -#define TOML11_LEXER_HPP -#include -#include -#include -#include - -#include "combinator.hpp" - -namespace toml -{ -namespace detail -{ - -// these scans contents from current location in a container of char -// and extract a region that matches their own pattern. -// to see the implementation of each component, see combinator.hpp. - -using lex_wschar = either, character<'\t'>>; -using lex_ws = repeat>; -using lex_newline = either, - sequence, character<'\n'>>>; -using lex_lower = in_range<'a', 'z'>; -using lex_upper = in_range<'A', 'Z'>; -using lex_alpha = either; -using lex_digit = in_range<'0', '9'>; -using lex_nonzero = in_range<'1', '9'>; -using lex_oct_dig = in_range<'0', '7'>; -using lex_bin_dig = in_range<'0', '1'>; -using lex_hex_dig = either, in_range<'a', 'f'>>; - -using lex_hex_prefix = sequence, character<'x'>>; -using lex_oct_prefix = sequence, character<'o'>>; -using lex_bin_prefix = sequence, character<'b'>>; -using lex_underscore = character<'_'>; -using lex_plus = character<'+'>; -using lex_minus = character<'-'>; -using lex_sign = either; - -// digit | nonzero 1*(digit | _ digit) -using lex_unsigned_dec_int = either>, at_least<1>>>, - lex_digit>; -// (+|-)? unsigned_dec_int -using lex_dec_int = sequence, lex_unsigned_dec_int>; - -// hex_prefix hex_dig *(hex_dig | _ hex_dig) -using lex_hex_int = sequence>, unlimited>>>; -// oct_prefix oct_dig *(oct_dig | _ oct_dig) -using lex_oct_int = sequence>, unlimited>>>; -// bin_prefix bin_dig *(bin_dig | _ bin_dig) -using lex_bin_int = sequence>, unlimited>>>; - -// (dec_int | hex_int | oct_int | bin_int) -using lex_integer = either; - -// =========================================================================== - -using lex_inf = sequence, character<'n'>, character<'f'>>; -using lex_nan = sequence, character<'a'>, character<'n'>>; -using lex_special_float = sequence, either>; - -using lex_zero_prefixable_int = sequence>, unlimited>>; - -using lex_fractional_part = sequence, lex_zero_prefixable_int>; - -using lex_exponent_part = sequence, character<'E'>>, - maybe, lex_zero_prefixable_int>; - -using lex_float = either>>>>; - -// =========================================================================== - -using lex_true = sequence, character<'r'>, - character<'u'>, character<'e'>>; -using lex_false = sequence, character<'a'>, character<'l'>, - character<'s'>, character<'e'>>; -using lex_boolean = either; - -// =========================================================================== - -using lex_date_fullyear = repeat>; -using lex_date_month = repeat>; -using lex_date_mday = repeat>; -using lex_time_delim = either, character<'t'>, character<' '>>; -using lex_time_hour = repeat>; -using lex_time_minute = repeat>; -using lex_time_second = repeat>; -using lex_time_secfrac = sequence, - repeat>>; - -using lex_time_numoffset = sequence, character<'-'>>, - sequence, - lex_time_minute>>; -using lex_time_offset = either, character<'z'>, - lex_time_numoffset>; - -using lex_partial_time = sequence, - lex_time_minute, character<':'>, - lex_time_second, maybe>; -using lex_full_date = sequence, - lex_date_month, character<'-'>, - lex_date_mday>; -using lex_full_time = sequence; - -using lex_offset_date_time = sequence; -using lex_local_date_time = sequence; -using lex_local_date = lex_full_date; -using lex_local_time = lex_partial_time; - -// =========================================================================== - -using lex_quotation_mark = character<'"'>; -using lex_basic_unescaped = exclude, // 0x09 (tab) is allowed - in_range<0x0A, 0x1F>, - character<0x22>, character<0x5C>, - character<0x7F>>>; - -using lex_escape = character<'\\'>; -using lex_escape_unicode_short = sequence, - repeat>>; -using lex_escape_unicode_long = sequence, - repeat>>; -using lex_escape_seq_char = either, character<'\\'>, - character<'b'>, character<'f'>, - character<'n'>, character<'r'>, - character<'t'>, - lex_escape_unicode_short, - lex_escape_unicode_long - >; -using lex_escaped = sequence; -using lex_basic_char = either; -using lex_basic_string = sequence, - lex_quotation_mark>; - -// After toml post-v0.5.0, it is explicitly clarified how quotes in ml-strings -// are allowed to be used. -// After this, the following strings are *explicitly* allowed. -// - One or two `"`s in a multi-line basic string is allowed wherever it is. -// - Three consecutive `"`s in a multi-line basic string is considered as a delimiter. -// - One or two `"`s can appear just before or after the delimiter. -// ```toml -// str4 = """Here are two quotation marks: "". Simple enough.""" -// str5 = """Here are three quotation marks: ""\".""" -// str6 = """Here are fifteen quotation marks: ""\"""\"""\"""\"""\".""" -// str7 = """"This," she said, "is just a pointless statement."""" -// ``` -// In the current implementation (v3.3.0), it is difficult to parse `str7` in -// the above example. It is difficult to recognize `"` at the end of string body -// collectly. It will be misunderstood as a `"""` delimiter and an additional, -// invalid `"`. Like this: -// ```console -// what(): [error] toml::parse_table: invalid line format -// --> hoge.toml -// | -// 13 | str7 = """"This," she said, "is just a pointless statement."""" -// | ^- expected newline, but got '"'. -// ``` -// As a quick workaround for this problem, `lex_ml_basic_string_delim` was -// split into two, `lex_ml_basic_string_open` and `lex_ml_basic_string_close`. -// `lex_ml_basic_string_open` allows only `"""`. `_close` allows 3-5 `"`s. -// In parse_ml_basic_string() function, the trailing `"`s will be attached to -// the string body. -// -using lex_ml_basic_string_delim = repeat>; -using lex_ml_basic_string_open = lex_ml_basic_string_delim; -using lex_ml_basic_string_close = sequence< - repeat>, - maybe, maybe - >; - -using lex_ml_basic_unescaped = exclude, // 0x09 is tab - in_range<0x0A, 0x1F>, - character<0x5C>, // backslash - character<0x7F>, // DEL - lex_ml_basic_string_delim>>; - -using lex_ml_basic_escaped_newline = sequence< - lex_escape, maybe, lex_newline, - repeat, unlimited>>; - -using lex_ml_basic_char = either; -using lex_ml_basic_body = repeat, - unlimited>; -using lex_ml_basic_string = sequence; - -using lex_literal_char = exclude, in_range<0x0A, 0x1F>, - character<0x7F>, character<0x27>>>; -using lex_apostrophe = character<'\''>; -using lex_literal_string = sequence, - lex_apostrophe>; - -// the same reason as above. -using lex_ml_literal_string_delim = repeat>; -using lex_ml_literal_string_open = lex_ml_literal_string_delim; -using lex_ml_literal_string_close = sequence< - repeat>, - maybe, maybe - >; - -using lex_ml_literal_char = exclude, - in_range<0x0A, 0x1F>, - character<0x7F>, - lex_ml_literal_string_delim>>; -using lex_ml_literal_body = repeat, - unlimited>; -using lex_ml_literal_string = sequence; - -using lex_string = either; - -// =========================================================================== -using lex_dot_sep = sequence, character<'.'>, maybe>; - -using lex_unquoted_key = repeat, character<'_'>>, - at_least<1>>; -using lex_quoted_key = either; -using lex_simple_key = either; -using lex_dotted_key = sequence, - at_least<1> - > - >; -using lex_key = either; - -using lex_keyval_sep = sequence, - character<'='>, - maybe>; - -using lex_std_table_open = character<'['>; -using lex_std_table_close = character<']'>; -using lex_std_table = sequence, - lex_key, - maybe, - lex_std_table_close>; - -using lex_array_table_open = sequence; -using lex_array_table_close = sequence; -using lex_array_table = sequence, - lex_key, - maybe, - lex_array_table_close>; - -using lex_utf8_1byte = in_range<0x00, 0x7F>; -using lex_utf8_2byte = sequence< - in_range(0xC2), static_cast(0xDF)>, - in_range(0x80), static_cast(0xBF)> - >; -using lex_utf8_3byte = sequence(0xE0)>, in_range(0xA0), static_cast(0xBF)>>, - sequence(0xE1), static_cast(0xEC)>, in_range(0x80), static_cast(0xBF)>>, - sequence(0xED)>, in_range(0x80), static_cast(0x9F)>>, - sequence(0xEE), static_cast(0xEF)>, in_range(0x80), static_cast(0xBF)>> - >, in_range(0x80), static_cast(0xBF)>>; -using lex_utf8_4byte = sequence(0xF0)>, in_range(0x90), static_cast(0xBF)>>, - sequence(0xF1), static_cast(0xF3)>, in_range(0x80), static_cast(0xBF)>>, - sequence(0xF4)>, in_range(0x80), static_cast(0x8F)>> - >, in_range(0x80), static_cast(0xBF)>, - in_range(0x80), static_cast(0xBF)>>; -using lex_utf8_code = either< - lex_utf8_1byte, - lex_utf8_2byte, - lex_utf8_3byte, - lex_utf8_4byte - >; - -using lex_comment_start_symbol = character<'#'>; -using lex_non_eol_ascii = either, in_range<0x20, 0x7E>>; -using lex_comment = sequence, unlimited>>; - -} // detail -} // toml -#endif // TOML_LEXER_HPP diff --git a/lib/toml/toml/literal.hpp b/lib/toml/toml/literal.hpp deleted file mode 100644 index 04fbbc1..0000000 --- a/lib/toml/toml/literal.hpp +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright Toru Niina 2019. -// Distributed under the MIT License. -#ifndef TOML11_LITERAL_HPP -#define TOML11_LITERAL_HPP -#include "parser.hpp" - -namespace toml -{ -inline namespace literals -{ -inline namespace toml_literals -{ - -// implementation -inline ::toml::basic_value -literal_internal_impl(::toml::detail::location loc) -{ - using value_type = ::toml::basic_value< - TOML11_DEFAULT_COMMENT_STRATEGY, std::unordered_map, std::vector>; - // if there are some comments or empty lines, skip them. - using skip_line = ::toml::detail::repeat, - ::toml::detail::maybe<::toml::detail::lex_comment>, - ::toml::detail::lex_newline - >, ::toml::detail::at_least<1>>; - skip_line::invoke(loc); - - // if there are some whitespaces before a value, skip them. - using skip_ws = ::toml::detail::repeat< - ::toml::detail::lex_ws, ::toml::detail::at_least<1>>; - skip_ws::invoke(loc); - - // to distinguish arrays and tables, first check it is a table or not. - // - // "[1,2,3]"_toml; // this is an array - // "[table]"_toml; // a table that has an empty table named "table" inside. - // "[[1,2,3]]"_toml; // this is an array of arrays - // "[[table]]"_toml; // this is a table that has an array of tables inside. - // - // "[[1]]"_toml; // this can be both... (currently it becomes a table) - // "1 = [{}]"_toml; // this is a table that has an array of table named 1. - // "[[1,]]"_toml; // this is an array of arrays. - // "[[1],]"_toml; // this also. - - const auto the_front = loc.iter(); - - const bool is_table_key = ::toml::detail::lex_std_table::invoke(loc); - loc.reset(the_front); - - const bool is_aots_key = ::toml::detail::lex_array_table::invoke(loc); - loc.reset(the_front); - - // If it is neither a table-key or a array-of-table-key, it may be a value. - if(!is_table_key && !is_aots_key) - { - if(auto data = ::toml::detail::parse_value(loc)) - { - return data.unwrap(); - } - } - - // Note that still it can be a table, because the literal might be something - // like the following. - // ```cpp - // R"( // c++11 raw string literals - // key = "value" - // int = 42 - // )"_toml; - // ``` - // It is a valid toml file. - // It should be parsed as if we parse a file with this content. - - if(auto data = ::toml::detail::parse_toml_file(loc)) - { - return data.unwrap(); - } - else // none of them. - { - throw ::toml::syntax_error(data.unwrap_err(), source_location(loc)); - } - -} - -inline ::toml::basic_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(str, str + len)); - // literal length does not include the null character at the end. - 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::basic_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(reinterpret_cast(str), - reinterpret_cast(str) + len)); - return literal_internal_impl(std::move(loc)); -} -#endif - -} // toml_literals -} // literals -} // toml -#endif//TOML11_LITERAL_HPP diff --git a/lib/toml/toml/macros.hpp b/lib/toml/toml/macros.hpp deleted file mode 100644 index e8f91ae..0000000 --- a/lib/toml/toml/macros.hpp +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef TOML11_MACROS_HPP -#define TOML11_MACROS_HPP - -#define TOML11_STRINGIZE_AUX(x) #x -#define TOML11_STRINGIZE(x) TOML11_STRINGIZE_AUX(x) - -#define TOML11_CONCATENATE_AUX(x, y) x##y -#define TOML11_CONCATENATE(x, y) TOML11_CONCATENATE_AUX(x, y) - -// ============================================================================ -// TOML11_DEFINE_CONVERSION_NON_INTRUSIVE - -#ifndef TOML11_WITHOUT_DEFINE_NON_INTRUSIVE - -// ---------------------------------------------------------------------------- -// TOML11_ARGS_SIZE - -#define TOML11_INDEX_RSEQ() \ - 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, \ - 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 -#define TOML11_ARGS_SIZE_IMPL(\ - ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9, ARG10, \ - ARG11, ARG12, ARG13, ARG14, ARG15, ARG16, ARG17, ARG18, ARG19, ARG20, \ - ARG21, ARG22, ARG23, ARG24, ARG25, ARG26, ARG27, ARG28, ARG29, ARG30, \ - ARG31, ARG32, N, ...) N -#define TOML11_ARGS_SIZE_AUX(...) TOML11_ARGS_SIZE_IMPL(__VA_ARGS__) -#define TOML11_ARGS_SIZE(...) TOML11_ARGS_SIZE_AUX(__VA_ARGS__, TOML11_INDEX_RSEQ()) - -// ---------------------------------------------------------------------------- -// TOML11_FOR_EACH_VA_ARGS - -#define TOML11_FOR_EACH_VA_ARGS_AUX_1( FUNCTOR, ARG1 ) FUNCTOR(ARG1) -#define TOML11_FOR_EACH_VA_ARGS_AUX_2( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_1( FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_3( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_2( FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_4( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_3( FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_5( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_4( FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_6( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_5( FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_7( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_6( FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_8( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_7( FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_9( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_8( FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_10(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_9( FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_11(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_10(FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_12(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_11(FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_13(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_12(FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_14(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_13(FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_15(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_14(FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_16(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_15(FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_17(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_16(FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_18(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_17(FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_19(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_18(FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_20(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_19(FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_21(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_20(FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_22(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_21(FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_23(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_22(FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_24(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_23(FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_25(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_24(FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_26(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_25(FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_27(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_26(FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_28(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_27(FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_29(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_28(FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_30(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_29(FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_31(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_30(FUNCTOR, __VA_ARGS__) -#define TOML11_FOR_EACH_VA_ARGS_AUX_32(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_31(FUNCTOR, __VA_ARGS__) - -#define TOML11_FOR_EACH_VA_ARGS(FUNCTOR, ...)\ - TOML11_CONCATENATE(TOML11_FOR_EACH_VA_ARGS_AUX_, TOML11_ARGS_SIZE(__VA_ARGS__))(FUNCTOR, __VA_ARGS__) - -// ---------------------------------------------------------------------------- -// TOML11_DEFINE_CONVERSION_NON_INTRUSIVE - -// use it in the following way. -// ```cpp -// namespace foo -// { -// struct Foo -// { -// std::string s; -// double d; -// int i; -// }; -// } // foo -// -// TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(foo::Foo, s, d, i) -// ``` -// And then you can use `toml::find(file, "foo");` -// -#define TOML11_FIND_MEMBER_VARIABLE_FROM_VALUE(VAR_NAME)\ - obj.VAR_NAME = toml::find(v, TOML11_STRINGIZE(VAR_NAME)); - -#define TOML11_ASSIGN_MEMBER_VARIABLE_TO_VALUE(VAR_NAME)\ - v[TOML11_STRINGIZE(VAR_NAME)] = obj.VAR_NAME; - -#define TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(NAME, ...)\ - namespace toml { \ - template<> \ - struct from \ - { \ - template class T, \ - template class A> \ - static NAME from_toml(const basic_value& v) \ - { \ - NAME obj; \ - TOML11_FOR_EACH_VA_ARGS(TOML11_FIND_MEMBER_VARIABLE_FROM_VALUE, __VA_ARGS__) \ - return obj; \ - } \ - }; \ - template<> \ - struct into \ - { \ - static value into_toml(const NAME& obj) \ - { \ - ::toml::value v = ::toml::table{}; \ - TOML11_FOR_EACH_VA_ARGS(TOML11_ASSIGN_MEMBER_VARIABLE_TO_VALUE, __VA_ARGS__) \ - return v; \ - } \ - }; \ - } /* toml */ - -#endif// TOML11_WITHOUT_DEFINE_NON_INTRUSIVE - -#endif// TOML11_MACROS_HPP diff --git a/lib/toml/toml/parser.hpp b/lib/toml/toml/parser.hpp deleted file mode 100644 index bfa5531..0000000 --- a/lib/toml/toml/parser.hpp +++ /dev/null @@ -1,2416 +0,0 @@ -// Copyright Toru Niina 2017. -// Distributed under the MIT License. -#ifndef TOML11_PARSER_HPP -#define TOML11_PARSER_HPP -#include -#include -#include - -#include "combinator.hpp" -#include "lexer.hpp" -#include "region.hpp" -#include "result.hpp" -#include "types.hpp" -#include "value.hpp" - -#ifndef TOML11_DISABLE_STD_FILESYSTEM -#ifdef __cpp_lib_filesystem -#if __has_include() -#define TOML11_HAS_STD_FILESYSTEM -#include -#endif // has_include() -#endif // __cpp_lib_filesystem -#endif // TOML11_DISABLE_STD_FILESYSTEM - -namespace toml -{ -namespace detail -{ - -inline result, std::string> -parse_boolean(location& loc) -{ - const auto first = loc.iter(); - if(const auto token = lex_boolean::invoke(loc)) - { - const auto reg = token.unwrap(); - if (reg.str() == "true") {return ok(std::make_pair(true, reg));} - else if(reg.str() == "false") {return ok(std::make_pair(false, reg));} - else // internal error. - { - throw internal_error(format_underline( - "toml::parse_boolean: internal error", - {{source_location(reg), "invalid token"}}), - source_location(reg)); - } - } - loc.reset(first); //rollback - return err(format_underline("toml::parse_boolean: ", - {{source_location(loc), "the next token is not a boolean"}})); -} - -inline result, std::string> -parse_binary_integer(location& loc) -{ - const auto first = loc.iter(); - if(const auto token = lex_bin_int::invoke(loc)) - { - auto str = token.unwrap().str(); - assert(str.size() > 2); // minimum -> 0b1 - integer retval(0), base(1); - for(auto i(str.rbegin()), e(str.rend() - 2); i!=e; ++i) - { - if (*i == '1'){retval += base; base *= 2;} - else if(*i == '0'){base *= 2;} - else if(*i == '_'){/* do nothing. */} - else // internal error. - { - throw internal_error(format_underline( - "toml::parse_integer: internal error", - {{source_location(token.unwrap()), "invalid token"}}), - source_location(loc)); - } - } - return ok(std::make_pair(retval, token.unwrap())); - } - loc.reset(first); - return err(format_underline("toml::parse_binary_integer:", - {{source_location(loc), "the next token is not an integer"}})); -} - -inline result, std::string> -parse_octal_integer(location& loc) -{ - const auto first = loc.iter(); - if(const auto token = lex_oct_int::invoke(loc)) - { - auto str = token.unwrap().str(); - str.erase(std::remove(str.begin(), str.end(), '_'), str.end()); - str.erase(str.begin()); str.erase(str.begin()); // remove `0o` prefix - - std::istringstream iss(str); - integer retval(0); - iss >> std::oct >> retval; - return ok(std::make_pair(retval, token.unwrap())); - } - loc.reset(first); - return err(format_underline("toml::parse_octal_integer:", - {{source_location(loc), "the next token is not an integer"}})); -} - -inline result, std::string> -parse_hexadecimal_integer(location& loc) -{ - const auto first = loc.iter(); - if(const auto token = lex_hex_int::invoke(loc)) - { - auto str = token.unwrap().str(); - str.erase(std::remove(str.begin(), str.end(), '_'), str.end()); - str.erase(str.begin()); str.erase(str.begin()); // remove `0x` prefix - - std::istringstream iss(str); - integer retval(0); - iss >> std::hex >> retval; - return ok(std::make_pair(retval, token.unwrap())); - } - loc.reset(first); - return err(format_underline("toml::parse_hexadecimal_integer", - {{source_location(loc), "the next token is not an integer"}})); -} - -inline result, std::string> -parse_integer(location& loc) -{ - const auto first = loc.iter(); - if(first != loc.end() && *first == '0') - { - const auto second = std::next(first); - if(second == loc.end()) // the token is just zero. - { - loc.advance(); - return ok(std::make_pair(0, region(loc, first, second))); - } - - if(*second == 'b') {return parse_binary_integer (loc);} // 0b1100 - if(*second == 'o') {return parse_octal_integer (loc);} // 0o775 - if(*second == 'x') {return parse_hexadecimal_integer(loc);} // 0xC0FFEE - - if(std::isdigit(*second)) - { - return err(format_underline("toml::parse_integer: " - "leading zero in an Integer is not allowed.", - {{source_location(loc), "leading zero"}})); - } - else if(std::isalpha(*second)) - { - return err(format_underline("toml::parse_integer: " - "unknown integer prefix appeared.", - {{source_location(loc), "none of 0x, 0o, 0b"}})); - } - } - - if(const auto token = lex_dec_int::invoke(loc)) - { - auto str = token.unwrap().str(); - str.erase(std::remove(str.begin(), str.end(), '_'), str.end()); - - std::istringstream iss(str); - integer retval(0); - iss >> retval; - return ok(std::make_pair(retval, token.unwrap())); - } - loc.reset(first); - return err(format_underline("toml::parse_integer: ", - {{source_location(loc), "the next token is not an integer"}})); -} - -inline result, std::string> -parse_floating(location& loc) -{ - const auto first = loc.iter(); - if(const auto token = lex_float::invoke(loc)) - { - auto str = token.unwrap().str(); - if(str == "inf" || str == "+inf") - { - if(std::numeric_limits::has_infinity) - { - return ok(std::make_pair( - std::numeric_limits::infinity(), token.unwrap())); - } - else - { - throw std::domain_error("toml::parse_floating: inf value found" - " but the current environment does not support inf. Please" - " make sure that the floating-point implementation conforms" - " IEEE 754/ISO 60559 international standard."); - } - } - else if(str == "-inf") - { - if(std::numeric_limits::has_infinity) - { - return ok(std::make_pair( - -std::numeric_limits::infinity(), token.unwrap())); - } - else - { - throw std::domain_error("toml::parse_floating: inf value found" - " but the current environment does not support inf. Please" - " make sure that the floating-point implementation conforms" - " IEEE 754/ISO 60559 international standard."); - } - } - else if(str == "nan" || str == "+nan") - { - if(std::numeric_limits::has_quiet_NaN) - { - return ok(std::make_pair( - std::numeric_limits::quiet_NaN(), token.unwrap())); - } - else if(std::numeric_limits::has_signaling_NaN) - { - return ok(std::make_pair( - std::numeric_limits::signaling_NaN(), token.unwrap())); - } - else - { - throw std::domain_error("toml::parse_floating: NaN value found" - " but the current environment does not support NaN. Please" - " make sure that the floating-point implementation conforms" - " IEEE 754/ISO 60559 international standard."); - } - } - else if(str == "-nan") - { - if(std::numeric_limits::has_quiet_NaN) - { - return ok(std::make_pair( - -std::numeric_limits::quiet_NaN(), token.unwrap())); - } - else if(std::numeric_limits::has_signaling_NaN) - { - return ok(std::make_pair( - -std::numeric_limits::signaling_NaN(), token.unwrap())); - } - else - { - throw std::domain_error("toml::parse_floating: NaN value found" - " but the current environment does not support NaN. Please" - " make sure that the floating-point implementation conforms" - " IEEE 754/ISO 60559 international standard."); - } - } - str.erase(std::remove(str.begin(), str.end(), '_'), str.end()); - std::istringstream iss(str); - floating v(0.0); - iss >> v; - return ok(std::make_pair(v, token.unwrap())); - } - loc.reset(first); - return err(format_underline("toml::parse_floating: ", - {{source_location(loc), "the next token is not a float"}})); -} - -inline std::string read_utf8_codepoint(const region& reg, const location& loc) -{ - const auto str = reg.str().substr(1); - std::uint_least32_t codepoint; - std::istringstream iss(str); - iss >> std::hex >> codepoint; - - const auto to_char = [](const std::uint_least32_t i) noexcept -> char { - const auto uc = static_cast(i); - return *reinterpret_cast(std::addressof(uc)); - }; - - std::string character; - if(codepoint < 0x80) // U+0000 ... U+0079 ; just an ASCII. - { - character += static_cast(codepoint); - } - else if(codepoint < 0x800) //U+0080 ... U+07FF - { - // 110yyyyx 10xxxxxx; 0x3f == 0b0011'1111 - character += to_char(0xC0| codepoint >> 6); - character += to_char(0x80|(codepoint & 0x3F)); - } - else if(codepoint < 0x10000) // U+0800...U+FFFF - { - if(0xD800 <= codepoint && codepoint <= 0xDFFF) - { - throw syntax_error(format_underline( - "toml::read_utf8_codepoint: codepoints in the range " - "[0xD800, 0xDFFF] are not valid UTF-8.", {{ - source_location(loc), "not a valid UTF-8 codepoint" - }}), source_location(loc)); - } - assert(codepoint < 0xD800 || 0xDFFF < codepoint); - // 1110yyyy 10yxxxxx 10xxxxxx - character += to_char(0xE0| codepoint >> 12); - character += to_char(0x80|(codepoint >> 6 & 0x3F)); - character += to_char(0x80|(codepoint & 0x3F)); - } - else if(codepoint < 0x110000) // U+010000 ... U+10FFFF - { - // 11110yyy 10yyxxxx 10xxxxxx 10xxxxxx - character += to_char(0xF0| codepoint >> 18); - character += to_char(0x80|(codepoint >> 12 & 0x3F)); - character += to_char(0x80|(codepoint >> 6 & 0x3F)); - character += to_char(0x80|(codepoint & 0x3F)); - } - else // out of UTF-8 region - { - throw syntax_error(format_underline("toml::read_utf8_codepoint:" - " input codepoint is too large.", - {{source_location(loc), "should be in [0x00..0x10FFFF]"}}), - source_location(loc)); - } - return character; -} - -inline result parse_escape_sequence(location& loc) -{ - const auto first = loc.iter(); - if(first == loc.end() || *first != '\\') - { - return err(format_underline("toml::parse_escape_sequence: ", {{ - source_location(loc), "the next token is not a backslash \"\\\""}})); - } - loc.advance(); - switch(*loc.iter()) - { - case '\\':{loc.advance(); return ok(std::string("\\"));} - case '"' :{loc.advance(); return ok(std::string("\""));} - case 'b' :{loc.advance(); return ok(std::string("\b"));} - case 't' :{loc.advance(); return ok(std::string("\t"));} - case 'n' :{loc.advance(); return ok(std::string("\n"));} - case 'f' :{loc.advance(); return ok(std::string("\f"));} - case 'r' :{loc.advance(); return ok(std::string("\r"));} - case 'u' : - { - if(const auto token = lex_escape_unicode_short::invoke(loc)) - { - return ok(read_utf8_codepoint(token.unwrap(), loc)); - } - else - { - return err(format_underline("parse_escape_sequence: " - "invalid token found in UTF-8 codepoint uXXXX.", - {{source_location(loc), "here"}})); - } - } - case 'U': - { - if(const auto token = lex_escape_unicode_long::invoke(loc)) - { - return ok(read_utf8_codepoint(token.unwrap(), loc)); - } - else - { - return err(format_underline("parse_escape_sequence: " - "invalid token found in UTF-8 codepoint Uxxxxxxxx", - {{source_location(loc), "here"}})); - } - } - } - - const auto msg = format_underline("parse_escape_sequence: " - "unknown escape sequence appeared.", {{source_location(loc), - "escape sequence is one of \\, \", b, t, n, f, r, uxxxx, Uxxxxxxxx"}}, - /* Hints = */{"if you want to write backslash as just one backslash, " - "use literal string like: regex = '<\\i\\c*\\s*>'"}); - loc.reset(first); - return err(msg); -} - -inline std::ptrdiff_t check_utf8_validity(const std::string& reg) -{ - location loc("tmp", reg); - const auto u8 = repeat::invoke(loc); - if(!u8 || loc.iter() != loc.end()) - { - const auto error_location = std::distance(loc.begin(), loc.iter()); - assert(0 <= error_location); - return error_location; - } - return -1; -} - -inline result, std::string> -parse_ml_basic_string(location& loc) -{ - const auto first = loc.iter(); - if(const auto token = lex_ml_basic_string::invoke(loc)) - { - auto inner_loc = loc; - inner_loc.reset(first); - - std::string retval; - retval.reserve(token.unwrap().size()); - - auto delim = lex_ml_basic_string_open::invoke(inner_loc); - if(!delim) - { - throw internal_error(format_underline( - "parse_ml_basic_string: invalid token", - {{source_location(inner_loc), "should be \"\"\""}}), - source_location(inner_loc)); - } - // immediate newline is ignored (if exists) - /* discard return value */ lex_newline::invoke(inner_loc); - - delim = none(); - while(!delim) - { - using lex_unescaped_seq = repeat< - either, unlimited>; - if(auto unescaped = lex_unescaped_seq::invoke(inner_loc)) - { - retval += unescaped.unwrap().str(); - } - if(auto escaped = parse_escape_sequence(inner_loc)) - { - retval += escaped.unwrap(); - } - if(auto esc_nl = lex_ml_basic_escaped_newline::invoke(inner_loc)) - { - // ignore newline after escape until next non-ws char - } - if(inner_loc.iter() == inner_loc.end()) - { - throw internal_error(format_underline( - "parse_ml_basic_string: unexpected end of region", - {{source_location(inner_loc), "not sufficient token"}}), - source_location(inner_loc)); - } - delim = lex_ml_basic_string_close::invoke(inner_loc); - } - // `lex_ml_basic_string_close` allows 3 to 5 `"`s to allow 1 or 2 `"`s - // at just before the delimiter. Here, we need to attach `"`s at the - // end of the string body, if it exists. - // For detail, see the definition of `lex_ml_basic_string_close`. - assert(std::all_of(delim.unwrap().first(), delim.unwrap().last(), - [](const char c) noexcept {return c == '\"';})); - switch(delim.unwrap().size()) - { - case 3: {break;} - case 4: {retval += "\""; break;} - case 5: {retval += "\"\""; break;} - default: - { - throw internal_error(format_underline( - "parse_ml_basic_string: closing delimiter has invalid length", - {{source_location(inner_loc), "end of this"}}), - source_location(inner_loc)); - } - } - - const auto err_loc = check_utf8_validity(token.unwrap().str()); - if(err_loc == -1) - { - return ok(std::make_pair(toml::string(retval), token.unwrap())); - } - else - { - inner_loc.reset(first); - inner_loc.advance(err_loc); - throw syntax_error(format_underline( - "parse_ml_basic_string: invalid utf8 sequence found", - {{source_location(inner_loc), "here"}}), - source_location(inner_loc)); - } - } - else - { - loc.reset(first); - return err(format_underline("toml::parse_ml_basic_string: " - "the next token is not a valid multiline string", - {{source_location(loc), "here"}})); - } -} - -inline result, std::string> -parse_basic_string(location& loc) -{ - const auto first = loc.iter(); - if(const auto token = lex_basic_string::invoke(loc)) - { - auto inner_loc = loc; - inner_loc.reset(first); - - auto quot = lex_quotation_mark::invoke(inner_loc); - if(!quot) - { - throw internal_error(format_underline("parse_basic_string: " - "invalid token", {{source_location(inner_loc), "should be \""}}), - source_location(inner_loc)); - } - - std::string retval; - retval.reserve(token.unwrap().size()); - - quot = none(); - while(!quot) - { - using lex_unescaped_seq = repeat; - if(auto unescaped = lex_unescaped_seq::invoke(inner_loc)) - { - retval += unescaped.unwrap().str(); - } - if(auto escaped = parse_escape_sequence(inner_loc)) - { - retval += escaped.unwrap(); - } - if(inner_loc.iter() == inner_loc.end()) - { - throw internal_error(format_underline( - "parse_basic_string: unexpected end of region", - {{source_location(inner_loc), "not sufficient token"}}), - source_location(inner_loc)); - } - quot = lex_quotation_mark::invoke(inner_loc); - } - - const auto err_loc = check_utf8_validity(token.unwrap().str()); - if(err_loc == -1) - { - return ok(std::make_pair(toml::string(retval), token.unwrap())); - } - else - { - inner_loc.reset(first); - inner_loc.advance(err_loc); - throw syntax_error(format_underline( - "parse_ml_basic_string: invalid utf8 sequence found", - {{source_location(inner_loc), "here"}}), - source_location(inner_loc)); - } - } - else - { - loc.reset(first); // rollback - return err(format_underline("toml::parse_basic_string: " - "the next token is not a valid string", - {{source_location(loc), "here"}})); - } -} - -inline result, std::string> -parse_ml_literal_string(location& loc) -{ - const auto first = loc.iter(); - if(const auto token = lex_ml_literal_string::invoke(loc)) - { - location inner_loc(loc.name(), token.unwrap().str()); - - const auto open = lex_ml_literal_string_open::invoke(inner_loc); - if(!open) - { - throw internal_error(format_underline( - "parse_ml_literal_string: invalid token", - {{source_location(inner_loc), "should be '''"}}), - source_location(inner_loc)); - } - // immediate newline is ignored (if exists) - /* discard return value */ lex_newline::invoke(inner_loc); - - const auto body = lex_ml_literal_body::invoke(inner_loc); - - const auto close = lex_ml_literal_string_close::invoke(inner_loc); - if(!close) - { - throw internal_error(format_underline( - "parse_ml_literal_string: invalid token", - {{source_location(inner_loc), "should be '''"}}), - source_location(inner_loc)); - } - // `lex_ml_literal_string_close` allows 3 to 5 `'`s to allow 1 or 2 `'`s - // at just before the delimiter. Here, we need to attach `'`s at the - // end of the string body, if it exists. - // For detail, see the definition of `lex_ml_basic_string_close`. - - std::string retval = body.unwrap().str(); - assert(std::all_of(close.unwrap().first(), close.unwrap().last(), - [](const char c) noexcept {return c == '\'';})); - switch(close.unwrap().size()) - { - case 3: {break;} - case 4: {retval += "'"; break;} - case 5: {retval += "''"; break;} - default: - { - throw internal_error(format_underline( - "parse_ml_literal_string: closing delimiter has invalid length", - {{source_location(inner_loc), "end of this"}}), - source_location(inner_loc)); - } - } - - const auto err_loc = check_utf8_validity(token.unwrap().str()); - if(err_loc == -1) - { - return ok(std::make_pair(toml::string(retval, toml::string_t::literal), - token.unwrap())); - } - else - { - inner_loc.reset(first); - inner_loc.advance(err_loc); - throw syntax_error(format_underline( - "parse_ml_basic_string: invalid utf8 sequence found", - {{source_location(inner_loc), "here"}}), - source_location(inner_loc)); - } - } - else - { - loc.reset(first); // rollback - return err(format_underline("toml::parse_ml_literal_string: " - "the next token is not a valid multiline literal string", - {{source_location(loc), "here"}})); - } -} - -inline result, std::string> -parse_literal_string(location& loc) -{ - const auto first = loc.iter(); - if(const auto token = lex_literal_string::invoke(loc)) - { - location inner_loc(loc.name(), token.unwrap().str()); - - const auto open = lex_apostrophe::invoke(inner_loc); - if(!open) - { - throw internal_error(format_underline( - "parse_literal_string: invalid token", - {{source_location(inner_loc), "should be '"}}), - source_location(inner_loc)); - } - - const auto body = repeat::invoke(inner_loc); - - const auto close = lex_apostrophe::invoke(inner_loc); - if(!close) - { - throw internal_error(format_underline( - "parse_literal_string: invalid token", - {{source_location(inner_loc), "should be '"}}), - source_location(inner_loc)); - } - - const auto err_loc = check_utf8_validity(token.unwrap().str()); - if(err_loc == -1) - { - return ok(std::make_pair( - toml::string(body.unwrap().str(), toml::string_t::literal), - token.unwrap())); - } - else - { - inner_loc.reset(first); - inner_loc.advance(err_loc); - throw syntax_error(format_underline( - "parse_ml_basic_string: invalid utf8 sequence found", - {{source_location(inner_loc), "here"}}), - source_location(inner_loc)); - } - } - else - { - loc.reset(first); // rollback - return err(format_underline("toml::parse_literal_string: " - "the next token is not a valid literal string", - {{source_location(loc), "here"}})); - } -} - -inline result, std::string> -parse_string(location& loc) -{ - if(loc.iter() != loc.end() && *(loc.iter()) == '"') - { - if(loc.iter() + 1 != loc.end() && *(loc.iter() + 1) == '"' && - loc.iter() + 2 != loc.end() && *(loc.iter() + 2) == '"') - { - return parse_ml_basic_string(loc); - } - else - { - return parse_basic_string(loc); - } - } - else if(loc.iter() != loc.end() && *(loc.iter()) == '\'') - { - if(loc.iter() + 1 != loc.end() && *(loc.iter() + 1) == '\'' && - loc.iter() + 2 != loc.end() && *(loc.iter() + 2) == '\'') - { - return parse_ml_literal_string(loc); - } - else - { - return parse_literal_string(loc); - } - } - return err(format_underline("toml::parse_string: ", - {{source_location(loc), "the next token is not a string"}})); -} - -inline result, std::string> -parse_local_date(location& loc) -{ - const auto first = loc.iter(); - if(const auto token = lex_local_date::invoke(loc)) - { - location inner_loc(loc.name(), token.unwrap().str()); - - const auto y = lex_date_fullyear::invoke(inner_loc); - if(!y || inner_loc.iter() == inner_loc.end() || *inner_loc.iter() != '-') - { - throw internal_error(format_underline( - "toml::parse_inner_local_date: invalid year format", - {{source_location(inner_loc), "should be `-`"}}), - source_location(inner_loc)); - } - inner_loc.advance(); - const auto m = lex_date_month::invoke(inner_loc); - if(!m || inner_loc.iter() == inner_loc.end() || *inner_loc.iter() != '-') - { - throw internal_error(format_underline( - "toml::parse_local_date: invalid month format", - {{source_location(inner_loc), "should be `-`"}}), - source_location(inner_loc)); - } - inner_loc.advance(); - const auto d = lex_date_mday::invoke(inner_loc); - if(!d) - { - throw internal_error(format_underline( - "toml::parse_local_date: invalid day format", - {{source_location(inner_loc), "here"}}), - source_location(inner_loc)); - } - - const auto year = static_cast(from_string(y.unwrap().str(), 0)); - const auto month = static_cast(from_string(m.unwrap().str(), 0)); - const auto day = static_cast(from_string(d.unwrap().str(), 0)); - - // We briefly check whether the input date is valid or not. But here, we - // only check if the RFC3339 compliance. - // Actually there are several special date that does not exist, - // because of historical reasons, such as 1582/10/5-1582/10/14 (only in - // several countries). But here, we do not care about such a complicated - // rule. It makes the code complicated and there is only low probability - // that such a specific date is needed in practice. If someone need to - // validate date accurately, that means that the one need a specialized - // library for their purpose in a different layer. - { - const bool is_leap = (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)); - const auto max_day = (month == 2) ? (is_leap ? 29 : 28) : - ((month == 4 || month == 6 || month == 9 || month == 11) ? 30 : 31); - - if((month < 1 || 12 < month) || (day < 1 || max_day < day)) - { - throw syntax_error(format_underline("toml::parse_date: " - "invalid date: it does not conform RFC3339.", {{ - source_location(loc), "month should be 01-12, day should be" - " 01-28,29,30,31, depending on month/year." - }}), source_location(inner_loc)); - } - } - return ok(std::make_pair(local_date(year, static_cast(month - 1), day), - token.unwrap())); - } - else - { - loc.reset(first); - return err(format_underline("toml::parse_local_date: ", - {{source_location(loc), "the next token is not a local_date"}})); - } -} - -inline result, std::string> -parse_local_time(location& loc) -{ - const auto first = loc.iter(); - if(const auto token = lex_local_time::invoke(loc)) - { - location inner_loc(loc.name(), token.unwrap().str()); - - const auto h = lex_time_hour::invoke(inner_loc); - if(!h || inner_loc.iter() == inner_loc.end() || *inner_loc.iter() != ':') - { - throw internal_error(format_underline( - "toml::parse_local_time: invalid year format", - {{source_location(inner_loc), "should be `:`"}}), - source_location(inner_loc)); - } - inner_loc.advance(); - const auto m = lex_time_minute::invoke(inner_loc); - if(!m || inner_loc.iter() == inner_loc.end() || *inner_loc.iter() != ':') - { - throw internal_error(format_underline( - "toml::parse_local_time: invalid month format", - {{source_location(inner_loc), "should be `:`"}}), - source_location(inner_loc)); - } - inner_loc.advance(); - const auto s = lex_time_second::invoke(inner_loc); - if(!s) - { - throw internal_error(format_underline( - "toml::parse_local_time: invalid second format", - {{source_location(inner_loc), "here"}}), - source_location(inner_loc)); - } - - const int hour = from_string(h.unwrap().str(), 0); - const int minute = from_string(m.unwrap().str(), 0); - const int second = from_string(s.unwrap().str(), 0); - - if((hour < 0 || 23 < hour) || (minute < 0 || 59 < minute) || - (second < 0 || 60 < second)) // it may be leap second - { - throw syntax_error(format_underline("toml::parse_time: " - "invalid time: it does not conform RFC3339.", {{ - source_location(loc), "hour should be 00-23, minute should be" - " 00-59, second should be 00-60 (depending on the leap" - " second rules.)"}}), source_location(inner_loc)); - } - - local_time time(hour, minute, second, 0, 0); - - const auto before_secfrac = inner_loc.iter(); - if(const auto secfrac = lex_time_secfrac::invoke(inner_loc)) - { - auto sf = secfrac.unwrap().str(); - sf.erase(sf.begin()); // sf.front() == '.' - switch(sf.size() % 3) - { - case 2: sf += '0'; break; - case 1: sf += "00"; break; - case 0: break; - default: break; - } - if(sf.size() >= 9) - { - time.millisecond = from_string(sf.substr(0, 3), 0u); - time.microsecond = from_string(sf.substr(3, 3), 0u); - time.nanosecond = from_string(sf.substr(6, 3), 0u); - } - else if(sf.size() >= 6) - { - time.millisecond = from_string(sf.substr(0, 3), 0u); - time.microsecond = from_string(sf.substr(3, 3), 0u); - } - else if(sf.size() >= 3) - { - time.millisecond = from_string(sf, 0u); - time.microsecond = 0u; - } - } - else - { - if(before_secfrac != inner_loc.iter()) - { - throw internal_error(format_underline( - "toml::parse_local_time: invalid subsecond format", - {{source_location(inner_loc), "here"}}), - source_location(inner_loc)); - } - } - return ok(std::make_pair(time, token.unwrap())); - } - else - { - loc.reset(first); - return err(format_underline("toml::parse_local_time: ", - {{source_location(loc), "the next token is not a local_time"}})); - } -} - -inline result, std::string> -parse_local_datetime(location& loc) -{ - const auto first = loc.iter(); - if(const auto token = lex_local_date_time::invoke(loc)) - { - location inner_loc(loc.name(), token.unwrap().str()); - const auto date = parse_local_date(inner_loc); - if(!date || inner_loc.iter() == inner_loc.end()) - { - throw internal_error(format_underline( - "toml::parse_local_datetime: invalid datetime format", - {{source_location(inner_loc), "date, not datetime"}}), - source_location(inner_loc)); - } - const char delim = *(inner_loc.iter()); - if(delim != 'T' && delim != 't' && delim != ' ') - { - throw internal_error(format_underline( - "toml::parse_local_datetime: invalid datetime format", - {{source_location(inner_loc), "should be `T` or ` ` (space)"}}), - source_location(inner_loc)); - } - inner_loc.advance(); - const auto time = parse_local_time(inner_loc); - if(!time) - { - throw internal_error(format_underline( - "toml::parse_local_datetime: invalid datetime format", - {{source_location(inner_loc), "invalid time format"}}), - source_location(inner_loc)); - } - return ok(std::make_pair( - local_datetime(date.unwrap().first, time.unwrap().first), - token.unwrap())); - } - else - { - loc.reset(first); - return err(format_underline("toml::parse_local_datetime: ", - {{source_location(loc), "the next token is not a local_datetime"}})); - } -} - -inline result, std::string> -parse_offset_datetime(location& loc) -{ - const auto first = loc.iter(); - if(const auto token = lex_offset_date_time::invoke(loc)) - { - location inner_loc(loc.name(), token.unwrap().str()); - const auto datetime = parse_local_datetime(inner_loc); - if(!datetime || inner_loc.iter() == inner_loc.end()) - { - throw internal_error(format_underline( - "toml::parse_offset_datetime: invalid datetime format", - {{source_location(inner_loc), "date, not datetime"}}), - source_location(inner_loc)); - } - time_offset offset(0, 0); - if(const auto ofs = lex_time_numoffset::invoke(inner_loc)) - { - const auto str = ofs.unwrap().str(); - - const auto hour = from_string(str.substr(1,2), 0); - const auto minute = from_string(str.substr(4,2), 0); - - if((hour < 0 || 23 < hour) || (minute < 0 || 59 < minute)) - { - throw syntax_error(format_underline("toml::parse_offset_datetime: " - "invalid offset: it does not conform RFC3339.", {{ - source_location(loc), "month should be 01-12, day should be" - " 01-28,29,30,31, depending on month/year." - }}), source_location(inner_loc)); - } - - if(str.front() == '+') - { - offset = time_offset(hour, minute); - } - else - { - offset = time_offset(-hour, -minute); - } - } - else if(*inner_loc.iter() != 'Z' && *inner_loc.iter() != 'z') - { - throw internal_error(format_underline( - "toml::parse_offset_datetime: invalid datetime format", - {{source_location(inner_loc), "should be `Z` or `+HH:MM`"}}), - source_location(inner_loc)); - } - return ok(std::make_pair(offset_datetime(datetime.unwrap().first, offset), - token.unwrap())); - } - else - { - loc.reset(first); - return err(format_underline("toml::parse_offset_datetime: ", - {{source_location(loc), "the next token is not a offset_datetime"}})); - } -} - -inline result, std::string> -parse_simple_key(location& loc) -{ - if(const auto bstr = parse_basic_string(loc)) - { - return ok(std::make_pair(bstr.unwrap().first.str, bstr.unwrap().second)); - } - if(const auto lstr = parse_literal_string(loc)) - { - return ok(std::make_pair(lstr.unwrap().first.str, lstr.unwrap().second)); - } - if(const auto bare = lex_unquoted_key::invoke(loc)) - { - const auto reg = bare.unwrap(); - return ok(std::make_pair(reg.str(), reg)); - } - return err(format_underline("toml::parse_simple_key: ", - {{source_location(loc), "the next token is not a simple key"}})); -} - -// dotted key become vector of keys -inline result, region>, std::string> -parse_key(location& loc) -{ - const auto first = loc.iter(); - // dotted key -> `foo.bar.baz` where several single keys are chained by - // dots. Whitespaces between keys and dots are allowed. - if(const auto token = lex_dotted_key::invoke(loc)) - { - const auto reg = token.unwrap(); - location inner_loc(loc.name(), reg.str()); - std::vector keys; - - while(inner_loc.iter() != inner_loc.end()) - { - lex_ws::invoke(inner_loc); - if(const auto k = parse_simple_key(inner_loc)) - { - keys.push_back(k.unwrap().first); - } - else - { - throw internal_error(format_underline( - "toml::detail::parse_key: dotted key contains invalid key", - {{source_location(inner_loc), k.unwrap_err()}}), - source_location(inner_loc)); - } - - lex_ws::invoke(inner_loc); - if(inner_loc.iter() == inner_loc.end()) - { - break; - } - else if(*inner_loc.iter() == '.') - { - inner_loc.advance(); // to skip `.` - } - else - { - throw internal_error(format_underline("toml::parse_key: " - "dotted key contains invalid key ", - {{source_location(inner_loc), "should be `.`"}}), - source_location(inner_loc)); - } - } - return ok(std::make_pair(keys, reg)); - } - loc.reset(first); - - // simple_key: a single (basic_string|literal_string|bare key) - if(const auto smpl = parse_simple_key(loc)) - { - return ok(std::make_pair(std::vector(1, smpl.unwrap().first), - smpl.unwrap().second)); - } - return err(format_underline("toml::parse_key: an invalid key appeared.", - {{source_location(loc), "is not a valid key"}}, { - "bare keys : non-empty strings composed only of [A-Za-z0-9_-].", - "quoted keys: same as \"basic strings\" or 'literal strings'.", - "dotted keys: sequence of bare or quoted keys joined with a dot." - })); -} - -// forward-decl to implement parse_array and parse_table -template -result parse_value(location&); - -template -result, std::string> -parse_array(location& loc) -{ - using value_type = Value; - using array_type = typename value_type::array_type; - - const auto first = loc.iter(); - if(loc.iter() == loc.end()) - { - return err("toml::parse_array: input is empty"); - } - if(*loc.iter() != '[') - { - return err("toml::parse_array: token is not an array"); - } - loc.advance(); - - using lex_ws_comment_newline = repeat< - either, unlimited>; - - array_type retval; - while(loc.iter() != loc.end()) - { - lex_ws_comment_newline::invoke(loc); // skip - - if(loc.iter() != loc.end() && *loc.iter() == ']') - { - loc.advance(); // skip ']' - return ok(std::make_pair(retval, - region(loc, first, loc.iter()))); - } - - if(auto val = parse_value(loc)) - { - // After TOML v1.0.0-rc.1, array becomes to be able to have values - // with different types. So here we will omit this by default. - // - // But some of the test-suite checks if the parser accepts a hetero- - // geneous arrays, so we keep this for a while. -#ifdef TOML11_DISALLOW_HETEROGENEOUS_ARRAYS - if(!retval.empty() && retval.front().type() != val.as_ok().type()) - { - auto array_start_loc = loc; - array_start_loc.reset(first); - - throw syntax_error(format_underline("toml::parse_array: " - "type of elements should be the same each other.", { - {source_location(array_start_loc), "array starts here"}, - { - retval.front().location(), - "value has type " + stringize(retval.front().type()) - }, - { - val.unwrap().location(), - "value has different type, " + stringize(val.unwrap().type()) - } - }), source_location(loc)); - } -#endif - retval.push_back(std::move(val.unwrap())); - } - else - { - auto array_start_loc = loc; - array_start_loc.reset(first); - - throw syntax_error(format_underline("toml::parse_array: " - "value having invalid format appeared in an array", { - {source_location(array_start_loc), "array starts here"}, - {source_location(loc), "it is not a valid value."} - }), source_location(loc)); - } - - using lex_array_separator = sequence, character<','>>; - const auto sp = lex_array_separator::invoke(loc); - if(!sp) - { - lex_ws_comment_newline::invoke(loc); - if(loc.iter() != loc.end() && *loc.iter() == ']') - { - loc.advance(); // skip ']' - return ok(std::make_pair(retval, - region(loc, first, loc.iter()))); - } - else - { - auto array_start_loc = loc; - array_start_loc.reset(first); - - throw syntax_error(format_underline("toml::parse_array:" - " missing array separator `,` after a value", { - {source_location(array_start_loc), "array starts here"}, - {source_location(loc), "should be `,`"} - }), source_location(loc)); - } - } - } - loc.reset(first); - throw syntax_error(format_underline("toml::parse_array: " - "array did not closed by `]`", - {{source_location(loc), "should be closed"}}), - source_location(loc)); -} - -template -result, region>, Value>, std::string> -parse_key_value_pair(location& loc) -{ - using value_type = Value; - - const auto first = loc.iter(); - auto key_reg = parse_key(loc); - if(!key_reg) - { - std::string msg = std::move(key_reg.unwrap_err()); - // if the next token is keyvalue-separator, it means that there are no - // key. then we need to show error as "empty key is not allowed". - if(const auto keyval_sep = lex_keyval_sep::invoke(loc)) - { - loc.reset(first); - msg = format_underline("toml::parse_key_value_pair: " - "empty key is not allowed.", - {{source_location(loc), "key expected before '='"}}); - } - return err(std::move(msg)); - } - - const auto kvsp = lex_keyval_sep::invoke(loc); - if(!kvsp) - { - std::string msg; - // if the line contains '=' after the invalid sequence, possibly the - // error is in the key (like, invalid character in bare key). - const auto line_end = std::find(loc.iter(), loc.end(), '\n'); - if(std::find(loc.iter(), line_end, '=') != line_end) - { - msg = format_underline("toml::parse_key_value_pair: " - "invalid format for key", - {{source_location(loc), "invalid character in key"}}, - {"Did you forget '.' to separate dotted-key?", - "Allowed characters for bare key are [0-9a-zA-Z_-]."}); - } - else // if not, the error is lack of key-value separator. - { - msg = format_underline("toml::parse_key_value_pair: " - "missing key-value separator `=`", - {{source_location(loc), "should be `=`"}}); - } - loc.reset(first); - return err(std::move(msg)); - } - - const auto after_kvsp = loc.iter(); // err msg - auto val = parse_value(loc); - if(!val) - { - std::string msg; - loc.reset(after_kvsp); - // check there is something not a comment/whitespace after `=` - if(sequence, maybe, lex_newline>::invoke(loc)) - { - loc.reset(after_kvsp); - msg = format_underline("toml::parse_key_value_pair: " - "missing value after key-value separator '='", - {{source_location(loc), "expected value, but got nothing"}}); - } - else // there is something not a comment/whitespace, so invalid format. - { - msg = std::move(val.unwrap_err()); - } - loc.reset(first); - return err(msg); - } - return ok(std::make_pair(std::move(key_reg.unwrap()), - std::move(val.unwrap()))); -} - -// for error messages. -template -std::string format_dotted_keys(InputIterator first, const InputIterator last) -{ - static_assert(std::is_same::value_type>::value,""); - - std::string retval(*first++); - for(; first != last; ++first) - { - retval += '.'; - retval += *first; - } - return retval; -} - -// forward decl for is_valid_forward_table_definition -result, region>, std::string> -parse_table_key(location& loc); -template -result, std::string> -parse_inline_table(location& loc); - -// The following toml file is allowed. -// ```toml -// [a.b.c] # here, table `a` has element `b`. -// foo = "bar" -// [a] # merge a = {baz = "qux"} to a = {b = {...}} -// baz = "qux" -// ``` -// But the following is not allowed. -// ```toml -// [a] -// b.c.foo = "bar" -// [a] # error! the same table [a] defined! -// baz = "qux" -// ``` -// The following is neither allowed. -// ```toml -// a = { b.c.foo = "bar"} -// [a] # error! the same table [a] defined! -// baz = "qux" -// ``` -// Here, it parses region of `tab->at(k)` as a table key and check the depth -// of the key. If the key region points deeper node, it would be allowed. -// Otherwise, the key points the same node. It would be rejected. -template -bool is_valid_forward_table_definition(const Value& fwd, const Value& inserting, - Iterator key_first, Iterator key_curr, Iterator key_last) -{ - // ------------------------------------------------------------------------ - // check type of the value to be inserted/merged - - std::string inserting_reg = ""; - if(const auto ptr = detail::get_region(inserting)) - { - inserting_reg = ptr->str(); - } - location inserting_def("internal", std::move(inserting_reg)); - if(const auto inlinetable = parse_inline_table(inserting_def)) - { - // check if we are overwriting existing table. - // ```toml - // # NG - // a.b = 42 - // a = {d = 3.14} - // ``` - // Inserting an inline table to a existing super-table is not allowed in - // any case. If we found it, we can reject it without further checking. - return false; - } - - // Valid and invalid cases when inserting to the [a.b] table: - // - // ## Invalid - // - // ```toml - // # invalid - // [a] - // b.c.d = "foo" - // [a.b] # a.b is already defined and closed - // d = "bar" - // ``` - // ```toml - // # invalid - // a = {b.c.d = "foo"} - // [a.b] # a is already defined and inline table is closed - // d = "bar" - // ``` - // ```toml - // # invalid - // a.b.c.d = "foo" - // [a.b] # a.b is already defined and dotted-key table is closed - // d = "bar" - // ``` - // - // ## Valid - // - // ```toml - // # OK. a.b is defined, but is *overwritable* - // [a.b.c] - // d = "foo" - // [a.b] - // d = "bar" - // ``` - // ```toml - // # OK. a.b is defined, but is *overwritable* - // [a] - // b.c.d = "foo" - // b.e = "bar" - // ``` - - // ------------------------------------------------------------------------ - // check table defined before - - std::string internal = ""; - if(const auto ptr = detail::get_region(fwd)) - { - internal = ptr->str(); - } - location def("internal", std::move(internal)); - if(const auto tabkeys = parse_table_key(def)) // [table.key] - { - // table keys always contains all the nodes from the root. - const auto& tks = tabkeys.unwrap().first; - if(std::size_t(std::distance(key_first, key_last)) == tks.size() && - std::equal(tks.begin(), tks.end(), key_first)) - { - // the keys are equivalent. it is not allowed. - return false; - } - // the keys are not equivalent. it is allowed. - return true; - } - if(const auto dotkeys = parse_key(def)) // a.b.c = "foo" - { - // consider the following case. - // [a] - // b.c = {d = 42} - // [a.b.c] - // e = 2.71 - // this defines the table [a.b.c] twice. no? - if(const auto reopening_dotkey_by_table = parse_table_key(inserting_def)) - { - // re-opening a dotkey-defined table by a table is invalid. - // only dotkey can append a key-val. Like: - // ```toml - // a.b.c = "foo" - // a.b.d = "bar" # OK. reopen `a.b` by dotkey - // [a.b] - // e = "bar" # Invalid. re-opening `a.b` by [a.b] is not allowed. - // ``` - return false; - } - - // a dotted key starts from the node representing a table in which the - // dotted key belongs to. - const auto& dks = dotkeys.unwrap().first; - if(std::size_t(std::distance(key_curr, key_last)) == dks.size() && - std::equal(dks.begin(), dks.end(), key_curr)) - { - // the keys are equivalent. it is not allowed. - return false; - } - // the keys are not equivalent. it is allowed. - return true; - } - return false; -} - -template -result -insert_nested_key(typename Value::table_type& root, const Value& v, - InputIterator iter, const InputIterator last, - region key_reg, - const bool is_array_of_table = false) -{ - static_assert(std::is_same::value_type>::value,""); - - using value_type = Value; - using table_type = typename value_type::table_type; - using array_type = typename value_type::array_type; - - const auto first = iter; - assert(iter != last); - - table_type* tab = std::addressof(root); - for(; iter != last; ++iter) // search recursively - { - const key& k = *iter; - if(std::next(iter) == last) // k is the last key - { - // XXX if the value is array-of-tables, there can be several - // tables that are in the same array. in that case, we need to - // find the last element and insert it to there. - if(is_array_of_table) - { - if(tab->count(k) == 1) // there is already an array of table - { - if(tab->at(k).is_table()) - { - // show special err msg for conflicting table - throw syntax_error(format_underline(concat_to_string( - "toml::insert_value: array of table (\"", - format_dotted_keys(first, last), - "\") cannot be defined"), { - {tab->at(k).location(), "table already defined"}, - {v.location(), "this conflicts with the previous table"} - }), v.location()); - } - else if(!(tab->at(k).is_array())) - { - throw syntax_error(format_underline(concat_to_string( - "toml::insert_value: array of table (\"", - format_dotted_keys(first, last), "\") collides with" - " existing value"), { - {tab->at(k).location(), - concat_to_string("this ", tab->at(k).type(), - " value already exists")}, - {v.location(), - "while inserting this array-of-tables"} - }), v.location()); - } - // the above if-else-if checks tab->at(k) is an array - auto& a = tab->at(k).as_array(); - // If table element is defined as [[array_of_tables]], it - // cannot be an empty array. If an array of tables is - // defined as `aot = []`, it cannot be appended. - if(a.empty() || !(a.front().is_table())) - { - throw syntax_error(format_underline(concat_to_string( - "toml::insert_value: array of table (\"", - format_dotted_keys(first, last), "\") collides with" - " existing value"), { - {tab->at(k).location(), - concat_to_string("this ", tab->at(k).type(), - " value already exists")}, - {v.location(), - "while inserting this array-of-tables"} - }), v.location()); - } - // avoid conflicting array of table like the following. - // ```toml - // a = [{b = 42}] # define a as an array of *inline* tables - // [[a]] # a is an array of *multi-line* tables - // b = 54 - // ``` - // Here, from the type information, these cannot be detected - // because inline table is also a table. - // But toml v0.5.0 explicitly says it is invalid. The above - // array-of-tables has a static size and appending to the - // array is invalid. - // In this library, multi-line table value has a region - // that points to the key of the table (e.g. [[a]]). By - // comparing the first two letters in key, we can detect - // the array-of-table is inline or multiline. - if(const auto ptr = detail::get_region(a.front())) - { - if(ptr->str().substr(0,2) != "[[") - { - throw syntax_error(format_underline(concat_to_string( - "toml::insert_value: array of table (\"", - format_dotted_keys(first, last), "\") collides " - "with existing array-of-tables"), { - {tab->at(k).location(), - concat_to_string("this ", tab->at(k).type(), - " value has static size")}, - {v.location(), - "appending it to the statically sized array"} - }), v.location()); - } - } - a.push_back(v); - return ok(true); - } - else // if not, we need to create the array of table - { - // XXX: Consider the following array of tables. - // ```toml - // # This is a comment. - // [[aot]] - // foo = "bar" - // ``` - // Here, the comment is for `aot`. But here, actually two - // values are defined. An array that contains tables, named - // `aot`, and the 0th element of the `aot`, `{foo = "bar"}`. - // Those two are different from each other. But both of them - // points to the same portion of the TOML file, `[[aot]]`, - // so `key_reg.comments()` returns `# This is a comment`. - // If it is assigned as a comment of `aot` defined here, the - // comment will be duplicated. Both the `aot` itself and - // the 0-th element will have the same comment. This causes - // "duplication of the same comments" bug when the data is - // serialized. - // Next, consider the following. - // ```toml - // # comment 1 - // aot = [ - // # comment 2 - // {foo = "bar"}, - // ] - // ``` - // In this case, we can distinguish those two comments. So - // here we need to add "comment 1" to the `aot` and - // "comment 2" to the 0th element of that. - // To distinguish those two, we check the key region. - std::vector comments{/* empty by default */}; - if(key_reg.str().substr(0, 2) != "[[") - { - comments = key_reg.comments(); - } - value_type aot(array_type(1, v), key_reg, std::move(comments)); - tab->insert(std::make_pair(k, aot)); - return ok(true); - } - } // end if(array of table) - - if(tab->count(k) == 1) - { - if(tab->at(k).is_table() && v.is_table()) - { - if(!is_valid_forward_table_definition( - tab->at(k), v, first, iter, last)) - { - throw syntax_error(format_underline(concat_to_string( - "toml::insert_value: table (\"", - format_dotted_keys(first, last), - "\") already exists."), { - {tab->at(k).location(), "table already exists here"}, - {v.location(), "table defined twice"} - }), v.location()); - } - // to allow the following toml file. - // [a.b.c] - // d = 42 - // [a] - // e = 2.71 - auto& t = tab->at(k).as_table(); - for(const auto& kv : v.as_table()) - { - if(tab->at(k).contains(kv.first)) - { - throw syntax_error(format_underline(concat_to_string( - "toml::insert_value: value (\"", - format_dotted_keys(first, last), - "\") already exists."), { - {t.at(kv.first).location(), "already exists here"}, - {v.location(), "this defined twice"} - }), v.location()); - } - t[kv.first] = kv.second; - } - detail::change_region(tab->at(k), key_reg); - return ok(true); - } - else if(v.is_table() && - tab->at(k).is_array() && - tab->at(k).as_array().size() > 0 && - tab->at(k).as_array().front().is_table()) - { - throw syntax_error(format_underline(concat_to_string( - "toml::insert_value: array of tables (\"", - format_dotted_keys(first, last), "\") already exists."), { - {tab->at(k).location(), "array of tables defined here"}, - {v.location(), "table conflicts with the previous array of table"} - }), v.location()); - } - else - { - throw syntax_error(format_underline(concat_to_string( - "toml::insert_value: value (\"", - format_dotted_keys(first, last), "\") already exists."), { - {tab->at(k).location(), "value already exists here"}, - {v.location(), "value defined twice"} - }), v.location()); - } - } - tab->insert(std::make_pair(k, v)); - return ok(true); - } - else // k is not the last one, we should insert recursively - { - // if there is no corresponding value, insert it first. - // related: you don't need to write - // # [x] - // # [x.y] - // to write - // [x.y.z] - if(tab->count(k) == 0) - { - // a table that is defined implicitly doesn't have any comments. - (*tab)[k] = value_type(table_type{}, key_reg, {/*no comment*/}); - } - - // type checking... - if(tab->at(k).is_table()) - { - // According to toml-lang/toml:36d3091b3 "Clarify that inline - // tables are immutable", check if it adds key-value pair to an - // inline table. - if(const auto* ptr = get_region(tab->at(k))) - { - // here, if the value is a (multi-line) table, the region - // should be something like `[table-name]`. - if(ptr->front() == '{') - { - throw syntax_error(format_underline(concat_to_string( - "toml::insert_value: inserting to an inline table (", - format_dotted_keys(first, std::next(iter)), - ") but inline tables are immutable"), { - {tab->at(k).location(), "inline tables are immutable"}, - {v.location(), "inserting this"} - }), v.location()); - } - } - tab = std::addressof((*tab)[k].as_table()); - } - else if(tab->at(k).is_array()) // inserting to array-of-tables? - { - auto& a = (*tab)[k].as_array(); - if(!a.back().is_table()) - { - throw syntax_error(format_underline(concat_to_string( - "toml::insert_value: target (", - format_dotted_keys(first, std::next(iter)), - ") is neither table nor an array of tables"), { - {a.back().location(), concat_to_string( - "actual type is ", a.back().type())}, - {v.location(), "inserting this"} - }), v.location()); - } - tab = std::addressof(a.back().as_table()); - } - else - { - throw syntax_error(format_underline(concat_to_string( - "toml::insert_value: target (", - format_dotted_keys(first, std::next(iter)), - ") is neither table nor an array of tables"), { - {tab->at(k).location(), concat_to_string( - "actual type is ", tab->at(k).type())}, - {v.location(), "inserting this"} - }), v.location()); - } - } - } - return err(std::string("toml::detail::insert_nested_key: never reach here")); -} - -template -result, std::string> -parse_inline_table(location& loc) -{ - using value_type = Value; - using table_type = typename value_type::table_type; - - const auto first = loc.iter(); - table_type retval; - if(!(loc.iter() != loc.end() && *loc.iter() == '{')) - { - return err(format_underline("toml::parse_inline_table: ", - {{source_location(loc), "the next token is not an inline table"}})); - } - loc.advance(); - - // check if the inline table is an empty table = { } - maybe::invoke(loc); - if(loc.iter() != loc.end() && *loc.iter() == '}') - { - loc.advance(); // skip `}` - return ok(std::make_pair(retval, region(loc, first, loc.iter()))); - } - - // it starts from "{". it should be formatted as inline-table - while(loc.iter() != loc.end()) - { - const auto kv_r = parse_key_value_pair(loc); - if(!kv_r) - { - return err(kv_r.unwrap_err()); - } - - const auto& kvpair = kv_r.unwrap(); - const std::vector& keys = kvpair.first.first; - const auto& key_reg = kvpair.first.second; - const value_type& val = kvpair.second; - - const auto inserted = - insert_nested_key(retval, val, keys.begin(), keys.end(), key_reg); - if(!inserted) - { - throw internal_error("toml::parse_inline_table: " - "failed to insert value into table: " + inserted.unwrap_err(), - source_location(loc)); - } - - using lex_table_separator = sequence, character<','>>; - const auto sp = lex_table_separator::invoke(loc); - - if(!sp) - { - maybe::invoke(loc); - - if(loc.iter() == loc.end()) - { - throw syntax_error(format_underline( - "toml::parse_inline_table: missing table separator `}` ", - {{source_location(loc), "should be `}`"}}), - source_location(loc)); - } - else if(*loc.iter() == '}') - { - loc.advance(); // skip `}` - return ok(std::make_pair( - retval, region(loc, first, loc.iter()))); - } - else if(*loc.iter() == '#' || *loc.iter() == '\r' || *loc.iter() == '\n') - { - throw syntax_error(format_underline( - "toml::parse_inline_table: missing curly brace `}`", - {{source_location(loc), "should be `}`"}}), - source_location(loc)); - } - else - { - throw syntax_error(format_underline( - "toml::parse_inline_table: missing table separator `,` ", - {{source_location(loc), "should be `,`"}}), - source_location(loc)); - } - } - else // `,` is found - { - maybe::invoke(loc); - if(loc.iter() != loc.end() && *loc.iter() == '}') - { - throw syntax_error(format_underline( - "toml::parse_inline_table: trailing comma is not allowed in" - " an inline table", - {{source_location(loc), "should be `}`"}}), - source_location(loc)); - } - } - } - loc.reset(first); - throw syntax_error(format_underline("toml::parse_inline_table: " - "inline table did not closed by `}`", - {{source_location(loc), "should be closed"}}), - source_location(loc)); -} - -inline result guess_number_type(const location& l) -{ - // This function tries to find some (common) mistakes by checking characters - // that follows the last character of a value. But it is often difficult - // because some non-newline characters can appear after a value. E.g. - // spaces, tabs, commas (in an array or inline table), closing brackets - // (of an array or inline table), comment-sign (#). Since this function - // does not parse further, those characters are always allowed to be there. - location loc = l; - - if(lex_offset_date_time::invoke(loc)) {return ok(value_t::offset_datetime);} - loc.reset(l.iter()); - - if(lex_local_date_time::invoke(loc)) - { - // bad offset may appear after this. - if(loc.iter() != loc.end() && (*loc.iter() == '+' || *loc.iter() == '-' - || *loc.iter() == 'Z' || *loc.iter() == 'z')) - { - return err(format_underline("bad offset: should be [+-]HH:MM or Z", - {{source_location(loc), "[+-]HH:MM or Z"}}, - {"pass: +09:00, -05:30", "fail: +9:00, -5:30"})); - } - return ok(value_t::local_datetime); - } - loc.reset(l.iter()); - - if(lex_local_date::invoke(loc)) - { - // bad time may appear after this. - // A space is allowed as a delimiter between local time. But there are - // both cases in which a space becomes valid or invalid. - // - invalid: 2019-06-16 7:00:00 - // - valid : 2019-06-16 07:00:00 - if(loc.iter() != loc.end()) - { - const auto c = *loc.iter(); - if(c == 'T' || c == 't') - { - return err(format_underline("bad time: should be HH:MM:SS.subsec", - {{source_location(loc), "HH:MM:SS.subsec"}}, - {"pass: 1979-05-27T07:32:00, 1979-05-27 07:32:00.999999", - "fail: 1979-05-27T7:32:00, 1979-05-27 17:32"})); - } - if('0' <= c && c <= '9') - { - return err(format_underline("bad time: missing T", - {{source_location(loc), "T or space required here"}}, - {"pass: 1979-05-27T07:32:00, 1979-05-27 07:32:00.999999", - "fail: 1979-05-27T7:32:00, 1979-05-27 7:32"})); - } - if(c == ' ' && std::next(loc.iter()) != loc.end() && - ('0' <= *std::next(loc.iter()) && *std::next(loc.iter())<= '9')) - { - loc.advance(); - return err(format_underline("bad time: should be HH:MM:SS.subsec", - {{source_location(loc), "HH:MM:SS.subsec"}}, - {"pass: 1979-05-27T07:32:00, 1979-05-27 07:32:00.999999", - "fail: 1979-05-27T7:32:00, 1979-05-27 7:32"})); - } - } - return ok(value_t::local_date); - } - loc.reset(l.iter()); - - if(lex_local_time::invoke(loc)) {return ok(value_t::local_time);} - loc.reset(l.iter()); - - if(lex_float::invoke(loc)) - { - if(loc.iter() != loc.end() && *loc.iter() == '_') - { - return err(format_underline("bad float: `_` should be surrounded by digits", - {{source_location(loc), "here"}}, - {"pass: +1.0, -2e-2, 3.141_592_653_589, inf, nan", - "fail: .0, 1., _1.0, 1.0_, 1_.0, 1.0__0"})); - } - return ok(value_t::floating); - } - loc.reset(l.iter()); - - if(lex_integer::invoke(loc)) - { - if(loc.iter() != loc.end()) - { - const auto c = *loc.iter(); - if(c == '_') - { - return err(format_underline("bad integer: `_` should be surrounded by digits", - {{source_location(loc), "here"}}, - {"pass: -42, 1_000, 1_2_3_4_5, 0xC0FFEE, 0b0010, 0o755", - "fail: 1__000, 0123"})); - } - if('0' <= c && c <= '9') - { - // leading zero. point '0' - loc.retrace(); - return err(format_underline("bad integer: leading zero", - {{source_location(loc), "here"}}, - {"pass: -42, 1_000, 1_2_3_4_5, 0xC0FFEE, 0b0010, 0o755", - "fail: 1__000, 0123"})); - } - if(c == ':' || c == '-') - { - return err(format_underline("bad datetime: invalid format", - {{source_location(loc), "here"}}, - {"pass: 1979-05-27T07:32:00-07:00, 1979-05-27 07:32:00.999999Z", - "fail: 1979-05-27T7:32:00-7:00, 1979-05-27 7:32-00:30"})); - } - if(c == '.' || c == 'e' || c == 'E') - { - return err(format_underline("bad float: invalid format", - {{source_location(loc), "here"}}, - {"pass: +1.0, -2e-2, 3.141_592_653_589, inf, nan", - "fail: .0, 1., _1.0, 1.0_, 1_.0, 1.0__0"})); - } - } - return ok(value_t::integer); - } - if(loc.iter() != loc.end() && *loc.iter() == '.') - { - return err(format_underline("bad float: invalid format", - {{source_location(loc), "integer part required before this"}}, - {"pass: +1.0, -2e-2, 3.141_592_653_589, inf, nan", - "fail: .0, 1., _1.0, 1.0_, 1_.0, 1.0__0"})); - } - if(loc.iter() != loc.end() && *loc.iter() == '_') - { - return err(format_underline("bad number: `_` should be surrounded by digits", - {{source_location(loc), "`_` is not surrounded by digits"}}, - {"pass: -42, 1_000, 1_2_3_4_5, 0xC0FFEE, 0b0010, 0o755", - "fail: 1__000, 0123"})); - } - return err(format_underline("bad format: unknown value appeared", - {{source_location(loc), "here"}})); -} - -inline result guess_value_type(const location& loc) -{ - switch(*loc.iter()) - { - case '"' : {return ok(value_t::string); } - case '\'': {return ok(value_t::string); } - case 't' : {return ok(value_t::boolean); } - case 'f' : {return ok(value_t::boolean); } - case '[' : {return ok(value_t::array); } - case '{' : {return ok(value_t::table); } - case 'i' : {return ok(value_t::floating);} // inf. - case 'n' : {return ok(value_t::floating);} // nan. - default : {return guess_number_type(loc);} - } -} - -template -result -parse_value_helper(result, std::string> rslt) -{ - if(rslt.is_ok()) - { - auto comments = rslt.as_ok().second.comments(); - return ok(Value(std::move(rslt.as_ok()), std::move(comments))); - } - else - { - return err(std::move(rslt.as_err())); - } -} - -template -result parse_value(location& loc) -{ - const auto first = loc.iter(); - if(first == loc.end()) - { - return err(format_underline("toml::parse_value: input is empty", - {{source_location(loc), ""}})); - } - - const auto type = guess_value_type(loc); - if(!type) - { - return err(type.unwrap_err()); - } - - switch(type.unwrap()) - { - case value_t::boolean : {return parse_value_helper(parse_boolean(loc) );} - case value_t::integer : {return parse_value_helper(parse_integer(loc) );} - case value_t::floating : {return parse_value_helper(parse_floating(loc) );} - case value_t::string : {return parse_value_helper(parse_string(loc) );} - case value_t::offset_datetime: {return parse_value_helper(parse_offset_datetime(loc) );} - case value_t::local_datetime : {return parse_value_helper(parse_local_datetime(loc) );} - case value_t::local_date : {return parse_value_helper(parse_local_date(loc) );} - case value_t::local_time : {return parse_value_helper(parse_local_time(loc) );} - case value_t::array : {return parse_value_helper(parse_array(loc) );} - case value_t::table : {return parse_value_helper(parse_inline_table(loc));} - default: - { - const auto msg = format_underline("toml::parse_value: " - "unknown token appeared", {{source_location(loc), "unknown"}}); - loc.reset(first); - return err(msg); - } - } -} - -inline result, region>, std::string> -parse_table_key(location& loc) -{ - if(auto token = lex_std_table::invoke(loc)) - { - location inner_loc(loc.name(), token.unwrap().str()); - - const auto open = lex_std_table_open::invoke(inner_loc); - if(!open || inner_loc.iter() == inner_loc.end()) - { - throw internal_error(format_underline( - "toml::parse_table_key: no `[`", - {{source_location(inner_loc), "should be `[`"}}), - source_location(inner_loc)); - } - // to skip [ a . b . c ] - // ^----------- this whitespace - lex_ws::invoke(inner_loc); - const auto keys = parse_key(inner_loc); - if(!keys) - { - throw internal_error(format_underline( - "toml::parse_table_key: invalid key", - {{source_location(inner_loc), "not key"}}), - source_location(inner_loc)); - } - // to skip [ a . b . c ] - // ^-- this whitespace - lex_ws::invoke(inner_loc); - const auto close = lex_std_table_close::invoke(inner_loc); - if(!close) - { - throw internal_error(format_underline( - "toml::parse_table_key: no `]`", - {{source_location(inner_loc), "should be `]`"}}), - source_location(inner_loc)); - } - - // after [table.key], newline or EOF(empty table) required. - if(loc.iter() != loc.end()) - { - using lex_newline_after_table_key = - sequence, maybe, lex_newline>; - const auto nl = lex_newline_after_table_key::invoke(loc); - if(!nl) - { - throw syntax_error(format_underline( - "toml::parse_table_key: newline required after [table.key]", - {{source_location(loc), "expected newline"}}), - source_location(loc)); - } - } - return ok(std::make_pair(keys.unwrap().first, token.unwrap())); - } - else - { - return err(format_underline("toml::parse_table_key: " - "not a valid table key", {{source_location(loc), "here"}})); - } -} - -inline result, region>, std::string> -parse_array_table_key(location& loc) -{ - if(auto token = lex_array_table::invoke(loc)) - { - location inner_loc(loc.name(), token.unwrap().str()); - - const auto open = lex_array_table_open::invoke(inner_loc); - if(!open || inner_loc.iter() == inner_loc.end()) - { - throw internal_error(format_underline( - "toml::parse_array_table_key: no `[[`", - {{source_location(inner_loc), "should be `[[`"}}), - source_location(inner_loc)); - } - lex_ws::invoke(inner_loc); - const auto keys = parse_key(inner_loc); - if(!keys) - { - throw internal_error(format_underline( - "toml::parse_array_table_key: invalid key", - {{source_location(inner_loc), "not a key"}}), - source_location(inner_loc)); - } - lex_ws::invoke(inner_loc); - const auto close = lex_array_table_close::invoke(inner_loc); - if(!close) - { - throw internal_error(format_underline( - "toml::parse_table_key: no `]]`", - {{source_location(inner_loc), "should be `]]`"}}), - source_location(inner_loc)); - } - - // after [[table.key]], newline or EOF(empty table) required. - if(loc.iter() != loc.end()) - { - using lex_newline_after_table_key = - sequence, maybe, lex_newline>; - const auto nl = lex_newline_after_table_key::invoke(loc); - if(!nl) - { - throw syntax_error(format_underline("toml::" - "parse_array_table_key: newline required after [[table.key]]", - {{source_location(loc), "expected newline"}}), - source_location(loc)); - } - } - return ok(std::make_pair(keys.unwrap().first, token.unwrap())); - } - else - { - return err(format_underline("toml::parse_array_table_key: " - "not a valid table key", {{source_location(loc), "here"}})); - } -} - -// parse table body (key-value pairs until the iter hits the next [tablekey]) -template -result -parse_ml_table(location& loc) -{ - using value_type = Value; - using table_type = typename value_type::table_type; - - const auto first = loc.iter(); - if(first == loc.end()) - { - return ok(table_type{}); - } - - // XXX at lest one newline is needed. - using skip_line = repeat< - sequence, maybe, lex_newline>, at_least<1>>; - skip_line::invoke(loc); - lex_ws::invoke(loc); - - table_type tab; - while(loc.iter() != loc.end()) - { - lex_ws::invoke(loc); - const auto before = loc.iter(); - if(const auto tmp = parse_array_table_key(loc)) // next table found - { - loc.reset(before); - return ok(tab); - } - if(const auto tmp = parse_table_key(loc)) // next table found - { - loc.reset(before); - return ok(tab); - } - - if(const auto kv = parse_key_value_pair(loc)) - { - const auto& kvpair = kv.unwrap(); - const std::vector& keys = kvpair.first.first; - const auto& key_reg = kvpair.first.second; - const value_type& val = kvpair.second; - const auto inserted = - insert_nested_key(tab, val, keys.begin(), keys.end(), key_reg); - if(!inserted) - { - return err(inserted.unwrap_err()); - } - } - else - { - return err(kv.unwrap_err()); - } - - // comment lines are skipped by the above function call. - // However, since the `skip_line` requires at least 1 newline, it fails - // if the file ends with ws and/or comment without newline. - // `skip_line` matches `ws? + comment? + newline`, not `ws` or `comment` - // itself. To skip the last ws and/or comment, call lexers. - // It does not matter if these fails, so the return value is discarded. - lex_ws::invoke(loc); - lex_comment::invoke(loc); - - // skip_line is (whitespace? comment? newline)_{1,}. multiple empty lines - // and comments after the last key-value pairs are allowed. - const auto newline = skip_line::invoke(loc); - if(!newline && loc.iter() != loc.end()) - { - const auto before2 = loc.iter(); - lex_ws::invoke(loc); // skip whitespace - const auto msg = format_underline("toml::parse_table: " - "invalid line format", {{source_location(loc), concat_to_string( - "expected newline, but got '", show_char(*loc.iter()), "'.")}}); - loc.reset(before2); - return err(msg); - } - - // the skip_lines only matches with lines that includes newline. - // to skip the last line that includes comment and/or whitespace - // but no newline, call them one more time. - lex_ws::invoke(loc); - lex_comment::invoke(loc); - } - return ok(tab); -} - -template -result parse_toml_file(location& loc) -{ - using value_type = Value; - using table_type = typename value_type::table_type; - - const auto first = loc.iter(); - if(first == loc.end()) - { - // For empty files, return an empty table with an empty region (zero-length). - // Without the region, error messages would miss the filename. - return ok(value_type(table_type{}, region(loc, first, first), {})); - } - - // put the first line as a region of a file - // Here first != loc.end(), so taking std::next is okay - const region file(loc, first, std::next(loc.iter())); - - // The first successive comments that are separated from the first value - // by an empty line are for a file itself. - // ```toml - // # this is a comment for a file. - // - // key = "the first value" - // ``` - // ```toml - // # this is a comment for "the first value". - // key = "the first value" - // ``` - std::vector comments; - using lex_first_comments = sequence< - repeat, lex_comment, lex_newline>, at_least<1>>, - sequence, lex_newline> - >; - if(const auto token = lex_first_comments::invoke(loc)) - { - location inner_loc(loc.name(), token.unwrap().str()); - while(inner_loc.iter() != inner_loc.end()) - { - maybe::invoke(inner_loc); // remove ws if exists - if(lex_newline::invoke(inner_loc)) - { - assert(inner_loc.iter() == inner_loc.end()); - break; // empty line found. - } - auto com = lex_comment::invoke(inner_loc).unwrap().str(); - com.erase(com.begin()); // remove # sign - comments.push_back(std::move(com)); - lex_newline::invoke(inner_loc); - } - } - - table_type data; - // root object is also a table, but without [tablename] - if(const auto tab = parse_ml_table(loc)) - { - data = std::move(tab.unwrap()); - } - else // failed (empty table is regarded as success in parse_ml_table) - { - return err(tab.unwrap_err()); - } - while(loc.iter() != loc.end()) - { - // here, the region of [table] is regarded as the table-key because - // the table body is normally too big and it is not so informative - // if the first key-value pair of the table is shown in the error - // message. - if(const auto tabkey = parse_array_table_key(loc)) - { - const auto tab = parse_ml_table(loc); - if(!tab){return err(tab.unwrap_err());} - - const auto& tk = tabkey.unwrap(); - const auto& keys = tk.first; - const auto& reg = tk.second; - - const auto inserted = insert_nested_key(data, - value_type(tab.unwrap(), reg, reg.comments()), - keys.begin(), keys.end(), reg, - /*is_array_of_table=*/ true); - if(!inserted) {return err(inserted.unwrap_err());} - - continue; - } - if(const auto tabkey = parse_table_key(loc)) - { - const auto tab = parse_ml_table(loc); - if(!tab){return err(tab.unwrap_err());} - - const auto& tk = tabkey.unwrap(); - const auto& keys = tk.first; - const auto& reg = tk.second; - - const auto inserted = insert_nested_key(data, - value_type(tab.unwrap(), reg, reg.comments()), - keys.begin(), keys.end(), reg); - if(!inserted) {return err(inserted.unwrap_err());} - - continue; - } - return err(format_underline("toml::parse_toml_file: " - "unknown line appeared", {{source_location(loc), "unknown format"}})); - } - - return ok(Value(std::move(data), file, comments)); -} - -} // detail - -template class Table = std::unordered_map, - template class Array = std::vector> -basic_value -parse(std::istream& is, const std::string& fname = "unknown file") -{ - using value_type = basic_value; - - const auto beg = is.tellg(); - is.seekg(0, std::ios::end); - const auto end = is.tellg(); - const auto fsize = end - beg; - is.seekg(beg); - - // read whole file as a sequence of char - assert(fsize >= 0); - std::vector letters(static_cast(fsize)); - is.read(letters.data(), fsize); - - // append LF. - // Although TOML does not require LF at the EOF, to make parsing logic - // simpler, we "normalize" the content by adding LF if it does not exist. - // It also checks if the last char is CR, to avoid changing the meaning. - // This is not the *best* way to deal with the last character, but is a - // simple and quick fix. - if(!letters.empty() && letters.back() != '\n' && letters.back() != '\r') - { - letters.push_back('\n'); - } - - detail::location loc(std::move(fname), std::move(letters)); - - // skip BOM if exists. - // XXX component of BOM (like 0xEF) exceeds the representable range of - // signed char, so on some (actually, most) of the environment, these cannot - // be compared to char. However, since we are always out of luck, we need to - // check our chars are equivalent to BOM. To do this, first we need to - // convert char to unsigned char to guarantee the comparability. - if(loc.source()->size() >= 3) - { - std::array BOM; - std::memcpy(BOM.data(), loc.source()->data(), 3); - if(BOM[0] == 0xEF && BOM[1] == 0xBB && BOM[2] == 0xBF) - { - loc.advance(3); // BOM found. skip. - } - } - - const auto data = detail::parse_toml_file(loc); - if(!data) - { - throw syntax_error(data.unwrap_err(), source_location(loc)); - } - return data.unwrap(); -} - -template class Table = std::unordered_map, - template class Array = std::vector> -basic_value parse(const std::string& fname) -{ - std::ifstream ifs(fname.c_str(), std::ios_base::binary); - if(!ifs.good()) - { - throw std::runtime_error("toml::parse: file open error -> " + fname); - } - return parse(ifs, fname); -} - -#ifdef TOML11_HAS_STD_FILESYSTEM -// This function just forwards `parse("filename.toml")` to std::string version -// to avoid the ambiguity in overload resolution. -// -// Both std::string and std::filesystem::path are convertible from const char*. -// Without this, both parse(std::string) and parse(std::filesystem::path) -// matches to parse("filename.toml"). This breaks the existing code. -// -// This function exactly matches to the invocation with c-string. -// So this function is preferred than others and the ambiguity disappears. -template class Table = std::unordered_map, - template class Array = std::vector> -basic_value parse(const char* fname) -{ - return parse(std::string(fname)); -} - -template class Table = std::unordered_map, - template class Array = std::vector> -basic_value parse(const std::filesystem::path& fpath) -{ - std::ifstream ifs(fpath, std::ios_base::binary); - if(!ifs.good()) - { - throw std::runtime_error("toml::parse: file open error -> " + - fpath.string()); - } - return parse(ifs, fpath.string()); -} -#endif // TOML11_HAS_STD_FILESYSTEM - -} // toml -#endif// TOML11_PARSER_HPP diff --git a/lib/toml/toml/region.hpp b/lib/toml/toml/region.hpp deleted file mode 100644 index 2e01e51..0000000 --- a/lib/toml/toml/region.hpp +++ /dev/null @@ -1,417 +0,0 @@ -// Copyright Toru Niina 2017. -// Distributed under the MIT License. -#ifndef TOML11_REGION_HPP -#define TOML11_REGION_HPP -#include -#include -#include -#include -#include -#include -#include -#include "color.hpp" - -namespace toml -{ -namespace detail -{ - -// helper function to avoid std::string(0, 'c') or std::string(iter, iter) -template -std::string make_string(Iterator first, Iterator last) -{ - if(first == last) {return "";} - return std::string(first, last); -} -inline std::string make_string(std::size_t len, char c) -{ - if(len == 0) {return "";} - return std::string(len, c); -} - -// region_base is a base class of location and region that are defined below. -// it will be used to generate better error messages. -struct region_base -{ - region_base() = default; - virtual ~region_base() = default; - region_base(const region_base&) = default; - region_base(region_base&& ) = default; - region_base& operator=(const region_base&) = default; - region_base& operator=(region_base&& ) = default; - - virtual bool is_ok() const noexcept {return false;} - virtual char front() const noexcept {return '\0';} - - virtual std::string str() const {return std::string("unknown region");} - virtual std::string name() const {return std::string("unknown file");} - virtual std::string line() const {return std::string("unknown line");} - virtual std::string line_num() const {return std::string("?");} - - // length of the region - virtual std::size_t size() const noexcept {return 0;} - // number of characters in the line before the region - virtual std::size_t before() const noexcept {return 0;} - // number of characters in the line after the region - virtual std::size_t after() const noexcept {return 0;} - - virtual std::vector comments() const {return {};} - // ```toml - // # comment_before - // key = "value" # comment_inline - // ``` -}; - -// location represents a position in a container, which contains a file content. -// it can be considered as a region that contains only one character. -// -// it contains pointer to the file content and iterator that points the current -// location. -struct location final : public region_base -{ - using const_iterator = typename std::vector::const_iterator; - using difference_type = typename const_iterator::difference_type; - using source_ptr = std::shared_ptr>; - - location(std::string source_name, std::vector cont) - : source_(std::make_shared>(std::move(cont))), - line_number_(1), source_name_(std::move(source_name)), iter_(source_->cbegin()) - {} - location(std::string source_name, const std::string& cont) - : source_(std::make_shared>(cont.begin(), cont.end())), - line_number_(1), source_name_(std::move(source_name)), iter_(source_->cbegin()) - {} - - location(const location&) = default; - location(location&&) = default; - location& operator=(const location&) = default; - location& operator=(location&&) = default; - ~location() = default; - - bool is_ok() const noexcept override {return static_cast(source_);} - char front() const noexcept override {return *iter_;} - - // this const prohibits codes like `++(loc.iter())`. - const const_iterator iter() const noexcept {return iter_;} - - const_iterator begin() const noexcept {return source_->cbegin();} - const_iterator end() const noexcept {return source_->cend();} - - // XXX `location::line_num()` used to be implemented using `std::count` to - // count a number of '\n'. But with a long toml file (typically, 10k lines), - // it becomes intolerably slow because each time it generates error messages, - // it counts '\n' from thousands of characters. To workaround it, I decided - // to introduce `location::line_number_` member variable and synchronize it - // to the location changes the point to look. So an overload of `iter()` - // which returns mutable reference is removed and `advance()`, `retrace()` - // and `reset()` is added. - void advance(difference_type n = 1) noexcept - { - this->line_number_ += static_cast( - std::count(this->iter_, std::next(this->iter_, n), '\n')); - this->iter_ += n; - return; - } - void retrace(difference_type n = 1) noexcept - { - this->line_number_ -= static_cast( - std::count(std::prev(this->iter_, n), this->iter_, '\n')); - this->iter_ -= n; - return; - } - void reset(const_iterator rollback) noexcept - { - // since c++11, std::distance works in both ways for random-access - // iterators and returns a negative value if `first > last`. - if(0 <= std::distance(rollback, this->iter_)) // rollback < iter - { - this->line_number_ -= static_cast( - std::count(rollback, this->iter_, '\n')); - } - else // iter < rollback [[unlikely]] - { - this->line_number_ += static_cast( - std::count(this->iter_, rollback, '\n')); - } - this->iter_ = rollback; - return; - } - - std::string str() const override {return make_string(1, *this->iter());} - std::string name() const override {return source_name_;} - - std::string line_num() const override - { - return std::to_string(this->line_number_); - } - - std::string line() const override - { - return make_string(this->line_begin(), this->line_end()); - } - - const_iterator line_begin() const noexcept - { - using reverse_iterator = std::reverse_iterator; - return std::find(reverse_iterator(this->iter()), - reverse_iterator(this->begin()), '\n').base(); - } - const_iterator line_end() const noexcept - { - return std::find(this->iter(), this->end(), '\n'); - } - - // location is always points a character. so the size is 1. - std::size_t size() const noexcept override - { - return 1u; - } - std::size_t before() const noexcept override - { - const auto sz = std::distance(this->line_begin(), this->iter()); - assert(sz >= 0); - return static_cast(sz); - } - std::size_t after() const noexcept override - { - const auto sz = std::distance(this->iter(), this->line_end()); - assert(sz >= 0); - return static_cast(sz); - } - - source_ptr const& source() const& noexcept {return source_;} - source_ptr&& source() && noexcept {return std::move(source_);} - - private: - - source_ptr source_; - std::size_t line_number_; - std::string source_name_; - const_iterator iter_; -}; - -// region represents a range in a container, which contains a file content. -// -// it contains pointer to the file content and iterator that points the first -// and last location. -struct region final : public region_base -{ - using const_iterator = typename std::vector::const_iterator; - using source_ptr = std::shared_ptr>; - - // delete default constructor. source_ never be null. - region() = delete; - - explicit region(const location& loc) - : source_(loc.source()), source_name_(loc.name()), - first_(loc.iter()), last_(loc.iter()) - {} - explicit region(location&& loc) - : source_(loc.source()), source_name_(loc.name()), - first_(loc.iter()), last_(loc.iter()) - {} - - region(const location& loc, const_iterator f, const_iterator l) - : source_(loc.source()), source_name_(loc.name()), first_(f), last_(l) - {} - region(location&& loc, const_iterator f, const_iterator l) - : source_(loc.source()), source_name_(loc.name()), first_(f), last_(l) - {} - - region(const region&) = default; - region(region&&) = default; - region& operator=(const region&) = default; - region& operator=(region&&) = default; - ~region() = default; - - region& operator+=(const region& other) - { - // different regions cannot be concatenated - assert(this->begin() == other.begin() && this->end() == other.end() && - this->last_ == other.first_); - - this->last_ = other.last_; - return *this; - } - - bool is_ok() const noexcept override {return static_cast(source_);} - char front() const noexcept override {return *first_;} - - std::string str() const override {return make_string(first_, last_);} - std::string line() const override - { - if(this->contain_newline()) - { - return make_string(this->line_begin(), - std::find(this->line_begin(), this->last(), '\n')); - } - return make_string(this->line_begin(), this->line_end()); - } - std::string line_num() const override - { - return std::to_string(1 + std::count(this->begin(), this->first(), '\n')); - } - - std::size_t size() const noexcept override - { - const auto sz = std::distance(first_, last_); - assert(sz >= 0); - return static_cast(sz); - } - std::size_t before() const noexcept override - { - const auto sz = std::distance(this->line_begin(), this->first()); - assert(sz >= 0); - return static_cast(sz); - } - std::size_t after() const noexcept override - { - const auto sz = std::distance(this->last(), this->line_end()); - assert(sz >= 0); - return static_cast(sz); - } - - bool contain_newline() const noexcept - { - return std::find(this->first(), this->last(), '\n') != this->last(); - } - - const_iterator line_begin() const noexcept - { - using reverse_iterator = std::reverse_iterator; - return std::find(reverse_iterator(this->first()), - reverse_iterator(this->begin()), '\n').base(); - } - const_iterator line_end() const noexcept - { - return std::find(this->last(), this->end(), '\n'); - } - - const_iterator begin() const noexcept {return source_->cbegin();} - const_iterator end() const noexcept {return source_->cend();} - const_iterator first() const noexcept {return first_;} - const_iterator last() const noexcept {return last_;} - - source_ptr const& source() const& noexcept {return source_;} - source_ptr&& source() && noexcept {return std::move(source_);} - - std::string name() const override {return source_name_;} - - std::vector comments() const override - { - // assuming the current region (`*this`) points a value. - // ```toml - // a = "value" - // ^^^^^^^- this region - // ``` - using rev_iter = std::reverse_iterator; - - std::vector com{}; - { - // find comments just before the current region. - // ```toml - // # this should be collected. - // # this also. - // a = value # not this. - // ``` - - // # this is a comment for `a`, not array elements. - // a = [1, 2, 3, 4, 5] - if(this->first() == std::find_if(this->line_begin(), this->first(), - [](const char c) noexcept -> bool {return c == '[' || c == '{';})) - { - auto iter = this->line_begin(); // points the first character - while(iter != this->begin()) - { - iter = std::prev(iter); - - // range [line_start, iter) represents the previous line - const auto line_start = std::find( - rev_iter(iter), rev_iter(this->begin()), '\n').base(); - const auto comment_found = std::find(line_start, iter, '#'); - if(comment_found == iter) - { - break; // comment not found. - } - - // exclude the following case. - // > a = "foo" # comment // <-- this is not a comment for b but a. - // > b = "current value" - if(std::all_of(line_start, comment_found, - [](const char c) noexcept -> bool { - return c == ' ' || c == '\t'; - })) - { - // unwrap the first '#' by std::next. - auto s = make_string(std::next(comment_found), iter); - if(!s.empty() && s.back() == '\r') {s.pop_back();} - com.push_back(std::move(s)); - } - else - { - break; - } - iter = line_start; - } - } - } - - if(com.size() > 1) - { - std::reverse(com.begin(), com.end()); - } - - { - // find comments just after the current region. - // ```toml - // # not this. - // a = value # this one. - // a = [ # not this (technically difficult) - // - // ] # and this. - // ``` - // The reason why it's difficult is that it requires parsing in the - // following case. - // ```toml - // a = [ 10 # this comment is for `10`. not for `a` but `a[0]`. - // # ... - // ] # this is apparently a comment for a. - // - // b = [ - // 3.14 ] # there is no way to add a comment to `3.14` currently. - // - // c = [ - // 3.14 # do this if you need a comment here. - // ] - // ``` - const auto comment_found = - std::find(this->last(), this->line_end(), '#'); - if(comment_found != this->line_end()) // '#' found - { - // table = {key = "value"} # what is this for? - // the above comment is not for "value", but {key="value"}. - if(comment_found == std::find_if(this->last(), comment_found, - [](const char c) noexcept -> bool { - return !(c == ' ' || c == '\t' || c == ','); - })) - { - // unwrap the first '#' by std::next. - auto s = make_string(std::next(comment_found), this->line_end()); - if(!s.empty() && s.back() == '\r') {s.pop_back();} - com.push_back(std::move(s)); - } - } - } - return com; - } - - private: - - source_ptr source_; - std::string source_name_; - const_iterator first_, last_; -}; - -} // detail -} // toml -#endif// TOML11_REGION_H diff --git a/lib/toml/toml/result.hpp b/lib/toml/toml/result.hpp deleted file mode 100644 index 77cd46c..0000000 --- a/lib/toml/toml/result.hpp +++ /dev/null @@ -1,717 +0,0 @@ -// Copyright Toru Niina 2017. -// Distributed under the MIT License. -#ifndef TOML11_RESULT_HPP -#define TOML11_RESULT_HPP -#include "traits.hpp" -#include -#include -#include -#include -#include -#include -#include - -namespace toml -{ - -template -struct success -{ - using value_type = T; - value_type value; - - explicit success(const value_type& v) - noexcept(std::is_nothrow_copy_constructible::value) - : value(v) - {} - explicit success(value_type&& v) - noexcept(std::is_nothrow_move_constructible::value) - : value(std::move(v)) - {} - - template - explicit success(U&& v): value(std::forward(v)) {} - - template - explicit success(const success& v): value(v.value) {} - template - explicit success(success&& v): value(std::move(v.value)) {} - - ~success() = default; - success(const success&) = default; - success(success&&) = default; - success& operator=(const success&) = default; - success& operator=(success&&) = default; -}; - -template -struct failure -{ - using value_type = T; - value_type value; - - explicit failure(const value_type& v) - noexcept(std::is_nothrow_copy_constructible::value) - : value(v) - {} - explicit failure(value_type&& v) - noexcept(std::is_nothrow_move_constructible::value) - : value(std::move(v)) - {} - - template - explicit failure(U&& v): value(std::forward(v)) {} - - template - explicit failure(const failure& v): value(v.value) {} - template - explicit failure(failure&& v): value(std::move(v.value)) {} - - ~failure() = default; - failure(const failure&) = default; - failure(failure&&) = default; - failure& operator=(const failure&) = default; - failure& operator=(failure&&) = default; -}; - -template -success::type>::type> -ok(T&& v) -{ - return success< - typename std::remove_cv::type>::type - >(std::forward(v)); -} -template -failure::type>::type> -err(T&& v) -{ - return failure< - typename std::remove_cv::type>::type - >(std::forward(v)); -} - -inline success ok(const char* literal) -{ - return success(std::string(literal)); -} -inline failure err(const char* literal) -{ - return failure(std::string(literal)); -} - - -template -struct result -{ - using value_type = T; - using error_type = E; - using success_type = success; - using failure_type = failure; - - result(const success_type& s): is_ok_(true) - { - auto tmp = ::new(std::addressof(this->succ)) success_type(s); - assert(tmp == std::addressof(this->succ)); - (void)tmp; - } - result(const failure_type& f): is_ok_(false) - { - auto tmp = ::new(std::addressof(this->fail)) failure_type(f); - assert(tmp == std::addressof(this->fail)); - (void)tmp; - } - result(success_type&& s): is_ok_(true) - { - auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s)); - assert(tmp == std::addressof(this->succ)); - (void)tmp; - } - result(failure_type&& f): is_ok_(false) - { - auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f)); - assert(tmp == std::addressof(this->fail)); - (void)tmp; - } - - template - result(const success& s): is_ok_(true) - { - auto tmp = ::new(std::addressof(this->succ)) success_type(s.value); - assert(tmp == std::addressof(this->succ)); - (void)tmp; - } - template - result(const failure& f): is_ok_(false) - { - auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value); - assert(tmp == std::addressof(this->fail)); - (void)tmp; - } - template - result(success&& s): is_ok_(true) - { - auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value)); - assert(tmp == std::addressof(this->succ)); - (void)tmp; - } - template - result(failure&& f): is_ok_(false) - { - auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value)); - assert(tmp == std::addressof(this->fail)); - (void)tmp; - } - - result& operator=(const success_type& s) - { - this->cleanup(); - this->is_ok_ = true; - auto tmp = ::new(std::addressof(this->succ)) success_type(s); - assert(tmp == std::addressof(this->succ)); - (void)tmp; - return *this; - } - result& operator=(const failure_type& f) - { - this->cleanup(); - this->is_ok_ = false; - auto tmp = ::new(std::addressof(this->fail)) failure_type(f); - assert(tmp == std::addressof(this->fail)); - (void)tmp; - return *this; - } - result& operator=(success_type&& s) - { - this->cleanup(); - this->is_ok_ = true; - auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s)); - assert(tmp == std::addressof(this->succ)); - (void)tmp; - return *this; - } - result& operator=(failure_type&& f) - { - this->cleanup(); - this->is_ok_ = false; - auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f)); - assert(tmp == std::addressof(this->fail)); - (void)tmp; - return *this; - } - - template - result& operator=(const success& s) - { - this->cleanup(); - this->is_ok_ = true; - auto tmp = ::new(std::addressof(this->succ)) success_type(s.value); - assert(tmp == std::addressof(this->succ)); - (void)tmp; - return *this; - } - template - result& operator=(const failure& f) - { - this->cleanup(); - this->is_ok_ = false; - auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value); - assert(tmp == std::addressof(this->fail)); - (void)tmp; - return *this; - } - template - result& operator=(success&& s) - { - this->cleanup(); - this->is_ok_ = true; - auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value)); - assert(tmp == std::addressof(this->succ)); - (void)tmp; - return *this; - } - template - result& operator=(failure&& f) - { - this->cleanup(); - this->is_ok_ = false; - auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value)); - assert(tmp == std::addressof(this->fail)); - (void)tmp; - return *this; - } - - ~result() noexcept {this->cleanup();} - - result(const result& other): is_ok_(other.is_ok()) - { - if(other.is_ok()) - { - auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok()); - assert(tmp == std::addressof(this->succ)); - (void)tmp; - } - else - { - auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err()); - assert(tmp == std::addressof(this->fail)); - (void)tmp; - } - } - result(result&& other): is_ok_(other.is_ok()) - { - if(other.is_ok()) - { - auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok())); - assert(tmp == std::addressof(this->succ)); - (void)tmp; - } - else - { - auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err())); - assert(tmp == std::addressof(this->fail)); - (void)tmp; - } - } - - template - result(const result& other): is_ok_(other.is_ok()) - { - if(other.is_ok()) - { - auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok()); - assert(tmp == std::addressof(this->succ)); - (void)tmp; - } - else - { - auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err()); - assert(tmp == std::addressof(this->fail)); - (void)tmp; - } - } - template - result(result&& other): is_ok_(other.is_ok()) - { - if(other.is_ok()) - { - auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok())); - assert(tmp == std::addressof(this->succ)); - (void)tmp; - } - else - { - auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err())); - assert(tmp == std::addressof(this->fail)); - (void)tmp; - } - } - - result& operator=(const result& other) - { - this->cleanup(); - if(other.is_ok()) - { - auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok()); - assert(tmp == std::addressof(this->succ)); - (void)tmp; - } - else - { - auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err()); - assert(tmp == std::addressof(this->fail)); - (void)tmp; - } - is_ok_ = other.is_ok(); - return *this; - } - result& operator=(result&& other) - { - this->cleanup(); - if(other.is_ok()) - { - auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok())); - assert(tmp == std::addressof(this->succ)); - (void)tmp; - } - else - { - auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err())); - assert(tmp == std::addressof(this->fail)); - (void)tmp; - } - is_ok_ = other.is_ok(); - return *this; - } - - template - result& operator=(const result& other) - { - this->cleanup(); - if(other.is_ok()) - { - auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok()); - assert(tmp == std::addressof(this->succ)); - (void)tmp; - } - else - { - auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err()); - assert(tmp == std::addressof(this->fail)); - (void)tmp; - } - is_ok_ = other.is_ok(); - return *this; - } - template - result& operator=(result&& other) - { - this->cleanup(); - if(other.is_ok()) - { - auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok())); - assert(tmp == std::addressof(this->succ)); - (void)tmp; - } - else - { - auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err())); - assert(tmp == std::addressof(this->fail)); - (void)tmp; - } - is_ok_ = other.is_ok(); - return *this; - } - - bool is_ok() const noexcept {return is_ok_;} - bool is_err() const noexcept {return !is_ok_;} - - operator bool() const noexcept {return is_ok_;} - - value_type& unwrap() & - { - if(is_err()) - { - throw std::runtime_error("toml::result: bad unwrap: " + - format_error(this->as_err())); - } - return this->succ.value; - } - value_type const& unwrap() const& - { - if(is_err()) - { - throw std::runtime_error("toml::result: bad unwrap: " + - format_error(this->as_err())); - } - return this->succ.value; - } - value_type&& unwrap() && - { - if(is_err()) - { - throw std::runtime_error("toml::result: bad unwrap: " + - format_error(this->as_err())); - } - return std::move(this->succ.value); - } - - value_type& unwrap_or(value_type& opt) & - { - if(is_err()) {return opt;} - return this->succ.value; - } - value_type const& unwrap_or(value_type const& opt) const& - { - if(is_err()) {return opt;} - return this->succ.value; - } - value_type unwrap_or(value_type opt) && - { - if(is_err()) {return opt;} - return this->succ.value; - } - - error_type& unwrap_err() & - { - if(is_ok()) {throw std::runtime_error("toml::result: bad unwrap_err");} - return this->fail.value; - } - error_type const& unwrap_err() const& - { - if(is_ok()) {throw std::runtime_error("toml::result: bad unwrap_err");} - return this->fail.value; - } - error_type&& unwrap_err() && - { - if(is_ok()) {throw std::runtime_error("toml::result: bad unwrap_err");} - return std::move(this->fail.value); - } - - value_type& as_ok() & noexcept {return this->succ.value;} - value_type const& as_ok() const& noexcept {return this->succ.value;} - value_type&& as_ok() && noexcept {return std::move(this->succ.value);} - - error_type& as_err() & noexcept {return this->fail.value;} - error_type const& as_err() const& noexcept {return this->fail.value;} - error_type&& as_err() && noexcept {return std::move(this->fail.value);} - - - // prerequisities - // F: T -> U - // retval: result - template - result, error_type> - map(F&& f) & - { - if(this->is_ok()){return ok(f(this->as_ok()));} - return err(this->as_err()); - } - template - result, error_type> - map(F&& f) const& - { - if(this->is_ok()){return ok(f(this->as_ok()));} - return err(this->as_err()); - } - template - result, error_type> - map(F&& f) && - { - if(this->is_ok()){return ok(f(std::move(this->as_ok())));} - return err(std::move(this->as_err())); - } - - // prerequisities - // F: E -> F - // retval: result - template - result> - map_err(F&& f) & - { - if(this->is_err()){return err(f(this->as_err()));} - return ok(this->as_ok()); - } - template - result> - map_err(F&& f) const& - { - if(this->is_err()){return err(f(this->as_err()));} - return ok(this->as_ok()); - } - template - result> - map_err(F&& f) && - { - if(this->is_err()){return err(f(std::move(this->as_err())));} - return ok(std::move(this->as_ok())); - } - - // prerequisities - // F: T -> U - // retval: U - template - detail::return_type_of_t - map_or_else(F&& f, U&& opt) & - { - if(this->is_err()){return std::forward(opt);} - return f(this->as_ok()); - } - template - detail::return_type_of_t - map_or_else(F&& f, U&& opt) const& - { - if(this->is_err()){return std::forward(opt);} - return f(this->as_ok()); - } - template - detail::return_type_of_t - map_or_else(F&& f, U&& opt) && - { - if(this->is_err()){return std::forward(opt);} - return f(std::move(this->as_ok())); - } - - // prerequisities - // F: E -> U - // retval: U - template - detail::return_type_of_t - map_err_or_else(F&& f, U&& opt) & - { - if(this->is_ok()){return std::forward(opt);} - return f(this->as_err()); - } - template - detail::return_type_of_t - map_err_or_else(F&& f, U&& opt) const& - { - if(this->is_ok()){return std::forward(opt);} - return f(this->as_err()); - } - template - detail::return_type_of_t - map_err_or_else(F&& f, U&& opt) && - { - if(this->is_ok()){return std::forward(opt);} - return f(std::move(this->as_err())); - } - - // prerequisities: - // F: func T -> U - // toml::err(error_type) should be convertible to U. - // normally, type U is another result and E is convertible to F - template - detail::return_type_of_t - and_then(F&& f) & - { - if(this->is_ok()){return f(this->as_ok());} - return err(this->as_err()); - } - template - detail::return_type_of_t - and_then(F&& f) const& - { - if(this->is_ok()){return f(this->as_ok());} - return err(this->as_err()); - } - template - detail::return_type_of_t - and_then(F&& f) && - { - if(this->is_ok()){return f(std::move(this->as_ok()));} - return err(std::move(this->as_err())); - } - - // prerequisities: - // F: func E -> U - // toml::ok(value_type) should be convertible to U. - // normally, type U is another result and T is convertible to S - template - detail::return_type_of_t - or_else(F&& f) & - { - if(this->is_err()){return f(this->as_err());} - return ok(this->as_ok()); - } - template - detail::return_type_of_t - or_else(F&& f) const& - { - if(this->is_err()){return f(this->as_err());} - return ok(this->as_ok()); - } - template - detail::return_type_of_t - or_else(F&& f) && - { - if(this->is_err()){return f(std::move(this->as_err()));} - return ok(std::move(this->as_ok())); - } - - // if *this is error, returns *this. otherwise, returns other. - result and_other(const result& other) const& - { - return this->is_err() ? *this : other; - } - result and_other(result&& other) && - { - return this->is_err() ? std::move(*this) : std::move(other); - } - - // if *this is okay, returns *this. otherwise, returns other. - result or_other(const result& other) const& - { - return this->is_ok() ? *this : other; - } - result or_other(result&& other) && - { - return this->is_ok() ? std::move(*this) : std::move(other); - } - - void swap(result& other) - { - result tmp(std::move(*this)); - *this = std::move(other); - other = std::move(tmp); - return ; - } - - private: - - static std::string format_error(std::exception const& excpt) - { - return std::string(excpt.what()); - } - template::value, std::nullptr_t>::type = nullptr> - static std::string format_error(U const& others) - { - std::ostringstream oss; oss << others; - return oss.str(); - } - - void cleanup() noexcept - { - if(this->is_ok_) {this->succ.~success_type();} - else {this->fail.~failure_type();} - return; - } - - private: - - bool is_ok_; - union - { - success_type succ; - failure_type fail; - }; -}; - -template -void swap(result& lhs, result& rhs) -{ - lhs.swap(rhs); - return; -} - -// this might be confusing because it eagerly evaluated, while in the other -// cases operator && and || are short-circuited. -// -// template -// inline result -// operator&&(const result& lhs, const result& rhs) noexcept -// { -// return lhs.is_ok() ? rhs : lhs; -// } -// -// template -// inline result -// operator||(const result& lhs, const result& rhs) noexcept -// { -// return lhs.is_ok() ? lhs : rhs; -// } - -// ---------------------------------------------------------------------------- -// re-use result as a optional with none_t - -namespace detail -{ -struct none_t {}; -inline bool operator==(const none_t&, const none_t&) noexcept {return true;} -inline bool operator!=(const none_t&, const none_t&) noexcept {return false;} -inline bool operator< (const none_t&, const none_t&) noexcept {return false;} -inline bool operator<=(const none_t&, const none_t&) noexcept {return true;} -inline bool operator> (const none_t&, const none_t&) noexcept {return false;} -inline bool operator>=(const none_t&, const none_t&) noexcept {return true;} -template -std::basic_ostream& -operator<<(std::basic_ostream& os, const none_t&) -{ - os << "none"; - return os; -} -inline failure none() noexcept {return failure{none_t{}};} -} // detail -} // toml11 -#endif// TOML11_RESULT_H diff --git a/lib/toml/toml/serializer.hpp b/lib/toml/toml/serializer.hpp deleted file mode 100644 index 88ae775..0000000 --- a/lib/toml/toml/serializer.hpp +++ /dev/null @@ -1,922 +0,0 @@ -// Copyright Toru Niina 2019. -// Distributed under the MIT License. -#ifndef TOML11_SERIALIZER_HPP -#define TOML11_SERIALIZER_HPP -#include -#include - -#include - -#include "lexer.hpp" -#include "value.hpp" - -namespace toml -{ - -// This function serialize a key. It checks a string is a bare key and -// escapes special characters if the string is not compatible to a bare key. -// ```cpp -// std::string k("non.bare.key"); // the key itself includes `.`s. -// std::string formatted = toml::format_key(k); -// assert(formatted == "\"non.bare.key\""); -// ``` -// -// This function is exposed to make it easy to write a user-defined serializer. -// Since toml restricts characters available in a bare key, generally a string -// should be escaped. But checking whether a string needs to be surrounded by -// a `"` and escaping some special character is boring. -template -std::basic_string -format_key(const std::basic_string& k) -{ - if(k.empty()) - { - return std::string("\"\""); - } - - // check the key can be a bare (unquoted) key - detail::location loc(k, std::vector(k.begin(), k.end())); - detail::lex_unquoted_key::invoke(loc); - if(loc.iter() == loc.end()) - { - return k; // all the tokens are consumed. the key is unquoted-key. - } - - //if it includes special characters, then format it in a "quoted" key. - std::basic_string serialized("\""); - for(const char c : k) - { - switch(c) - { - case '\\': {serialized += "\\\\"; break;} - case '\"': {serialized += "\\\""; break;} - case '\b': {serialized += "\\b"; break;} - case '\t': {serialized += "\\t"; break;} - case '\f': {serialized += "\\f"; break;} - case '\n': {serialized += "\\n"; break;} - case '\r': {serialized += "\\r"; break;} - default : {serialized += c; break;} - } - } - serialized += "\""; - return serialized; -} - -template -std::basic_string -format_keys(const std::vector>& keys) -{ - if(keys.empty()) - { - return std::string("\"\""); - } - - std::basic_string serialized; - for(const auto& ky : keys) - { - serialized += format_key(ky); - serialized += charT('.'); - } - serialized.pop_back(); // remove the last dot '.' - return serialized; -} - -template -struct serializer -{ - static_assert(detail::is_basic_value::value, - "toml::serializer is for toml::value and its variants, " - "toml::basic_value<...>."); - - using value_type = Value; - using key_type = typename value_type::key_type ; - using comment_type = typename value_type::comment_type ; - using boolean_type = typename value_type::boolean_type ; - using integer_type = typename value_type::integer_type ; - using floating_type = typename value_type::floating_type ; - using string_type = typename value_type::string_type ; - using local_time_type = typename value_type::local_time_type ; - using local_date_type = typename value_type::local_date_type ; - using local_datetime_type = typename value_type::local_datetime_type ; - using offset_datetime_type = typename value_type::offset_datetime_type; - using array_type = typename value_type::array_type ; - using table_type = typename value_type::table_type ; - - serializer(const std::size_t w = 80u, - const int float_prec = std::numeric_limits::max_digits10, - const bool can_be_inlined = false, - const bool no_comment = false, - std::vector ks = {}, - const bool value_has_comment = false) - : can_be_inlined_(can_be_inlined), no_comment_(no_comment), - value_has_comment_(value_has_comment && !no_comment), - float_prec_(float_prec), width_(w), keys_(std::move(ks)) - {} - ~serializer() = default; - - std::string operator()(const boolean_type& b) const - { - return b ? "true" : "false"; - } - std::string operator()(const integer_type i) const - { - return std::to_string(i); - } - std::string operator()(const floating_type f) const - { - if(std::isnan(f)) - { - if(std::signbit(f)) - { - return std::string("-nan"); - } - else - { - return std::string("nan"); - } - } - else if(!std::isfinite(f)) - { - if(std::signbit(f)) - { - return std::string("-inf"); - } - else - { - return std::string("inf"); - } - } - - const auto fmt = "%.*g"; - const auto bsz = std::snprintf(nullptr, 0, fmt, this->float_prec_, f); - // +1 for null character(\0) - std::vector buf(static_cast(bsz + 1), '\0'); - std::snprintf(buf.data(), buf.size(), fmt, this->float_prec_, f); - - std::string token(buf.begin(), std::prev(buf.end())); - if(!token.empty() && token.back() == '.') // 1. => 1.0 - { - token += '0'; - } - - const auto e = std::find_if( - token.cbegin(), token.cend(), [](const char c) noexcept -> bool { - return c == 'e' || c == 'E'; - }); - const auto has_exponent = (token.cend() != e); - const auto has_fraction = (token.cend() != std::find( - token.cbegin(), token.cend(), '.')); - - if(!has_exponent && !has_fraction) - { - // the resulting value does not have any float specific part! - token += ".0"; - } - return token; - } - std::string operator()(const string_type& s) const - { - if(s.kind == string_t::basic) - { - if((std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend() || - std::find(s.str.cbegin(), s.str.cend(), '\"') != s.str.cend()) && - this->width_ != (std::numeric_limits::max)()) - { - // if linefeed or double-quote is contained, - // make it multiline basic string. - const auto escaped = this->escape_ml_basic_string(s.str); - std::string open("\"\"\""); - std::string close("\"\"\""); - if(escaped.find('\n') != std::string::npos || - this->width_ < escaped.size() + 6) - { - // if the string body contains newline or is enough long, - // add newlines after and before delimiters. - open += "\n"; - close = std::string("\\\n") + close; - } - return open + escaped + close; - } - - // no linefeed. try to make it oneline-string. - std::string oneline = this->escape_basic_string(s.str); - if(oneline.size() + 2 < width_ || width_ < 2) - { - const std::string quote("\""); - return quote + oneline + quote; - } - - // the line is too long compared to the specified width. - // split it into multiple lines. - std::string token("\"\"\"\n"); - while(!oneline.empty()) - { - if(oneline.size() < width_) - { - token += oneline; - oneline.clear(); - } - else if(oneline.at(width_-2) == '\\') - { - token += oneline.substr(0, width_-2); - token += "\\\n"; - oneline.erase(0, width_-2); - } - else - { - token += oneline.substr(0, width_-1); - token += "\\\n"; - oneline.erase(0, width_-1); - } - } - return token + std::string("\\\n\"\"\""); - } - else // the string `s` is literal-string. - { - if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend() || - std::find(s.str.cbegin(), s.str.cend(), '\'') != s.str.cend() ) - { - std::string open("'''"); - if(this->width_ + 6 < s.str.size()) - { - open += '\n'; // the first newline is ignored by TOML spec - } - const std::string close("'''"); - return open + s.str + close; - } - else - { - const std::string quote("'"); - return quote + s.str + quote; - } - } - } - - std::string operator()(const local_date_type& d) const - { - std::ostringstream oss; - oss << d; - return oss.str(); - } - std::string operator()(const local_time_type& t) const - { - std::ostringstream oss; - oss << t; - return oss.str(); - } - std::string operator()(const local_datetime_type& dt) const - { - std::ostringstream oss; - oss << dt; - return oss.str(); - } - std::string operator()(const offset_datetime_type& odt) const - { - std::ostringstream oss; - oss << odt; - return oss.str(); - } - - std::string operator()(const array_type& v) const - { - if(v.empty()) - { - return std::string("[]"); - } - if(this->is_array_of_tables(v)) - { - return make_array_of_tables(v); - } - - // not an array of tables. normal array. - // first, try to make it inline if none of the elements have a comment. - if( ! this->has_comment_inside(v)) - { - const auto inl = this->make_inline_array(v); - if(inl.size() < this->width_ && - std::find(inl.cbegin(), inl.cend(), '\n') == inl.cend()) - { - return inl; - } - } - - // if the length exceeds this->width_, print multiline array. - // key = [ - // # ... - // 42, - // ... - // ] - std::string token; - std::string current_line; - token += "[\n"; - for(const auto& item : v) - { - if( ! item.comments().empty() && !no_comment_) - { - // if comment exists, the element must be the only element in the line. - // e.g. the following is not allowed. - // ```toml - // array = [ - // # comment for what? - // 1, 2, 3, 4, 5 - // ] - // ``` - if(!current_line.empty()) - { - if(current_line.back() != '\n') - { - current_line += '\n'; - } - token += current_line; - current_line.clear(); - } - for(const auto& c : item.comments()) - { - token += '#'; - token += c; - token += '\n'; - } - token += toml::visit(*this, item); - if(!token.empty() && token.back() == '\n') {token.pop_back();} - token += ",\n"; - continue; - } - std::string next_elem; - if(item.is_table()) - { - serializer ser(*this); - ser.can_be_inlined_ = true; - ser.width_ = (std::numeric_limits::max)(); - next_elem += toml::visit(ser, item); - } - else - { - next_elem += toml::visit(*this, item); - } - - // comma before newline. - if(!next_elem.empty() && next_elem.back() == '\n') {next_elem.pop_back();} - - // if current line does not exceeds the width limit, continue. - if(current_line.size() + next_elem.size() + 1 < this->width_) - { - current_line += next_elem; - current_line += ','; - } - else if(current_line.empty()) - { - // if current line was empty, force put the next_elem because - // next_elem is not splittable - token += next_elem; - token += ",\n"; - // current_line is kept empty - } - else // reset current_line - { - assert(current_line.back() == ','); - token += current_line; - token += '\n'; - current_line = next_elem; - current_line += ','; - } - } - if(!current_line.empty()) - { - if(!current_line.empty() && current_line.back() != '\n') - { - current_line += '\n'; - } - token += current_line; - } - token += "]\n"; - return token; - } - - // templatize for any table-like container - std::string operator()(const table_type& v) const - { - // if an element has a comment, then it can't be inlined. - // table = {# how can we write a comment for this? key = "value"} - if(this->can_be_inlined_ && !(this->has_comment_inside(v))) - { - std::string token; - if(!this->keys_.empty()) - { - token += format_key(this->keys_.back()); - token += " = "; - } - token += this->make_inline_table(v); - if(token.size() < this->width_ && - token.end() == std::find(token.begin(), token.end(), '\n')) - { - return token; - } - } - - std::string token; - if(!keys_.empty()) - { - token += '['; - token += format_keys(keys_); - token += "]\n"; - } - token += this->make_multiline_table(v); - return token; - } - - private: - - std::string escape_basic_string(const std::string& s) const - { - //XXX assuming `s` is a valid utf-8 sequence. - std::string retval; - for(const char c : s) - { - switch(c) - { - case '\\': {retval += "\\\\"; break;} - case '\"': {retval += "\\\""; break;} - case '\b': {retval += "\\b"; break;} - case '\t': {retval += "\\t"; break;} - case '\f': {retval += "\\f"; break;} - case '\n': {retval += "\\n"; break;} - case '\r': {retval += "\\r"; break;} - default : - { - if((0x00 <= c && c <= 0x08) || (0x0A <= c && c <= 0x1F) || c == 0x7F) - { - retval += "\\u00"; - retval += char(48 + (c / 16)); - retval += char((c % 16 < 10 ? 48 : 55) + (c % 16)); - } - else - { - retval += c; - } - } - } - } - return retval; - } - - std::string escape_ml_basic_string(const std::string& s) const - { - std::string retval; - for(auto i=s.cbegin(), e=s.cend(); i!=e; ++i) - { - switch(*i) - { - case '\\': {retval += "\\\\"; break;} - // One or two consecutive "s are allowed. - // Later we will check there are no three consecutive "s. - // case '\"': {retval += "\\\""; break;} - case '\b': {retval += "\\b"; break;} - case '\t': {retval += "\\t"; break;} - case '\f': {retval += "\\f"; break;} - case '\n': {retval += "\n"; break;} - case '\r': - { - if(std::next(i) != e && *std::next(i) == '\n') - { - retval += "\r\n"; - ++i; - } - else - { - retval += "\\r"; - } - break; - } - default : - { - const auto c = *i; - if((0x00 <= c && c <= 0x08) || (0x0A <= c && c <= 0x1F) || c == 0x7F) - { - retval += "\\u00"; - retval += char(48 + (c / 16)); - retval += char((c % 16 < 10 ? 48 : 55) + (c % 16)); - } - else - { - retval += c; - } - } - - } - } - // Only 1 or 2 consecutive `"`s are allowed in multiline basic string. - // 3 consecutive `"`s are considered as a closing delimiter. - // We need to check if there are 3 or more consecutive `"`s and insert - // backslash to break them down into several short `"`s like the `str6` - // in the following example. - // ```toml - // str4 = """Here are two quotation marks: "". Simple enough.""" - // # str5 = """Here are three quotation marks: """.""" # INVALID - // str5 = """Here are three quotation marks: ""\".""" - // str6 = """Here are fifteen quotation marks: ""\"""\"""\"""\"""\".""" - // ``` - auto found_3_quotes = retval.find("\"\"\""); - while(found_3_quotes != std::string::npos) - { - retval.replace(found_3_quotes, 3, "\"\"\\\""); - found_3_quotes = retval.find("\"\"\""); - } - return retval; - } - - // if an element of a table or an array has a comment, it cannot be inlined. - bool has_comment_inside(const array_type& a) const noexcept - { - // if no_comment is set, comments would not be written. - if(this->no_comment_) {return false;} - - for(const auto& v : a) - { - if(!v.comments().empty()) {return true;} - } - return false; - } - bool has_comment_inside(const table_type& t) const noexcept - { - // if no_comment is set, comments would not be written. - if(this->no_comment_) {return false;} - - for(const auto& kv : t) - { - if(!kv.second.comments().empty()) {return true;} - } - return false; - } - - std::string make_inline_array(const array_type& v) const - { - assert(!has_comment_inside(v)); - std::string token; - token += '['; - bool is_first = true; - for(const auto& item : v) - { - if(is_first) {is_first = false;} else {token += ',';} - token += visit(serializer( - (std::numeric_limits::max)(), this->float_prec_, - /* inlined */ true, /*no comment*/ false, /*keys*/ {}, - /*has_comment*/ !item.comments().empty()), item); - } - token += ']'; - return token; - } - - std::string make_inline_table(const table_type& v) const - { - assert(!has_comment_inside(v)); - assert(this->can_be_inlined_); - std::string token; - token += '{'; - bool is_first = true; - for(const auto& kv : v) - { - // in inline tables, trailing comma is not allowed (toml-lang #569). - if(is_first) {is_first = false;} else {token += ',';} - token += format_key(kv.first); - token += '='; - token += visit(serializer( - (std::numeric_limits::max)(), this->float_prec_, - /* inlined */ true, /*no comment*/ false, /*keys*/ {}, - /*has_comment*/ !kv.second.comments().empty()), kv.second); - } - token += '}'; - return token; - } - - std::string make_multiline_table(const table_type& v) const - { - std::string token; - - // print non-table elements first. - // ```toml - // [foo] # a table we're writing now here - // key = "value" # <- non-table element, "key" - // # ... - // [foo.bar] # <- table element, "bar" - // ``` - // because after printing [foo.bar], the remaining non-table values will - // be assigned into [foo.bar], not [foo]. Those values should be printed - // earlier. - for(const auto& kv : v) - { - if(kv.second.is_table() || is_array_of_tables(kv.second)) - { - continue; - } - - token += write_comments(kv.second); - - const auto key_and_sep = format_key(kv.first) + " = "; - const auto residual_width = (this->width_ > key_and_sep.size()) ? - this->width_ - key_and_sep.size() : 0; - token += key_and_sep; - token += visit(serializer(residual_width, this->float_prec_, - /*can be inlined*/ true, /*no comment*/ false, /*keys*/ {}, - /*has_comment*/ !kv.second.comments().empty()), kv.second); - - if(token.back() != '\n') - { - token += '\n'; - } - } - - // normal tables / array of tables - - // after multiline table appeared, the other tables cannot be inline - // because the table would be assigned into the table. - // [foo] - // ... - // bar = {...} # <- bar will be a member of [foo]. - bool multiline_table_printed = false; - for(const auto& kv : v) - { - if(!kv.second.is_table() && !is_array_of_tables(kv.second)) - { - continue; // other stuff are already serialized. skip them. - } - - std::vector ks(this->keys_); - ks.push_back(kv.first); - - auto tmp = visit(serializer(this->width_, this->float_prec_, - !multiline_table_printed, this->no_comment_, ks, - /*has_comment*/ !kv.second.comments().empty()), kv.second); - - // If it is the first time to print a multi-line table, it would be - // helpful to separate normal key-value pair and subtables by a - // newline. - // (this checks if the current key-value pair contains newlines. - // but it is not perfect because multi-line string can also contain - // a newline. in such a case, an empty line will be written) TODO - if((!multiline_table_printed) && - std::find(tmp.cbegin(), tmp.cend(), '\n') != tmp.cend()) - { - multiline_table_printed = true; - token += '\n'; // separate key-value pairs and subtables - - token += write_comments(kv.second); - token += tmp; - - // care about recursive tables (all tables in each level prints - // newline and there will be a full of newlines) - if(tmp.substr(tmp.size() - 2, 2) != "\n\n" && - tmp.substr(tmp.size() - 4, 4) != "\r\n\r\n" ) - { - token += '\n'; - } - } - else - { - token += write_comments(kv.second); - token += tmp; - token += '\n'; - } - } - return token; - } - - std::string make_array_of_tables(const array_type& v) const - { - // if it's not inlined, we need to add `[[table.key]]`. - // but if it can be inlined, we can format it as the following. - // ``` - // table.key = [ - // {...}, - // # comment - // {...}, - // ] - // ``` - // This function checks if inlinization is possible or not, and then - // format the array-of-tables in a proper way. - // - // Note about comments: - // - // If the array itself has a comment (value_has_comment_ == true), we - // should try to make it inline. - // ```toml - // # comment about array - // array = [ - // # comment about table element - // {of = "table"} - // ] - // ``` - // If it is formatted as a multiline table, the two comments becomes - // indistinguishable. - // ```toml - // # comment about array - // # comment about table element - // [[array]] - // of = "table" - // ``` - // So we need to try to make it inline, and it force-inlines regardless - // of the line width limit. - // It may fail if the element of a table has comment. In that case, - // the array-of-tables will be formatted as a multiline table. - if(this->can_be_inlined_ || this->value_has_comment_) - { - std::string token; - if(!keys_.empty()) - { - token += format_key(keys_.back()); - token += " = "; - } - - bool failed = false; - token += "[\n"; - for(const auto& item : v) - { - // if an element of the table has a comment, the table - // cannot be inlined. - if(this->has_comment_inside(item.as_table())) - { - failed = true; - break; - } - // write comments for the table itself - token += write_comments(item); - - const auto t = this->make_inline_table(item.as_table()); - - if(t.size() + 1 > width_ || // +1 for the last comma {...}, - std::find(t.cbegin(), t.cend(), '\n') != t.cend()) - { - // if the value itself has a comment, ignore the line width limit - if( ! this->value_has_comment_) - { - failed = true; - break; - } - } - token += t; - token += ",\n"; - } - - if( ! failed) - { - token += "]\n"; - return token; - } - // if failed, serialize them as [[array.of.tables]]. - } - - std::string token; - for(const auto& item : v) - { - token += write_comments(item); - token += "[["; - token += format_keys(keys_); - token += "]]\n"; - token += this->make_multiline_table(item.as_table()); - } - return token; - } - - std::string write_comments(const value_type& v) const - { - std::string retval; - if(this->no_comment_) {return retval;} - - for(const auto& c : v.comments()) - { - retval += '#'; - retval += c; - retval += '\n'; - } - return retval; - } - - bool is_array_of_tables(const value_type& v) const - { - if(!v.is_array() || v.as_array().empty()) {return false;} - return is_array_of_tables(v.as_array()); - } - bool is_array_of_tables(const array_type& v) const - { - // Since TOML v0.5.0, heterogeneous arrays are allowed. So we need to - // check all the element in an array to check if the array is an array - // of tables. - return std::all_of(v.begin(), v.end(), [](const value_type& elem) { - return elem.is_table(); - }); - } - - private: - - bool can_be_inlined_; - bool no_comment_; - bool value_has_comment_; - int float_prec_; - std::size_t width_; - std::vector keys_; -}; - -template class M, template class V> -std::string -format(const basic_value& v, std::size_t w = 80u, - int fprec = std::numeric_limits::max_digits10, - bool no_comment = false, bool force_inline = false) -{ - using value_type = basic_value; - // if value is a table, it is considered to be a root object. - // the root object can't be an inline table. - if(v.is_table()) - { - std::ostringstream oss; - if(!v.comments().empty()) - { - oss << v.comments(); - oss << '\n'; // to split the file comment from the first element - } - const auto serialized = visit(serializer(w, fprec, false, no_comment), v); - oss << serialized; - return oss.str(); - } - return visit(serializer(w, fprec, force_inline), v); -} - -namespace detail -{ -template -int comment_index(std::basic_ostream&) -{ - static const int index = std::ios_base::xalloc(); - return index; -} -} // detail - -template -std::basic_ostream& -nocomment(std::basic_ostream& os) -{ - // by default, it is zero. and by default, it shows comments. - os.iword(detail::comment_index(os)) = 1; - return os; -} - -template -std::basic_ostream& -showcomment(std::basic_ostream& os) -{ - // by default, it is zero. and by default, it shows comments. - os.iword(detail::comment_index(os)) = 0; - return os; -} - -template class M, template class V> -std::basic_ostream& -operator<<(std::basic_ostream& os, const basic_value& v) -{ - using value_type = basic_value; - - // get status of std::setw(). - const auto w = static_cast(os.width()); - const int fprec = static_cast(os.precision()); - os.width(0); - - // by default, iword is initialized by 0. And by default, toml11 outputs - // comments. So `0` means showcomment. 1 means nocommnet. - const bool no_comment = (1 == os.iword(detail::comment_index(os))); - - if(!no_comment && v.is_table() && !v.comments().empty()) - { - os << v.comments(); - os << '\n'; // to split the file comment from the first element - } - // the root object can't be an inline table. so pass `false`. - const auto serialized = visit(serializer(w, fprec, no_comment, false), v); - os << serialized; - - // if v is a non-table value, and has only one comment, then - // put a comment just after a value. in the following way. - // - // ```toml - // key = "value" # comment. - // ``` - // - // Since the top-level toml object is a table, one who want to put a - // non-table toml value must use this in a following way. - // - // ```cpp - // toml::value v; - // std::cout << "user-defined-key = " << v << std::endl; - // ``` - // - // In this case, it is impossible to put comments before key-value pair. - // The only way to preserve comments is to put all of them after a value. - if(!no_comment && !v.is_table() && !v.comments().empty()) - { - os << " #"; - for(const auto& c : v.comments()) {os << c;} - } - return os; -} - -} // toml -#endif// TOML11_SERIALIZER_HPP diff --git a/lib/toml/toml/source_location.hpp b/lib/toml/toml/source_location.hpp deleted file mode 100644 index fa175b5..0000000 --- a/lib/toml/toml/source_location.hpp +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright Toru Niina 2019. -// Distributed under the MIT License. -#ifndef TOML11_SOURCE_LOCATION_HPP -#define TOML11_SOURCE_LOCATION_HPP -#include -#include - -#include "region.hpp" - -namespace toml -{ - -// A struct to contain location in a toml file. -// The interface imitates std::experimental::source_location, -// but not completely the same. -// -// It would be constructed by toml::value. It can be used to generate -// user-defined error messages. -// -// - std::uint_least32_t line() const noexcept -// - returns the line number where the region is on. -// - std::uint_least32_t column() const noexcept -// - returns the column number where the region starts. -// - std::uint_least32_t region() const noexcept -// - returns the size of the region. -// -// +-- line() +-- region of interest (region() == 9) -// v .---+---. -// 12 | value = "foo bar" -// ^ -// +-- column() -// -// - std::string const& file_name() const noexcept; -// - name of the file. -// - std::string const& line_str() const noexcept; -// - the whole line that contains the region of interest. -// -struct source_location -{ - public: - - source_location() - : line_num_(1), column_num_(1), region_size_(1), - file_name_("unknown file"), line_str_("") - {} - - explicit source_location(const detail::region_base* reg) - : line_num_(1), column_num_(1), region_size_(1), - file_name_("unknown file"), line_str_("") - { - if(reg) - { - if(reg->line_num() != detail::region_base().line_num()) - { - line_num_ = static_cast( - std::stoul(reg->line_num())); - } - column_num_ = static_cast(reg->before() + 1); - region_size_ = static_cast(reg->size()); - file_name_ = reg->name(); - line_str_ = reg->line(); - } - } - - explicit source_location(const detail::region& reg) - : line_num_(static_cast(std::stoul(reg.line_num()))), - column_num_(static_cast(reg.before() + 1)), - region_size_(static_cast(reg.size())), - file_name_(reg.name()), - line_str_ (reg.line()) - {} - explicit source_location(const detail::location& loc) - : line_num_(static_cast(std::stoul(loc.line_num()))), - column_num_(static_cast(loc.before() + 1)), - region_size_(static_cast(loc.size())), - file_name_(loc.name()), - line_str_ (loc.line()) - {} - - ~source_location() = default; - source_location(source_location const&) = default; - source_location(source_location &&) = default; - source_location& operator=(source_location const&) = default; - source_location& operator=(source_location &&) = default; - - std::uint_least32_t line() const noexcept {return line_num_;} - std::uint_least32_t column() const noexcept {return column_num_;} - std::uint_least32_t region() const noexcept {return region_size_;} - - std::string const& file_name() const noexcept {return file_name_;} - std::string const& line_str() const noexcept {return line_str_;} - - private: - - std::uint_least32_t line_num_; - std::uint_least32_t column_num_; - std::uint_least32_t region_size_; - std::string file_name_; - std::string line_str_; -}; - -namespace detail -{ - -// internal error message generation. -inline std::string format_underline(const std::string& message, - const std::vector>& loc_com, - const std::vector& 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(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(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(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 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 -#endif// TOML11_SOURCE_LOCATION_HPP diff --git a/lib/toml/toml/storage.hpp b/lib/toml/toml/storage.hpp deleted file mode 100644 index 202f903..0000000 --- a/lib/toml/toml/storage.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright Toru Niina 2017. -// Distributed under the MIT License. -#ifndef TOML11_STORAGE_HPP -#define TOML11_STORAGE_HPP -#include "utility.hpp" - -namespace toml -{ -namespace detail -{ - -// this contains pointer and deep-copy the content if copied. -// to avoid recursive pointer. -template -struct storage -{ - using value_type = T; - - explicit storage(value_type const& v): ptr(toml::make_unique(v)) {} - explicit storage(value_type&& v): ptr(toml::make_unique(std::move(v))) {} - ~storage() = default; - storage(const storage& rhs): ptr(toml::make_unique(*rhs.ptr)) {} - storage& operator=(const storage& rhs) - { - this->ptr = toml::make_unique(*rhs.ptr); - return *this; - } - storage(storage&&) = default; - storage& operator=(storage&&) = default; - - bool is_ok() const noexcept {return static_cast(ptr);} - - value_type& value() & noexcept {return *ptr;} - value_type const& value() const& noexcept {return *ptr;} - value_type&& value() && noexcept {return std::move(*ptr);} - - private: - std::unique_ptr ptr; -}; - -} // detail -} // toml -#endif// TOML11_STORAGE_HPP diff --git a/lib/toml/toml/string.hpp b/lib/toml/toml/string.hpp deleted file mode 100644 index def3e57..0000000 --- a/lib/toml/toml/string.hpp +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright Toru Niina 2017. -// Distributed under the MIT License. -#ifndef TOML11_STRING_HPP -#define TOML11_STRING_HPP - -#include "version.hpp" - -#include - -#include -#include - -#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L -#if __has_include() -#define TOML11_USING_STRING_VIEW 1 -#include -#endif -#endif - -namespace toml -{ - -enum class string_t : std::uint8_t -{ - basic = 0, - literal = 1, -}; - -struct string -{ - string() = default; - ~string() = default; - string(const string& s) = default; - string(string&& s) = default; - string& operator=(const string& s) = default; - string& operator=(string&& s) = default; - - string(const std::string& s): kind(string_t::basic), str(s){} - string(const std::string& s, string_t k): kind(k), str(s){} - string(const char* s): kind(string_t::basic), str(s){} - string(const char* s, string_t k): kind(k), str(s){} - - string(std::string&& s): kind(string_t::basic), str(std::move(s)){} - string(std::string&& s, string_t k): kind(k), str(std::move(s)){} - - string& operator=(const std::string& s) - {kind = string_t::basic; str = s; return *this;} - string& operator=(std::string&& s) - {kind = string_t::basic; str = std::move(s); return *this;} - - operator std::string& () & noexcept {return str;} - operator std::string const& () const& noexcept {return str;} - operator std::string&& () && noexcept {return std::move(str);} - - string& operator+=(const char* rhs) {str += rhs; return *this;} - string& operator+=(const char rhs) {str += rhs; return *this;} - string& operator+=(const std::string& rhs) {str += rhs; return *this;} - string& operator+=(const string& rhs) {str += rhs.str; return *this;} - -#if defined(TOML11_USING_STRING_VIEW) && TOML11_USING_STRING_VIEW>0 - explicit string(std::string_view s): kind(string_t::basic), str(s){} - string(std::string_view s, string_t k): kind(k), str(s){} - - string& operator=(std::string_view s) - {kind = string_t::basic; str = s; return *this;} - - explicit operator std::string_view() const noexcept - {return std::string_view(str);} - - string& operator+=(const std::string_view& rhs) {str += rhs; return *this;} -#endif - - string_t kind; - std::string str; -}; - -inline bool operator==(const string& lhs, const string& rhs) -{ - return lhs.kind == rhs.kind && lhs.str == rhs.str; -} -inline bool operator!=(const string& lhs, const string& rhs) -{ - return !(lhs == rhs); -} -inline bool operator<(const string& lhs, const string& rhs) -{ - return (lhs.kind == rhs.kind) ? (lhs.str < rhs.str) : (lhs.kind < rhs.kind); -} -inline bool operator>(const string& lhs, const string& rhs) -{ - return rhs < lhs; -} -inline bool operator<=(const string& lhs, const string& rhs) -{ - return !(rhs < lhs); -} -inline bool operator>=(const string& lhs, const string& rhs) -{ - return !(lhs < rhs); -} - -inline bool -operator==(const string& lhs, const std::string& rhs) {return lhs.str == rhs;} -inline bool -operator!=(const string& lhs, const std::string& rhs) {return lhs.str != rhs;} -inline bool -operator< (const string& lhs, const std::string& rhs) {return lhs.str < rhs;} -inline bool -operator> (const string& lhs, const std::string& rhs) {return lhs.str > rhs;} -inline bool -operator<=(const string& lhs, const std::string& rhs) {return lhs.str <= rhs;} -inline bool -operator>=(const string& lhs, const std::string& rhs) {return lhs.str >= rhs;} - -inline bool -operator==(const std::string& lhs, const string& rhs) {return lhs == rhs.str;} -inline bool -operator!=(const std::string& lhs, const string& rhs) {return lhs != rhs.str;} -inline bool -operator< (const std::string& lhs, const string& rhs) {return lhs < rhs.str;} -inline bool -operator> (const std::string& lhs, const string& rhs) {return lhs > rhs.str;} -inline bool -operator<=(const std::string& lhs, const string& rhs) {return lhs <= rhs.str;} -inline bool -operator>=(const std::string& lhs, const string& rhs) {return lhs >= rhs.str;} - -inline bool -operator==(const string& lhs, const char* rhs) {return lhs.str == std::string(rhs);} -inline bool -operator!=(const string& lhs, const char* rhs) {return lhs.str != std::string(rhs);} -inline bool -operator< (const string& lhs, const char* rhs) {return lhs.str < std::string(rhs);} -inline bool -operator> (const string& lhs, const char* rhs) {return lhs.str > std::string(rhs);} -inline bool -operator<=(const string& lhs, const char* rhs) {return lhs.str <= std::string(rhs);} -inline bool -operator>=(const string& lhs, const char* rhs) {return lhs.str >= std::string(rhs);} - -inline bool -operator==(const char* lhs, const string& rhs) {return std::string(lhs) == rhs.str;} -inline bool -operator!=(const char* lhs, const string& rhs) {return std::string(lhs) != rhs.str;} -inline bool -operator< (const char* lhs, const string& rhs) {return std::string(lhs) < rhs.str;} -inline bool -operator> (const char* lhs, const string& rhs) {return std::string(lhs) > rhs.str;} -inline bool -operator<=(const char* lhs, const string& rhs) {return std::string(lhs) <= rhs.str;} -inline bool -operator>=(const char* lhs, const string& rhs) {return std::string(lhs) >= rhs.str;} - -template -std::basic_ostream& -operator<<(std::basic_ostream& os, const string& s) -{ - if(s.kind == string_t::basic) - { - if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend()) - { - // it contains newline. make it multiline string. - os << "\"\"\"\n"; - for(auto i=s.str.cbegin(), e=s.str.cend(); i!=e; ++i) - { - switch(*i) - { - case '\\': {os << "\\\\"; break;} - case '\"': {os << "\\\""; break;} - case '\b': {os << "\\b"; break;} - case '\t': {os << "\\t"; break;} - case '\f': {os << "\\f"; break;} - case '\n': {os << '\n'; break;} - case '\r': - { - // since it is a multiline string, - // CRLF is not needed to be escaped. - if(std::next(i) != e && *std::next(i) == '\n') - { - os << "\r\n"; - ++i; - } - else - { - os << "\\r"; - } - break; - } - default: {os << *i; break;} - } - } - os << "\\\n\"\"\""; - return os; - } - // no newline. make it inline. - os << "\""; - for(const auto c : s.str) - { - switch(c) - { - case '\\': {os << "\\\\"; break;} - case '\"': {os << "\\\""; break;} - case '\b': {os << "\\b"; break;} - case '\t': {os << "\\t"; break;} - case '\f': {os << "\\f"; break;} - case '\n': {os << "\\n"; break;} - case '\r': {os << "\\r"; break;} - default : {os << c; break;} - } - } - os << "\""; - return os; - } - // the string `s` is literal-string. - if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend() || - std::find(s.str.cbegin(), s.str.cend(), '\'') != s.str.cend() ) - { - // contains newline or single quote. make it multiline. - os << "'''\n" << s.str << "'''"; - return os; - } - // normal literal string - os << '\'' << s.str << '\''; - return os; -} - -} // toml -#endif// TOML11_STRING_H diff --git a/lib/toml/toml/traits.hpp b/lib/toml/toml/traits.hpp deleted file mode 100644 index 255d9e8..0000000 --- a/lib/toml/toml/traits.hpp +++ /dev/null @@ -1,328 +0,0 @@ -// Copyright Toru Niina 2017. -// Distributed under the MIT License. -#ifndef TOML11_TRAITS_HPP -#define TOML11_TRAITS_HPP - -#include "from.hpp" -#include "into.hpp" -#include "version.hpp" - -#include -#include -#include -#include -#include -#include - -#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L -#if __has_include() -#include -#endif // has_include() -#endif // cplusplus >= C++17 - -namespace toml -{ -template class T, template class A> -class basic_value; - -namespace detail -{ -// --------------------------------------------------------------------------- -// check whether type T is a kind of container/map class - -struct has_iterator_impl -{ - template static std::true_type check(typename T::iterator*); - template static std::false_type check(...); -}; -struct has_value_type_impl -{ - template static std::true_type check(typename T::value_type*); - template static std::false_type check(...); -}; -struct has_key_type_impl -{ - template static std::true_type check(typename T::key_type*); - template static std::false_type check(...); -}; -struct has_mapped_type_impl -{ - template static std::true_type check(typename T::mapped_type*); - template static std::false_type check(...); -}; -struct has_reserve_method_impl -{ - template static std::false_type check(...); - template static std::true_type check( - decltype(std::declval().reserve(std::declval()))*); -}; -struct has_push_back_method_impl -{ - template static std::false_type check(...); - template static std::true_type check( - decltype(std::declval().push_back(std::declval()))*); -}; -struct is_comparable_impl -{ - template static std::false_type check(...); - template static std::true_type check( - decltype(std::declval() < std::declval())*); -}; - -struct has_from_toml_method_impl -{ - template class Tb, template class A> - static std::true_type check( - decltype(std::declval().from_toml( - std::declval<::toml::basic_value>()))*); - - template class Tb, template class A> - static std::false_type check(...); -}; -struct has_into_toml_method_impl -{ - template - static std::true_type check(decltype(std::declval().into_toml())*); - template - static std::false_type check(...); -}; - -struct has_specialized_from_impl -{ - template - static std::false_type check(...); - template)> - static std::true_type check(::toml::from*); -}; -struct has_specialized_into_impl -{ - template - static std::false_type check(...); - template)> - static std::true_type check(::toml::from*); -}; - - -/// Intel C++ compiler can not use decltype in parent class declaration, here -/// is a hack to work around it. https://stackoverflow.com/a/23953090/4692076 -#ifdef __INTEL_COMPILER -#define decltype(...) std::enable_if::type -#endif - -template -struct has_iterator : decltype(has_iterator_impl::check(nullptr)){}; -template -struct has_value_type : decltype(has_value_type_impl::check(nullptr)){}; -template -struct has_key_type : decltype(has_key_type_impl::check(nullptr)){}; -template -struct has_mapped_type : decltype(has_mapped_type_impl::check(nullptr)){}; -template -struct has_reserve_method : decltype(has_reserve_method_impl::check(nullptr)){}; -template -struct has_push_back_method : decltype(has_push_back_method_impl::check(nullptr)){}; -template -struct is_comparable : decltype(is_comparable_impl::check(nullptr)){}; - -template class Tb, template class A> -struct has_from_toml_method -: decltype(has_from_toml_method_impl::check(nullptr)){}; - -template -struct has_into_toml_method -: decltype(has_into_toml_method_impl::check(nullptr)){}; - -template -struct has_specialized_from : decltype(has_specialized_from_impl::check(nullptr)){}; -template -struct has_specialized_into : decltype(has_specialized_into_impl::check(nullptr)){}; - -#ifdef __INTEL_COMPILER -#undef decltype -#endif - -// --------------------------------------------------------------------------- -// C++17 and/or/not - -#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L - -using std::conjunction; -using std::disjunction; -using std::negation; - -#else - -template struct conjunction : std::true_type{}; -template struct conjunction : T{}; -template -struct conjunction : - std::conditional(T::value), conjunction, T>::type -{}; - -template struct disjunction : std::false_type{}; -template struct disjunction : T {}; -template -struct disjunction : - std::conditional(T::value), T, disjunction>::type -{}; - -template -struct negation : std::integral_constant(T::value)>{}; - -#endif - -// --------------------------------------------------------------------------- -// type checkers - -template struct is_std_pair : std::false_type{}; -template -struct is_std_pair> : std::true_type{}; - -template struct is_std_tuple : std::false_type{}; -template -struct is_std_tuple> : std::true_type{}; - -template struct is_std_forward_list : std::false_type{}; -template -struct is_std_forward_list> : std::true_type{}; - -template struct is_chrono_duration: std::false_type{}; -template -struct is_chrono_duration>: std::true_type{}; - -template -struct is_map : conjunction< // map satisfies all the following conditions - has_iterator, // has T::iterator - has_value_type, // has T::value_type - has_key_type, // has T::key_type - has_mapped_type // has T::mapped_type - >{}; -template struct is_map : is_map{}; -template struct is_map : is_map{}; -template struct is_map : is_map{}; -template struct is_map : is_map{}; - -template -struct is_container : conjunction< - negation>, // not a map - negation>, // not a std::string -#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L -#if __has_include() - negation>, // not a std::string_view -#endif // has_include() -#endif - has_iterator, // has T::iterator - has_value_type // has T::value_type - >{}; -template struct is_container : is_container{}; -template struct is_container : is_container{}; -template struct is_container : is_container{}; -template struct is_container : is_container{}; - -template -struct is_basic_value: std::false_type{}; -template struct is_basic_value : is_basic_value{}; -template struct is_basic_value : is_basic_value{}; -template struct is_basic_value : is_basic_value{}; -template struct is_basic_value : is_basic_value{}; -template class M, template class V> -struct is_basic_value<::toml::basic_value>: std::true_type{}; - -// --------------------------------------------------------------------------- -// C++14 index_sequence - -#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201402L - -using std::index_sequence; -using std::make_index_sequence; - -#else - -template struct index_sequence{}; - -template struct push_back_index_sequence{}; -template -struct push_back_index_sequence, N> -{ - typedef index_sequence type; -}; - -template -struct index_sequence_maker -{ - typedef typename push_back_index_sequence< - typename index_sequence_maker::type, N>::type type; -}; -template<> -struct index_sequence_maker<0> -{ - typedef index_sequence<0> type; -}; -template -using make_index_sequence = typename index_sequence_maker::type; - -#endif // cplusplus >= 2014 - -// --------------------------------------------------------------------------- -// C++14 enable_if_t - -#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201402L - -using std::enable_if_t; - -#else - -template -using enable_if_t = typename std::enable_if::type; - -#endif // cplusplus >= 2014 - -// --------------------------------------------------------------------------- -// return_type_of_t - -#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L && defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable>=201703 - -template -using return_type_of_t = std::invoke_result_t; - -#else -// result_of is deprecated after C++17 -template -using return_type_of_t = typename std::result_of::type; - -#endif - -// --------------------------------------------------------------------------- -// is_string_literal -// -// to use this, pass `typename remove_reference::type` to T. - -template -struct is_string_literal: -disjunction< - std::is_same, - conjunction< - std::is_array, - std::is_same::type> - > - >{}; - -// --------------------------------------------------------------------------- -// C++20 remove_cvref_t - -template -struct remove_cvref -{ - using type = typename std::remove_cv< - typename std::remove_reference::type>::type; -}; - -template -using remove_cvref_t = typename remove_cvref::type; - -}// detail -}//toml -#endif // TOML_TRAITS diff --git a/lib/toml/toml/types.hpp b/lib/toml/toml/types.hpp deleted file mode 100644 index 1e420e7..0000000 --- a/lib/toml/toml/types.hpp +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright Toru Niina 2017. -// Distributed under the MIT License. -#ifndef TOML11_TYPES_HPP -#define TOML11_TYPES_HPP -#include -#include - -#include "comments.hpp" -#include "datetime.hpp" -#include "string.hpp" -#include "traits.hpp" - -namespace toml -{ - -template class Table, // map-like class - template class Array> // vector-like class -class basic_value; - -using character = char; -using key = std::string; - -#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ <= 4 -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wshadow" -#endif - -using boolean = bool; -using integer = std::int64_t; -using floating = double; // "float" is a keyword, cannot use it here. -// the following stuffs are structs defined here, so aliases are not needed. -// - string -// - offset_datetime -// - offset_datetime -// - local_datetime -// - local_date -// - local_time - -#if defined(__GNUC__) && !defined(__clang__) -# pragma GCC diagnostic pop -#endif - -// default toml::value and default array/table. these are defined after defining -// basic_value itself. -// using value = basic_value; -// using array = typename value::array_type; -// using table = typename value::table_type; - -// to avoid warnings about `value_t::integer` is "shadowing" toml::integer in -// GCC -Wshadow=global. -#if defined(__GNUC__) && !defined(__clang__) -# pragma GCC diagnostic push -# if 7 <= __GNUC__ -# pragma GCC diagnostic ignored "-Wshadow=global" -# else // gcc-6 or older -# pragma GCC diagnostic ignored "-Wshadow" -# endif -#endif -enum class value_t : std::uint8_t -{ - empty = 0, - boolean = 1, - integer = 2, - floating = 3, - string = 4, - offset_datetime = 5, - local_datetime = 6, - local_date = 7, - local_time = 8, - array = 9, - table = 10, -}; -#if defined(__GNUC__) && !defined(__clang__) -# pragma GCC diagnostic pop -#endif - -template -inline std::basic_ostream& -operator<<(std::basic_ostream& os, value_t t) -{ - switch(t) - { - case value_t::boolean : os << "boolean"; return os; - case value_t::integer : os << "integer"; return os; - case value_t::floating : os << "floating"; return os; - case value_t::string : os << "string"; return os; - case value_t::offset_datetime : os << "offset_datetime"; return os; - case value_t::local_datetime : os << "local_datetime"; return os; - case value_t::local_date : os << "local_date"; return os; - case value_t::local_time : os << "local_time"; return os; - case value_t::array : os << "array"; return os; - case value_t::table : os << "table"; return os; - case value_t::empty : os << "empty"; return os; - default : os << "unknown"; return os; - } -} - -template, - typename alloc = std::allocator> -inline std::basic_string stringize(value_t t) -{ - std::basic_ostringstream oss; - oss << t; - return oss.str(); -} - -namespace detail -{ - -// helper to define a type that represents a value_t value. -template -using value_t_constant = std::integral_constant; - -// meta-function that convertes from value_t to the exact toml type that corresponds to. -// It takes toml::basic_value type because array and table types depend on it. -template struct enum_to_type {using type = void ;}; -template struct enum_to_type{using type = void ;}; -template struct enum_to_type{using type = boolean ;}; -template struct enum_to_type{using type = integer ;}; -template struct enum_to_type{using type = floating ;}; -template struct enum_to_type{using type = string ;}; -template struct enum_to_type{using type = offset_datetime ;}; -template struct enum_to_type{using type = local_datetime ;}; -template struct enum_to_type{using type = local_date ;}; -template struct enum_to_type{using type = local_time ;}; -template struct enum_to_type{using type = typename Value::array_type;}; -template struct enum_to_type{using type = typename Value::table_type;}; - -// meta-function that converts from an exact toml type to the enum that corresponds to. -template -struct type_to_enum : std::conditional< - std::is_same::value, // if T == array_type, - value_t_constant, // then value_t::array - typename std::conditional< // else... - std::is_same::value, // if T == table_type - value_t_constant, // then value_t::table - value_t_constant // else value_t::empty - >::type - >::type {}; -template struct type_to_enum: value_t_constant {}; -template struct type_to_enum: value_t_constant {}; -template struct type_to_enum: value_t_constant {}; -template struct type_to_enum: value_t_constant {}; -template struct type_to_enum: value_t_constant {}; -template struct type_to_enum: value_t_constant {}; -template struct type_to_enum: value_t_constant {}; -template struct type_to_enum: value_t_constant {}; - -// meta-function that checks the type T is the same as one of the toml::* types. -template -struct is_exact_toml_type : disjunction< - std::is_same, - std::is_same, - std::is_same, - std::is_same, - std::is_same, - std::is_same, - std::is_same, - std::is_same, - std::is_same, - std::is_same - >{}; -template struct is_exact_toml_type : is_exact_toml_type{}; -template struct is_exact_toml_type : is_exact_toml_type{}; -template struct is_exact_toml_type : is_exact_toml_type{}; -template struct is_exact_toml_type: is_exact_toml_type{}; - -} // detail -} // toml - -#endif// TOML11_TYPES_H diff --git a/lib/toml/toml/utility.hpp b/lib/toml/toml/utility.hpp deleted file mode 100644 index 53a18b9..0000000 --- a/lib/toml/toml/utility.hpp +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright Toru Niina 2017. -// Distributed under the MIT License. -#ifndef TOML11_UTILITY_HPP -#define TOML11_UTILITY_HPP -#include -#include -#include - -#include "traits.hpp" -#include "version.hpp" - -#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201402L -# define TOML11_MARK_AS_DEPRECATED(msg) [[deprecated(msg)]] -#elif defined(__GNUC__) -# define TOML11_MARK_AS_DEPRECATED(msg) __attribute__((deprecated(msg))) -#elif defined(_MSC_VER) -# define TOML11_MARK_AS_DEPRECATED(msg) __declspec(deprecated(msg)) -#else -# define TOML11_MARK_AS_DEPRECATED -#endif - -namespace toml -{ - -#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201402L - -using std::make_unique; - -#else - -template -inline std::unique_ptr make_unique(Ts&& ... args) -{ - return std::unique_ptr(new T(std::forward(args)...)); -} - -#endif // TOML11_CPLUSPLUS_STANDARD_VERSION >= 2014 - -namespace detail -{ -template -void try_reserve_impl(Container& container, std::size_t N, std::true_type) -{ - container.reserve(N); - return; -} -template -void try_reserve_impl(Container&, std::size_t, std::false_type) noexcept -{ - return; -} -} // detail - -template -void try_reserve(Container& container, std::size_t N) -{ - if(N <= container.size()) {return;} - detail::try_reserve_impl(container, N, detail::has_reserve_method{}); - return; -} - -namespace detail -{ -inline std::string concat_to_string_impl(std::ostringstream& oss) -{ - return oss.str(); -} -template -std::string concat_to_string_impl(std::ostringstream& oss, T&& head, Ts&& ... tail) -{ - oss << std::forward(head); - return concat_to_string_impl(oss, std::forward(tail) ... ); -} -} // detail - -template -std::string concat_to_string(Ts&& ... args) -{ - std::ostringstream oss; - oss << std::boolalpha << std::fixed; - return detail::concat_to_string_impl(oss, std::forward(args) ...); -} - -template -T from_string(const std::string& str, T opt) -{ - T v(opt); - std::istringstream iss(str); - iss >> v; - return v; -} - -namespace detail -{ -#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201402L -template -decltype(auto) last_one(T&& tail) noexcept -{ - return std::forward(tail); -} - -template -decltype(auto) last_one(T&& /*head*/, Ts&& ... tail) noexcept -{ - return last_one(std::forward(tail)...); -} -#else // C++11 -// The following code -// ```cpp -// 1 | template -// 2 | auto last_one(T&& /*head*/, Ts&& ... tail) -// 3 | -> decltype(last_one(std::forward(tail)...)) -// 4 | { -// 5 | return last_one(std::forward(tail)...); -// 6 | } -// ``` -// does not work because the function `last_one(...)` is not yet defined at -// line #3, so `decltype()` cannot deduce the type returned from `last_one`. -// So we need to determine return type in a different way, like a meta func. - -template -struct last_one_in_pack -{ - using type = typename last_one_in_pack::type; -}; -template -struct last_one_in_pack -{ - using type = T; -}; -template -using last_one_in_pack_t = typename last_one_in_pack::type; - -template -T&& last_one(T&& tail) noexcept -{ - return std::forward(tail); -} -template -enable_if_t<(sizeof...(Ts) > 0), last_one_in_pack_t> -last_one(T&& /*head*/, Ts&& ... tail) -{ - return last_one(std::forward(tail)...); -} - -#endif -} // detail - -}// toml -#endif // TOML11_UTILITY diff --git a/lib/toml/toml/value.hpp b/lib/toml/toml/value.hpp deleted file mode 100644 index 1b43db8..0000000 --- a/lib/toml/toml/value.hpp +++ /dev/null @@ -1,2035 +0,0 @@ -// Copyright Toru Niina 2017. -// Distributed under the MIT License. -#ifndef TOML11_VALUE_HPP -#define TOML11_VALUE_HPP -#include - -#include "comments.hpp" -#include "exception.hpp" -#include "into.hpp" -#include "region.hpp" -#include "source_location.hpp" -#include "storage.hpp" -#include "traits.hpp" -#include "types.hpp" -#include "utility.hpp" - -namespace toml -{ - -namespace detail -{ - -// to show error messages. not recommended for users. -template -inline region_base const* get_region(const Value& v) -{ - return v.region_info_.get(); -} - -template -void change_region(Value& v, region reg) -{ - v.region_info_ = std::make_shared(std::move(reg)); - return; -} - -template -[[noreturn]] inline void -throw_bad_cast(const std::string& funcname, value_t actual, const Value& v) -{ - throw type_error(detail::format_underline( - concat_to_string(funcname, "bad_cast to ", Expected), { - {v.location(), concat_to_string("the actual type is ", actual)} - }), v.location()); -} - -// Throw `out_of_range` from `toml::value::at()` and `toml::find()` -// after generating an error message. -// -// The implementation is a bit complicated and there are many edge-cases. -// If you are not interested in the error message generation, just skip this. -template -[[noreturn]] void -throw_key_not_found_error(const Value& v, const key& ky) -{ - // The top-level table has its region at the first character of the file. - // That means that, in the case when a key is not found in the top-level - // table, the error message points to the first character. If the file has - // its first table at the first line, the error message would be like this. - // ```console - // [error] key "a" not found - // --> example.toml - // | - // 1 | [table] - // | ^------ in this table - // ``` - // 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 - // message should explicitly say "key not found in the top-level table", - // or "the parsed file is empty" if there is no content at all (0 bytes in file). - const auto loc = v.location(); - if(loc.line() == 1 && loc.region() == 0) - { - // First line with a zero-length region means "empty file". - // The region will be generated at `parse_toml_file` function - // if the file contains no bytes. - throw std::out_of_range(format_underline(concat_to_string( - "key \"", ky, "\" not found in the top-level table"), { - {loc, "the parsed file is empty"} - })); - } - else if(loc.line() == 1 && loc.region() == 1) - { - // Here it assumes that top-level table starts at the first character. - // The region corresponds to the top-level table will be generated at - // `parse_toml_file` function. - // It also assumes that the top-level table size is just one and - // the line number is `1`. It is always satisfied. And those conditions - // are satisfied only if the table is the top-level table. - // - // 1. one-character dot-key at the first line - // ```toml - // a.b = "c" - // ``` - // toml11 counts whole key as the table key. Here, `a.b` is the region - // of the table "a". It could be counter intuitive, but it works. - // The size of the region is 3, not 1. The above example is the shortest - // dot-key example. The size cannot be 1. - // - // 2. one-character inline-table at the first line - // ```toml - // a = {b = "c"} - // ``` - // toml11 considers the inline table body as the table region. Here, - // `{b = "c"}` is the region of the table "a". The size of the region - // is 9, not 1. The shotest inline table still has two characters, `{` - // and `}`. The size cannot be 1. - // - // 3. one-character table declaration at the first line - // ```toml - // [a] - // ``` - // toml11 considers the whole table key as the table region. Here, - // `[a]` is the table region. The size is 3, not 1. - // - throw std::out_of_range(format_underline(concat_to_string( - "key \"", ky, "\" not found in the top-level table"), { - {loc, "the top-level table starts here"} - })); - } - else - { - // normal table. - throw std::out_of_range(format_underline(concat_to_string( - "key \"", ky, "\" not found"), { {loc, "in this table"} })); - } -} - -// switch by `value_t` at the compile time. -template -struct switch_cast {}; -#define TOML11_GENERATE_SWITCH_CASTER(TYPE) \ - template<> \ - struct switch_cast \ - { \ - template \ - static typename Value::TYPE##_type& invoke(Value& v) \ - { \ - return v.as_##TYPE(); \ - } \ - template \ - static typename Value::TYPE##_type const& invoke(const Value& v) \ - { \ - return v.as_##TYPE(); \ - } \ - template \ - static typename Value::TYPE##_type&& invoke(Value&& v) \ - { \ - return std::move(v).as_##TYPE(); \ - } \ - }; \ - /**/ -TOML11_GENERATE_SWITCH_CASTER(boolean) -TOML11_GENERATE_SWITCH_CASTER(integer) -TOML11_GENERATE_SWITCH_CASTER(floating) -TOML11_GENERATE_SWITCH_CASTER(string) -TOML11_GENERATE_SWITCH_CASTER(offset_datetime) -TOML11_GENERATE_SWITCH_CASTER(local_datetime) -TOML11_GENERATE_SWITCH_CASTER(local_date) -TOML11_GENERATE_SWITCH_CASTER(local_time) -TOML11_GENERATE_SWITCH_CASTER(array) -TOML11_GENERATE_SWITCH_CASTER(table) - -#undef TOML11_GENERATE_SWITCH_CASTER - -}// detail - -template class Table = std::unordered_map, - template class Array = std::vector> -class basic_value -{ - template - static void assigner(T& dst, U&& v) - { - const auto tmp = ::new(std::addressof(dst)) T(std::forward(v)); - assert(tmp == std::addressof(dst)); - (void)tmp; - } - - using region_base = detail::region_base; - - template class T, - template class A> - friend class basic_value; - - public: - - using comment_type = Comment; - using key_type = ::toml::key; - using value_type = basic_value; - using boolean_type = ::toml::boolean; - using integer_type = ::toml::integer; - using floating_type = ::toml::floating; - using string_type = ::toml::string; - using local_time_type = ::toml::local_time; - using local_date_type = ::toml::local_date; - using local_datetime_type = ::toml::local_datetime; - using offset_datetime_type = ::toml::offset_datetime; - using array_type = Array; - using table_type = Table; - - public: - - basic_value() noexcept - : type_(value_t::empty), - region_info_(std::make_shared(region_base{})) - {} - ~basic_value() noexcept {this->cleanup();} - - basic_value(const basic_value& v) - : type_(v.type()), region_info_(v.region_info_), comments_(v.comments_) - { - switch(v.type()) - { - case value_t::boolean : assigner(boolean_ , v.boolean_ ); break; - case value_t::integer : assigner(integer_ , v.integer_ ); break; - case value_t::floating : assigner(floating_ , v.floating_ ); break; - case value_t::string : assigner(string_ , v.string_ ); break; - case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break; - case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break; - case value_t::local_date : assigner(local_date_ , v.local_date_ ); break; - case value_t::local_time : assigner(local_time_ , v.local_time_ ); break; - case value_t::array : assigner(array_ , v.array_ ); break; - case value_t::table : assigner(table_ , v.table_ ); break; - default: break; - } - } - basic_value(basic_value&& v) - : type_(v.type()), region_info_(std::move(v.region_info_)), - comments_(std::move(v.comments_)) - { - switch(this->type_) // here this->type_ is already initialized - { - case value_t::boolean : assigner(boolean_ , std::move(v.boolean_ )); break; - case value_t::integer : assigner(integer_ , std::move(v.integer_ )); break; - case value_t::floating : assigner(floating_ , std::move(v.floating_ )); break; - case value_t::string : assigner(string_ , std::move(v.string_ )); break; - case value_t::offset_datetime: assigner(offset_datetime_, std::move(v.offset_datetime_)); break; - case value_t::local_datetime : assigner(local_datetime_ , std::move(v.local_datetime_ )); break; - case value_t::local_date : assigner(local_date_ , std::move(v.local_date_ )); break; - case value_t::local_time : assigner(local_time_ , std::move(v.local_time_ )); break; - case value_t::array : assigner(array_ , std::move(v.array_ )); break; - case value_t::table : assigner(table_ , std::move(v.table_ )); break; - default: break; - } - } - basic_value& operator=(const basic_value& v) - { - this->cleanup(); - this->region_info_ = v.region_info_; - this->comments_ = v.comments_; - this->type_ = v.type(); - switch(this->type_) - { - case value_t::boolean : assigner(boolean_ , v.boolean_ ); break; - case value_t::integer : assigner(integer_ , v.integer_ ); break; - case value_t::floating : assigner(floating_ , v.floating_ ); break; - case value_t::string : assigner(string_ , v.string_ ); break; - case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break; - case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break; - case value_t::local_date : assigner(local_date_ , v.local_date_ ); break; - case value_t::local_time : assigner(local_time_ , v.local_time_ ); break; - case value_t::array : assigner(array_ , v.array_ ); break; - case value_t::table : assigner(table_ , v.table_ ); break; - default: break; - } - return *this; - } - basic_value& operator=(basic_value&& v) - { - this->cleanup(); - this->region_info_ = std::move(v.region_info_); - this->comments_ = std::move(v.comments_); - this->type_ = v.type(); - switch(this->type_) - { - case value_t::boolean : assigner(boolean_ , std::move(v.boolean_ )); break; - case value_t::integer : assigner(integer_ , std::move(v.integer_ )); break; - case value_t::floating : assigner(floating_ , std::move(v.floating_ )); break; - case value_t::string : assigner(string_ , std::move(v.string_ )); break; - case value_t::offset_datetime: assigner(offset_datetime_, std::move(v.offset_datetime_)); break; - case value_t::local_datetime : assigner(local_datetime_ , std::move(v.local_datetime_ )); break; - case value_t::local_date : assigner(local_date_ , std::move(v.local_date_ )); break; - case value_t::local_time : assigner(local_time_ , std::move(v.local_time_ )); break; - case value_t::array : assigner(array_ , std::move(v.array_ )); break; - case value_t::table : assigner(table_ , std::move(v.table_ )); break; - default: break; - } - return *this; - } - - // overwrite comments ---------------------------------------------------- - - basic_value(const basic_value& v, std::vector com) - : type_(v.type()), region_info_(v.region_info_), - comments_(std::move(com)) - { - switch(v.type()) - { - case value_t::boolean : assigner(boolean_ , v.boolean_ ); break; - case value_t::integer : assigner(integer_ , v.integer_ ); break; - case value_t::floating : assigner(floating_ , v.floating_ ); break; - case value_t::string : assigner(string_ , v.string_ ); break; - case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break; - case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break; - case value_t::local_date : assigner(local_date_ , v.local_date_ ); break; - case value_t::local_time : assigner(local_time_ , v.local_time_ ); break; - case value_t::array : assigner(array_ , v.array_ ); break; - case value_t::table : assigner(table_ , v.table_ ); break; - default: break; - } - } - - basic_value(basic_value&& v, std::vector com) - : type_(v.type()), region_info_(std::move(v.region_info_)), - comments_(std::move(com)) - { - switch(this->type_) // here this->type_ is already initialized - { - case value_t::boolean : assigner(boolean_ , std::move(v.boolean_ )); break; - case value_t::integer : assigner(integer_ , std::move(v.integer_ )); break; - case value_t::floating : assigner(floating_ , std::move(v.floating_ )); break; - case value_t::string : assigner(string_ , std::move(v.string_ )); break; - case value_t::offset_datetime: assigner(offset_datetime_, std::move(v.offset_datetime_)); break; - case value_t::local_datetime : assigner(local_datetime_ , std::move(v.local_datetime_ )); break; - case value_t::local_date : assigner(local_date_ , std::move(v.local_date_ )); break; - case value_t::local_time : assigner(local_time_ , std::move(v.local_time_ )); break; - case value_t::array : assigner(array_ , std::move(v.array_ )); break; - case value_t::table : assigner(table_ , std::move(v.table_ )); break; - default: break; - } - } - - // ----------------------------------------------------------------------- - // conversion between different basic_values. - template class T, - template class A> - basic_value(const basic_value& v) - : type_(v.type()), region_info_(v.region_info_), comments_(v.comments()) - { - switch(v.type()) - { - case value_t::boolean : assigner(boolean_ , v.boolean_ ); break; - case value_t::integer : assigner(integer_ , v.integer_ ); break; - case value_t::floating : assigner(floating_ , v.floating_ ); break; - case value_t::string : assigner(string_ , v.string_ ); break; - case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break; - case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break; - case value_t::local_date : assigner(local_date_ , v.local_date_ ); break; - case value_t::local_time : assigner(local_time_ , v.local_time_ ); break; - case value_t::array : - { - array_type tmp(v.as_array(std::nothrow).begin(), - v.as_array(std::nothrow).end()); - assigner(array_, std::move(tmp)); - break; - } - case value_t::table : - { - table_type tmp(v.as_table(std::nothrow).begin(), - v.as_table(std::nothrow).end()); - assigner(table_, std::move(tmp)); - break; - } - default: break; - } - } - template class T, - template class A> - basic_value(const basic_value& v, std::vector com) - : type_(v.type()), region_info_(v.region_info_), - comments_(std::move(com)) - { - switch(v.type()) - { - case value_t::boolean : assigner(boolean_ , v.boolean_ ); break; - case value_t::integer : assigner(integer_ , v.integer_ ); break; - case value_t::floating : assigner(floating_ , v.floating_ ); break; - case value_t::string : assigner(string_ , v.string_ ); break; - case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break; - case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break; - case value_t::local_date : assigner(local_date_ , v.local_date_ ); break; - case value_t::local_time : assigner(local_time_ , v.local_time_ ); break; - case value_t::array : - { - array_type tmp(v.as_array(std::nothrow).begin(), - v.as_array(std::nothrow).end()); - assigner(array_, std::move(tmp)); - break; - } - case value_t::table : - { - table_type tmp(v.as_table(std::nothrow).begin(), - v.as_table(std::nothrow).end()); - assigner(table_, std::move(tmp)); - break; - } - default: break; - } - } - template class T, - template class A> - basic_value& operator=(const basic_value& v) - { - this->region_info_ = v.region_info_; - this->comments_ = comment_type(v.comments()); - this->type_ = v.type(); - switch(v.type()) - { - case value_t::boolean : assigner(boolean_ , v.boolean_ ); break; - case value_t::integer : assigner(integer_ , v.integer_ ); break; - case value_t::floating : assigner(floating_ , v.floating_ ); break; - case value_t::string : assigner(string_ , v.string_ ); break; - case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break; - case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break; - case value_t::local_date : assigner(local_date_ , v.local_date_ ); break; - case value_t::local_time : assigner(local_time_ , v.local_time_ ); break; - case value_t::array : - { - array_type tmp(v.as_array(std::nothrow).begin(), - v.as_array(std::nothrow).end()); - assigner(array_, std::move(tmp)); - break; - } - case value_t::table : - { - table_type tmp(v.as_table(std::nothrow).begin(), - v.as_table(std::nothrow).end()); - assigner(table_, std::move(tmp)); - break; - } - default: break; - } - return *this; - } - - // boolean ============================================================== - - basic_value(boolean b) - : type_(value_t::boolean), - region_info_(std::make_shared(region_base{})) - { - assigner(this->boolean_, b); - } - basic_value& operator=(boolean b) - { - this->cleanup(); - this->type_ = value_t::boolean; - this->region_info_ = std::make_shared(region_base{}); - assigner(this->boolean_, b); - return *this; - } - basic_value(boolean b, std::vector com) - : type_(value_t::boolean), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - assigner(this->boolean_, b); - } - - // integer ============================================================== - - template, detail::negation>>::value, - std::nullptr_t>::type = nullptr> - basic_value(T i) - : type_(value_t::integer), - region_info_(std::make_shared(region_base{})) - { - assigner(this->integer_, static_cast(i)); - } - - template, detail::negation>>::value, - std::nullptr_t>::type = nullptr> - basic_value& operator=(T i) - { - this->cleanup(); - this->type_ = value_t::integer; - this->region_info_ = std::make_shared(region_base{}); - assigner(this->integer_, static_cast(i)); - return *this; - } - - template, detail::negation>>::value, - std::nullptr_t>::type = nullptr> - basic_value(T i, std::vector com) - : type_(value_t::integer), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - assigner(this->integer_, static_cast(i)); - } - - // floating ============================================================= - - template::value, std::nullptr_t>::type = nullptr> - basic_value(T f) - : type_(value_t::floating), - region_info_(std::make_shared(region_base{})) - { - assigner(this->floating_, static_cast(f)); - } - - - template::value, std::nullptr_t>::type = nullptr> - basic_value& operator=(T f) - { - this->cleanup(); - this->type_ = value_t::floating; - this->region_info_ = std::make_shared(region_base{}); - assigner(this->floating_, static_cast(f)); - return *this; - } - - template::value, std::nullptr_t>::type = nullptr> - basic_value(T f, std::vector com) - : type_(value_t::floating), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - assigner(this->floating_, f); - } - - // string =============================================================== - - basic_value(toml::string s) - : type_(value_t::string), - region_info_(std::make_shared(region_base{})) - { - assigner(this->string_, std::move(s)); - } - basic_value& operator=(toml::string s) - { - this->cleanup(); - this->type_ = value_t::string ; - this->region_info_ = std::make_shared(region_base{}); - assigner(this->string_, s); - return *this; - } - basic_value(toml::string s, std::vector com) - : type_(value_t::string), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - assigner(this->string_, std::move(s)); - } - - basic_value(std::string s) - : type_(value_t::string), - region_info_(std::make_shared(region_base{})) - { - assigner(this->string_, toml::string(std::move(s))); - } - basic_value& operator=(std::string s) - { - this->cleanup(); - this->type_ = value_t::string ; - this->region_info_ = std::make_shared(region_base{}); - assigner(this->string_, toml::string(std::move(s))); - return *this; - } - basic_value(std::string s, string_t kind) - : type_(value_t::string), - region_info_(std::make_shared(region_base{})) - { - assigner(this->string_, toml::string(std::move(s), kind)); - } - basic_value(std::string s, std::vector com) - : type_(value_t::string), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - assigner(this->string_, toml::string(std::move(s))); - } - basic_value(std::string s, string_t kind, std::vector com) - : type_(value_t::string), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - assigner(this->string_, toml::string(std::move(s), kind)); - } - - basic_value(const char* s) - : type_(value_t::string), - region_info_(std::make_shared(region_base{})) - { - assigner(this->string_, toml::string(std::string(s))); - } - basic_value& operator=(const char* s) - { - this->cleanup(); - this->type_ = value_t::string ; - this->region_info_ = std::make_shared(region_base{}); - assigner(this->string_, toml::string(std::string(s))); - return *this; - } - basic_value(const char* s, string_t kind) - : type_(value_t::string), - region_info_(std::make_shared(region_base{})) - { - assigner(this->string_, toml::string(std::string(s), kind)); - } - basic_value(const char* s, std::vector com) - : type_(value_t::string), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - assigner(this->string_, toml::string(std::string(s))); - } - basic_value(const char* s, string_t kind, std::vector com) - : type_(value_t::string), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - assigner(this->string_, toml::string(std::string(s), kind)); - } - -#if defined(TOML11_USING_STRING_VIEW) && TOML11_USING_STRING_VIEW>0 - basic_value(std::string_view s) - : type_(value_t::string), - region_info_(std::make_shared(region_base{})) - { - assigner(this->string_, toml::string(s)); - } - basic_value& operator=(std::string_view s) - { - this->cleanup(); - this->type_ = value_t::string ; - this->region_info_ = std::make_shared(region_base{}); - assigner(this->string_, toml::string(s)); - return *this; - } - basic_value(std::string_view s, std::vector com) - : type_(value_t::string), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - assigner(this->string_, toml::string(s)); - } - basic_value(std::string_view s, string_t kind) - : type_(value_t::string), - region_info_(std::make_shared(region_base{})) - { - assigner(this->string_, toml::string(s, kind)); - } - basic_value(std::string_view s, string_t kind, std::vector com) - : type_(value_t::string), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - assigner(this->string_, toml::string(s, kind)); - } -#endif - - // local date =========================================================== - - basic_value(const local_date& ld) - : type_(value_t::local_date), - region_info_(std::make_shared(region_base{})) - { - assigner(this->local_date_, ld); - } - basic_value& operator=(const local_date& ld) - { - this->cleanup(); - this->type_ = value_t::local_date; - this->region_info_ = std::make_shared(region_base{}); - assigner(this->local_date_, ld); - return *this; - } - basic_value(const local_date& ld, std::vector com) - : type_(value_t::local_date), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - assigner(this->local_date_, ld); - } - - // local time =========================================================== - - basic_value(const local_time& lt) - : type_(value_t::local_time), - region_info_(std::make_shared(region_base{})) - { - assigner(this->local_time_, lt); - } - basic_value(const local_time& lt, std::vector com) - : type_(value_t::local_time), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - assigner(this->local_time_, lt); - } - basic_value& operator=(const local_time& lt) - { - this->cleanup(); - this->type_ = value_t::local_time; - this->region_info_ = std::make_shared(region_base{}); - assigner(this->local_time_, lt); - return *this; - } - - template - basic_value(const std::chrono::duration& dur) - : type_(value_t::local_time), - region_info_(std::make_shared(region_base{})) - { - assigner(this->local_time_, local_time(dur)); - } - template - basic_value(const std::chrono::duration& dur, - std::vector com) - : type_(value_t::local_time), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - assigner(this->local_time_, local_time(dur)); - } - template - basic_value& operator=(const std::chrono::duration& dur) - { - this->cleanup(); - this->type_ = value_t::local_time; - this->region_info_ = std::make_shared(region_base{}); - assigner(this->local_time_, local_time(dur)); - return *this; - } - - // local datetime ======================================================= - - basic_value(const local_datetime& ldt) - : type_(value_t::local_datetime), - region_info_(std::make_shared(region_base{})) - { - assigner(this->local_datetime_, ldt); - } - basic_value(const local_datetime& ldt, std::vector com) - : type_(value_t::local_datetime), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - assigner(this->local_datetime_, ldt); - } - basic_value& operator=(const local_datetime& ldt) - { - this->cleanup(); - this->type_ = value_t::local_datetime; - this->region_info_ = std::make_shared(region_base{}); - assigner(this->local_datetime_, ldt); - return *this; - } - - // offset datetime ====================================================== - - basic_value(const offset_datetime& odt) - : type_(value_t::offset_datetime), - region_info_(std::make_shared(region_base{})) - { - assigner(this->offset_datetime_, odt); - } - basic_value(const offset_datetime& odt, std::vector com) - : type_(value_t::offset_datetime), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - assigner(this->offset_datetime_, odt); - } - basic_value& operator=(const offset_datetime& odt) - { - this->cleanup(); - this->type_ = value_t::offset_datetime; - this->region_info_ = std::make_shared(region_base{}); - assigner(this->offset_datetime_, odt); - return *this; - } - basic_value(const std::chrono::system_clock::time_point& tp) - : type_(value_t::offset_datetime), - region_info_(std::make_shared(region_base{})) - { - assigner(this->offset_datetime_, offset_datetime(tp)); - } - basic_value(const std::chrono::system_clock::time_point& tp, - std::vector com) - : type_(value_t::offset_datetime), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - assigner(this->offset_datetime_, offset_datetime(tp)); - } - basic_value& operator=(const std::chrono::system_clock::time_point& tp) - { - this->cleanup(); - this->type_ = value_t::offset_datetime; - this->region_info_ = std::make_shared(region_base{}); - assigner(this->offset_datetime_, offset_datetime(tp)); - return *this; - } - - // array ================================================================ - - basic_value(const array_type& ary) - : type_(value_t::array), - region_info_(std::make_shared(region_base{})) - { - assigner(this->array_, ary); - } - basic_value(const array_type& ary, std::vector com) - : type_(value_t::array), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - assigner(this->array_, ary); - } - basic_value& operator=(const array_type& ary) - { - this->cleanup(); - this->type_ = value_t::array ; - this->region_info_ = std::make_shared(region_base{}); - assigner(this->array_, ary); - return *this; - } - - // array (initializer_list) ---------------------------------------------- - - template::value, - std::nullptr_t>::type = nullptr> - basic_value(std::initializer_list list) - : type_(value_t::array), - region_info_(std::make_shared(region_base{})) - { - array_type ary(list.begin(), list.end()); - assigner(this->array_, std::move(ary)); - } - template::value, - std::nullptr_t>::type = nullptr> - basic_value(std::initializer_list list, std::vector com) - : type_(value_t::array), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - array_type ary(list.begin(), list.end()); - assigner(this->array_, std::move(ary)); - } - template::value, - std::nullptr_t>::type = nullptr> - basic_value& operator=(std::initializer_list list) - { - this->cleanup(); - this->type_ = value_t::array; - this->region_info_ = std::make_shared(region_base{}); - - array_type ary(list.begin(), list.end()); - assigner(this->array_, std::move(ary)); - return *this; - } - - // array (STL Containers) ------------------------------------------------ - - template>, - detail::is_container - >::value, std::nullptr_t>::type = nullptr> - basic_value(const T& list) - : type_(value_t::array), - region_info_(std::make_shared(region_base{})) - { - static_assert(std::is_convertible::value, - "elements of a container should be convertible to toml::value"); - - array_type ary(list.size()); - std::copy(list.begin(), list.end(), ary.begin()); - assigner(this->array_, std::move(ary)); - } - template>, - detail::is_container - >::value, std::nullptr_t>::type = nullptr> - basic_value(const T& list, std::vector com) - : type_(value_t::array), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - static_assert(std::is_convertible::value, - "elements of a container should be convertible to toml::value"); - - array_type ary(list.size()); - std::copy(list.begin(), list.end(), ary.begin()); - assigner(this->array_, std::move(ary)); - } - template>, - detail::is_container - >::value, std::nullptr_t>::type = nullptr> - basic_value& operator=(const T& list) - { - static_assert(std::is_convertible::value, - "elements of a container should be convertible to toml::value"); - - this->cleanup(); - this->type_ = value_t::array; - this->region_info_ = std::make_shared(region_base{}); - - array_type ary(list.size()); - std::copy(list.begin(), list.end(), ary.begin()); - assigner(this->array_, std::move(ary)); - return *this; - } - - // table ================================================================ - - basic_value(const table_type& tab) - : type_(value_t::table), - region_info_(std::make_shared(region_base{})) - { - assigner(this->table_, tab); - } - basic_value(const table_type& tab, std::vector com) - : type_(value_t::table), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - assigner(this->table_, tab); - } - basic_value& operator=(const table_type& tab) - { - this->cleanup(); - this->type_ = value_t::table; - this->region_info_ = std::make_shared(region_base{}); - assigner(this->table_, tab); - return *this; - } - - // initializer-list ------------------------------------------------------ - - basic_value(std::initializer_list> list) - : type_(value_t::table), - region_info_(std::make_shared(region_base{})) - { - table_type tab; - for(const auto& elem : list) {tab[elem.first] = elem.second;} - assigner(this->table_, std::move(tab)); - } - - basic_value(std::initializer_list> list, - std::vector com) - : type_(value_t::table), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - table_type tab; - for(const auto& elem : list) {tab[elem.first] = elem.second;} - assigner(this->table_, std::move(tab)); - } - basic_value& operator=(std::initializer_list> list) - { - this->cleanup(); - this->type_ = value_t::table; - this->region_info_ = std::make_shared(region_base{}); - - table_type tab; - for(const auto& elem : list) {tab[elem.first] = elem.second;} - assigner(this->table_, std::move(tab)); - return *this; - } - - // other table-like ----------------------------------------------------- - - template>, - detail::is_map - >::value, std::nullptr_t>::type = nullptr> - basic_value(const Map& mp) - : type_(value_t::table), - region_info_(std::make_shared(region_base{})) - { - table_type tab; - for(const auto& elem : mp) {tab[elem.first] = elem.second;} - assigner(this->table_, std::move(tab)); - } - template>, - detail::is_map - >::value, std::nullptr_t>::type = nullptr> - basic_value(const Map& mp, std::vector com) - : type_(value_t::table), - region_info_(std::make_shared(region_base{})), - comments_(std::move(com)) - { - table_type tab; - for(const auto& elem : mp) {tab[elem.first] = elem.second;} - assigner(this->table_, std::move(tab)); - } - template>, - detail::is_map - >::value, std::nullptr_t>::type = nullptr> - basic_value& operator=(const Map& mp) - { - this->cleanup(); - this->type_ = value_t::table; - this->region_info_ = std::make_shared(region_base{}); - - table_type tab; - for(const auto& elem : mp) {tab[elem.first] = elem.second;} - assigner(this->table_, std::move(tab)); - return *this; - } - - // user-defined ========================================================= - - // convert using into_toml() method ------------------------------------- - - template::value, std::nullptr_t>::type = nullptr> - basic_value(const T& ud): basic_value(ud.into_toml()) {} - - template::value, std::nullptr_t>::type = nullptr> - basic_value(const T& ud, std::vector com) - : basic_value(ud.into_toml(), std::move(com)) - {} - template::value, std::nullptr_t>::type = nullptr> - basic_value& operator=(const T& ud) - { - *this = ud.into_toml(); - return *this; - } - - // convert using into struct ----------------------------------------- - - template)> - basic_value(const T& ud): basic_value(::toml::into::into_toml(ud)) {} - template)> - basic_value(const T& ud, std::vector com) - : basic_value(::toml::into::into_toml(ud), std::move(com)) - {} - template)> - basic_value& operator=(const T& ud) - { - *this = ::toml::into::into_toml(ud); - return *this; - } - - // for internal use ------------------------------------------------------ - // - // Those constructors take detail::region that contains parse result. - - basic_value(boolean b, detail::region reg, std::vector cm) - : type_(value_t::boolean), - region_info_(std::make_shared(std::move(reg))), - comments_(std::move(cm)) - { - assigner(this->boolean_, b); - } - template, detail::negation> - >::value, std::nullptr_t>::type = nullptr> - basic_value(T i, detail::region reg, std::vector cm) - : type_(value_t::integer), - region_info_(std::make_shared(std::move(reg))), - comments_(std::move(cm)) - { - assigner(this->integer_, static_cast(i)); - } - template::value, std::nullptr_t>::type = nullptr> - basic_value(T f, detail::region reg, std::vector cm) - : type_(value_t::floating), - region_info_(std::make_shared(std::move(reg))), - comments_(std::move(cm)) - { - assigner(this->floating_, static_cast(f)); - } - basic_value(toml::string s, detail::region reg, - std::vector cm) - : type_(value_t::string), - region_info_(std::make_shared(std::move(reg))), - comments_(std::move(cm)) - { - assigner(this->string_, std::move(s)); - } - basic_value(const local_date& ld, detail::region reg, - std::vector cm) - : type_(value_t::local_date), - region_info_(std::make_shared(std::move(reg))), - comments_(std::move(cm)) - { - assigner(this->local_date_, ld); - } - basic_value(const local_time& lt, detail::region reg, - std::vector cm) - : type_(value_t::local_time), - region_info_(std::make_shared(std::move(reg))), - comments_(std::move(cm)) - { - assigner(this->local_time_, lt); - } - basic_value(const local_datetime& ldt, detail::region reg, - std::vector cm) - : type_(value_t::local_datetime), - region_info_(std::make_shared(std::move(reg))), - comments_(std::move(cm)) - { - assigner(this->local_datetime_, ldt); - } - basic_value(const offset_datetime& odt, detail::region reg, - std::vector cm) - : type_(value_t::offset_datetime), - region_info_(std::make_shared(std::move(reg))), - comments_(std::move(cm)) - { - assigner(this->offset_datetime_, odt); - } - basic_value(const array_type& ary, detail::region reg, - std::vector cm) - : type_(value_t::array), - region_info_(std::make_shared(std::move(reg))), - comments_(std::move(cm)) - { - assigner(this->array_, ary); - } - basic_value(const table_type& tab, detail::region reg, - std::vector cm) - : type_(value_t::table), - region_info_(std::make_shared(std::move(reg))), - comments_(std::move(cm)) - { - assigner(this->table_, tab); - } - - template::value, - std::nullptr_t>::type = nullptr> - basic_value(std::pair parse_result, std::vector com) - : basic_value(std::move(parse_result.first), - std::move(parse_result.second), - std::move(com)) - {} - - // type checking and casting ============================================ - - template::value, - std::nullptr_t>::type = nullptr> - bool is() const noexcept - { - return detail::type_to_enum::value == this->type_; - } - bool is(value_t t) const noexcept {return t == this->type_;} - - bool is_uninitialized() const noexcept {return this->is(value_t::empty );} - bool is_boolean() const noexcept {return this->is(value_t::boolean );} - bool is_integer() const noexcept {return this->is(value_t::integer );} - bool is_floating() const noexcept {return this->is(value_t::floating );} - bool is_string() const noexcept {return this->is(value_t::string );} - bool is_offset_datetime() const noexcept {return this->is(value_t::offset_datetime);} - bool is_local_datetime() const noexcept {return this->is(value_t::local_datetime );} - bool is_local_date() const noexcept {return this->is(value_t::local_date );} - bool is_local_time() const noexcept {return this->is(value_t::local_time );} - bool is_array() const noexcept {return this->is(value_t::array );} - bool is_table() const noexcept {return this->is(value_t::table );} - - value_t type() const noexcept {return type_;} - - template - typename detail::enum_to_type::type& cast() & - { - if(this->type_ != T) - { - detail::throw_bad_cast("toml::value::cast: ", this->type_, *this); - } - return detail::switch_cast::invoke(*this); - } - template - typename detail::enum_to_type::type const& cast() const& - { - if(this->type_ != T) - { - detail::throw_bad_cast("toml::value::cast: ", this->type_, *this); - } - return detail::switch_cast::invoke(*this); - } - template - typename detail::enum_to_type::type&& cast() && - { - if(this->type_ != T) - { - detail::throw_bad_cast("toml::value::cast: ", this->type_, *this); - } - return detail::switch_cast::invoke(std::move(*this)); - } - - // ------------------------------------------------------------------------ - // nothrow version - - boolean const& as_boolean (const std::nothrow_t&) const& noexcept {return this->boolean_;} - integer const& as_integer (const std::nothrow_t&) const& noexcept {return this->integer_;} - floating const& as_floating (const std::nothrow_t&) const& noexcept {return this->floating_;} - string const& as_string (const std::nothrow_t&) const& noexcept {return this->string_;} - offset_datetime const& as_offset_datetime(const std::nothrow_t&) const& noexcept {return this->offset_datetime_;} - local_datetime const& as_local_datetime (const std::nothrow_t&) const& noexcept {return this->local_datetime_;} - local_date const& as_local_date (const std::nothrow_t&) const& noexcept {return this->local_date_;} - local_time const& as_local_time (const std::nothrow_t&) const& noexcept {return this->local_time_;} - array_type const& as_array (const std::nothrow_t&) const& noexcept {return this->array_.value();} - table_type const& as_table (const std::nothrow_t&) const& noexcept {return this->table_.value();} - - boolean & as_boolean (const std::nothrow_t&) & noexcept {return this->boolean_;} - integer & as_integer (const std::nothrow_t&) & noexcept {return this->integer_;} - floating & as_floating (const std::nothrow_t&) & noexcept {return this->floating_;} - string & as_string (const std::nothrow_t&) & noexcept {return this->string_;} - offset_datetime& as_offset_datetime(const std::nothrow_t&) & noexcept {return this->offset_datetime_;} - local_datetime & as_local_datetime (const std::nothrow_t&) & noexcept {return this->local_datetime_;} - local_date & as_local_date (const std::nothrow_t&) & noexcept {return this->local_date_;} - local_time & as_local_time (const std::nothrow_t&) & noexcept {return this->local_time_;} - array_type & as_array (const std::nothrow_t&) & noexcept {return this->array_.value();} - table_type & as_table (const std::nothrow_t&) & noexcept {return this->table_.value();} - - boolean && as_boolean (const std::nothrow_t&) && noexcept {return std::move(this->boolean_);} - integer && as_integer (const std::nothrow_t&) && noexcept {return std::move(this->integer_);} - floating && as_floating (const std::nothrow_t&) && noexcept {return std::move(this->floating_);} - string && as_string (const std::nothrow_t&) && noexcept {return std::move(this->string_);} - offset_datetime&& as_offset_datetime(const std::nothrow_t&) && noexcept {return std::move(this->offset_datetime_);} - local_datetime && as_local_datetime (const std::nothrow_t&) && noexcept {return std::move(this->local_datetime_);} - local_date && as_local_date (const std::nothrow_t&) && noexcept {return std::move(this->local_date_);} - local_time && as_local_time (const std::nothrow_t&) && noexcept {return std::move(this->local_time_);} - array_type && as_array (const std::nothrow_t&) && noexcept {return std::move(this->array_.value());} - table_type && as_table (const std::nothrow_t&) && noexcept {return std::move(this->table_.value());} - - // ======================================================================== - // throw version - // ------------------------------------------------------------------------ - // const reference {{{ - - boolean const& as_boolean() const& - { - if(this->type_ != value_t::boolean) - { - detail::throw_bad_cast( - "toml::value::as_boolean(): ", this->type_, *this); - } - return this->boolean_; - } - integer const& as_integer() const& - { - if(this->type_ != value_t::integer) - { - detail::throw_bad_cast( - "toml::value::as_integer(): ", this->type_, *this); - } - return this->integer_; - } - floating const& as_floating() const& - { - if(this->type_ != value_t::floating) - { - detail::throw_bad_cast( - "toml::value::as_floating(): ", this->type_, *this); - } - return this->floating_; - } - string const& as_string() const& - { - if(this->type_ != value_t::string) - { - detail::throw_bad_cast( - "toml::value::as_string(): ", this->type_, *this); - } - return this->string_; - } - offset_datetime const& as_offset_datetime() const& - { - if(this->type_ != value_t::offset_datetime) - { - detail::throw_bad_cast( - "toml::value::as_offset_datetime(): ", this->type_, *this); - } - return this->offset_datetime_; - } - local_datetime const& as_local_datetime() const& - { - if(this->type_ != value_t::local_datetime) - { - detail::throw_bad_cast( - "toml::value::as_local_datetime(): ", this->type_, *this); - } - return this->local_datetime_; - } - local_date const& as_local_date() const& - { - if(this->type_ != value_t::local_date) - { - detail::throw_bad_cast( - "toml::value::as_local_date(): ", this->type_, *this); - } - return this->local_date_; - } - local_time const& as_local_time() const& - { - if(this->type_ != value_t::local_time) - { - detail::throw_bad_cast( - "toml::value::as_local_time(): ", this->type_, *this); - } - return this->local_time_; - } - array_type const& as_array() const& - { - if(this->type_ != value_t::array) - { - detail::throw_bad_cast( - "toml::value::as_array(): ", this->type_, *this); - } - return this->array_.value(); - } - table_type const& as_table() const& - { - if(this->type_ != value_t::table) - { - detail::throw_bad_cast( - "toml::value::as_table(): ", this->type_, *this); - } - return this->table_.value(); - } - // }}} - // ------------------------------------------------------------------------ - // nonconst reference {{{ - - boolean & as_boolean() & - { - if(this->type_ != value_t::boolean) - { - detail::throw_bad_cast( - "toml::value::as_boolean(): ", this->type_, *this); - } - return this->boolean_; - } - integer & as_integer() & - { - if(this->type_ != value_t::integer) - { - detail::throw_bad_cast( - "toml::value::as_integer(): ", this->type_, *this); - } - return this->integer_; - } - floating & as_floating() & - { - if(this->type_ != value_t::floating) - { - detail::throw_bad_cast( - "toml::value::as_floating(): ", this->type_, *this); - } - return this->floating_; - } - string & as_string() & - { - if(this->type_ != value_t::string) - { - detail::throw_bad_cast( - "toml::value::as_string(): ", this->type_, *this); - } - return this->string_; - } - offset_datetime & as_offset_datetime() & - { - if(this->type_ != value_t::offset_datetime) - { - detail::throw_bad_cast( - "toml::value::as_offset_datetime(): ", this->type_, *this); - } - return this->offset_datetime_; - } - local_datetime & as_local_datetime() & - { - if(this->type_ != value_t::local_datetime) - { - detail::throw_bad_cast( - "toml::value::as_local_datetime(): ", this->type_, *this); - } - return this->local_datetime_; - } - local_date & as_local_date() & - { - if(this->type_ != value_t::local_date) - { - detail::throw_bad_cast( - "toml::value::as_local_date(): ", this->type_, *this); - } - return this->local_date_; - } - local_time & as_local_time() & - { - if(this->type_ != value_t::local_time) - { - detail::throw_bad_cast( - "toml::value::as_local_time(): ", this->type_, *this); - } - return this->local_time_; - } - array_type & as_array() & - { - if(this->type_ != value_t::array) - { - detail::throw_bad_cast( - "toml::value::as_array(): ", this->type_, *this); - } - return this->array_.value(); - } - table_type & as_table() & - { - if(this->type_ != value_t::table) - { - detail::throw_bad_cast( - "toml::value::as_table(): ", this->type_, *this); - } - return this->table_.value(); - } - - // }}} - // ------------------------------------------------------------------------ - // rvalue reference {{{ - - boolean && as_boolean() && - { - if(this->type_ != value_t::boolean) - { - detail::throw_bad_cast( - "toml::value::as_boolean(): ", this->type_, *this); - } - return std::move(this->boolean_); - } - integer && as_integer() && - { - if(this->type_ != value_t::integer) - { - detail::throw_bad_cast( - "toml::value::as_integer(): ", this->type_, *this); - } - return std::move(this->integer_); - } - floating && as_floating() && - { - if(this->type_ != value_t::floating) - { - detail::throw_bad_cast( - "toml::value::as_floating(): ", this->type_, *this); - } - return std::move(this->floating_); - } - string && as_string() && - { - if(this->type_ != value_t::string) - { - detail::throw_bad_cast( - "toml::value::as_string(): ", this->type_, *this); - } - return std::move(this->string_); - } - offset_datetime && as_offset_datetime() && - { - if(this->type_ != value_t::offset_datetime) - { - detail::throw_bad_cast( - "toml::value::as_offset_datetime(): ", this->type_, *this); - } - return std::move(this->offset_datetime_); - } - local_datetime && as_local_datetime() && - { - if(this->type_ != value_t::local_datetime) - { - detail::throw_bad_cast( - "toml::value::as_local_datetime(): ", this->type_, *this); - } - return std::move(this->local_datetime_); - } - local_date && as_local_date() && - { - if(this->type_ != value_t::local_date) - { - detail::throw_bad_cast( - "toml::value::as_local_date(): ", this->type_, *this); - } - return std::move(this->local_date_); - } - local_time && as_local_time() && - { - if(this->type_ != value_t::local_time) - { - detail::throw_bad_cast( - "toml::value::as_local_time(): ", this->type_, *this); - } - return std::move(this->local_time_); - } - array_type && as_array() && - { - if(this->type_ != value_t::array) - { - detail::throw_bad_cast( - "toml::value::as_array(): ", this->type_, *this); - } - return std::move(this->array_.value()); - } - table_type && as_table() && - { - if(this->type_ != value_t::table) - { - detail::throw_bad_cast( - "toml::value::as_table(): ", this->type_, *this); - } - return std::move(this->table_.value()); - } - // }}} - - // accessors ============================================================= - // - // may throw type_error or out_of_range - // - value_type& at(const key& k) - { - if(!this->is_table()) - { - detail::throw_bad_cast( - "toml::value::at(key): ", this->type_, *this); - } - if(this->as_table(std::nothrow).count(k) == 0) - { - detail::throw_key_not_found_error(*this, k); - } - return this->as_table(std::nothrow).at(k); - } - value_type const& at(const key& k) const - { - if(!this->is_table()) - { - detail::throw_bad_cast( - "toml::value::at(key): ", this->type_, *this); - } - if(this->as_table(std::nothrow).count(k) == 0) - { - detail::throw_key_not_found_error(*this, k); - } - return this->as_table(std::nothrow).at(k); - } - value_type& operator[](const key& k) - { - if(this->is_uninitialized()) - { - *this = table_type{}; - } - else if(!this->is_table()) // initialized, but not a table - { - detail::throw_bad_cast( - "toml::value::operator[](key): ", this->type_, *this); - } - return this->as_table(std::nothrow)[k]; - } - - value_type& at(const std::size_t idx) - { - if(!this->is_array()) - { - detail::throw_bad_cast( - "toml::value::at(idx): ", this->type_, *this); - } - if(this->as_array(std::nothrow).size() <= idx) - { - throw std::out_of_range(detail::format_underline( - "toml::value::at(idx): no element corresponding to the index", { - {this->location(), concat_to_string("the length is ", - this->as_array(std::nothrow).size(), - ", and the specified index is ", idx)} - })); - } - return this->as_array().at(idx); - } - value_type const& at(const std::size_t idx) const - { - if(!this->is_array()) - { - detail::throw_bad_cast( - "toml::value::at(idx): ", this->type_, *this); - } - if(this->as_array(std::nothrow).size() <= idx) - { - throw std::out_of_range(detail::format_underline( - "toml::value::at(idx): no element corresponding to the index", { - {this->location(), concat_to_string("the length is ", - this->as_array(std::nothrow).size(), - ", and the specified index is ", idx)} - })); - } - return this->as_array(std::nothrow).at(idx); - } - - value_type& operator[](const std::size_t idx) noexcept - { - // no check... - return this->as_array(std::nothrow)[idx]; - } - value_type const& operator[](const std::size_t idx) const noexcept - { - // no check... - return this->as_array(std::nothrow)[idx]; - } - - void push_back(const value_type& x) - { - if(!this->is_array()) - { - detail::throw_bad_cast( - "toml::value::push_back(value): ", this->type_, *this); - } - this->as_array(std::nothrow).push_back(x); - return; - } - void push_back(value_type&& x) - { - if(!this->is_array()) - { - detail::throw_bad_cast( - "toml::value::push_back(value): ", this->type_, *this); - } - this->as_array(std::nothrow).push_back(std::move(x)); - return; - } - - template - value_type& emplace_back(Ts&& ... args) - { - if(!this->is_array()) - { - detail::throw_bad_cast( - "toml::value::emplace_back(...): ", this->type_, *this); - } - this->as_array(std::nothrow).emplace_back(std::forward(args) ...); - return this->as_array(std::nothrow).back(); - } - - std::size_t size() const - { - switch(this->type_) - { - case value_t::array: - { - return this->as_array(std::nothrow).size(); - } - case value_t::table: - { - return this->as_table(std::nothrow).size(); - } - case value_t::string: - { - return this->as_string(std::nothrow).str.size(); - } - default: - { - throw type_error(detail::format_underline( - "toml::value::size(): bad_cast to container types", { - {this->location(), - concat_to_string("the actual type is ", this->type_)} - }), this->location()); - } - } - } - - std::size_t count(const key_type& k) const - { - if(!this->is_table()) - { - detail::throw_bad_cast( - "toml::value::count(key): ", this->type_, *this); - } - return this->as_table(std::nothrow).count(k); - } - - bool contains(const key_type& k) const - { - if(!this->is_table()) - { - detail::throw_bad_cast( - "toml::value::contains(key): ", this->type_, *this); - } - return (this->as_table(std::nothrow).count(k) != 0); - } - - source_location location() const - { - return source_location(this->region_info_.get()); - } - - comment_type const& comments() const noexcept {return this->comments_;} - comment_type& comments() noexcept {return this->comments_;} - - private: - - void cleanup() noexcept - { - switch(this->type_) - { - case value_t::string : {string_.~string(); return;} - case value_t::array : {array_.~array_storage(); return;} - case value_t::table : {table_.~table_storage(); return;} - default : return; - } - } - - // for error messages - template - friend region_base const* detail::get_region(const Value& v); - - template - friend void detail::change_region(Value& v, detail::region reg); - - private: - - using array_storage = detail::storage; - using table_storage = detail::storage; - - value_t type_; - union - { - boolean boolean_; - integer integer_; - floating floating_; - string string_; - offset_datetime offset_datetime_; - local_datetime local_datetime_; - local_date local_date_; - local_time local_time_; - array_storage array_; - table_storage table_; - }; - std::shared_ptr region_info_; - comment_type comments_; -}; - -// default toml::value and default array/table. -// TOML11_DEFAULT_COMMENT_STRATEGY is defined in comments.hpp -using value = basic_value; -using array = typename value::array_type; -using table = typename value::table_type; - -template class T, template class A> -inline bool -operator==(const basic_value& lhs, const basic_value& rhs) -{ - if(lhs.type() != rhs.type()) {return false;} - if(lhs.comments() != rhs.comments()) {return false;} - - switch(lhs.type()) - { - case value_t::boolean : - { - return lhs.as_boolean() == rhs.as_boolean(); - } - case value_t::integer : - { - return lhs.as_integer() == rhs.as_integer(); - } - case value_t::floating : - { - return lhs.as_floating() == rhs.as_floating(); - } - case value_t::string : - { - return lhs.as_string() == rhs.as_string(); - } - case value_t::offset_datetime: - { - return lhs.as_offset_datetime() == rhs.as_offset_datetime(); - } - case value_t::local_datetime: - { - return lhs.as_local_datetime() == rhs.as_local_datetime(); - } - case value_t::local_date: - { - return lhs.as_local_date() == rhs.as_local_date(); - } - case value_t::local_time: - { - return lhs.as_local_time() == rhs.as_local_time(); - } - case value_t::array : - { - return lhs.as_array() == rhs.as_array(); - } - case value_t::table : - { - return lhs.as_table() == rhs.as_table(); - } - case value_t::empty : {return true; } - default: {return false;} - } -} - -template class T, template class A> -inline bool operator!=(const basic_value& lhs, const basic_value& rhs) -{ - return !(lhs == rhs); -} - -template class T, template class A> -typename std::enable_if::array_type>, - detail::is_comparable::table_type> - >::value, bool>::type -operator<(const basic_value& lhs, const basic_value& rhs) -{ - if(lhs.type() != rhs.type()){return (lhs.type() < rhs.type());} - switch(lhs.type()) - { - case value_t::boolean : - { - return lhs.as_boolean() < rhs.as_boolean() || - (lhs.as_boolean() == rhs.as_boolean() && - lhs.comments() < rhs.comments()); - } - case value_t::integer : - { - return lhs.as_integer() < rhs.as_integer() || - (lhs.as_integer() == rhs.as_integer() && - lhs.comments() < rhs.comments()); - } - case value_t::floating : - { - return lhs.as_floating() < rhs.as_floating() || - (lhs.as_floating() == rhs.as_floating() && - lhs.comments() < rhs.comments()); - } - case value_t::string : - { - return lhs.as_string() < rhs.as_string() || - (lhs.as_string() == rhs.as_string() && - lhs.comments() < rhs.comments()); - } - case value_t::offset_datetime: - { - return lhs.as_offset_datetime() < rhs.as_offset_datetime() || - (lhs.as_offset_datetime() == rhs.as_offset_datetime() && - lhs.comments() < rhs.comments()); - } - case value_t::local_datetime: - { - return lhs.as_local_datetime() < rhs.as_local_datetime() || - (lhs.as_local_datetime() == rhs.as_local_datetime() && - lhs.comments() < rhs.comments()); - } - case value_t::local_date: - { - return lhs.as_local_date() < rhs.as_local_date() || - (lhs.as_local_date() == rhs.as_local_date() && - lhs.comments() < rhs.comments()); - } - case value_t::local_time: - { - return lhs.as_local_time() < rhs.as_local_time() || - (lhs.as_local_time() == rhs.as_local_time() && - lhs.comments() < rhs.comments()); - } - case value_t::array : - { - return lhs.as_array() < rhs.as_array() || - (lhs.as_array() == rhs.as_array() && - lhs.comments() < rhs.comments()); - } - case value_t::table : - { - return lhs.as_table() < rhs.as_table() || - (lhs.as_table() == rhs.as_table() && - lhs.comments() < rhs.comments()); - } - case value_t::empty : - { - return lhs.comments() < rhs.comments(); - } - default: - { - return lhs.comments() < rhs.comments(); - } - } -} - -template class T, template class A> -typename std::enable_if::array_type>, - detail::is_comparable::table_type> - >::value, bool>::type -operator<=(const basic_value& lhs, const basic_value& rhs) -{ - return (lhs < rhs) || (lhs == rhs); -} -template class T, template class A> -typename std::enable_if::array_type>, - detail::is_comparable::table_type> - >::value, bool>::type -operator>(const basic_value& lhs, const basic_value& rhs) -{ - return !(lhs <= rhs); -} -template class T, template class A> -typename std::enable_if::array_type>, - detail::is_comparable::table_type> - >::value, bool>::type -operator>=(const basic_value& lhs, const basic_value& rhs) -{ - return !(lhs < rhs); -} - -template class T, template class A> -inline std::string format_error(const std::string& err_msg, - const basic_value& v, const std::string& comment, - std::vector hints = {}, - const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED) -{ - return detail::format_underline(err_msg, {{v.location(), comment}}, - std::move(hints), colorize); -} - -template class T, template class A> -inline std::string format_error(const std::string& err_msg, - const toml::basic_value& v1, const std::string& comment1, - const toml::basic_value& v2, const std::string& comment2, - std::vector hints = {}, - const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED) -{ - return detail::format_underline(err_msg, { - {v1.location(), comment1}, {v2.location(), comment2} - }, std::move(hints), colorize); -} - -template class T, template class A> -inline std::string format_error(const std::string& err_msg, - const toml::basic_value& v1, const std::string& comment1, - const toml::basic_value& v2, const std::string& comment2, - const toml::basic_value& v3, const std::string& comment3, - std::vector hints = {}, - const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED) -{ - return detail::format_underline(err_msg, {{v1.location(), comment1}, - {v2.location(), comment2}, {v3.location(), comment3} - }, std::move(hints), colorize); -} - -template class T, template class A> -detail::return_type_of_t -visit(Visitor&& visitor, const toml::basic_value& v) -{ - switch(v.type()) - { - case value_t::boolean : {return visitor(v.as_boolean ());} - case value_t::integer : {return visitor(v.as_integer ());} - case value_t::floating : {return visitor(v.as_floating ());} - case value_t::string : {return visitor(v.as_string ());} - case value_t::offset_datetime: {return visitor(v.as_offset_datetime());} - case value_t::local_datetime : {return visitor(v.as_local_datetime ());} - case value_t::local_date : {return visitor(v.as_local_date ());} - case value_t::local_time : {return visitor(v.as_local_time ());} - case value_t::array : {return visitor(v.as_array ());} - case value_t::table : {return visitor(v.as_table ());} - case value_t::empty : break; - default: break; - } - throw std::runtime_error(format_error("[error] toml::visit: toml::basic_value " - "does not have any valid basic_value.", v, "here")); -} - -template class T, template class A> -detail::return_type_of_t -visit(Visitor&& visitor, toml::basic_value& v) -{ - switch(v.type()) - { - case value_t::boolean : {return visitor(v.as_boolean ());} - case value_t::integer : {return visitor(v.as_integer ());} - case value_t::floating : {return visitor(v.as_floating ());} - case value_t::string : {return visitor(v.as_string ());} - case value_t::offset_datetime: {return visitor(v.as_offset_datetime());} - case value_t::local_datetime : {return visitor(v.as_local_datetime ());} - case value_t::local_date : {return visitor(v.as_local_date ());} - case value_t::local_time : {return visitor(v.as_local_time ());} - case value_t::array : {return visitor(v.as_array ());} - case value_t::table : {return visitor(v.as_table ());} - case value_t::empty : break; - default: break; - } - throw std::runtime_error(format_error("[error] toml::visit: toml::basic_value " - "does not have any valid basic_value.", v, "here")); -} - -template class T, template class A> -detail::return_type_of_t -visit(Visitor&& visitor, toml::basic_value&& v) -{ - switch(v.type()) - { - case value_t::boolean : {return visitor(std::move(v.as_boolean ()));} - case value_t::integer : {return visitor(std::move(v.as_integer ()));} - case value_t::floating : {return visitor(std::move(v.as_floating ()));} - case value_t::string : {return visitor(std::move(v.as_string ()));} - case value_t::offset_datetime: {return visitor(std::move(v.as_offset_datetime()));} - case value_t::local_datetime : {return visitor(std::move(v.as_local_datetime ()));} - case value_t::local_date : {return visitor(std::move(v.as_local_date ()));} - case value_t::local_time : {return visitor(std::move(v.as_local_time ()));} - case value_t::array : {return visitor(std::move(v.as_array ()));} - case value_t::table : {return visitor(std::move(v.as_table ()));} - case value_t::empty : break; - default: break; - } - throw std::runtime_error(format_error("[error] toml::visit: toml::basic_value " - "does not have any valid basic_value.", v, "here")); -} - -}// toml -#endif// TOML11_VALUE diff --git a/lib/toml/toml/version.hpp b/lib/toml/toml/version.hpp deleted file mode 100644 index 9cbfa39..0000000 --- a/lib/toml/toml/version.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef TOML11_VERSION_HPP -#define TOML11_VERSION_HPP - -// This file checks C++ version. - -#ifndef __cplusplus -# error "__cplusplus is not defined" -#endif - -// Since MSVC does not define `__cplusplus` correctly unless you pass -// `/Zc:__cplusplus` when compiling, the workaround macros are added. -// Those enables you to define version manually or to use MSVC specific -// version macro automatically. -// -// The value of `__cplusplus` macro is defined in the C++ standard spec, but -// MSVC ignores the value, maybe because of backward compatibility. Instead, -// MSVC defines _MSVC_LANG that has the same value as __cplusplus defined in -// the C++ standard. First we check the manual version definition, and then -// we check if _MSVC_LANG is defined. If neither, use normal `__cplusplus`. -// -// FYI: https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus?view=msvc-170 -// https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=msvc-170 -// -#if defined(TOML11_ENFORCE_CXX11) -# define TOML11_CPLUSPLUS_STANDARD_VERSION 201103L -#elif defined(TOML11_ENFORCE_CXX14) -# define TOML11_CPLUSPLUS_STANDARD_VERSION 201402L -#elif defined(TOML11_ENFORCE_CXX17) -# define TOML11_CPLUSPLUS_STANDARD_VERSION 201703L -#elif defined(TOML11_ENFORCE_CXX20) -# define TOML11_CPLUSPLUS_STANDARD_VERSION 202002L -#elif defined(_MSVC_LANG) && defined(_MSC_VER) && 1910 <= _MSC_VER -# define TOML11_CPLUSPLUS_STANDARD_VERSION _MSVC_LANG -#else -# define TOML11_CPLUSPLUS_STANDARD_VERSION __cplusplus -#endif - -#if TOML11_CPLUSPLUS_STANDARD_VERSION < 201103L && _MSC_VER < 1900 -# error "toml11 requires C++11 or later." -#endif - -#endif// TOML11_VERSION_HPP diff --git a/src/main.cpp b/src/main.cpp index ecb9404..de2a9b2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,7 +6,7 @@ int main(int argc, char *argv[]) Settings &settings = Settings::Instance(); command = Command(); - home_dir = settings.getSetting("autom_home_dir"); + home_dir = settings.value["autom_home_dir"]; input(argc, argv); return 0; @@ -40,11 +40,11 @@ void runScript(int argc, char *argv[]) { std::map dir_options; - std::string dir = home_dir; + std::string dir = home_dir; - for (auto search_dir : settings.getSetting>("search_dirs")) + for (auto search_dir : settings.value["search_dirs"]) { - if (std::filesystem::exists(search_dir + "/" + argv[1])) + if (std::filesystem::exists((std::string)search_dir + "/" + argv[1])) { dir_options[dir_options.size()] = search_dir; } @@ -99,9 +99,9 @@ void showScript(int argc, char *argv[]) std::map dir_options; std::string dir = ""; - for (auto search_dir : settings.getSetting>("search_dirs")) + for (auto search_dir : settings.value["search_dirs"]) { - if (std::filesystem::exists(search_dir + "/" + argv[1])) + if (std::filesystem::exists((std::string)search_dir + "/" + argv[1])) { dir_options[dir_options.size()] = search_dir; } @@ -155,9 +155,7 @@ void showScript(int argc, char *argv[]) void listScripts(int argc, char *argv[]) { - std::vector search_dirs = settings.getSetting>("search_dirs"); - - for (auto &search_dir : search_dirs) + for (auto &search_dir : settings.value["search_dirs"]) { std::cout << "Scripts (" << search_dir << "):" << std::endl; for (const auto &entry : std::filesystem::directory_iterator(search_dir)) @@ -177,10 +175,10 @@ void addScript(int argc, char *argv[]) { std::string dir = home_dir; - if (settings.getSetting>("search_dirs").size() > 1) + if (settings.value["search_dirs"].size() > 1) { std::cout << "Which directory do you want to add the script to?" << std::endl; - std::vector search_dirs = settings.getSetting>("search_dirs"); + auto search_dirs = settings.value["search_dirs"]; for (int i = 0; i < search_dirs.size(); i++) { std::cout << i << " " << search_dirs[i] << std::endl; @@ -219,11 +217,11 @@ void editScript(int argc, char *argv[]) { std::map dir_options; - std::string dir = home_dir; + std::string dir = home_dir; - for (auto search_dir : settings.getSetting>("search_dirs")) + for (auto search_dir : settings.value["search_dirs"]) { - if (std::filesystem::exists(search_dir + "/" + argv[1])) + if (std::filesystem::exists((std::string)search_dir + "/" + argv[1])) { dir_options[dir_options.size()] = search_dir; } @@ -260,18 +258,18 @@ void editScript(std::string name, std::string dir) { std::string script = dir + "/" + name; - system((settings.getSetting("editor") + " " + script).c_str()); + system(((std::string)settings.value["editor"] + " " + script).c_str()); } void removeScript(int argc, char *argv[]) { std::map dir_options; - std::string dir = home_dir; + std::string dir = home_dir; - for (auto search_dir : settings.getSetting>("search_dirs")) + for (auto search_dir : settings.value["search_dirs"]) { - if (std::filesystem::exists(search_dir + "/" + argv[1])) + if (std::filesystem::exists((std::string)search_dir + "/" + argv[1])) { dir_options[dir_options.size()] = search_dir; } diff --git a/src/settings.cpp b/src/settings.cpp index 9aa882e..83e8113 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -16,12 +16,12 @@ Settings::~Settings(void) void Settings::readSettings() { - std::ifstream file(setup.home + "/.automconfig.toml"); + std::ifstream file(setup.home + "/.automconfig.json"); if (!file.is_open()) { - std::cout << "Error:" + setup.home + "/.automconfig.toml not found" << std::endl; + std::cout << "Error:" + setup.home + "/.automconfig.json not found" << std::endl; setup.createSettings(); readSettings(); } - this->value = toml::parse(file); + this->value = json::parse(file); } \ No newline at end of file diff --git a/src/settings.h b/src/settings.h index ca82353..d78ebb5 100644 --- a/src/settings.h +++ b/src/settings.h @@ -3,7 +3,9 @@ #ifndef SETTINGS_H #define SETTINGS_H -#include "../lib/toml/toml.hpp" +#include + +using json = nlohmann::json; #ifdef _WIN32 #include @@ -20,21 +22,14 @@ class Settings : public Singleton { private: - std::string settings_name = ".automconfig.toml"; - toml::value value; + std::string settings_name = ".automconfig.json"; public: + json value; Settings(void); ~Settings(void); void readSettings(); Settings &operator=(const Settings &) = default; - -template -T getSetting(std::string path) -{ - T setting = toml::find(value, path); - return setting; -} }; #endif // SETTINGS_H \ No newline at end of file diff --git a/src/setup.h b/src/setup.h index 48ca95f..eb5a789 100644 --- a/src/setup.h +++ b/src/setup.h @@ -9,6 +9,9 @@ #include #include +#include +using json = nlohmann::json; + class Setup { private: @@ -45,12 +48,19 @@ public: { std::replace(home.begin(), home.end(), '\\', '/'); - std::ofstream file(home + "/.automconfig.toml"); - file << "editor = \"" << editor << "\"" << std::endl; - file << "search_dirs = [\"" << home << "\"]" << std::endl; - file << "autom_home_dir = \"" << home << "\"" << std::endl; + + std::ofstream file(home + "/.automconfig.json"); + + json j = { + {"editor", editor}, + {"search_dirs", {home}}, + {"autom_home_dir", home} + }; + + file << j.dump(4); file.close(); + } void runSetup() @@ -59,7 +69,7 @@ public: if (!std::filesystem::exists(home)) createFolder(); - if (!std::filesystem::exists(home + "/.automconfig.toml")) + if (!std::filesystem::exists(home + "/.automconfig.json")) createSettings(); } };