🔀 Merge branch 'v3'

This commit is contained in:
ToruNiina
2019-07-03 17:31:45 +09:00
54 changed files with 7507 additions and 3778 deletions

View File

@@ -15,6 +15,29 @@ jobs:
g++ -std=c++11 -O2 -Wall -Wextra -Werror -I../ check_toml_test.cpp -o check_toml_test g++ -std=c++11 -O2 -Wall -Wextra -Werror -I../ check_toml_test.cpp -o check_toml_test
go get github.com/BurntSushi/toml-test go get github.com/BurntSushi/toml-test
$GOPATH/bin/toml-test ./check_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: output_result:
docker: docker:
- image: circleci/buildpack-deps:bionic - image: circleci/buildpack-deps:bionic
@@ -24,7 +47,7 @@ jobs:
command: | command: |
g++ --version g++ --version
cd tests/ cd tests/
g++ -std=c++11 -O2 -Wall -Wextra -Werror -I../ check.cpp -o check g++ -std=c++11 -O2 -Wall -Wextra -Wpedantic -Werror -I../ check.cpp -o check
git clone https://github.com/BurntSushi/toml-test.git git clone https://github.com/BurntSushi/toml-test.git
cp check toml-test/tests/invalid cp check toml-test/tests/invalid
cp check toml-test/tests/valid cp check toml-test/tests/valid
@@ -56,4 +79,5 @@ workflows:
test: test:
jobs: jobs:
- test_suite - test_suite
- test_serialization
- output_result - output_result

View File

@@ -10,9 +10,10 @@ matrix:
apt: apt:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-5 - g++-5
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: gcc compiler: gcc
@@ -21,9 +22,10 @@ matrix:
apt: apt:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-6 - g++-6
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: gcc compiler: gcc
@@ -32,9 +34,10 @@ matrix:
apt: apt:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-7 - g++-7
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: gcc compiler: gcc
@@ -43,9 +46,10 @@ matrix:
apt: apt:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-8 - g++-8
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: gcc compiler: gcc
@@ -54,9 +58,10 @@ matrix:
apt: apt:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-8 - g++-8
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: clang compiler: clang
@@ -66,9 +71,11 @@ matrix:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.7 - llvm-toolchain-precise-3.7
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-8
- clang-3.7 - clang-3.7
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: clang compiler: clang
@@ -78,9 +85,11 @@ matrix:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-trusty-4.0 - llvm-toolchain-trusty-4.0
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-8
- clang-4.0 - clang-4.0
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: clang compiler: clang
@@ -90,9 +99,11 @@ matrix:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-trusty-5.0 - llvm-toolchain-trusty-5.0
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-8
- clang-5.0 - clang-5.0
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: clang compiler: clang
@@ -102,9 +113,11 @@ matrix:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-trusty-6.0 - llvm-toolchain-trusty-6.0
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-8
- clang-6.0 - clang-6.0
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: clang compiler: clang
@@ -114,9 +127,11 @@ matrix:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-trusty-7 - llvm-toolchain-trusty-7
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-8
- clang-7 - clang-7
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: clang compiler: clang
@@ -126,9 +141,11 @@ matrix:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-trusty-8 - llvm-toolchain-trusty-8
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- g++-8
- clang-8 - clang-8
- libboost-all-dev - boost1.70
- os: linux - os: linux
language: cpp language: cpp
compiler: clang compiler: clang
@@ -138,10 +155,11 @@ matrix:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-trusty-8 - llvm-toolchain-trusty-8
- sourceline: 'ppa:mhier/libboost-latest'
packages: packages:
- clang-8 - clang-8
- g++-8 - g++-8
- libboost-all-dev - boost1.70
- os: osx - os: osx
language: cpp language: cpp
compiler: clang compiler: clang
@@ -151,11 +169,11 @@ script:
- | - |
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
mkdir -p cmake mkdir -p cmake
travis_retry wget "https://cmake.org/files/v3.11/cmake-3.11.2-Linux-x86_64.tar.gz" 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.11.2-Linux-x86_64.tar.gz -C cmake --strip-components=1 tar xf cmake-3.14.5-Linux-x86_64.tar.gz -C cmake --strip-components=1
export PATH=${TRAVIS_BUILD_DIR}/cmake/bin:${PATH} export PATH=${TRAVIS_BUILD_DIR}/cmake/bin:${PATH}
else else
brew upgrade cmake brew upgrade cmake boost
fi fi
- cmake --version - cmake --version
- mkdir build - mkdir build

View File

@@ -3,11 +3,11 @@ enable_testing()
project(toml11) project(toml11)
set(toml11_VERSION_MAYOR 2) set(toml11_VERSION_MAYOR 3)
set(toml11_VERSION_MINOR 4) set(toml11_VERSION_MINOR 0)
set(toml11_VERSION_PATCH 0) set(toml11_VERSION_PATCH 0)
set(toml11_VERSION set(toml11_VERSION
"${toml11_VERSION_MAYOR}.${toml11_VERSION_MINOR}.${toml11_VERSION_PATCH}" "${toml11_VERSION_MAYOR}.${toml11_VERSION_MINOR}.${toml11_VERSION_PATCH}-beta"
) )
option(toml11_BUILD_TEST "Build toml tests" ON) option(toml11_BUILD_TEST "Build toml tests" ON)

1179
README.md

File diff suppressed because it is too large Load Diff

View File

@@ -19,7 +19,7 @@ build_script:
- cd build - cd build
- git clone https://github.com/toml-lang/toml.git - git clone https://github.com/toml-lang/toml.git
- file --mime-encoding toml/tests/hard_example_unicode.toml - file --mime-encoding toml/tests/hard_example_unicode.toml
- cmake -G"%generator%" -DBOOST_ROOT=C:/Libraries/boost_1_63_0 .. - cmake -G"%generator%" -DBOOST_ROOT=C:/Libraries/boost_1_69_0 ..
- cmake --build . --config "%configuration%" - cmake --build . --config "%configuration%"
test_script: test_script:

View File

@@ -1,5 +1,6 @@
set(TEST_NAMES set(TEST_NAMES
test_datetime test_datetime
test_string
test_utility test_utility
test_result test_result
test_traits test_traits
@@ -23,8 +24,10 @@ set(TEST_NAMES
test_literals test_literals
test_comments test_comments
test_get test_get
test_get_related_func test_get_or
test_from_toml test_find
test_find_or
test_expect
test_parse_file test_parse_file
test_serialize_file test_serialize_file
test_parse_unicode test_parse_unicode
@@ -33,13 +36,16 @@ set(TEST_NAMES
test_extended_conversions test_extended_conversions
) )
CHECK_CXX_COMPILER_FLAG("-Wall" COMPILER_SUPPORTS_WALL) 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("-Wpedantic" COMPILER_SUPPORTS_WPEDANTIC)
if(COMPILER_SUPPORTS_WALL) if(COMPILER_SUPPORTS_WALL)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
endif() endif()
if(COMPILER_SUPPORTS_WEXTRA)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
endif()
if(COMPILER_SUPPORTS_WPEDANTIC) if(COMPILER_SUPPORTS_WPEDANTIC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
endif() endif()

View File

@@ -0,0 +1,57 @@
#include "toml.hpp"
#include <iostream>
#include <iomanip>
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)
{
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<toml::preserve_comments>(filename);
{
std::ofstream ofs("tmp.toml");
ofs << std::setprecision(16) << std::setw(80) << data;
}
const auto serialized = toml::parse<toml::preserve_comments>("tmp.toml");
if(data != serialized)
{
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;
}

View File

@@ -84,8 +84,8 @@ struct json_serializer
{ {
if(!is_first) {std::cout << ", ";} if(!is_first) {std::cout << ", ";}
is_first = false; is_first = false;
std::cout << toml::format(toml::string(elem.first), std::cout << toml::format(toml::value(elem.first),
std::numeric_limits<std::size_t>::max()); std::numeric_limits<std::size_t>::max());
std::cout << ':'; std::cout << ':';
toml::visit(*this, elem.second); toml::visit(*this, elem.second);
} }

View File

@@ -10,116 +10,505 @@
BOOST_AUTO_TEST_CASE(test_comment_before) BOOST_AUTO_TEST_CASE(test_comment_before)
{ {
using namespace toml::literals::toml_literals;
{ {
const toml::value v = u8R"( const std::string file = u8R"(
# comment for a. # comment for a.
a = 42 a = 42
# comment for b. # comment for b.
b = "baz" b = "baz"
)"_toml; )";
std::istringstream iss(file);
const auto v = toml::parse<toml::preserve_comments>(iss);
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_before(), u8"# comment for a."); const auto& a = toml::find(v, "a");
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_before(), u8"# comment for b."); const auto& b = toml::find(v, "b");
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_inline(), "");
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_inline(), "");
BOOST_CHECK_EQUAL(toml::find(v, "a").comment(), u8"# comment for a."); BOOST_TEST(a.comments().size() == 1u);
BOOST_CHECK_EQUAL(toml::find(v, "b").comment(), u8"# comment for b."); BOOST_TEST(a.comments().front() == u8" comment for a.");
BOOST_TEST(b.comments().size() == 1u);
BOOST_TEST(b.comments().front() == u8" comment for b.");
} }
{ {
const toml::value v = u8R"( const std::string file = u8R"(
# comment for a. # comment for a.
# another comment for a. # another comment for a.
a = 42 a = 42
# comment for b. # comment for b.
# also comment for b. # also comment for b.
b = "baz" b = "baz"
)"_toml; )";
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_before(), u8R"(# comment for a. std::istringstream iss(file);
# another comment for a.)"); const auto v = toml::parse<toml::preserve_comments>(iss);
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_before(), u8R"(# comment for b.
# also comment for b.)");
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_inline(), u8"");
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_inline(), u8"");
BOOST_CHECK_EQUAL(toml::find(v, "a").comment(), u8R"(# comment for a. const auto& a = toml::find(v, "a");
# another comment for a.)"); const auto& b = toml::find(v, "b");
BOOST_CHECK_EQUAL(toml::find(v, "b").comment(), u8R"(# comment for b.
# also comment for b.)"); BOOST_TEST(a.comments().size() == 2u);
BOOST_TEST(a.comments().front() == u8" comment for a.");
BOOST_TEST(a.comments().back() == u8" another comment for a.");
BOOST_TEST(b.comments().size() == 2u);
BOOST_TEST(b.comments().front() == u8" comment for b.");
BOOST_TEST(b.comments().back() == u8" also comment for b.");
} }
} }
BOOST_AUTO_TEST_CASE(test_comment_inline) BOOST_AUTO_TEST_CASE(test_comment_inline)
{ {
using namespace toml::literals::toml_literals;
{ {
const toml::value v = u8R"( const std::string file = u8R"(
a = 42 # comment for a. a = 42 # comment for a.
b = "baz" # comment for b. b = "baz" # comment for b.
)"_toml; )";
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_before(), ""); std::istringstream iss(file);
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_before(), ""); const auto v = toml::parse<toml::preserve_comments>(iss);
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_inline(), u8"# comment for a.");
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_inline(), u8"# comment for b.");
BOOST_CHECK_EQUAL(toml::find(v, "a").comment(), u8"# comment for a."); const auto& a = toml::find(v, "a");
BOOST_CHECK_EQUAL(toml::find(v, "b").comment(), u8"# comment for b."); const auto& b = toml::find(v, "b");
BOOST_TEST(a.comments().size() == 1u);
BOOST_TEST(a.comments().front() == u8" comment for a.");
BOOST_TEST(b.comments().size() == 1u);
BOOST_TEST(b.comments().front() == u8" comment for b.");
} }
{ {
const toml::value v = u8R"( const std::string file = u8R"(
a = [ # comment for a. a = [
42, 42,
] # this also. ] # comment for a.
b = [ # comment for b. b = [
"bar", "bar", # this is not a comment for b, but "bar"
] ] # this is a comment for b.
c = [ )";
3.14, # this is not a comment for c, but 3.14.
] # comment for c.
)"_toml;
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_before(), ""); std::istringstream iss(file);
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_before(), ""); const auto v = toml::parse<toml::preserve_comments>(iss);
BOOST_CHECK_EQUAL(toml::find(v, "c").comment_before(), "");
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_inline(), u8R"(# comment for a. const auto& a = toml::find(v, "a");
# this also.)"); const auto& b = toml::find(v, "b");
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_inline(), u8"# comment for b."); const auto& b0 = b.as_array().at(0);
BOOST_CHECK_EQUAL(toml::find(v, "c").comment_inline(), u8"# comment for c.");
BOOST_CHECK_EQUAL(toml::find(v, "a").comment(), u8R"(# comment for a. BOOST_TEST(a.comments().size() == 1u);
# this also.)"); BOOST_TEST(a.comments().front() == u8" comment for a.");
BOOST_CHECK_EQUAL(toml::find(v, "b").comment(), u8"# comment for b."); BOOST_TEST(b.comments().size() == 1u);
BOOST_CHECK_EQUAL(toml::find(v, "c").comment(), u8"# comment for c."); BOOST_TEST(b.comments().front() == u8" this is a comment for b.");
BOOST_TEST(b0.comments().size() == 1u);
const auto& c0 = toml::find<toml::array>(v, "c").at(0); BOOST_TEST(b0.comments().front() == u8" this is not a comment for b, but \"bar\"");
BOOST_CHECK_EQUAL(c0.comment(), u8"# this is not a comment for c, but 3.14.");
} }
} }
BOOST_AUTO_TEST_CASE(test_comment_both) BOOST_AUTO_TEST_CASE(test_comment_both)
{ {
using namespace toml::literals::toml_literals;
{ {
const toml::value v = u8R"( const std::string file = u8R"(
# comment for a. # comment for a.
a = 42 # inline comment for a. a = 42 # inline comment for a.
# comment for b. # comment for b.
b = "baz" # inline comment for b. b = "baz" # inline comment for b.
)"_toml; # comment for c.
c = [ # this comment will be ignored
# comment for the first element.
10 # this also.
] # another comment for c.
)";
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_before(), "# comment for a."); std::istringstream iss(file);
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_before(), "# comment for b."); const auto v = toml::parse<toml::preserve_comments>(iss);
BOOST_CHECK_EQUAL(toml::find(v, "a").comment_inline(), "# inline comment for a.");
BOOST_CHECK_EQUAL(toml::find(v, "b").comment_inline(), "# inline comment for b.");
BOOST_CHECK_EQUAL(toml::find(v, "a").comment(), u8R"(# comment for a. const auto& a = toml::find(v, "a");
# inline comment for a.)"); const auto& b = toml::find(v, "b");
BOOST_CHECK_EQUAL(toml::find(v, "b").comment(), u8R"(# comment for b. const auto& c = toml::find(v, "c");
# inline comment for b.)"); const auto& c0 = c.as_array().at(0);
BOOST_TEST(a.comments().size() == 2u);
BOOST_TEST(a.comments().front() == u8" comment for a.");
BOOST_TEST(a.comments().back() == u8" inline comment for a.");
BOOST_TEST(b.comments().size() == 2u);
BOOST_TEST(b.comments().front() == u8" comment for b.");
BOOST_TEST(b.comments().back() == u8" inline comment for b.");
BOOST_TEST(c.comments().size() == 2u);
BOOST_TEST(c.comments().front() == u8" comment for c.");
BOOST_TEST(c.comments().back() == u8" another comment for c.");
BOOST_TEST(c0.comments().size() == 2u);
BOOST_TEST(c0.comments().front() == u8" comment for the first element.");
BOOST_TEST(c0.comments().back() == u8" this also.");
} }
} }
BOOST_AUTO_TEST_CASE(test_discard_comment)
{
const std::string file = u8R"(
# 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<toml::preserve_comments>;
{
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 __cplusplus >= 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<std::chrono::system_clock::time_point>(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<std::chrono::system_clock::time_point>(
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<int> 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<int> 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<std::pair<std::string, value_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::map<std::string, value_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");
}
}
BOOST_AUTO_TEST_CASE(test_overwrite_comments)
{
using value_type = toml::basic_value<toml::preserve_comments>;
{
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<toml::preserve_comments>;
{
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");
}
}

View File

@@ -11,47 +11,47 @@ BOOST_AUTO_TEST_CASE(test_local_date)
{ {
const toml::local_date date(2018, toml::month_t::Jan, 1); const toml::local_date date(2018, toml::month_t::Jan, 1);
const toml::local_date date1(date); const toml::local_date date1(date);
BOOST_CHECK_EQUAL(date, date1); BOOST_TEST(date == date1);
const std::chrono::system_clock::time_point tp(date); const std::chrono::system_clock::time_point tp(date);
const toml::local_date date2(tp); const toml::local_date date2(tp);
BOOST_CHECK_EQUAL(date, date2); BOOST_TEST(date == date2);
const toml::local_date date3(2017, toml::month_t::Dec, 31); const toml::local_date date3(2017, toml::month_t::Dec, 31);
BOOST_CHECK(date > date3); BOOST_TEST(date > date3);
std::ostringstream oss; std::ostringstream oss;
oss << date; oss << date;
BOOST_CHECK_EQUAL(oss.str(), std::string("2018-01-01")); BOOST_TEST(oss.str() == std::string("2018-01-01"));
} }
BOOST_AUTO_TEST_CASE(test_local_time) BOOST_AUTO_TEST_CASE(test_local_time)
{ {
const toml::local_time time(12, 30, 45); const toml::local_time time(12, 30, 45);
const toml::local_time time1(time); const toml::local_time time1(time);
BOOST_CHECK_EQUAL(time, time1); BOOST_TEST(time == time1);
const std::chrono::nanoseconds dur(time); const std::chrono::nanoseconds dur(time);
std::chrono::nanoseconds ns(0); std::chrono::nanoseconds ns(0);
ns += std::chrono::hours (12); ns += std::chrono::hours (12);
ns += std::chrono::minutes(30); ns += std::chrono::minutes(30);
ns += std::chrono::seconds(45); ns += std::chrono::seconds(45);
BOOST_CHECK_EQUAL(dur.count(), ns.count()); BOOST_TEST(dur.count() == ns.count());
const toml::local_time time3(12, 15, 45); const toml::local_time time3(12, 15, 45);
BOOST_CHECK(time > time3); BOOST_TEST(time > time3);
{ {
std::ostringstream oss; std::ostringstream oss;
oss << time; oss << time;
BOOST_CHECK_EQUAL(oss.str(), std::string("12:30:45")); BOOST_TEST(oss.str() == std::string("12:30:45"));
} }
{ {
const toml::local_time time4(12, 30, 45, 123, 456); const toml::local_time time4(12, 30, 45, 123, 456);
std::ostringstream oss; std::ostringstream oss;
oss << time4; oss << time4;
BOOST_CHECK_EQUAL(oss.str(), std::string("12:30:45.123456")); BOOST_TEST(oss.str() == std::string("12:30:45.123456"));
} }
} }
@@ -59,20 +59,20 @@ BOOST_AUTO_TEST_CASE(test_time_offset)
{ {
const toml::time_offset time(9, 30); const toml::time_offset time(9, 30);
const toml::time_offset time1(time); const toml::time_offset time1(time);
BOOST_CHECK_EQUAL(time, time1); BOOST_TEST(time == time1);
const std::chrono::minutes dur(time); const std::chrono::minutes dur(time);
std::chrono::minutes m(0); std::chrono::minutes m(0);
m += std::chrono::hours (9); m += std::chrono::hours (9);
m += std::chrono::minutes(30); m += std::chrono::minutes(30);
BOOST_CHECK_EQUAL(dur.count(), m.count()); BOOST_TEST(dur.count() == m.count());
const toml::time_offset time2(9, 0); const toml::time_offset time2(9, 0);
BOOST_CHECK(time2 < time); BOOST_TEST(time2 < time);
std::ostringstream oss; std::ostringstream oss;
oss << time; oss << time;
BOOST_CHECK_EQUAL(oss.str(), std::string("+09:30")); BOOST_TEST(oss.str() == std::string("+09:30"));
} }
BOOST_AUTO_TEST_CASE(test_local_datetime) BOOST_AUTO_TEST_CASE(test_local_datetime)
@@ -80,15 +80,15 @@ BOOST_AUTO_TEST_CASE(test_local_datetime)
const toml::local_datetime dt(toml::local_date(2018, toml::month_t::Jan, 1), const toml::local_datetime dt(toml::local_date(2018, toml::month_t::Jan, 1),
toml::local_time(12, 30, 45)); toml::local_time(12, 30, 45));
const toml::local_datetime dt1(dt); const toml::local_datetime dt1(dt);
BOOST_CHECK_EQUAL(dt, dt1); BOOST_TEST(dt == dt1);
const std::chrono::system_clock::time_point tp(dt); const std::chrono::system_clock::time_point tp(dt);
const toml::local_datetime dt2(tp); const toml::local_datetime dt2(tp);
BOOST_CHECK_EQUAL(dt, dt2); BOOST_TEST(dt == dt2);
std::ostringstream oss; std::ostringstream oss;
oss << dt; oss << dt;
BOOST_CHECK_EQUAL(oss.str(), std::string("2018-01-01T12:30:45")); BOOST_TEST(oss.str() == std::string("2018-01-01T12:30:45"));
} }
BOOST_AUTO_TEST_CASE(test_offset_datetime) BOOST_AUTO_TEST_CASE(test_offset_datetime)
@@ -97,17 +97,18 @@ BOOST_AUTO_TEST_CASE(test_offset_datetime)
toml::local_time(12, 30, 45), toml::local_time(12, 30, 45),
toml::time_offset(9, 30)); toml::time_offset(9, 30));
const toml::offset_datetime dt1(dt); const toml::offset_datetime dt1(dt);
BOOST_CHECK_EQUAL(dt, dt1); BOOST_TEST(dt == dt1);
const std::chrono::system_clock::time_point tp1(dt); const std::chrono::system_clock::time_point tp1(dt);
const toml::offset_datetime dt2(tp1); const toml::offset_datetime dt2(tp1);
const std::chrono::system_clock::time_point tp2(dt2); const std::chrono::system_clock::time_point tp2(dt2);
BOOST_CHECK(tp1 == tp2); const bool tp_same = (tp1 == tp2);
BOOST_TEST(tp_same);
{ {
std::ostringstream oss; std::ostringstream oss;
oss << dt; oss << dt;
BOOST_CHECK_EQUAL(oss.str(), std::string("2018-01-01T12:30:45+09:30")); BOOST_TEST(oss.str() == std::string("2018-01-01T12:30:45+09:30"));
} }
{ {
const toml::offset_datetime dt3( const toml::offset_datetime dt3(
@@ -116,6 +117,6 @@ BOOST_AUTO_TEST_CASE(test_offset_datetime)
toml::time_offset(0, 0)); toml::time_offset(0, 0));
std::ostringstream oss; std::ostringstream oss;
oss << dt3; oss << dt3;
BOOST_CHECK_EQUAL(oss.str(), std::string("2018-01-01T12:30:45Z")); BOOST_TEST(oss.str() == std::string("2018-01-01T12:30:45Z"));
} }
} }

View File

@@ -12,50 +12,19 @@
BOOST_AUTO_TEST_CASE(test_detect_empty_key) BOOST_AUTO_TEST_CASE(test_detect_empty_key)
{ {
std::istringstream stream(std::string("= \"value\"")); std::istringstream stream(std::string("= \"value\""));
bool exception_thrown = false; BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
try
{
toml::parse(stream, "test_detect_empty_key");
}
catch(const toml::syntax_error& syn)
{
// to see the error message
std::cerr << syn.what() << std::endl;
exception_thrown = true;
}
BOOST_CHECK(exception_thrown);
} }
BOOST_AUTO_TEST_CASE(test_detect_missing_value) BOOST_AUTO_TEST_CASE(test_detect_missing_value)
{ {
std::istringstream stream(std::string("a =")); std::istringstream stream(std::string("a ="));
bool exception_thrown = false; BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
try
{
toml::parse(stream, "test_detect_missing_value");
}
catch(const toml::syntax_error& syn)
{
std::cerr << syn.what() << std::endl;
exception_thrown = true;
}
BOOST_CHECK(exception_thrown);
} }
BOOST_AUTO_TEST_CASE(test_detect_too_many_value) BOOST_AUTO_TEST_CASE(test_detect_too_many_value)
{ {
std::istringstream stream(std::string("a = 1 = \"value\"")); std::istringstream stream(std::string("a = 1 = \"value\""));
bool exception_thrown = false; BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
try
{
toml::parse(stream, "test_detect_too_many_value");
}
catch(const toml::syntax_error& syn)
{
std::cerr << syn.what() << std::endl;
exception_thrown = true;
}
BOOST_CHECK(exception_thrown);
} }
BOOST_AUTO_TEST_CASE(test_detect_duplicate_table) BOOST_AUTO_TEST_CASE(test_detect_duplicate_table)
@@ -66,17 +35,7 @@ BOOST_AUTO_TEST_CASE(test_detect_duplicate_table)
"[table]\n" "[table]\n"
"b = 42\n" "b = 42\n"
)); ));
bool exception_thrown = false; BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
try
{
toml::parse(stream, "test_detect_duplicate_table");
}
catch(const toml::syntax_error& syn)
{
std::cerr << syn.what() << std::endl;
exception_thrown = true;
}
BOOST_CHECK(exception_thrown);
} }
BOOST_AUTO_TEST_CASE(test_detect_conflict_array_table) BOOST_AUTO_TEST_CASE(test_detect_conflict_array_table)
@@ -87,17 +46,7 @@ BOOST_AUTO_TEST_CASE(test_detect_conflict_array_table)
"[table]\n" "[table]\n"
"b = 42\n" "b = 42\n"
)); ));
bool exception_thrown = false; BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
try
{
toml::parse(stream, "test_detect_conflict_array_table");
}
catch(const toml::syntax_error& syn)
{
std::cerr << syn.what() << std::endl;
exception_thrown = true;
}
BOOST_CHECK(exception_thrown);
} }
BOOST_AUTO_TEST_CASE(test_detect_conflict_table_array) BOOST_AUTO_TEST_CASE(test_detect_conflict_table_array)
@@ -108,17 +57,7 @@ BOOST_AUTO_TEST_CASE(test_detect_conflict_table_array)
"[[table]]\n" "[[table]]\n"
"b = 42\n" "b = 42\n"
)); ));
bool exception_thrown = false; BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
try
{
toml::parse(stream, "test_detect_conflict_table_array");
}
catch(const toml::syntax_error& syn)
{
std::cerr << syn.what() << std::endl;
exception_thrown = true;
}
BOOST_CHECK(exception_thrown);
} }
BOOST_AUTO_TEST_CASE(test_detect_duplicate_value) BOOST_AUTO_TEST_CASE(test_detect_duplicate_value)
@@ -127,17 +66,7 @@ BOOST_AUTO_TEST_CASE(test_detect_duplicate_value)
"a = 1\n" "a = 1\n"
"a = 2\n" "a = 2\n"
)); ));
bool exception_thrown = false; BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
try
{
toml::parse(stream, "test_detect_duplicate_value");
}
catch(const toml::syntax_error& syn)
{
std::cerr << syn.what() << std::endl;
exception_thrown = true;
}
BOOST_CHECK(exception_thrown);
} }
BOOST_AUTO_TEST_CASE(test_detect_conflicting_value) BOOST_AUTO_TEST_CASE(test_detect_conflicting_value)
@@ -146,17 +75,7 @@ BOOST_AUTO_TEST_CASE(test_detect_conflicting_value)
"a.b = 1\n" "a.b = 1\n"
"a.b.c = 2\n" "a.b.c = 2\n"
)); ));
bool exception_thrown = false; BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
try
{
toml::parse(stream, "test_detect_conflicting_value");
}
catch(const toml::syntax_error& syn)
{
std::cerr << syn.what() << std::endl;
exception_thrown = true;
}
BOOST_CHECK(exception_thrown);
} }
BOOST_AUTO_TEST_CASE(test_detect_inhomogeneous_array) BOOST_AUTO_TEST_CASE(test_detect_inhomogeneous_array)
@@ -164,17 +83,7 @@ BOOST_AUTO_TEST_CASE(test_detect_inhomogeneous_array)
std::istringstream stream(std::string( std::istringstream stream(std::string(
"a = [1, 1.0]\n" "a = [1, 1.0]\n"
)); ));
bool exception_thrown = false; BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
try
{
toml::parse(stream, "test_detect_inhomogeneous_array");
}
catch(const toml::syntax_error& syn)
{
std::cerr << syn.what() << std::endl;
exception_thrown = true;
}
BOOST_CHECK(exception_thrown);
} }
BOOST_AUTO_TEST_CASE(test_detect_appending_array_of_table) BOOST_AUTO_TEST_CASE(test_detect_appending_array_of_table)
@@ -184,16 +93,5 @@ BOOST_AUTO_TEST_CASE(test_detect_appending_array_of_table)
"[[a]]\n" "[[a]]\n"
"b = 2\n" "b = 2\n"
)); ));
bool exception_thrown = false; BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
try
{
toml::parse(stream, "test_detect_appending_array_of_table");
}
catch(const toml::syntax_error& syn)
{
std::cerr << syn.what() << std::endl;
exception_thrown = true;
}
BOOST_CHECK(exception_thrown);
} }

30
tests/test_expect.cpp Normal file
View File

@@ -0,0 +1,30 @@
#define BOOST_TEST_MODULE "test_expect"
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
#include <boost/test/unit_test.hpp>
#else
#define BOOST_TEST_NO_LIB
#include <boost/test/included/unit_test.hpp>
#endif
#include <toml.hpp>
#include <map>
#include <unordered_map>
#include <list>
#include <deque>
#include <array>
BOOST_AUTO_TEST_CASE(test_expect)
{
{
toml::value v1(42);
toml::value v2(3.14);
const auto v1_or_0 = toml::expect<int>(v1).unwrap_or(0);
const auto v2_or_0 = toml::expect<int>(v2).unwrap_or(0);
BOOST_TEST(42 == v1_or_0);
BOOST_TEST( 0 == v2_or_0);
const auto v1_or_none = toml::expect<int>(v1).map([](int i){return std::to_string(i);}).unwrap_or(std::string("none"));
const auto v2_or_none = toml::expect<int>(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);
}
}

View File

@@ -6,6 +6,8 @@
#include <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>
#endif #endif
#include <toml.hpp> #include <toml.hpp>
#include <deque>
#include <map>
namespace extlib namespace extlib
{ {
@@ -54,63 +56,237 @@ struct into<extlib::foo>
}; };
} // toml } // toml
// ---------------------------------------------------------------------------
namespace extlib2
{
struct foo
{
int a;
std::string b;
};
struct bar
{
int a;
std::string b;
template<typename C, template<typename ...> class M, template<typename ...> class A>
void from_toml(const toml::basic_value<C, M, A>& v)
{
this->a = toml::find<int>(v, "a");
this->b = toml::find<std::string>(v, "b");
return ;
}
toml::table into_toml() const
{
return toml::table{{"a", this->a}, {"b", this->b}};
}
};
} // extlib2
namespace toml
{
template<>
struct from<extlib2::foo>
{
template<typename C, template<typename ...> class M, template<typename ...> class A>
static extlib2::foo from_toml(const toml::basic_value<C, M, A>& v)
{
return extlib2::foo{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
}
};
template<>
struct into<extlib2::foo>
{
static toml::table into_toml(const extlib2::foo& f)
{
return toml::table{{"a", f.a}, {"b", f.b}};
}
};
} // toml
// ---------------------------------------------------------------------------
BOOST_AUTO_TEST_CASE(test_conversion_by_member_methods) BOOST_AUTO_TEST_CASE(test_conversion_by_member_methods)
{ {
const toml::value v{{"a", 42}, {"b", "baz"}}; {
const toml::value v{{"a", 42}, {"b", "baz"}};
const auto foo = toml::get<extlib::foo>(v); const auto foo = toml::get<extlib::foo>(v);
BOOST_CHECK_EQUAL(foo.a, 42); BOOST_TEST(foo.a == 42);
BOOST_CHECK_EQUAL(foo.b, "baz"); BOOST_TEST(foo.b == "baz");
const toml::value v2(foo); const toml::value v2(foo);
BOOST_CHECK_EQUAL(v, v2); BOOST_TEST(v == v2);
}
{
const toml::value v{{"a", 42}, {"b", "baz"}};
const auto foo = toml::get<extlib2::foo>(v);
BOOST_TEST(foo.a == 42);
BOOST_TEST(foo.b == "baz");
const toml::value v2(foo);
BOOST_TEST(v == v2);
}
{
const toml::basic_value<toml::discard_comments, std::map, std::deque>
v{{"a", 42}, {"b", "baz"}};
const auto foo = toml::get<extlib2::foo>(v);
BOOST_TEST(foo.a == 42);
BOOST_TEST(foo.b == "baz");
const toml::basic_value<toml::discard_comments, std::map, std::deque>
v2(foo);
BOOST_TEST(v == v2);
}
} }
BOOST_AUTO_TEST_CASE(test_conversion_by_specialization) BOOST_AUTO_TEST_CASE(test_conversion_by_specialization)
{ {
const toml::value v{{"a", 42}, {"b", "baz"}}; {
const toml::value v{{"a", 42}, {"b", "baz"}};
const auto bar = toml::get<extlib::bar>(v); const auto bar = toml::get<extlib::bar>(v);
BOOST_CHECK_EQUAL(bar.a, 42); BOOST_TEST(bar.a == 42);
BOOST_CHECK_EQUAL(bar.b, "baz"); BOOST_TEST(bar.b == "baz");
const toml::value v2(bar); const toml::value v2(bar);
BOOST_CHECK_EQUAL(v, v2); BOOST_TEST(v == v2);
}
{
const toml::value v{{"a", 42}, {"b", "baz"}};
const auto bar = toml::get<extlib2::bar>(v);
BOOST_TEST(bar.a == 42);
BOOST_TEST(bar.b == "baz");
const toml::value v2(bar);
BOOST_TEST(v == v2);
}
{
const toml::basic_value<toml::discard_comments, std::map, std::deque>
v{{"a", 42}, {"b", "baz"}};
const auto bar = toml::get<extlib2::bar>(v);
BOOST_TEST(bar.a == 42);
BOOST_TEST(bar.b == "baz");
const toml::basic_value<toml::discard_comments, std::map, std::deque>
v2(bar);
BOOST_TEST(v == v2);
}
} }
BOOST_AUTO_TEST_CASE(test_recursive_conversion) BOOST_AUTO_TEST_CASE(test_recursive_conversion)
{ {
const toml::value v{ {
toml::table{{"a", 42}, {"b", "baz"}}, const toml::value v{
toml::table{{"a", 43}, {"b", "qux"}}, toml::table{{"a", 42}, {"b", "baz"}},
toml::table{{"a", 44}, {"b", "quux"}}, toml::table{{"a", 43}, {"b", "qux"}},
toml::table{{"a", 45}, {"b", "foobar"}}, toml::table{{"a", 44}, {"b", "quux"}},
}; toml::table{{"a", 45}, {"b", "foobar"}},
};
const auto foos = toml::get<std::vector<extlib::foo>>(v); const auto foos = toml::get<std::vector<extlib::foo>>(v);
BOOST_CHECK_EQUAL(foos.size() , 4ul); BOOST_TEST(foos.size() == 4ul);
BOOST_CHECK_EQUAL(foos.at(0).a , 42); BOOST_TEST(foos.at(0).a == 42);
BOOST_CHECK_EQUAL(foos.at(1).a , 43); BOOST_TEST(foos.at(1).a == 43);
BOOST_CHECK_EQUAL(foos.at(2).a , 44); BOOST_TEST(foos.at(2).a == 44);
BOOST_CHECK_EQUAL(foos.at(3).a , 45); BOOST_TEST(foos.at(3).a == 45);
BOOST_CHECK_EQUAL(foos.at(0).b , "baz"); BOOST_TEST(foos.at(0).b == "baz");
BOOST_CHECK_EQUAL(foos.at(1).b , "qux"); BOOST_TEST(foos.at(1).b == "qux");
BOOST_CHECK_EQUAL(foos.at(2).b , "quux"); BOOST_TEST(foos.at(2).b == "quux");
BOOST_CHECK_EQUAL(foos.at(3).b , "foobar"); BOOST_TEST(foos.at(3).b == "foobar");
const auto bars = toml::get<std::vector<extlib::bar>>(v); const auto bars = toml::get<std::vector<extlib::bar>>(v);
BOOST_CHECK_EQUAL(bars.size() , 4ul); BOOST_TEST(bars.size() == 4ul);
BOOST_CHECK_EQUAL(bars.at(0).a , 42); BOOST_TEST(bars.at(0).a == 42);
BOOST_CHECK_EQUAL(bars.at(1).a , 43); BOOST_TEST(bars.at(1).a == 43);
BOOST_CHECK_EQUAL(bars.at(2).a , 44); BOOST_TEST(bars.at(2).a == 44);
BOOST_CHECK_EQUAL(bars.at(3).a , 45); BOOST_TEST(bars.at(3).a == 45);
BOOST_CHECK_EQUAL(bars.at(0).b , "baz"); BOOST_TEST(bars.at(0).b == "baz");
BOOST_CHECK_EQUAL(bars.at(1).b , "qux"); BOOST_TEST(bars.at(1).b == "qux");
BOOST_CHECK_EQUAL(bars.at(2).b , "quux"); BOOST_TEST(bars.at(2).b == "quux");
BOOST_CHECK_EQUAL(bars.at(3).b , "foobar"); 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<std::vector<extlib2::foo>>(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<std::vector<extlib2::bar>>(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<toml::discard_comments, std::map, std::deque>
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<std::vector<extlib2::foo>>(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<std::vector<extlib2::bar>>(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");
}
} }

432
tests/test_find.cpp Normal file
View File

@@ -0,0 +1,432 @@
#define BOOST_TEST_MODULE "test_find"
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
#include <boost/test/unit_test.hpp>
#else
#define BOOST_TEST_NO_LIB
#include <boost/test/included/unit_test.hpp>
#endif
#include <toml.hpp>
#include <map>
#include <unordered_map>
#include <list>
#include <deque>
#include <array>
#if __cplusplus >= 201703L
#include <string_view>
#endif
#include <tuple>
using test_value_types = std::tuple<
toml::value,
toml::basic_value<toml::preserve_comments>,
toml::basic_value<toml::discard_comments, std::map, std::deque>,
toml::basic_value<toml::preserve_comments, std::map, std::deque>
>;
BOOST_AUTO_TEST_CASE(test_find_throws)
{
{
// value is not a table
toml::value v(true);
BOOST_CHECK_THROW(toml::find<toml::boolean>(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<toml::boolean>(v, "key"), toml::type_error);
}
{
// the value corresponding to the key is not found
toml::value v{{"key", 42}};
BOOST_CHECK_THROW(toml::find<toml::integer>(v, "different_key"),
std::out_of_range);
}
{
// the positive control.
toml::value v{{"key", 42}};
BOOST_TEST(42 == toml::find<int>(v, "key"));
}
}
BOOST_AUTO_TEST_CASE(test_find_recursive)
{
// recursively search tables
{
toml::value v{
{"a", {
{"b", {
{"c", {
{"d", 42}
}}
}}
}}
};
BOOST_TEST(42 == toml::find<int>(v, "a", "b", "c", "d"));
// reference that can be used to modify the content
auto& num = toml::find<toml::integer>(v, "a", "b", "c", "d");
num = 54;
BOOST_TEST(54 == toml::find<int>(v, "a", "b", "c", "d"));
const std::string a("a"), b("b"), c("c"), d("d");
auto& num2 = toml::find<toml::integer>(v, a, b, c, d);
num2 = 42;
BOOST_TEST(42 == toml::find<int>(v, a, b, c, d));
}
}
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
{
{
value_type v{{"key", true}};
BOOST_TEST(true == toml::find<toml::boolean>(v, "key"));
toml::find<toml::boolean>(v, "key") = false;
BOOST_TEST(false == toml::find<toml::boolean>(v, "key"));
}
{
value_type v{{"key", 42}};
BOOST_TEST(toml::integer(42) == toml::find<toml::integer>(v, "key"));
toml::find<toml::integer>(v, "key") = 54;
BOOST_TEST(toml::integer(54) == toml::find<toml::integer>(v, "key"));
}
{
value_type v{{"key", 3.14}};
BOOST_TEST(toml::floating(3.14) == toml::find<toml::floating>(v, "key"));
toml::find<toml::floating>(v, "key") = 2.71;
BOOST_TEST(toml::floating(2.71) == toml::find<toml::floating>(v, "key"));
}
{
value_type v{{"key", "foo"}};
BOOST_TEST(toml::string("foo", toml::string_t::basic) ==
toml::find<toml::string>(v, "key"));
toml::find<toml::string>(v, "key").str += "bar";
BOOST_TEST(toml::string("foobar", toml::string_t::basic) ==
toml::find<toml::string>(v, "key"));
}
{
value_type v{{"key", value_type("foo", toml::string_t::literal)}};
BOOST_TEST(toml::string("foo", toml::string_t::literal) ==
toml::find<toml::string>(v, "key"));
toml::find<toml::string>(v, "key").str += "bar";
BOOST_TEST(toml::string("foobar", toml::string_t::literal) ==
toml::find<toml::string>(v, "key"));
}
{
toml::local_date d(2018, toml::month_t::Apr, 22);
value_type v{{"key", d}};
BOOST_CHECK(d == toml::find<toml::local_date>(v, "key"));
toml::find<toml::local_date>(v, "key").year = 2017;
d.year = 2017;
BOOST_CHECK(d == toml::find<toml::local_date>(v, "key"));
}
{
toml::local_time t(12, 30, 45);
value_type v{{"key", t}};
BOOST_CHECK(t == toml::find<toml::local_time>(v, "key"));
toml::find<toml::local_time>(v, "key").hour = 9;
t.hour = 9;
BOOST_CHECK(t == toml::find<toml::local_time>(v, "key"));
}
{
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<toml::local_datetime>(v, "key"));
toml::find<toml::local_datetime>(v, "key").date.year = 2017;
dt.date.year = 2017;
BOOST_CHECK(dt == toml::find<toml::local_datetime>(v, "key"));
}
{
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<toml::offset_datetime>(v, "key"));
toml::find<toml::offset_datetime>(v, "key").date.year = 2017;
dt.date.year = 2017;
BOOST_CHECK(dt == toml::find<toml::offset_datetime>(v, "key"));
}
{
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<typename value_type::array_type>(v, "key"));
BOOST_CHECK(result1);
toml::find<typename value_type::array_type>(v, "key").push_back(value_type(123));
vec.push_back(value_type(123));
const bool result2 = (vec == toml::find<typename value_type::array_type>(v, "key"));
BOOST_CHECK(result2);
}
{
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<typename value_type::table_type>(v, "key"));
BOOST_CHECK(result1);
toml::find<typename value_type::table_type>(v, "key")["key3"] = value_type(123);
tab["key3"] = value_type(123);
const bool result2 = (tab == toml::find<typename value_type::table_type>(v, "key"));
BOOST_CHECK(result2);
}
{
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"));
}
}
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<int >(v, "key"));
BOOST_TEST(short(42) == toml::find<short >(v, "key"));
BOOST_TEST(char(42) == toml::find<char >(v, "key"));
BOOST_TEST(unsigned(42) == toml::find<unsigned >(v, "key"));
BOOST_TEST(long(42) == toml::find<long >(v, "key"));
BOOST_TEST(std::int64_t(42) == toml::find<std::int64_t >(v, "key"));
BOOST_TEST(std::uint64_t(42) == toml::find<std::uint64_t>(v, "key"));
BOOST_TEST(std::int16_t(42) == toml::find<std::int16_t >(v, "key"));
BOOST_TEST(std::uint16_t(42) == toml::find<std::uint16_t>(v, "key"));
}
}
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_floating_type, value_type, test_value_types)
{
{
value_type v{{"key", 3.14}};
BOOST_TEST(static_cast<float >(3.14) == toml::find<float >(v, "key"));
BOOST_TEST(static_cast<double >(3.14) == toml::find<double >(v, "key"));
BOOST_TEST(static_cast<long double>(3.14) == toml::find<long double>(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<std::string>(v, "key"));
toml::find<std::string>(v, "key") += "bar";
BOOST_TEST("foobar" == toml::find<std::string>(v, "key"));
}
{
value_type v{{"key", toml::string("foo", toml::string_t::literal)}};
BOOST_TEST("foo" == toml::find<std::string>(v, "key"));
toml::find<std::string>(v, "key") += "bar";
BOOST_TEST("foobar" == toml::find<std::string>(v, "key"));
}
#if __cplusplus >= 201703L
{
value_type v{{"key", toml::string("foo", toml::string_t::basic)}};
BOOST_TEST("foo" == toml::find<std::string_view>(v, "key"));
}
{
value_type v{{"key", toml::string("foo", toml::string_t::literal)}};
BOOST_TEST("foo" == toml::find<std::string_view>(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<int> vec = toml::find<std::vector<int>>(v, "key");
const std::list<short> lst = toml::find<std::list<short>>(v, "key");
const std::deque<std::int64_t> deq = toml::find<std::deque<std::int64_t>>(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<short>::const_iterator iter = lst.begin();
BOOST_TEST(static_cast<short>(42) == *(iter++));
BOOST_TEST(static_cast<short>(54) == *(iter++));
BOOST_TEST(static_cast<short>(69) == *(iter++));
BOOST_TEST(static_cast<short>(72) == *(iter++));
BOOST_TEST(static_cast<std::int64_t>(42) == deq.at(0));
BOOST_TEST(static_cast<std::int64_t>(54) == deq.at(1));
BOOST_TEST(static_cast<std::int64_t>(69) == deq.at(2));
BOOST_TEST(static_cast<std::int64_t>(72) == deq.at(3));
std::array<int, 4> ary = toml::find<std::array<int, 4>>(v, "key");
BOOST_TEST(static_cast<int>(42) == ary.at(0));
BOOST_TEST(static_cast<int>(54) == ary.at(1));
BOOST_TEST(static_cast<int>(69) == ary.at(2));
BOOST_TEST(static_cast<int>(72) == ary.at(3));
std::tuple<int, short, unsigned, long> tpl =
toml::find<std::tuple<int, short, unsigned, long>>(v, "key");
BOOST_TEST(static_cast<int >(42) == std::get<0>(tpl));
BOOST_TEST(static_cast<short >(54) == std::get<1>(tpl));
BOOST_TEST(static_cast<unsigned>(69) == std::get<2>(tpl));
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
value_type p{{"key", {3.14, 2.71}}};
std::pair<double, double> pr = toml::find<std::pair<double, double> >(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<int>, std::vector<std::string>> p =
toml::find<std::pair<std::vector<int>, std::vector<std::string>>>(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<int>, std::vector<std::string>> t =
toml::find<std::tuple<std::vector<int>, std::vector<std::string>>>(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_toml_table, value_type, test_value_types)
{
value_type v1{{"key", {
{"key1", 1}, {"key2", 2}, {"key3", 3}, {"key4", 4}
}}};
const auto v = toml::find<std::map<std::string, int>>(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<std::chrono::system_clock::time_point>(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<std::chrono::seconds>(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<std::chrono::system_clock::time_point>(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<std::chrono::system_clock::time_point>(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<std::chrono::system_clock::time_point>(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);
}
}

360
tests/test_find_or.cpp Normal file
View File

@@ -0,0 +1,360 @@
#define BOOST_TEST_MODULE "test_find_or"
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
#include <boost/test/unit_test.hpp>
#else
#define BOOST_TEST_NO_LIB
#include <boost/test/included/unit_test.hpp>
#endif
#include <toml.hpp>
#include <map>
#include <unordered_map>
#include <list>
#include <deque>
#include <array>
#include <tuple>
#if __cplusplus >= 201703L
#include <string_view>
#endif
using test_value_types = std::tuple<
toml::value,
toml::basic_value<toml::preserve_comments>,
toml::basic_value<toml::discard_comments, std::map, std::deque>,
toml::basic_value<toml::preserve_comments, std::map, std::deque>
>;
namespace test
{
template<typename charT, typename traits, typename T, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const std::vector<T, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << i << ' ';}
os << ']';
return os;
}
template<typename charT, typename traits, typename T, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const std::deque<T, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << i << ' ';}
os << ']';
return os;
}
template<typename charT, typename traits, typename T, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const std::list<T, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << i << ' ';}
os << ']';
return os;
}
template<typename charT, typename traits,
typename Key, typename Value, typename Comp, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os,
const std::map<Key, Value, Comp, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";}
os << ']';
return os;
}
template<typename charT, typename traits,
typename Key, typename Value, typename Hash, typename Eq, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os,
const std::unordered_map<Key, Value, Hash, Eq, Alloc>& 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_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<toml::toml_type>(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<typename value_type::array_type>(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<typename value_type::table_type>(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 = toml::table{{"num", 42}};
BOOST_TEST(42u == toml::find_or(v, "num", 0u));
BOOST_TEST(0u == toml::find_or(v, "foo", 0u));
}
}
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));
BOOST_TEST(static_cast<float>(double(3.14)) == toml::find_or(v2, "key", 2.71f));
}
}
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)));
}
// 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));
}
}

View File

@@ -1,4 +1,4 @@
#define BOOST_TEST_MODULE "test_value" #define BOOST_TEST_MODULE "test_format_error"
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST #ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#else #else

View File

@@ -1,63 +0,0 @@
#define BOOST_TEST_MODULE "test_from_toml"
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
#include <boost/test/unit_test.hpp>
#else
#define BOOST_TEST_NO_LIB
#include <boost/test/included/unit_test.hpp>
#endif
#include <toml.hpp>
#include <map>
#include <unordered_map>
#include <list>
#include <deque>
#include <array>
BOOST_AUTO_TEST_CASE(test_from_toml)
{
toml::boolean b = false;
toml::integer i = 0;
toml::floating f = 0.;
toml::string s;
toml::local_date dt;
toml::array a;
toml::table t;
{
toml::value v(true);
toml::from_toml(std::tie(b, i, f, s, dt, a, t), v);
BOOST_CHECK_EQUAL(b, true);
}
{
toml::value v(42);
toml::from_toml(std::tie(b, i, f, s, dt, a, t), v);
BOOST_CHECK_EQUAL(i, 42);
}
{
toml::value v(3.14);
toml::from_toml(std::tie(b, i, f, s, dt, a, t), v);
BOOST_CHECK_EQUAL(f, 3.14);
}
{
toml::value v("foo");
toml::from_toml(std::tie(b, i, f, s, dt, a, t), v);
BOOST_CHECK_EQUAL(s, "foo");
}
{
toml::value v(toml::local_date(2018, toml::month_t::Apr, 22));
toml::from_toml(std::tie(b, i, f, s, dt, a, t), v);
BOOST_CHECK(dt == toml::local_date(2018, toml::month_t::Apr, 22));
}
{
toml::array ref{toml::value(42), toml::value(54)};
toml::value v(ref);
toml::from_toml(std::tie(b, i, f, s, dt, a, t), v);
BOOST_CHECK(ref == a);
}
{
toml::table ref{{"key1", 42}, {"key2", 3.14}};
toml::value v(ref);
toml::from_toml(std::tie(b, i, f, s, dt, a, t), v);
BOOST_CHECK(ref == t);
}
}

View File

@@ -5,294 +5,284 @@
#define BOOST_TEST_NO_LIB #define BOOST_TEST_NO_LIB
#include <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>
#endif #endif
#include <toml/value.hpp> #include <toml.hpp>
#include <toml/get.hpp>
#include <map> #include <map>
#include <unordered_map> #include <unordered_map>
#include <list> #include <list>
#include <deque> #include <deque>
#include <array> #include <array>
#include <tuple>
#if __cplusplus >= 201703L #if __cplusplus >= 201703L
#include <string_view> #include <string_view>
#endif #endif
using test_value_types = std::tuple<
toml::value,
toml::basic_value<toml::preserve_comments>,
toml::basic_value<toml::discard_comments, std::map, std::deque>,
toml::basic_value<toml::preserve_comments, std::map, std::deque>
>;
BOOST_AUTO_TEST_CASE(test_get_exact) BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
{ {
{ {
toml::value v(true); value_type v(true);
BOOST_CHECK_EQUAL(true, toml::get<toml::boolean>(v)); BOOST_TEST(true == toml::get<toml::boolean>(v));
toml::get<toml::boolean>(v) = false; toml::get<toml::boolean>(v) = false;
BOOST_CHECK_EQUAL(false, toml::get<toml::boolean>(v)); BOOST_TEST(false == toml::get<toml::boolean>(v));
} }
{ {
toml::value v(42); value_type v(42);
BOOST_CHECK_EQUAL(toml::integer(42), toml::get<toml::integer>(v)); BOOST_TEST(toml::integer(42) == toml::get<toml::integer>(v));
toml::get<toml::integer>(v) = 54; toml::get<toml::integer>(v) = 54;
BOOST_CHECK_EQUAL(toml::integer(54), toml::get<toml::integer>(v)); BOOST_TEST(toml::integer(54) == toml::get<toml::integer>(v));
} }
{ {
toml::value v(3.14); value_type v(3.14);
BOOST_CHECK_EQUAL(toml::floating(3.14), toml::get<toml::floating>(v)); BOOST_TEST(toml::floating(3.14) == toml::get<toml::floating>(v));
toml::get<toml::floating>(v) = 2.71; toml::get<toml::floating>(v) = 2.71;
BOOST_CHECK_EQUAL(toml::floating(2.71), toml::get<toml::floating>(v)); BOOST_TEST(toml::floating(2.71) == toml::get<toml::floating>(v));
} }
{ {
toml::value v("foo"); value_type v("foo");
BOOST_CHECK_EQUAL(toml::string("foo", toml::string_t::basic), BOOST_TEST(toml::string("foo", toml::string_t::basic) ==
toml::get<toml::string>(v)); toml::get<toml::string>(v));
toml::get<toml::string>(v).str += "bar"; toml::get<toml::string>(v).str += "bar";
BOOST_CHECK_EQUAL(toml::string("foobar", toml::string_t::basic), BOOST_TEST(toml::string("foobar", toml::string_t::basic) ==
toml::get<toml::string>(v)); toml::get<toml::string>(v));
} }
{ {
toml::value v("foo", toml::string_t::literal); value_type v("foo", toml::string_t::literal);
BOOST_CHECK_EQUAL(toml::string("foo", toml::string_t::literal), BOOST_TEST(toml::string("foo", toml::string_t::literal) ==
toml::get<toml::string>(v)); toml::get<toml::string>(v));
toml::get<toml::string>(v).str += "bar"; toml::get<toml::string>(v).str += "bar";
BOOST_CHECK_EQUAL(toml::string("foobar", toml::string_t::literal), BOOST_TEST(toml::string("foobar", toml::string_t::literal) ==
toml::get<toml::string>(v)); toml::get<toml::string>(v));
} }
{ {
toml::local_date d(2018, toml::month_t::Apr, 22); toml::local_date d(2018, toml::month_t::Apr, 22);
toml::value v(d); value_type v(d);
BOOST_CHECK(d == toml::get<toml::local_date>(v)); BOOST_TEST(d == toml::get<toml::local_date>(v));
toml::get<toml::local_date>(v).year = 2017; toml::get<toml::local_date>(v).year = 2017;
d.year = 2017; d.year = 2017;
BOOST_CHECK(d == toml::get<toml::local_date>(v)); BOOST_TEST(d == toml::get<toml::local_date>(v));
} }
{ {
toml::local_time t(12, 30, 45); toml::local_time t(12, 30, 45);
toml::value v(t); value_type v(t);
BOOST_CHECK(t == toml::get<toml::local_time>(v)); BOOST_TEST(t == toml::get<toml::local_time>(v));
toml::get<toml::local_time>(v).hour = 9; toml::get<toml::local_time>(v).hour = 9;
t.hour = 9; t.hour = 9;
BOOST_CHECK(t == toml::get<toml::local_time>(v)); BOOST_TEST(t == toml::get<toml::local_time>(v));
} }
{ {
toml::local_datetime dt(toml::local_date(2018, toml::month_t::Apr, 22), toml::local_datetime dt(toml::local_date(2018, toml::month_t::Apr, 22),
toml::local_time(12, 30, 45)); toml::local_time(12, 30, 45));
toml::value v(dt); value_type v(dt);
BOOST_CHECK(dt == toml::get<toml::local_datetime>(v)); BOOST_TEST(dt == toml::get<toml::local_datetime>(v));
toml::get<toml::local_datetime>(v).date.year = 2017; toml::get<toml::local_datetime>(v).date.year = 2017;
dt.date.year = 2017; dt.date.year = 2017;
BOOST_CHECK(dt == toml::get<toml::local_datetime>(v)); BOOST_TEST(dt == toml::get<toml::local_datetime>(v));
} }
{ {
toml::offset_datetime dt(toml::local_datetime( toml::offset_datetime dt(toml::local_datetime(
toml::local_date(2018, toml::month_t::Apr, 22), toml::local_date(2018, toml::month_t::Apr, 22),
toml::local_time(12, 30, 45)), toml::time_offset(9, 0)); toml::local_time(12, 30, 45)), toml::time_offset(9, 0));
toml::value v(dt); value_type v(dt);
BOOST_CHECK(dt == toml::get<toml::offset_datetime>(v)); BOOST_TEST(dt == toml::get<toml::offset_datetime>(v));
toml::get<toml::offset_datetime>(v).date.year = 2017; toml::get<toml::offset_datetime>(v).date.year = 2017;
dt.date.year = 2017; dt.date.year = 2017;
BOOST_CHECK(dt == toml::get<toml::offset_datetime>(v)); BOOST_TEST(dt == toml::get<toml::offset_datetime>(v));
} }
{ {
toml::array vec; using array_type = typename value_type::array_type;
vec.push_back(toml::value(42)); array_type vec;
vec.push_back(toml::value(54)); vec.push_back(value_type(42));
toml::value v(vec); vec.push_back(value_type(54));
BOOST_CHECK(vec == toml::get<toml::array>(v)); value_type v(vec);
BOOST_TEST(vec == toml::get<array_type>(v));
toml::get<toml::array>(v).push_back(toml::value(123)); toml::get<array_type>(v).push_back(value_type(123));
vec.push_back(toml::value(123)); vec.push_back(value_type(123));
BOOST_CHECK(vec == toml::get<toml::array>(v)); BOOST_TEST(vec == toml::get<array_type>(v));
} }
{ {
toml::table tab; using table_type = typename value_type::table_type;
tab["key1"] = toml::value(42); table_type tab;
tab["key2"] = toml::value(3.14); tab["key1"] = value_type(42);
toml::value v(tab); tab["key2"] = value_type(3.14);
BOOST_CHECK(tab == toml::get<toml::table>(v)); value_type v(tab);
BOOST_TEST(tab == toml::get<table_type>(v));
toml::get<toml::table>(v)["key3"] = toml::value(123); toml::get<table_type>(v)["key3"] = value_type(123);
tab["key3"] = toml::value(123); tab["key3"] = value_type(123);
BOOST_CHECK(tab == toml::get<toml::table>(v)); BOOST_TEST(tab == toml::get<table_type>(v));
} }
{ {
toml::value v1(42); value_type v1(42);
BOOST_CHECK(v1 == toml::get<toml::value>(v1)); BOOST_TEST(v1 == toml::get<value_type>(v1));
toml::value v2(54); value_type v2(54);
toml::get<toml::value>(v1) = v2; toml::get<value_type>(v1) = v2;
BOOST_CHECK(v2 == toml::get<toml::value>(v1)); BOOST_TEST(v2 == toml::get<value_type>(v1));
} }
} }
BOOST_AUTO_TEST_CASE(test_get_integer_type) BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_integer_type, value_type, test_value_types)
{ {
{ {
toml::value v(42); value_type v(42);
BOOST_CHECK_EQUAL(int(42), toml::get<int >(v)); BOOST_TEST(int(42) == toml::get<int >(v));
BOOST_CHECK_EQUAL(short(42), toml::get<short >(v)); BOOST_TEST(short(42) == toml::get<short >(v));
BOOST_CHECK_EQUAL(char(42), toml::get<char >(v)); BOOST_TEST(char(42) == toml::get<char >(v));
BOOST_CHECK_EQUAL(unsigned(42), toml::get<unsigned >(v)); BOOST_TEST(unsigned(42) == toml::get<unsigned >(v));
BOOST_CHECK_EQUAL(long(42), toml::get<long >(v)); BOOST_TEST(long(42) == toml::get<long >(v));
BOOST_CHECK_EQUAL(std::int64_t(42), toml::get<std::int64_t >(v)); BOOST_TEST(std::int64_t(42) == toml::get<std::int64_t >(v));
BOOST_CHECK_EQUAL(std::uint64_t(42), toml::get<std::uint64_t>(v)); BOOST_TEST(std::uint64_t(42) == toml::get<std::uint64_t>(v));
BOOST_CHECK_EQUAL(std::int16_t(42), toml::get<std::int16_t >(v)); BOOST_TEST(std::int16_t(42) == toml::get<std::int16_t >(v));
BOOST_CHECK_EQUAL(std::uint16_t(42), toml::get<std::uint16_t>(v)); BOOST_TEST(std::uint16_t(42) == toml::get<std::uint16_t>(v));
} }
} }
BOOST_AUTO_TEST_CASE(test_get_floating_type) BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_floating_type, value_type, test_value_types)
{ {
{ {
toml::value v(3.14); value_type v(3.14);
BOOST_CHECK_EQUAL(static_cast<float >(3.14), toml::get<float >(v)); BOOST_TEST(static_cast<float >(3.14) == toml::get<float >(v));
BOOST_CHECK_EQUAL(static_cast<double >(3.14), toml::get<double >(v)); BOOST_TEST(static_cast<double >(3.14) == toml::get<double >(v));
BOOST_CHECK_EQUAL(static_cast<long double>(3.14), toml::get<long double>(v)); BOOST_TEST(static_cast<long double>(3.14) == toml::get<long double>(v));
} }
} }
BOOST_AUTO_TEST_CASE(test_get_string_type) BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_string_type, value_type, test_value_types)
{ {
{ {
toml::value v("foo", toml::string_t::basic); value_type v("foo", toml::string_t::basic);
BOOST_CHECK_EQUAL("foo", toml::get<std::string>(v)); BOOST_TEST("foo" == toml::get<std::string>(v));
toml::get<std::string>(v) += "bar"; toml::get<std::string>(v) += "bar";
BOOST_CHECK_EQUAL("foobar", toml::get<std::string>(v)); BOOST_TEST("foobar" == toml::get<std::string>(v));
} }
{ {
toml::value v("foo", toml::string_t::literal); value_type v("foo", toml::string_t::literal);
BOOST_CHECK_EQUAL("foo", toml::get<std::string>(v)); BOOST_TEST("foo" == toml::get<std::string>(v));
toml::get<std::string>(v) += "bar"; toml::get<std::string>(v) += "bar";
BOOST_CHECK_EQUAL("foobar", toml::get<std::string>(v)); BOOST_TEST("foobar" == toml::get<std::string>(v));
} }
#if __cplusplus >= 201703L #if __cplusplus >= 201703L
{ {
toml::value v("foo", toml::string_t::basic); value_type v("foo", toml::string_t::basic);
BOOST_CHECK_EQUAL("foo", toml::get<std::string_view>(v)); BOOST_TEST("foo" == toml::get<std::string_view>(v));
} }
{ {
toml::value v("foo", toml::string_t::literal); value_type v("foo", toml::string_t::literal);
BOOST_CHECK_EQUAL("foo", toml::get<std::string_view>(v)); BOOST_TEST("foo" == toml::get<std::string_view>(v));
} }
#endif #endif
} }
BOOST_AUTO_TEST_CASE(test_get_toml_array) BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array, value_type, test_value_types)
{ {
toml::value v(toml::array(0)); const value_type v{42, 54, 69, 72};
toml::get<toml::array>(v).push_back(toml::value(42));
toml::get<toml::array>(v).push_back(toml::value(54));
toml::get<toml::array>(v).push_back(toml::value(69));
toml::get<toml::array>(v).push_back(toml::value(72));
const std::vector<int> vec = toml::get<std::vector<int>>(v); const std::vector<int> vec = toml::get<std::vector<int>>(v);
const std::list<short> lst = toml::get<std::list<short>>(v); const std::list<short> lst = toml::get<std::list<short>>(v);
const std::deque<std::int64_t> deq = toml::get<std::deque<std::int64_t>>(v); const std::deque<std::int64_t> deq = toml::get<std::deque<std::int64_t>>(v);
BOOST_CHECK_EQUAL(42, vec.at(0)); BOOST_TEST(42 == vec.at(0));
BOOST_CHECK_EQUAL(54, vec.at(1)); BOOST_TEST(54 == vec.at(1));
BOOST_CHECK_EQUAL(69, vec.at(2)); BOOST_TEST(69 == vec.at(2));
BOOST_CHECK_EQUAL(72, vec.at(3)); BOOST_TEST(72 == vec.at(3));
std::list<short>::const_iterator iter = lst.begin(); std::list<short>::const_iterator iter = lst.begin();
BOOST_CHECK_EQUAL(static_cast<short>(42), *(iter++)); BOOST_TEST(static_cast<short>(42) == *(iter++));
BOOST_CHECK_EQUAL(static_cast<short>(54), *(iter++)); BOOST_TEST(static_cast<short>(54) == *(iter++));
BOOST_CHECK_EQUAL(static_cast<short>(69), *(iter++)); BOOST_TEST(static_cast<short>(69) == *(iter++));
BOOST_CHECK_EQUAL(static_cast<short>(72), *(iter++)); BOOST_TEST(static_cast<short>(72) == *(iter++));
BOOST_CHECK_EQUAL(static_cast<std::int64_t>(42), deq.at(0)); BOOST_TEST(static_cast<std::int64_t>(42) == deq.at(0));
BOOST_CHECK_EQUAL(static_cast<std::int64_t>(54), deq.at(1)); BOOST_TEST(static_cast<std::int64_t>(54) == deq.at(1));
BOOST_CHECK_EQUAL(static_cast<std::int64_t>(69), deq.at(2)); BOOST_TEST(static_cast<std::int64_t>(69) == deq.at(2));
BOOST_CHECK_EQUAL(static_cast<std::int64_t>(72), deq.at(3)); BOOST_TEST(static_cast<std::int64_t>(72) == deq.at(3));
std::array<int, 4> ary = toml::get<std::array<int, 4>>(v); std::array<int, 4> ary = toml::get<std::array<int, 4>>(v);
BOOST_CHECK_EQUAL(static_cast<int>(42), ary.at(0)); BOOST_TEST(static_cast<int>(42) == ary.at(0));
BOOST_CHECK_EQUAL(static_cast<int>(54), ary.at(1)); BOOST_TEST(static_cast<int>(54) == ary.at(1));
BOOST_CHECK_EQUAL(static_cast<int>(69), ary.at(2)); BOOST_TEST(static_cast<int>(69) == ary.at(2));
BOOST_CHECK_EQUAL(static_cast<int>(72), ary.at(3)); BOOST_TEST(static_cast<int>(72) == ary.at(3));
std::tuple<int, short, unsigned, long> tpl = std::tuple<int, short, unsigned, long> tpl =
toml::get<std::tuple<int, short, unsigned, long>>(v); toml::get<std::tuple<int, short, unsigned, long>>(v);
BOOST_CHECK_EQUAL(static_cast<int >(42), std::get<0>(tpl)); BOOST_TEST(static_cast<int >(42) == std::get<0>(tpl));
BOOST_CHECK_EQUAL(static_cast<short >(54), std::get<1>(tpl)); BOOST_TEST(static_cast<short >(54) == std::get<1>(tpl));
BOOST_CHECK_EQUAL(static_cast<unsigned>(69), std::get<2>(tpl)); BOOST_TEST(static_cast<unsigned>(69) == std::get<2>(tpl));
BOOST_CHECK_EQUAL(static_cast<long >(72), std::get<3>(tpl)); BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl));
toml::value p(toml::array{}); const value_type p{3.14, 2.71};
toml::get<toml::array>(p).push_back(toml::value(3.14));
toml::get<toml::array>(p).push_back(toml::value(2.71));
std::pair<double, double> pr = toml::get<std::pair<double, double> >(p); std::pair<double, double> pr = toml::get<std::pair<double, double> >(p);
BOOST_CHECK_EQUAL(3.14, pr.first); BOOST_TEST(3.14 == pr.first);
BOOST_CHECK_EQUAL(2.71, pr.second); BOOST_TEST(2.71 == pr.second);
} }
BOOST_AUTO_TEST_CASE(test_get_toml_array_of_array) BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array_of_array, value_type, test_value_types)
{ {
toml::value v1(toml::array{}); const value_type v1{42, 54, 69, 72};
toml::get<toml::array>(v1).push_back(toml::value(42)); const value_type v2{"foo", "bar", "baz"};
toml::get<toml::array>(v1).push_back(toml::value(54)); const value_type v{v1, v2};
toml::get<toml::array>(v1).push_back(toml::value(69));
toml::get<toml::array>(v1).push_back(toml::value(72));
toml::value v2(toml::array{});
toml::get<toml::array>(v2).push_back(toml::value("foo"));
toml::get<toml::array>(v2).push_back(toml::value("bar"));
toml::get<toml::array>(v2).push_back(toml::value("baz"));
toml::value v(toml::array(2));
toml::get<toml::array>(v).at(0) = v1;
toml::get<toml::array>(v).at(1) = v2;
std::pair<std::vector<int>, std::vector<std::string>> p = std::pair<std::vector<int>, std::vector<std::string>> p =
toml::get<std::pair<std::vector<int>, std::vector<std::string>>>(v); toml::get<std::pair<std::vector<int>, std::vector<std::string>>>(v);
BOOST_CHECK_EQUAL(p.first.at(0), 42); BOOST_TEST(p.first.at(0) == 42);
BOOST_CHECK_EQUAL(p.first.at(1), 54); BOOST_TEST(p.first.at(1) == 54);
BOOST_CHECK_EQUAL(p.first.at(2), 69); BOOST_TEST(p.first.at(2) == 69);
BOOST_CHECK_EQUAL(p.first.at(3), 72); BOOST_TEST(p.first.at(3) == 72);
BOOST_CHECK_EQUAL(p.second.at(0), "foo"); BOOST_TEST(p.second.at(0) == "foo");
BOOST_CHECK_EQUAL(p.second.at(1), "bar"); BOOST_TEST(p.second.at(1) == "bar");
BOOST_CHECK_EQUAL(p.second.at(2), "baz"); BOOST_TEST(p.second.at(2) == "baz");
std::tuple<std::vector<int>, std::vector<std::string>> t = std::tuple<std::vector<int>, std::vector<std::string>> t =
toml::get<std::tuple<std::vector<int>, std::vector<std::string>>>(v); toml::get<std::tuple<std::vector<int>, std::vector<std::string>>>(v);
BOOST_CHECK_EQUAL(std::get<0>(t).at(0), 42); BOOST_TEST(std::get<0>(t).at(0) == 42);
BOOST_CHECK_EQUAL(std::get<0>(t).at(1), 54); BOOST_TEST(std::get<0>(t).at(1) == 54);
BOOST_CHECK_EQUAL(std::get<0>(t).at(2), 69); BOOST_TEST(std::get<0>(t).at(2) == 69);
BOOST_CHECK_EQUAL(std::get<0>(t).at(3), 72); BOOST_TEST(std::get<0>(t).at(3) == 72);
BOOST_CHECK_EQUAL(std::get<1>(t).at(0), "foo"); BOOST_TEST(std::get<1>(t).at(0) == "foo");
BOOST_CHECK_EQUAL(std::get<1>(t).at(1), "bar"); BOOST_TEST(std::get<1>(t).at(1) == "bar");
BOOST_CHECK_EQUAL(std::get<1>(t).at(2), "baz"); BOOST_TEST(std::get<1>(t).at(2) == "baz");
} }
BOOST_AUTO_TEST_CASE(test_get_toml_table) BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_table, value_type, test_value_types)
{ {
toml::value v1(toml::table{ const value_type v1{
{"key1", 1}, {"key1", 1},
{"key2", 2}, {"key2", 2},
{"key3", 3}, {"key3", 3},
{"key4", 4} {"key4", 4}
}); };
const auto v = toml::get<std::map<std::string, int>>(v1); const auto v = toml::get<std::map<std::string, int>>(v1);
BOOST_CHECK_EQUAL(v.at("key1"), 1); BOOST_TEST(v.at("key1") == 1);
BOOST_CHECK_EQUAL(v.at("key2"), 2); BOOST_TEST(v.at("key2") == 2);
BOOST_CHECK_EQUAL(v.at("key3"), 3); BOOST_TEST(v.at("key3") == 3);
BOOST_CHECK_EQUAL(v.at("key4"), 4); BOOST_TEST(v.at("key4") == 4);
} }
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_local_date, value_type, test_value_types)
BOOST_AUTO_TEST_CASE(test_get_toml_local_date)
{ {
toml::value v1(toml::local_date{2018, toml::month_t::Apr, 1}); value_type v1(toml::local_date{2018, toml::month_t::Apr, 1});
const auto date = std::chrono::system_clock::to_time_t( const auto date = std::chrono::system_clock::to_time_t(
toml::get<std::chrono::system_clock::time_point>(v1)); toml::get<std::chrono::system_clock::time_point>(v1));
@@ -305,20 +295,22 @@ BOOST_AUTO_TEST_CASE(test_get_toml_local_date)
t.tm_sec = 0; t.tm_sec = 0;
t.tm_isdst = -1; t.tm_isdst = -1;
const auto c = std::mktime(&t); const auto c = std::mktime(&t);
BOOST_CHECK_EQUAL(c, date); BOOST_TEST(c == date);
} }
BOOST_AUTO_TEST_CASE(test_get_toml_local_time) BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_local_time, value_type, test_value_types)
{ {
toml::value v1(toml::local_time{12, 30, 45}); value_type v1(toml::local_time{12, 30, 45});
const auto time = toml::get<std::chrono::seconds>(v1); const auto time = toml::get<std::chrono::seconds>(v1);
BOOST_CHECK(time == std::chrono::hours(12) + const bool result = time == std::chrono::hours(12) +
std::chrono::minutes(30) + std::chrono::seconds(45)); std::chrono::minutes(30) +
std::chrono::seconds(45);
BOOST_TEST(result);
} }
BOOST_AUTO_TEST_CASE(test_get_toml_local_datetime) BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_local_datetime, value_type, test_value_types)
{ {
toml::value v1(toml::local_datetime( value_type v1(toml::local_datetime(
toml::local_date{2018, toml::month_t::Apr, 1}, toml::local_date{2018, toml::month_t::Apr, 1},
toml::local_time{12, 30, 45})); toml::local_time{12, 30, 45}));
@@ -333,13 +325,13 @@ BOOST_AUTO_TEST_CASE(test_get_toml_local_datetime)
t.tm_sec = 45; t.tm_sec = 45;
t.tm_isdst = -1; t.tm_isdst = -1;
const auto c = std::mktime(&t); const auto c = std::mktime(&t);
BOOST_CHECK_EQUAL(c, date); BOOST_TEST(c == date);
} }
BOOST_AUTO_TEST_CASE(test_get_toml_offset_datetime) BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_offset_datetime, value_type, test_value_types)
{ {
{ {
toml::value v1(toml::offset_datetime( value_type v1(toml::offset_datetime(
toml::local_date{2018, toml::month_t::Apr, 1}, toml::local_date{2018, toml::month_t::Apr, 1},
toml::local_time{12, 30, 0}, toml::local_time{12, 30, 0},
toml::time_offset{9, 0})); toml::time_offset{9, 0}));
@@ -351,18 +343,18 @@ BOOST_AUTO_TEST_CASE(test_get_toml_offset_datetime)
// get time_t as gmtime (2018-04-01T03:30:00Z) // get time_t as gmtime (2018-04-01T03:30:00Z)
const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe! const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe!
BOOST_CHECK(tmp); BOOST_TEST(tmp);
const auto tm = *tmp; const auto tm = *tmp;
BOOST_CHECK_EQUAL(tm.tm_year + 1900, 2018); BOOST_TEST(tm.tm_year + 1900 == 2018);
BOOST_CHECK_EQUAL(tm.tm_mon + 1, 4); BOOST_TEST(tm.tm_mon + 1 == 4);
BOOST_CHECK_EQUAL(tm.tm_mday, 1); BOOST_TEST(tm.tm_mday == 1);
BOOST_CHECK_EQUAL(tm.tm_hour, 3); BOOST_TEST(tm.tm_hour == 3);
BOOST_CHECK_EQUAL(tm.tm_min, 30); BOOST_TEST(tm.tm_min == 30);
BOOST_CHECK_EQUAL(tm.tm_sec, 0); BOOST_TEST(tm.tm_sec == 0);
} }
{ {
toml::value v1(toml::offset_datetime( value_type v1(toml::offset_datetime(
toml::local_date{2018, toml::month_t::Apr, 1}, toml::local_date{2018, toml::month_t::Apr, 1},
toml::local_time{12, 30, 0}, toml::local_time{12, 30, 0},
toml::time_offset{-8, 0})); toml::time_offset{-8, 0}));
@@ -374,14 +366,14 @@ BOOST_AUTO_TEST_CASE(test_get_toml_offset_datetime)
// get time_t as gmtime (2018-04-01T03:30:00Z) // get time_t as gmtime (2018-04-01T03:30:00Z)
const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe! const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe!
BOOST_CHECK(tmp); BOOST_TEST(tmp);
const auto tm = *tmp; const auto tm = *tmp;
BOOST_CHECK_EQUAL(tm.tm_year + 1900, 2018); BOOST_TEST(tm.tm_year + 1900 == 2018);
BOOST_CHECK_EQUAL(tm.tm_mon + 1, 4); BOOST_TEST(tm.tm_mon + 1 == 4);
BOOST_CHECK_EQUAL(tm.tm_mday, 1); BOOST_TEST(tm.tm_mday == 1);
BOOST_CHECK_EQUAL(tm.tm_hour, 20); BOOST_TEST(tm.tm_hour == 20);
BOOST_CHECK_EQUAL(tm.tm_min, 30); BOOST_TEST(tm.tm_min == 30);
BOOST_CHECK_EQUAL(tm.tm_sec, 0); BOOST_TEST(tm.tm_sec == 0);
} }
} }

360
tests/test_get_or.cpp Normal file
View File

@@ -0,0 +1,360 @@
#define BOOST_TEST_MODULE "test_get_or"
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
#include <boost/test/unit_test.hpp>
#else
#define BOOST_TEST_NO_LIB
#include <boost/test/included/unit_test.hpp>
#endif
#include <toml.hpp>
#include <map>
#include <unordered_map>
#include <list>
#include <deque>
#include <array>
#include <tuple>
#if __cplusplus >= 201703L
#include <string_view>
#endif
using test_value_types = std::tuple<
toml::value,
toml::basic_value<toml::preserve_comments>,
toml::basic_value<toml::discard_comments, std::map, std::deque>,
toml::basic_value<toml::preserve_comments, std::map, std::deque>
>;
namespace test
{
template<typename charT, typename traits, typename T, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const std::vector<T, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << i << ' ';}
os << ']';
return os;
}
template<typename charT, typename traits, typename T, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const std::deque<T, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << i << ' ';}
os << ']';
return os;
}
template<typename charT, typename traits, typename T, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const std::list<T, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << i << ' ';}
os << ']';
return os;
}
template<typename charT, typename traits,
typename Key, typename Value, typename Comp, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os,
const std::map<Key, Value, Comp, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";}
os << ']';
return os;
}
template<typename charT, typename traits,
typename Key, typename Value, typename Hash, typename Eq, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os,
const std::unordered_map<Key, Value, Hash, Eq, Alloc>& 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_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<toml::toml_type>(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<typename value_type::array_type>(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<typename value_type::table_type>(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));
}
}
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<float>(v2.as_floating()) == toml::get_or(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);
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));
}
}

View File

@@ -1,254 +0,0 @@
#define BOOST_TEST_MODULE "test_get_or"
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
#include <boost/test/unit_test.hpp>
#else
#define BOOST_TEST_NO_LIB
#include <boost/test/included/unit_test.hpp>
#endif
#include <toml.hpp>
#include <map>
#include <unordered_map>
#include <list>
#include <deque>
#include <array>
BOOST_AUTO_TEST_CASE(test_find)
{
{
toml::value v(true);
bool thrown = false;
try
{
toml::find<toml::boolean>(v, "key");
}
catch(toml::type_error const& te)
{
thrown = true;
}
BOOST_CHECK(thrown);
}
{
toml::table v{{"num", 42}};
BOOST_CHECK_EQUAL(42, toml::find<int>(v, "num"));
toml::find<toml::integer>(v, "num") = 54;
BOOST_CHECK_EQUAL(54, toml::find<int>(v, "num"));
}
{
toml::value v = toml::table{{"num", 42}};
BOOST_CHECK_EQUAL(42, toml::find<int>(v, "num"));
toml::find<toml::integer>(v, "num") = 54;
BOOST_CHECK_EQUAL(54, toml::find<int>(v, "num"));
}
}
BOOST_AUTO_TEST_CASE(test_get_or)
{
// requires conversion int -> uint
{
toml::value v1(42);
toml::value v2(3.14);
BOOST_CHECK_EQUAL(42u, toml::get_or(v1, 0u));
BOOST_CHECK_EQUAL(0u, toml::get_or(v2, 0u));
}
// exact toml type
{
toml::value v1(42);
toml::value v2(3.14);
toml::integer opt(0);
BOOST_CHECK_EQUAL(42, toml::get_or(v1, opt));
BOOST_CHECK_EQUAL(0, toml::get_or(v2, opt));
toml::value v3("foobar");
toml::string s("bazqux");
BOOST_CHECK_EQUAL("foobar", toml::get_or(v3, s));
BOOST_CHECK_EQUAL("bazqux", toml::get_or(v1, s));
}
// std::string
{
toml::value v1("foobar");
toml::value v2(42);
std::string s1("bazqux");
const std::string s2("bazqux");
BOOST_CHECK_EQUAL("foobar", toml::get_or(v1, s1));
BOOST_CHECK_EQUAL("bazqux", toml::get_or(v2, s1));
std::string& v1r = toml::get_or(v1, s1);
std::string& s1r = toml::get_or(v2, s1);
BOOST_CHECK_EQUAL("foobar", v1r);
BOOST_CHECK_EQUAL("bazqux", s1r);
BOOST_CHECK_EQUAL("foobar", toml::get_or(v1, s2));
BOOST_CHECK_EQUAL("bazqux", toml::get_or(v2, s2));
BOOST_CHECK_EQUAL("foobar", toml::get_or(v1, std::move(s1)));
BOOST_CHECK_EQUAL("bazqux", toml::get_or(v2, std::move(s1)));
}
// string literal
{
toml::value v1("foobar");
toml::value v2(42);
BOOST_CHECK_EQUAL("foobar", toml::get_or(v1, "bazqux"));
BOOST_CHECK_EQUAL("bazqux", toml::get_or(v2, "bazqux"));
const char* lit = "bazqux";
BOOST_CHECK_EQUAL("foobar", toml::get_or(v1, lit));
BOOST_CHECK_EQUAL("bazqux", toml::get_or(v2, lit));
}
}
BOOST_AUTO_TEST_CASE(test_find_or)
{
// ========================================================================
// pass toml::value
//
// requires conversion int -> uint
{
toml::table v{{"num", 42}};
BOOST_CHECK_EQUAL(42u, toml::find_or(v, "num", 0u));
BOOST_CHECK_EQUAL(0u, toml::find_or(v, "foo", 0u));
}
// exact toml type
{
toml::table v1{{"key", 42 }};
toml::table v2{{"key", 3.14}};
toml::table v3{{"not", "key"}};
toml::integer opt(0);
BOOST_CHECK_EQUAL(42, toml::find_or(v1, "key", opt));
BOOST_CHECK_EQUAL(0, toml::find_or(v2, "key", opt));
BOOST_CHECK_EQUAL(0, toml::find_or(v3, "key", opt));
toml::table v4{{"str", "foobar"}};
toml::string s("bazqux");
BOOST_CHECK_EQUAL("foobar", toml::find_or(v4, "str", s));
BOOST_CHECK_EQUAL("bazqux", toml::find_or(v1, "str", s));
}
// std::string
{
toml::table v1{{"key", "foobar"}};
toml::table v2{{"key", 42}};
std::string s1("bazqux");
const std::string s2("bazqux");
BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", s1));
BOOST_CHECK_EQUAL("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_CHECK_EQUAL("foobar", v1r);
BOOST_CHECK_EQUAL("bazqux", s1r);
BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", s2));
BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", s2));
BOOST_CHECK_EQUAL("foobar", toml::find_or(std::move(v1), "key", std::move(s1)));
s1 = "bazqux"; // restoring moved value
BOOST_CHECK_EQUAL("bazqux", toml::find_or(std::move(v2), "key", std::move(s1)));
}
// string literal
{
toml::table v1{{"key", "foobar"}};
toml::table v2{{"key",42}};
BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", "bazqux"));
BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", "bazqux"));
const char* lit = "bazqux";
BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", lit));
BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", lit));
}
// ========================================================================
// pass toml::value
//
// requires conversion int -> uint
{
toml::table v = toml::table{{"num", 42}};
BOOST_CHECK_EQUAL(42u, toml::find_or(v, "num", 0u));
BOOST_CHECK_EQUAL(0u, toml::find_or(v, "foo", 0u));
}
// exact toml type
{
toml::value v1 = toml::table{{"key", 42 }};
toml::value v2 = toml::table{{"key", 3.14}};
toml::value v3 = toml::table{{"not", "key"}};
BOOST_CHECK_EQUAL(42, toml::find_or(v1, "key", toml::integer(0)));
BOOST_CHECK_EQUAL( 0, toml::find_or(v2, "key", toml::integer(0)));
BOOST_CHECK_EQUAL( 0, toml::find_or(v3, "key", toml::integer(0)));
toml::value v4 = toml::table{{"str", "foobar"}};
toml::string s("bazqux");
BOOST_CHECK_EQUAL("foobar", toml::find_or(v4, "str", s));
BOOST_CHECK_EQUAL("bazqux", toml::find_or(v1, "str", s));
}
// std::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_CHECK_EQUAL("foobar", toml::find_or(v1, "key", s1));
BOOST_CHECK_EQUAL("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_CHECK_EQUAL("foobar", v1r);
BOOST_CHECK_EQUAL("bazqux", s1r);
BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", s2));
BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", s2));
BOOST_CHECK_EQUAL("foobar", toml::find_or(std::move(v1), "key", std::move(s1)));
s1 = "bazqux"; // restoring moved value
BOOST_CHECK_EQUAL("bazqux", toml::find_or(std::move(v2), "key", std::move(s1)));
}
// string literal
{
toml::value v1 = toml::table{{"key", "foobar"}};
toml::value v2 = toml::table{{"key",42}};
BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", "bazqux"));
BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", "bazqux"));
const char* lit = "bazqux";
BOOST_CHECK_EQUAL("foobar", toml::find_or(v1, "key", lit));
BOOST_CHECK_EQUAL("bazqux", toml::find_or(v2, "key", lit));
}
}
BOOST_AUTO_TEST_CASE(test_expect)
{
{
toml::value v1(42);
toml::value v2(3.14);
const auto v1_or_0 = toml::expect<int>(v1).unwrap_or(0);
const auto v2_or_0 = toml::expect<int>(v2).unwrap_or(0);
BOOST_CHECK_EQUAL(42, v1_or_0);
BOOST_CHECK_EQUAL( 0, v2_or_0);
const auto v1_or_none = toml::expect<int>(v1).map([](int i){return std::to_string(i);}).unwrap_or(std::string("none"));
const auto v2_or_none = toml::expect<int>(v2).map([](int i){return std::to_string(i);}).unwrap_or(std::string("none"));
BOOST_CHECK_EQUAL("42", v1_or_none);
BOOST_CHECK_EQUAL("none", v2_or_none);
}
}

View File

@@ -10,17 +10,17 @@ do { \
const std::string expected(expct); \ const std::string expected(expct); \
toml::detail::location<std::string> loc("test", token); \ toml::detail::location<std::string> loc("test", token); \
const auto result = lxr::invoke(loc); \ const auto result = lxr::invoke(loc); \
BOOST_CHECK(result.is_ok()); \ BOOST_TEST(result.is_ok()); \
if(result.is_ok()){ \ if(result.is_ok()){ \
const auto region = result.unwrap(); \ const auto region = result.unwrap(); \
BOOST_CHECK_EQUAL(region.str(), expected); \ BOOST_TEST(region.str() == expected); \
BOOST_CHECK_EQUAL(region.str().size(), expected.size()); \ BOOST_TEST(region.str().size() == expected.size()); \
BOOST_CHECK_EQUAL(static_cast<std::size_t>(std::distance( \ BOOST_TEST(static_cast<std::size_t>(std::distance( \
loc.begin(), loc.iter())), region.size()); \ loc.begin(), loc.iter())) == region.size()); \
} else { \ } else { \
std::cerr << "lexer failed with input `"; \ std::cerr << "lexer failed with input `"; \
std::cerr << token << "`. expected `" << expected << "`\n"; \ std::cerr << token << "`. expected `" << expected << "`\n"; \
std::cerr << "reason: " << result.unwrap_err() << '\n'; \ std::cerr << "reason: " << result.unwrap_err() << '\n'; \
} \ } \
} while(false); \ } while(false); \
/**/ /**/
@@ -30,6 +30,7 @@ do { \
const std::string token (tkn); \ const std::string token (tkn); \
toml::detail::location<std::string> loc("test", token); \ toml::detail::location<std::string> loc("test", token); \
const auto result = lxr::invoke(loc); \ const auto result = lxr::invoke(loc); \
BOOST_CHECK(result.is_err()); \ BOOST_TEST(result.is_err()); \
BOOST_CHECK(loc.begin() == loc.iter()); \ const bool loc_same = (loc.begin() == loc.iter()); \
BOOST_TEST(loc_same); \
} while(false); /**/ } while(false); /**/

View File

@@ -19,7 +19,7 @@ BOOST_AUTO_TEST_CASE(test_file_as_literal)
b = "baz" b = "baz"
)"_toml; )"_toml;
BOOST_CHECK_EQUAL(r, v); BOOST_TEST(r == v);
} }
{ {
const toml::value r{ const toml::value r{
@@ -33,7 +33,7 @@ BOOST_AUTO_TEST_CASE(test_file_as_literal)
b = "baz" b = "baz"
)"_toml; )"_toml;
BOOST_CHECK_EQUAL(r, v); BOOST_TEST(r == v);
} }
{ {
const toml::value r{ const toml::value r{
@@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE(test_file_as_literal)
b = "baz" b = "baz"
)"_toml; )"_toml;
BOOST_CHECK_EQUAL(r, v); BOOST_TEST(r == v);
} }
} }
@@ -57,31 +57,31 @@ BOOST_AUTO_TEST_CASE(test_value_as_literal)
const toml::value v1 = u8"true"_toml; const toml::value v1 = u8"true"_toml;
const toml::value v2 = u8"false"_toml; const toml::value v2 = u8"false"_toml;
BOOST_CHECK(v1.is_boolean()); BOOST_TEST(v1.is_boolean());
BOOST_CHECK(v2.is_boolean()); BOOST_TEST(v2.is_boolean());
BOOST_CHECK(toml::get<bool>(v1)); BOOST_TEST(toml::get<bool>(v1));
BOOST_CHECK(!toml::get<bool>(v2)); BOOST_TEST(!toml::get<bool>(v2));
} }
{ {
const toml::value v1 = u8"123_456"_toml; const toml::value v1 = u8"123_456"_toml;
const toml::value v2 = u8"0b0010"_toml; const toml::value v2 = u8"0b0010"_toml;
const toml::value v3 = u8"0xDEADBEEF"_toml; const toml::value v3 = u8"0xDEADBEEF"_toml;
BOOST_CHECK(v1.is_integer()); BOOST_TEST(v1.is_integer());
BOOST_CHECK(v2.is_integer()); BOOST_TEST(v2.is_integer());
BOOST_CHECK(v3.is_integer()); BOOST_TEST(v3.is_integer());
BOOST_CHECK_EQUAL(toml::get<toml::integer>(v1), 123456); BOOST_TEST(toml::get<toml::integer>(v1) == 123456);
BOOST_CHECK_EQUAL(toml::get<toml::integer>(v2), 2); BOOST_TEST(toml::get<toml::integer>(v2) == 2);
BOOST_CHECK_EQUAL(toml::get<toml::integer>(v3), 0xDEADBEEF); BOOST_TEST(toml::get<toml::integer>(v3) == 0xDEADBEEF);
} }
{ {
const toml::value v1 = u8"3.1415"_toml; const toml::value v1 = u8"3.1415"_toml;
const toml::value v2 = u8"6.02e+23"_toml; const toml::value v2 = u8"6.02e+23"_toml;
BOOST_CHECK(v1.is_floating()); BOOST_TEST(v1.is_floating());
BOOST_CHECK(v2.is_floating()); BOOST_TEST(v2.is_floating());
BOOST_CHECK_CLOSE(toml::get<double>(v1), 3.1415, 0.00001); BOOST_TEST(toml::get<double>(v1) == 3.1415, boost::test_tools::tolerance(0.00001));
BOOST_CHECK_CLOSE(toml::get<double>(v2), 6.02e23, 0.0001); BOOST_TEST(toml::get<double>(v2) == 6.02e23, boost::test_tools::tolerance(0.0001));
} }
{ {
const toml::value v1 = u8R"("foo")"_toml; const toml::value v1 = u8R"("foo")"_toml;
@@ -89,65 +89,74 @@ BOOST_AUTO_TEST_CASE(test_value_as_literal)
const toml::value v3 = u8R"("""foo""")"_toml; const toml::value v3 = u8R"("""foo""")"_toml;
const toml::value v4 = u8R"('''foo''')"_toml; const toml::value v4 = u8R"('''foo''')"_toml;
BOOST_CHECK(v1.is_string()); BOOST_TEST(v1.is_string());
BOOST_CHECK(v2.is_string()); BOOST_TEST(v2.is_string());
BOOST_CHECK(v3.is_string()); BOOST_TEST(v3.is_string());
BOOST_CHECK(v4.is_string()); BOOST_TEST(v4.is_string());
BOOST_CHECK_EQUAL(toml::get<std::string>(v1), "foo"); BOOST_TEST(toml::get<std::string>(v1) == "foo");
BOOST_CHECK_EQUAL(toml::get<std::string>(v2), "foo"); BOOST_TEST(toml::get<std::string>(v2) == "foo");
BOOST_CHECK_EQUAL(toml::get<std::string>(v3), "foo"); BOOST_TEST(toml::get<std::string>(v3) == "foo");
BOOST_CHECK_EQUAL(toml::get<std::string>(v4), "foo"); BOOST_TEST(toml::get<std::string>(v4) == "foo");
} }
{ {
const toml::value v1 = u8R"([1,2,3])"_toml; {
const toml::value v1 = u8R"([1,2,3])"_toml;
BOOST_CHECK(v1.is_array()); BOOST_TEST(v1.is_array());
BOOST_CHECK((toml::get<std::vector<int>>(v1) == std::vector<int>{1,2,3})); const bool result = (toml::get<std::vector<int>>(v1) == std::vector<int>{1,2,3});
BOOST_TEST(result);
const toml::value v2 = u8R"([1,])"_toml; }
{
BOOST_CHECK(v2.is_array()); const toml::value v2 = u8R"([1,])"_toml;
BOOST_CHECK((toml::get<std::vector<int>>(v2) == std::vector<int>{1})); BOOST_TEST(v2.is_array());
const bool result = (toml::get<std::vector<int>>(v2) == std::vector<int>{1});
const toml::value v3 = u8R"([[1,]])"_toml; BOOST_TEST(result);
BOOST_CHECK(v3.is_array()); }
BOOST_CHECK((toml::get<std::vector<int>>(toml::get<toml::array>(v3).front()) == std::vector<int>{1})); {
const toml::value v3 = u8R"([[1,]])"_toml;
const toml::value v4 = u8R"([[1],])"_toml; BOOST_TEST(v3.is_array());
BOOST_CHECK(v4.is_array()); const bool result = (toml::get<std::vector<int>>(toml::get<toml::array>(v3).front()) == std::vector<int>{1});
BOOST_CHECK((toml::get<std::vector<int>>(toml::get<toml::array>(v4).front()) == std::vector<int>{1})); BOOST_TEST(result);
}
{
const toml::value v4 = u8R"([[1],])"_toml;
BOOST_TEST(v4.is_array());
const bool result = (toml::get<std::vector<int>>(toml::get<toml::array>(v4).front()) == std::vector<int>{1});
BOOST_TEST(result);
}
} }
{ {
const toml::value v1 = u8R"({a = 42})"_toml; const toml::value v1 = u8R"({a = 42})"_toml;
BOOST_CHECK(v1.is_table()); BOOST_TEST(v1.is_table());
BOOST_CHECK((toml::get<std::map<std::string,int>>(v1) == const bool result = toml::get<std::map<std::string,int>>(v1) ==
std::map<std::string,int>{{"a", 42}})); std::map<std::string,int>{{"a", 42}};
BOOST_TEST(result);
} }
{ {
const toml::value v1 = u8"1979-05-27"_toml; const toml::value v1 = u8"1979-05-27"_toml;
BOOST_CHECK(v1.is_local_date()); BOOST_TEST(v1.is_local_date());
BOOST_CHECK_EQUAL(toml::get<toml::local_date>(v1), BOOST_TEST(toml::get<toml::local_date>(v1) ==
toml::local_date(1979, toml::month_t::May, 27)); toml::local_date(1979, toml::month_t::May, 27));
} }
{ {
const toml::value v1 = u8"12:00:00"_toml; const toml::value v1 = u8"12:00:00"_toml;
BOOST_CHECK(v1.is_local_time()); BOOST_TEST(v1.is_local_time());
BOOST_CHECK(toml::get<std::chrono::hours>(v1) == std::chrono::hours(12)); const bool result = toml::get<std::chrono::hours>(v1) == std::chrono::hours(12);
BOOST_TEST(result);
} }
{ {
const toml::value v1 = u8"1979-05-27T07:32:00"_toml; const toml::value v1 = u8"1979-05-27T07:32:00"_toml;
BOOST_CHECK(v1.is_local_datetime()); BOOST_TEST(v1.is_local_datetime());
BOOST_CHECK_EQUAL(toml::get<toml::local_datetime>(v1), BOOST_TEST(toml::get<toml::local_datetime>(v1) ==
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0))); toml::local_time(7, 32, 0)));
} }
{ {
const toml::value v1 = "1979-05-27T07:32:00Z"_toml; const toml::value v1 = "1979-05-27T07:32:00Z"_toml;
BOOST_CHECK(v1.is_offset_datetime()); BOOST_TEST(v1.is_offset_datetime());
BOOST_CHECK_EQUAL(toml::get<toml::offset_datetime>(v1), BOOST_TEST(toml::get<toml::offset_datetime>(v1) ==
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0), toml::time_offset(0, 0))); toml::local_time(7, 32, 0), toml::time_offset(0, 0)));
} }

View File

@@ -7,5 +7,5 @@ int main()
const std::string content("a = 0"); const std::string content("a = 0");
std::istringstream iss(content); std::istringstream iss(content);
const auto data = toml::parse(iss, "test_multiple_translation_unit.toml"); const auto data = toml::parse(iss, "test_multiple_translation_unit.toml");
return read_a(data); return read_a(toml::get<toml::table>(data));
} }

View File

@@ -1,4 +1,4 @@
#define BOOST_TEST_MODULE "parse_array_test" #define BOOST_TEST_MODULE "parse_array<toml::value>_test"
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST #ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#else #else
@@ -13,118 +13,118 @@ using namespace detail;
BOOST_AUTO_TEST_CASE(test_oneline_array) BOOST_AUTO_TEST_CASE(test_oneline_array)
{ {
TOML11_TEST_PARSE_EQUAL(parse_array, "[]", array()); TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[]", array());
{ {
array a(5); array a(5);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); 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); a[3] = toml::value(1); a[4] = toml::value(5);
TOML11_TEST_PARSE_EQUAL(parse_array, "[3,1,4,1,5]", a); TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[3,1,4,1,5]", a);
} }
{ {
array a(3); array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("bar"); a[0] = toml::value("foo"); a[1] = toml::value("bar");
a[2] = toml::value("baz"); a[2] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL(parse_array, "[\"foo\", \"bar\", \"baz\"]", a); TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[\"foo\", \"bar\", \"baz\"]", a);
} }
{ {
array a(5); array a(5);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); 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); a[3] = toml::value(1); a[4] = toml::value(5);
TOML11_TEST_PARSE_EQUAL(parse_array, "[3,1,4,1,5,]", a); TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[3,1,4,1,5,]", a);
} }
{ {
array a(3); array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("bar"); a[0] = toml::value("foo"); a[1] = toml::value("bar");
a[2] = toml::value("baz"); a[2] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL(parse_array, "[\"foo\", \"bar\", \"baz\",]", a); TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[\"foo\", \"bar\", \"baz\",]", a);
} }
} }
BOOST_AUTO_TEST_CASE(test_oneline_array_value) BOOST_AUTO_TEST_CASE(test_oneline_array_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[]", toml::value(array())); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[]", toml::value(array()));
{ {
array a(5); array a(5);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); 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); 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)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[3,1,4,1,5]", toml::value(a));
} }
{ {
array a(3); array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("bar"); a[0] = toml::value("foo"); a[1] = toml::value("bar");
a[2] = toml::value("baz"); a[2] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\", \"bar\", \"baz\"]", toml::value(a)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\", \"bar\", \"baz\"]", toml::value(a));
} }
{ {
array a(5); array a(5);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); 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); 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)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[3,1,4,1,5,]", toml::value(a));
} }
{ {
array a(3); array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("bar"); a[0] = toml::value("foo"); a[1] = toml::value("bar");
a[2] = toml::value("baz"); a[2] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\", \"bar\", \"baz\",]", toml::value(a)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\", \"bar\", \"baz\",]", toml::value(a));
} }
} }
BOOST_AUTO_TEST_CASE(test_multiline_array) BOOST_AUTO_TEST_CASE(test_multiline_array)
{ {
TOML11_TEST_PARSE_EQUAL(parse_array, "[\n#comment\n]", array()); TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[\n#comment\n]", array());
{ {
array a(5); array a(5);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); 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); a[3] = toml::value(1); a[4] = toml::value(5);
TOML11_TEST_PARSE_EQUAL(parse_array, "[3,\n1,\n4,\n1,\n5]", a); TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[3,\n1,\n4,\n1,\n5]", a);
} }
{ {
array a(3); array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("bar"); a[0] = toml::value("foo"); a[1] = toml::value("bar");
a[2] = toml::value("baz"); a[2] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL(parse_array, "[\"foo\",\n\"bar\",\n\"baz\"]", a); TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[\"foo\",\n\"bar\",\n\"baz\"]", a);
} }
{ {
array a(5); array a(5);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); 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); a[3] = toml::value(1); a[4] = toml::value(5);
TOML11_TEST_PARSE_EQUAL(parse_array, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5]", a); TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5]", a);
} }
{ {
array a(3); array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("b#r"); a[0] = toml::value("foo"); a[1] = toml::value("b#r");
a[2] = toml::value("b#z"); a[2] = toml::value("b#z");
TOML11_TEST_PARSE_EQUAL(parse_array, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", a); TOML11_TEST_PARSE_EQUAL(parse_array<toml::value>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", a);
} }
} }
BOOST_AUTO_TEST_CASE(test_multiline_array_value) BOOST_AUTO_TEST_CASE(test_multiline_array_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\n#comment\n]", toml::value(array())); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\n#comment\n]", toml::value(array()));
{ {
array a(5); array a(5);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); 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); a[3] = toml::value(1); a[4] = toml::value(5);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[3,\n1,\n4,\n1,\n5]", toml::value(a)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[3,\n1,\n4,\n1,\n5]", toml::value(a));
} }
{ {
array a(3); array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("bar"); a[0] = toml::value("foo"); a[1] = toml::value("bar");
a[2] = toml::value("baz"); a[2] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\",\n\"bar\",\n\"baz\"]", toml::value(a)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\",\n\"bar\",\n\"baz\"]", toml::value(a));
} }
{ {
array a(5); array a(5);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); 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); a[3] = toml::value(1); a[4] = toml::value(5);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5]", toml::value(a)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5]", toml::value(a));
} }
{ {
array a(3); array a(3);
a[0] = toml::value("foo"); a[1] = toml::value("b#r"); a[0] = toml::value("foo"); a[1] = toml::value("b#r");
a[2] = toml::value("b#z"); a[2] = toml::value("b#z");
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", toml::value(a)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", toml::value(a));
} }
} }

View File

@@ -1,8 +1,7 @@
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <algorithm> #include <algorithm>
#include <toml/region.hpp> #include <toml.hpp>
#include <toml/result.hpp>
// some of the parsers returns not only a value but also a region. // some of the parsers returns not only a value but also a region.
#define TOML11_TEST_PARSE_EQUAL(psr, tkn, expct) \ #define TOML11_TEST_PARSE_EQUAL(psr, tkn, expct) \
@@ -10,13 +9,13 @@ do { \
const std::string token(tkn); \ const std::string token(tkn); \
toml::detail::location<std::string> loc("test", token); \ toml::detail::location<std::string> loc("test", token); \
const auto result = psr(loc); \ const auto result = psr(loc); \
BOOST_CHECK(result.is_ok()); \ BOOST_TEST(result.is_ok()); \
if(result.is_ok()){ \ if(result.is_ok()){ \
BOOST_CHECK(result.unwrap().first == expct); \ BOOST_TEST(result.unwrap().first == expct); \
} else { \ } else { \
std::cerr << "parser " << #psr << " failed with input `"; \ std::cerr << "parser " << #psr << " failed with input `"; \
std::cerr << token << "`.\n"; \ std::cerr << token << "`.\n"; \
std::cerr << "reason: " << result.unwrap_err() << '\n'; \ std::cerr << "reason: " << result.unwrap_err() << '\n'; \
} \ } \
} while(false); \ } while(false); \
/**/ /**/
@@ -26,13 +25,13 @@ do { \
const std::string token(tkn); \ const std::string token(tkn); \
toml::detail::location<std::string> loc("test", token); \ toml::detail::location<std::string> loc("test", token); \
const auto result = psr(loc); \ const auto result = psr(loc); \
BOOST_CHECK(result.is_ok()); \ BOOST_TEST(result.is_ok()); \
if(result.is_ok()){ \ if(result.is_ok()){ \
BOOST_CHECK(result.unwrap() == expct); \ BOOST_TEST(result.unwrap() == expct); \
} else { \ } else { \
std::cerr << "parse_value failed with input `"; \ std::cerr << "parse_value failed with input `"; \
std::cerr << token << "`.\n"; \ std::cerr << token << "`.\n"; \
std::cerr << "reason: " << result.unwrap_err() << '\n'; \ std::cerr << "reason: " << result.unwrap_err() << '\n'; \
} \ } \
} while(false); \ } while(false); \
/**/ /**/

View File

@@ -19,6 +19,6 @@ BOOST_AUTO_TEST_CASE(test_boolean)
BOOST_AUTO_TEST_CASE(test_boolean_value) 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<toml::value>, "true", toml::value( true));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "false", toml::value(false)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "false", toml::value(false));
} }

View File

@@ -21,10 +21,10 @@ BOOST_AUTO_TEST_CASE(test_time)
BOOST_AUTO_TEST_CASE(test_time_value) 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<toml::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<toml::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<toml::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<toml::value>, "07:32:00.999999", toml::value(toml::local_time(7, 32, 0, 999, 999)));
} }
BOOST_AUTO_TEST_CASE(test_date) BOOST_AUTO_TEST_CASE(test_date)
@@ -34,7 +34,7 @@ BOOST_AUTO_TEST_CASE(test_date)
} }
BOOST_AUTO_TEST_CASE(test_date_value) BOOST_AUTO_TEST_CASE(test_date_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27",
value(toml::local_date(1979, toml::month_t::May, 27))); value(toml::local_date(1979, toml::month_t::May, 27)));
} }
@@ -64,25 +64,25 @@ BOOST_AUTO_TEST_CASE(test_datetime)
BOOST_AUTO_TEST_CASE(test_datetime_value) BOOST_AUTO_TEST_CASE(test_datetime_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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)))); toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999))));
} }
@@ -111,23 +111,23 @@ BOOST_AUTO_TEST_CASE(test_offset_datetime)
BOOST_AUTO_TEST_CASE(test_offset_datetime_value) BOOST_AUTO_TEST_CASE(test_offset_datetime_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00Z", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00Z",
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), 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)))); toml::local_time(7, 32, 0), toml::time_offset(0, 0))));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1979-05-27T07:32:00.99Z", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00.99Z",
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), 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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00.999999Z",
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), 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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00+09:00",
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), 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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00.99+09:00",
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), 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)))); 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", TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00.999999+09:00",
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), 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)))); toml::local_time(7, 32, 0, 999, 999), toml::time_offset(9, 0))));
} }

View File

@@ -8,73 +8,69 @@
#include <toml.hpp> #include <toml.hpp>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <map>
#include <deque>
BOOST_AUTO_TEST_CASE(test_example) BOOST_AUTO_TEST_CASE(test_example)
{ {
const auto data = toml::parse("toml/tests/example.toml"); const auto data = toml::parse("toml/tests/example.toml");
BOOST_CHECK_EQUAL(toml::get<std::string>(data.at("title")), "TOML Example"); BOOST_TEST(toml::find<std::string>(data, "title") == "TOML Example");
toml::Table owner = toml::get<toml::Table>(data.at("owner")); const auto& owner = toml::find(data, "owner");
{ {
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("name")), "Tom Preston-Werner"); BOOST_TEST(toml::find<std::string>(owner, "name") == "Tom Preston-Werner");
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("organization")), "GitHub"); BOOST_TEST(toml::find<std::string>(owner, "organization") == "GitHub");
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("bio")), BOOST_TEST(toml::find<std::string>(owner, "bio") ==
"GitHub Cofounder & CEO\nLikes tater tots and beer."); "GitHub Cofounder & CEO\nLikes tater tots and beer.");
BOOST_CHECK_EQUAL(toml::get<toml::Datetime>(owner.at("dob")), BOOST_TEST(toml::find<toml::offset_datetime>(owner, "dob") ==
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0), toml::time_offset(0, 0))); toml::local_time(7, 32, 0), toml::time_offset(0, 0)));
} }
toml::Table database = toml::get<toml::Table>(data.at("database")); const auto& database = toml::find(data, "database");
{ {
BOOST_CHECK_EQUAL(toml::get<std::string>(database.at("server")), "192.168.1.1"); BOOST_TEST(toml::find<std::string>(database, "server") == "192.168.1.1");
const std::vector<int> expected_ports{8001, 8001, 8002}; const std::vector<int> expected_ports{8001, 8001, 8002};
BOOST_CHECK(toml::get<std::vector<int>>(database.at("ports")) == expected_ports); BOOST_CHECK(toml::find<std::vector<int>>(database, "ports") == expected_ports);
BOOST_CHECK_EQUAL(toml::get<int>(database.at("connection_max")), 5000); BOOST_TEST(toml::find<int >(database, "connection_max") == 5000);
BOOST_CHECK_EQUAL(toml::get<bool>(database.at("enabled")), true); BOOST_TEST(toml::find<bool>(database, "enabled") == true);
} }
toml::Table servers = toml::get<toml::Table>(data.at("servers")); const auto& servers = toml::find(data, "servers");
{ {
toml::Table alpha = toml::get<toml::Table>(servers.at("alpha")); toml::table alpha = toml::find<toml::table>(servers, "alpha");
BOOST_CHECK_EQUAL(toml::get<std::string>(alpha.at("ip")), "10.0.0.1"); BOOST_TEST(toml::get<std::string>(alpha.at("ip")) == "10.0.0.1");
BOOST_CHECK_EQUAL(toml::get<std::string>(alpha.at("dc")), "eqdc10"); BOOST_TEST(toml::get<std::string>(alpha.at("dc")) == "eqdc10");
toml::Table beta = toml::get<toml::Table>(servers.at("beta")); toml::table beta = toml::find<toml::table>(servers, "beta");
BOOST_CHECK_EQUAL(toml::get<std::string>(beta.at("ip")), "10.0.0.2"); BOOST_TEST(toml::get<std::string>(beta.at("ip")) == "10.0.0.2");
BOOST_CHECK_EQUAL(toml::get<std::string>(beta.at("dc")), "eqdc10"); BOOST_TEST(toml::get<std::string>(beta.at("dc")) == "eqdc10");
BOOST_CHECK_EQUAL(toml::get<std::string>(beta.at("country")), "\xE4\xB8\xAD\xE5\x9B\xBD"); BOOST_TEST(toml::get<std::string>(beta.at("country")) == "\xE4\xB8\xAD\xE5\x9B\xBD");
} }
toml::Table clients = toml::get<toml::Table>(data.at("clients")); const auto& clients = toml::find(data, "clients");
{ {
toml::Array clients_data = toml::get<toml::Array>(clients.at("data")); toml::array clients_data = toml::find<toml::array>(clients, "data");
std::vector<std::string> expected_name{"gamma", "delta"}; std::vector<std::string> expected_name{"gamma", "delta"};
BOOST_CHECK(toml::get<std::vector<std::string>>(clients_data.at(0)) == BOOST_CHECK(toml::get<std::vector<std::string>>(clients_data.at(0)) == expected_name);
expected_name);
std::vector<int> expected_number{1, 2}; std::vector<int> expected_number{1, 2};
BOOST_CHECK(toml::get<std::vector<int>>(clients_data.at(1)) == BOOST_CHECK(toml::get<std::vector<int>>(clients_data.at(1)) == expected_number);
expected_number);
std::vector<std::string> expected_hosts{"alpha", "omega"}; std::vector<std::string> expected_hosts{"alpha", "omega"};
BOOST_CHECK(toml::get<std::vector<std::string>>(clients.at("hosts")) == BOOST_CHECK(toml::find<std::vector<std::string>>(clients, "hosts") == expected_hosts);
expected_hosts);
} }
std::vector<toml::Table> products = std::vector<toml::table> products =
toml::get<std::vector<toml::Table>>(data.at("products")); toml::find<std::vector<toml::table>>(data, "products");
{ {
BOOST_CHECK_EQUAL(toml::get<std::string>(products.at(0).at("name")), BOOST_TEST(toml::get<std::string>(products.at(0).at("name")) == "Hammer");
"Hammer"); BOOST_TEST(toml::get<std::int64_t>(products.at(0).at("sku")) == 738594937);
BOOST_CHECK_EQUAL(toml::get<std::int64_t>(products.at(0).at("sku")),
738594937);
BOOST_CHECK_EQUAL(toml::get<std::string>(products.at(1).at("name")), BOOST_TEST(toml::get<std::string>(products.at(1).at("name")) == "Nail");
"Nail"); BOOST_TEST(toml::get<std::int64_t>(products.at(1).at("sku")) == 284758393);
BOOST_CHECK_EQUAL(toml::get<std::int64_t>(products.at(1).at("sku")), BOOST_TEST(toml::get<std::string>(products.at(1).at("color")) == "gray");
284758393);
BOOST_CHECK_EQUAL(toml::get<std::string>(products.at(1).at("color")),
"gray");
} }
} }
@@ -83,42 +79,194 @@ BOOST_AUTO_TEST_CASE(test_example_stream)
std::ifstream ifs("toml/tests/example.toml"); std::ifstream ifs("toml/tests/example.toml");
const auto data = toml::parse(ifs); const auto data = toml::parse(ifs);
BOOST_CHECK_EQUAL(toml::get<std::string>(data.at("title")), "TOML Example"); BOOST_TEST(toml::find<std::string>(data, "title") == "TOML Example");
toml::Table owner = toml::get<toml::Table>(data.at("owner")); const auto& owner = toml::find(data, "owner");
{ {
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("name")), "Tom Preston-Werner"); BOOST_TEST(toml::find<std::string>(owner, "name") == "Tom Preston-Werner");
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("organization")), "GitHub"); BOOST_TEST(toml::find<std::string>(owner, "organization") == "GitHub");
BOOST_CHECK_EQUAL(toml::get<std::string>(owner.at("bio")), BOOST_TEST(toml::find<std::string>(owner, "bio") ==
"GitHub Cofounder & CEO\nLikes tater tots and beer."); "GitHub Cofounder & CEO\nLikes tater tots and beer.");
BOOST_CHECK_EQUAL(toml::get<toml::Datetime>(owner.at("dob")), BOOST_TEST(toml::find<toml::offset_datetime>(owner, "dob") ==
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0), toml::time_offset(0, 0))); toml::local_time(7, 32, 0), toml::time_offset(0, 0)));
} }
toml::Table database = toml::get<toml::Table>(data.at("database")); const auto& database = toml::find(data, "database");
{ {
BOOST_CHECK_EQUAL(toml::get<std::string>(database.at("server")), "192.168.1.1"); BOOST_TEST(toml::find<std::string>(database, "server") == "192.168.1.1");
const std::vector<int> expected_ports{8001, 8001, 8002}; const std::vector<int> expected_ports{8001, 8001, 8002};
BOOST_CHECK(toml::get<std::vector<int>>(database.at("ports")) == expected_ports); BOOST_CHECK(toml::find<std::vector<int>>(database, "ports") == expected_ports);
BOOST_CHECK_EQUAL(toml::get<int>(database.at("connection_max")), 5000); BOOST_TEST(toml::find<int >(database, "connection_max") == 5000);
BOOST_CHECK_EQUAL(toml::get<bool>(database.at("enabled")), true); BOOST_TEST(toml::find<bool>(database, "enabled") == true);
} }
toml::Table servers = toml::get<toml::Table>(data.at("servers")); const auto& servers = toml::find(data, "servers");
{ {
toml::Table alpha = toml::get<toml::Table>(servers.at("alpha")); toml::table alpha = toml::find<toml::table>(servers, "alpha");
BOOST_CHECK_EQUAL(toml::get<std::string>(alpha.at("ip")), "10.0.0.1"); BOOST_TEST(toml::get<std::string>(alpha.at("ip")) == "10.0.0.1");
BOOST_CHECK_EQUAL(toml::get<std::string>(alpha.at("dc")), "eqdc10"); BOOST_TEST(toml::get<std::string>(alpha.at("dc")) == "eqdc10");
toml::Table beta = toml::get<toml::Table>(servers.at("beta")); toml::table beta = toml::find<toml::table>(servers, "beta");
BOOST_CHECK_EQUAL(toml::get<std::string>(beta.at("ip")), "10.0.0.2"); BOOST_TEST(toml::get<std::string>(beta.at("ip")) == "10.0.0.2");
BOOST_CHECK_EQUAL(toml::get<std::string>(beta.at("dc")), "eqdc10"); BOOST_TEST(toml::get<std::string>(beta.at("dc")) == "eqdc10");
BOOST_CHECK_EQUAL(toml::get<std::string>(beta.at("country")), "\xE4\xB8\xAD\xE5\x9B\xBD"); BOOST_TEST(toml::get<std::string>(beta.at("country")) == "\xE4\xB8\xAD\xE5\x9B\xBD");
} }
toml::Table clients = toml::get<toml::Table>(data.at("clients")); const auto& clients = toml::find(data, "clients");
{ {
toml::Array clients_data = toml::get<toml::Array>(clients.at("data")); toml::array clients_data = toml::find<toml::array>(clients, "data");
std::vector<std::string> expected_name{"gamma", "delta"};
BOOST_CHECK(toml::get<std::vector<std::string>>(clients_data.at(0)) == expected_name);
std::vector<int> expected_number{1, 2};
BOOST_CHECK(toml::get<std::vector<int>>(clients_data.at(1)) == expected_number);
std::vector<std::string> expected_hosts{"alpha", "omega"};
BOOST_CHECK(toml::find<std::vector<std::string>>(clients, "hosts") == expected_hosts);
}
std::vector<toml::table> products =
toml::find<std::vector<toml::table>>(data, "products");
{
BOOST_TEST(toml::get<std::string>(products.at(0).at("name")) ==
"Hammer");
BOOST_TEST(toml::get<std::int64_t>(products.at(0).at("sku")) ==
738594937);
BOOST_TEST(toml::get<std::string>(products.at(1).at("name")) ==
"Nail");
BOOST_TEST(toml::get<std::int64_t>(products.at(1).at("sku")) ==
284758393);
BOOST_TEST(toml::get<std::string>(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::array>(toml::find(data, "fruit"), "blah");
BOOST_TEST(toml::find<std::string>(blah.at(0), "name") == "apple");
BOOST_TEST(toml::find<std::string>(blah.at(1), "name") == "banana");
{
const auto physical = toml::find(blah.at(0), "physical");
BOOST_TEST(toml::find<std::string>(physical, "color") == "red");
BOOST_TEST(toml::find<std::string>(physical, "shape") == "round");
}
{
const auto physical = toml::find(blah.at(1), "physical");
BOOST_TEST(toml::find<std::string>(physical, "color") == "yellow");
BOOST_TEST(toml::find<std::string>(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<std::string>(the, "test_string") ==
"You'll hate me after this - #");
const auto hard = toml::find(the, "hard");
const std::vector<std::string> expected_the_hard_test_array{"] ", " # "};
BOOST_CHECK(toml::find<std::vector<std::string>>(hard, "test_array") ==
expected_the_hard_test_array);
const std::vector<std::string> expected_the_hard_test_array2{
"Test #11 ]proved that", "Experiment #9 was a success"};
BOOST_CHECK(toml::find<std::vector<std::string>>(hard, "test_array2") ==
expected_the_hard_test_array2);
BOOST_TEST(toml::find<std::string>(hard, "another_test_string") ==
" Same thing, but with a string #");
BOOST_TEST(toml::find<std::string>(hard, "harder_test_string") ==
" And when \"'s are in the string, along with # \"");
const auto bit = toml::find(hard, "bit#");
BOOST_TEST(toml::find<std::string>(bit, "what?") ==
"You don't think some user won't do that?");
const std::vector<std::string> expected_multi_line_array{"]"};
BOOST_CHECK(toml::find<std::vector<std::string>>(bit, "multi_line_array") ==
expected_multi_line_array);
}
BOOST_AUTO_TEST_CASE(test_hard_example_comment)
{
const auto data = toml::parse<toml::preserve_comments>("toml/tests/hard_example.toml");
const auto the = toml::find(data, "the");
BOOST_TEST(toml::find<std::string>(the, "test_string") ==
"You'll hate me after this - #");
const auto hard = toml::find(the, "hard");
const std::vector<std::string> expected_the_hard_test_array{"] ", " # "};
BOOST_CHECK(toml::find<std::vector<std::string>>(hard, "test_array") ==
expected_the_hard_test_array);
const std::vector<std::string> expected_the_hard_test_array2{
"Test #11 ]proved that", "Experiment #9 was a success"};
BOOST_CHECK(toml::find<std::vector<std::string>>(hard, "test_array2") ==
expected_the_hard_test_array2);
BOOST_TEST(toml::find<std::string>(hard, "another_test_string") ==
" Same thing, but with a string #");
BOOST_TEST(toml::find<std::string>(hard, "harder_test_string") ==
" And when \"'s are in the string, along with # \"");
const auto bit = toml::find(hard, "bit#");
BOOST_TEST(toml::find<std::string>(bit, "what?") ==
"You don't think some user won't do that?");
const std::vector<std::string> expected_multi_line_array{"]"};
BOOST_CHECK(toml::find<std::vector<std::string>>(bit, "multi_line_array") ==
expected_multi_line_array);
}
BOOST_AUTO_TEST_CASE(test_example_preserve_comment)
{
const auto data = toml::parse<toml::preserve_comments>("toml/tests/example.toml");
BOOST_TEST(toml::find<std::string>(data, "title") == "TOML Example");
const auto& owner = toml::find(data, "owner");
{
BOOST_TEST(toml::find<std::string>(owner, "name") == "Tom Preston-Werner");
BOOST_TEST(toml::find<std::string>(owner, "organization") == "GitHub");
BOOST_TEST(toml::find<std::string>(owner, "bio") ==
"GitHub Cofounder & CEO\nLikes tater tots and beer.");
BOOST_TEST(toml::find<toml::offset_datetime>(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<std::string>(database, "server") == "192.168.1.1");
const std::vector<int> expected_ports{8001, 8001, 8002};
BOOST_CHECK(toml::find<std::vector<int>>(database, "ports") == expected_ports);
BOOST_TEST(toml::find<int >(database, "connection_max") == 5000);
BOOST_TEST(toml::find<bool>(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<std::string>(alpha, "ip") == "10.0.0.1");
BOOST_TEST(toml::find<std::string>(alpha, "dc") == "eqdc10");
const auto& beta = toml::find(servers, "beta");
BOOST_TEST(toml::find<std::string>(beta, "ip") == "10.0.0.2");
BOOST_TEST(toml::find<std::string>(beta, "dc") == "eqdc10");
BOOST_TEST(toml::find<std::string>(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<toml::array>(clients, "data");
std::vector<std::string> expected_name{"gamma", "delta"}; std::vector<std::string> expected_name{"gamma", "delta"};
BOOST_CHECK(toml::get<std::vector<std::string>>(clients_data.at(0)) == BOOST_CHECK(toml::get<std::vector<std::string>>(clients_data.at(0)) ==
expected_name); expected_name);
@@ -126,73 +274,118 @@ BOOST_AUTO_TEST_CASE(test_example_stream)
BOOST_CHECK(toml::get<std::vector<int>>(clients_data.at(1)) == BOOST_CHECK(toml::get<std::vector<int>>(clients_data.at(1)) ==
expected_number); expected_number);
std::vector<std::string> expected_hosts{"alpha", "omega"}; std::vector<std::string> expected_hosts{"alpha", "omega"};
BOOST_CHECK(toml::get<std::vector<std::string>>(clients.at("hosts")) == BOOST_CHECK(toml::find<std::vector<std::string>>(clients, "hosts") ==
expected_hosts); expected_hosts);
BOOST_TEST(toml::find(clients, "hosts").comments().at(0) ==
" Line breaks are OK when inside arrays");
} }
std::vector<toml::Table> products = std::vector<toml::table> products =
toml::get<std::vector<toml::Table>>(data.at("products")); toml::find<std::vector<toml::table>>(data, "products");
{ {
BOOST_CHECK_EQUAL(toml::get<std::string>(products.at(0).at("name")), BOOST_TEST(toml::get<std::string>(products.at(0).at("name")) ==
"Hammer"); "Hammer");
BOOST_CHECK_EQUAL(toml::get<std::int64_t>(products.at(0).at("sku")), BOOST_TEST(toml::get<std::int64_t>(products.at(0).at("sku")) ==
738594937); 738594937);
BOOST_CHECK_EQUAL(toml::get<std::string>(products.at(1).at("name")), BOOST_TEST(toml::get<std::string>(products.at(1).at("name")) ==
"Nail"); "Nail");
BOOST_CHECK_EQUAL(toml::get<std::int64_t>(products.at(1).at("sku")), BOOST_TEST(toml::get<std::int64_t>(products.at(1).at("sku")) ==
284758393); 284758393);
BOOST_CHECK_EQUAL(toml::get<std::string>(products.at(1).at("color")), BOOST_TEST(toml::get<std::string>(products.at(1).at("color")) ==
"gray"); "gray");
} }
} }
BOOST_AUTO_TEST_CASE(test_example_preserve_stdmap_stddeque)
BOOST_AUTO_TEST_CASE(test_fruit)
{ {
const auto data = toml::parse("toml/tests/fruit.toml"); const auto data = toml::parse<toml::preserve_comments, std::map, std::deque
const auto blah = toml::get<std::vector<toml::Table>>( >("toml/tests/example.toml");
toml::get<toml::Table>(data.at("fruit")).at("blah"));
BOOST_CHECK_EQUAL(toml::get<std::string>(blah.at(0).at("name")), "apple"); static_assert(std::is_same<typename decltype(data)::table_type,
BOOST_CHECK_EQUAL(toml::get<std::string>(blah.at(1).at("name")), "banana"); std::map<toml::key, typename std::remove_cv<decltype(data)>::type>
>::value, "");
static_assert(std::is_same<typename decltype(data)::array_type,
std::deque<typename std::remove_cv<decltype(data)>::type>
>::value, "");
BOOST_TEST(toml::find<std::string>(data, "title") == "TOML Example");
const auto& owner = toml::find(data, "owner");
{ {
const auto physical = toml::get<toml::Table>(blah.at(0).at("physical")); BOOST_TEST(toml::find<std::string>(owner, "name") == "Tom Preston-Werner");
BOOST_CHECK_EQUAL(toml::get<std::string>(physical.at("color")), "red"); BOOST_TEST(toml::find<std::string>(owner, "organization") == "GitHub");
BOOST_CHECK_EQUAL(toml::get<std::string>(physical.at("shape")), "round"); BOOST_TEST(toml::find<std::string>(owner, "bio") ==
"GitHub Cofounder & CEO\nLikes tater tots and beer.");
BOOST_TEST(toml::find<toml::offset_datetime>(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");
{ {
const auto physical = toml::get<toml::Table>(blah.at(1).at("physical")); BOOST_TEST(toml::find<std::string>(database, "server") == "192.168.1.1");
BOOST_CHECK_EQUAL(toml::get<std::string>(physical.at("color")), "yellow"); const std::vector<int> expected_ports{8001, 8001, 8002};
BOOST_CHECK_EQUAL(toml::get<std::string>(physical.at("shape")), "bent"); BOOST_CHECK(toml::find<std::vector<int>>(database, "ports") == expected_ports);
BOOST_TEST(toml::find<int >(database, "connection_max") == 5000);
BOOST_TEST(toml::find<bool>(database, "enabled") == true);
} }
}
BOOST_AUTO_TEST_CASE(test_hard_example) const auto& servers = toml::find(data, "servers");
{ {
const auto data = toml::parse("toml/tests/hard_example.toml"); const auto& alpha = toml::find(servers, "alpha");
const auto the = toml::get<toml::Table>(data.at("the")); BOOST_TEST(alpha.comments().at(0) ==
BOOST_CHECK_EQUAL(toml::get<std::string>(the.at("test_string")), " You can indent as you please. Tabs or spaces. TOML don't care.");
"You'll hate me after this - #"); BOOST_TEST(toml::find<std::string>(alpha, "ip") == "10.0.0.1");
BOOST_TEST(toml::find<std::string>(alpha, "dc") == "eqdc10");
const auto hard = toml::get<toml::Table>(the.at("hard")); const auto& beta = toml::find(servers, "beta");
const std::vector<std::string> expected_the_hard_test_array{"] ", " # "}; BOOST_TEST(toml::find<std::string>(beta, "ip") == "10.0.0.2");
BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array")) == BOOST_TEST(toml::find<std::string>(beta, "dc") == "eqdc10");
expected_the_hard_test_array); BOOST_TEST(toml::find<std::string>(beta, "country") ==
const std::vector<std::string> expected_the_hard_test_array2{ "\xE4\xB8\xAD\xE5\x9B\xBD");
"Test #11 ]proved that", "Experiment #9 was a success"}; BOOST_TEST(toml::find(beta, "country").comments().at(0) ==
BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array2")) == " This should be parsed as UTF-8");
expected_the_hard_test_array2); }
BOOST_CHECK_EQUAL(toml::get<std::string>(hard.at("another_test_string")),
" Same thing, but with a string #");
BOOST_CHECK_EQUAL(toml::get<std::string>(hard.at("harder_test_string")),
" And when \"'s are in the string, along with # \"");
const auto bit = toml::get<toml::Table>(hard.at("bit#")); const auto& clients = toml::find(data, "clients");
BOOST_CHECK_EQUAL(toml::get<std::string>(bit.at("what?")), {
"You don't think some user won't do that?"); BOOST_TEST(toml::find(clients, "data").comments().at(0) ==
const std::vector<std::string> expected_multi_line_array{"]"}; " just an update to make sure parsers support it");
BOOST_CHECK(toml::get<std::vector<std::string>>(bit.at("multi_line_array")) ==
expected_multi_line_array);
toml::array clients_data = toml::find<toml::array>(clients, "data");
std::vector<std::string> expected_name{"gamma", "delta"};
BOOST_CHECK(toml::get<std::vector<std::string>>(clients_data.at(0)) ==
expected_name);
std::vector<int> expected_number{1, 2};
BOOST_CHECK(toml::get<std::vector<int>>(clients_data.at(1)) ==
expected_number);
std::vector<std::string> expected_hosts{"alpha", "omega"};
BOOST_CHECK(toml::find<std::vector<std::string>>(clients, "hosts") ==
expected_hosts);
BOOST_TEST(toml::find(clients, "hosts").comments().at(0) ==
" Line breaks are OK when inside arrays");
}
std::vector<toml::table> products =
toml::find<std::vector<toml::table>>(data, "products");
{
BOOST_TEST(toml::get<std::string>(products.at(0).at("name")) ==
"Hammer");
BOOST_TEST(toml::get<std::int64_t>(products.at(0).at("sku")) ==
738594937);
BOOST_TEST(toml::get<std::string>(products.at(1).at("name")) ==
"Nail");
BOOST_TEST(toml::get<std::int64_t>(products.at(1).at("sku")) ==
284758393);
BOOST_TEST(toml::get<std::string>(products.at(1).at("color")) ==
"gray");
}
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -210,8 +403,8 @@ BOOST_AUTO_TEST_CASE(test_file_with_BOM)
std::istringstream iss(table); std::istringstream iss(table);
const auto data = toml::parse(iss, "test_file_with_BOM.toml"); const auto data = toml::parse(iss, "test_file_with_BOM.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -226,8 +419,8 @@ BOOST_AUTO_TEST_CASE(test_file_with_BOM)
} }
const auto data = toml::parse("tmp.toml"); const auto data = toml::parse("tmp.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -239,8 +432,8 @@ BOOST_AUTO_TEST_CASE(test_file_with_BOM)
std::istringstream iss(table); std::istringstream iss(table);
const auto data = toml::parse(iss, "test_file_with_BOM_CRLF.toml"); const auto data = toml::parse(iss, "test_file_with_BOM_CRLF.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -254,12 +447,12 @@ BOOST_AUTO_TEST_CASE(test_file_with_BOM)
// value will be "\r\r\n". To avoid the additional "\r", use binary // value will be "\r\r\n". To avoid the additional "\r", use binary
// mode. // mode.
std::ofstream ofs("tmp.toml", std::ios_base::binary); std::ofstream ofs("tmp.toml", std::ios_base::binary);
ofs.write(table.data(), table.size()); ofs.write(table.data(), static_cast<std::streamsize>(table.size()));
} }
const auto data = toml::parse("tmp.toml"); const auto data = toml::parse("tmp.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
} }
@@ -275,8 +468,8 @@ BOOST_AUTO_TEST_CASE(test_file_without_newline_at_the_end_of_file)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_file_without_newline_at_the_end_of_file.toml"); "test_file_without_newline_at_the_end_of_file.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -288,8 +481,8 @@ BOOST_AUTO_TEST_CASE(test_file_without_newline_at_the_end_of_file)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_file_without_newline_at_the_end_of_file_CRLF.toml"); "test_file_without_newline_at_the_end_of_file_CRLF.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
@@ -302,8 +495,8 @@ BOOST_AUTO_TEST_CASE(test_file_without_newline_at_the_end_of_file)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_file_without_newline_at_the_end_of_file_comment.toml"); "test_file_without_newline_at_the_end_of_file_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -315,8 +508,8 @@ BOOST_AUTO_TEST_CASE(test_file_without_newline_at_the_end_of_file)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_file_without_newline_at_the_end_of_file_comment.toml"); "test_file_without_newline_at_the_end_of_file_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
@@ -329,8 +522,8 @@ BOOST_AUTO_TEST_CASE(test_file_without_newline_at_the_end_of_file)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_file_without_newline_at_the_end_of_file_ws.toml"); "test_file_without_newline_at_the_end_of_file_ws.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -342,8 +535,8 @@ BOOST_AUTO_TEST_CASE(test_file_without_newline_at_the_end_of_file)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_file_without_newline_at_the_end_of_file_ws.toml"); "test_file_without_newline_at_the_end_of_file_ws.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
} }
@@ -362,8 +555,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_comment.toml"); "test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -377,8 +570,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_comment.toml"); "test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
// comment w/ newline // comment w/ newline
@@ -394,8 +587,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_comment.toml"); "test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -409,8 +602,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_comment.toml"); "test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
// CRLF version // CRLF version
@@ -426,8 +619,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_comment.toml"); "test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -441,8 +634,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_comment.toml"); "test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -455,8 +648,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_comment.toml"); "test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -470,8 +663,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_comment)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_comment.toml"); "test_files_end_with_comment.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
} }
@@ -489,8 +682,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -504,8 +697,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
// with whitespaces // with whitespaces
@@ -521,8 +714,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -536,8 +729,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -551,8 +744,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -566,8 +759,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
// with whitespaces but no newline // with whitespaces but no newline
@@ -582,8 +775,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
@@ -600,8 +793,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -615,8 +808,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
// with whitespaces // with whitespaces
@@ -632,8 +825,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -647,8 +840,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -662,8 +855,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -677,8 +870,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
{ {
const std::string table( const std::string table(
@@ -691,7 +884,8 @@ BOOST_AUTO_TEST_CASE(test_files_end_with_empty_lines)
const auto data = toml::parse(iss, const auto data = toml::parse(iss,
"test_files_end_with_newline.toml"); "test_files_end_with_newline.toml");
BOOST_CHECK_EQUAL(toml::get <std::string>(data.at("key")), "value"); BOOST_TEST(toml::find<std::string>(data, "key") == "value");
BOOST_CHECK_EQUAL(toml::find<std::string>(data.at("table"), "key"), "value"); BOOST_TEST(toml::find<std::string>(toml::find(data, "table"), "key") == "value");
} }
} }

View File

@@ -32,20 +32,20 @@ BOOST_AUTO_TEST_CASE(test_fractional)
BOOST_AUTO_TEST_CASE(test_fractional_value) 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<toml::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<toml::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<toml::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<toml::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<toml::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<toml::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<toml::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<toml::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<toml::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<toml::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<toml::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<toml::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<toml::value>, "+0.0", value( 0.0));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-0.0", value(-0.0)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-0.0", value(-0.0));
} }
BOOST_AUTO_TEST_CASE(test_exponential) BOOST_AUTO_TEST_CASE(test_exponential)
@@ -72,24 +72,24 @@ BOOST_AUTO_TEST_CASE(test_exponential)
BOOST_AUTO_TEST_CASE(test_exponential_value) BOOST_AUTO_TEST_CASE(test_exponential_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1e10", value(1e10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1e10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1e+10", value(1e10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1e+10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1e-10", value(1e-10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1e-10", value(1e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1e10", value(1e10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+1e10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1e+10", value(1e10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+1e+10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1e-10", value(1e-10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+1e-10", value(1e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1e10", value(-1e10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-1e10", value(-1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1e+10", value(-1e10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-1e+10", value(-1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1e-10", value(-1e-10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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<toml::value>, "123e-10", value(123e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1E10", value(1e10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1E10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1E+10", value(1e10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1E+10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1E-10", value(1e-10)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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<toml::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<toml::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<toml::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<toml::value>, "+0e0", value( 0.0));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-0e0", value(-0.0)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-0e0", value(-0.0));
} }
BOOST_AUTO_TEST_CASE(test_fe) BOOST_AUTO_TEST_CASE(test_fe)
{ {
@@ -99,9 +99,9 @@ BOOST_AUTO_TEST_CASE(test_fe)
} }
BOOST_AUTO_TEST_CASE(test_fe_vaule) 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<toml::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<toml::value>, "6.02e+23", value(6.02e23));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "1.112_650_06e-17", value(1.11265006e-17)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1.112_650_06e-17", value(1.11265006e-17));
} }
BOOST_AUTO_TEST_CASE(test_inf) BOOST_AUTO_TEST_CASE(test_inf)

View File

@@ -13,36 +13,36 @@ using namespace detail;
BOOST_AUTO_TEST_CASE(test_inline_table) BOOST_AUTO_TEST_CASE(test_inline_table)
{ {
TOML11_TEST_PARSE_EQUAL(parse_inline_table, "{}", table()); TOML11_TEST_PARSE_EQUAL(parse_inline_table<toml::value>, "{}", table());
{ {
table t; table t;
t["foo"] = toml::value(42); t["foo"] = toml::value(42);
t["bar"] = toml::value("baz"); t["bar"] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL(parse_inline_table, "{foo = 42, bar = \"baz\"}", t); TOML11_TEST_PARSE_EQUAL(parse_inline_table<toml::value>, "{foo = 42, bar = \"baz\"}", t);
} }
{ {
table t; table t;
table t_sub; table t_sub;
t_sub["name"] = toml::value("pug"); t_sub["name"] = toml::value("pug");
t["type"] = toml::value(t_sub); t["type"] = toml::value(t_sub);
TOML11_TEST_PARSE_EQUAL(parse_inline_table, "{type.name = \"pug\"}", t); TOML11_TEST_PARSE_EQUAL(parse_inline_table<toml::value>, "{type.name = \"pug\"}", t);
} }
} }
BOOST_AUTO_TEST_CASE(test_inline_table_value) BOOST_AUTO_TEST_CASE(test_inline_table_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "{}", value(table())); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "{}", value(table()));
{ {
table t; table t;
t["foo"] = toml::value(42); t["foo"] = toml::value(42);
t["bar"] = toml::value("baz"); t["bar"] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "{foo = 42, bar = \"baz\"}", value(t)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "{foo = 42, bar = \"baz\"}", value(t));
} }
{ {
table t; table t;
table t_sub; table t_sub;
t_sub["name"] = toml::value("pug"); t_sub["name"] = toml::value("pug");
t["type"] = toml::value(t_sub); t["type"] = toml::value(t_sub);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "{type.name = \"pug\"}", value(t)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "{type.name = \"pug\"}", value(t));
} }
} }

View File

@@ -25,14 +25,14 @@ BOOST_AUTO_TEST_CASE(test_decimal)
BOOST_AUTO_TEST_CASE(test_decimal_value) 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<toml::value>, "1234", toml::value( 1234));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "+1234", toml::value( 1234)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+1234", toml::value( 1234));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "-1234", toml::value( -1234)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-1234", toml::value( -1234));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0", toml::value( 0)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::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<toml::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<toml::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<toml::value>, "-1_2_3_4", toml::value( -1234));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "123_456_789", toml::value(123456789)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "123_456_789", toml::value(123456789));
} }
BOOST_AUTO_TEST_CASE(test_hex) BOOST_AUTO_TEST_CASE(test_hex)
@@ -50,15 +50,15 @@ BOOST_AUTO_TEST_CASE(test_hex)
BOOST_AUTO_TEST_CASE(test_hex_value) BOOST_AUTO_TEST_CASE(test_hex_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xDEADBEEF", value(0xDEADBEEF)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xDEADBEEF", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xdeadbeef", value(0xDEADBEEF)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xdeadbeef", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xDEADbeef", value(0xDEADBEEF)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xDEADbeef", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xDEAD_BEEF", value(0xDEADBEEF)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xDEAD_BEEF", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xdead_beef", value(0xDEADBEEF)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xdead_beef", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xdead_BEEF", value(0xDEADBEEF)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xdead_BEEF", value(0xDEADBEEF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0xFF", value(0xFF)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xFF", value(0xFF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0x00FF", value(0xFF)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0x00FF", value(0xFF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0x0000FF", value(0xFF)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0x0000FF", value(0xFF));
} }
BOOST_AUTO_TEST_CASE(test_oct) BOOST_AUTO_TEST_CASE(test_oct)
@@ -70,9 +70,9 @@ BOOST_AUTO_TEST_CASE(test_oct)
BOOST_AUTO_TEST_CASE(test_oct_value) 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<toml::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<toml::value>, "0o7_7_7", value(64*7+8*7+7));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0o007", value(7)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0o007", value(7));
} }
BOOST_AUTO_TEST_CASE(test_bin) BOOST_AUTO_TEST_CASE(test_bin)
@@ -85,8 +85,8 @@ BOOST_AUTO_TEST_CASE(test_bin)
BOOST_AUTO_TEST_CASE(test_bin_value) BOOST_AUTO_TEST_CASE(test_bin_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b10000", value(16)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0b10000", value(16));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b010000", value(16)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0b010000", value(16));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b01_00_00", value(16)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0b01_00_00", value(16));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, "0b111111", value(63)); TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0b111111", value(63));
} }

View File

@@ -29,16 +29,16 @@ BOOST_AUTO_TEST_CASE(test_string)
BOOST_AUTO_TEST_CASE(test_string_value) BOOST_AUTO_TEST_CASE(test_string_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"The quick brown fox jumps over the lazy dog\"", "\"The quick brown fox jumps over the lazy dog\"",
toml::value("The quick brown fox jumps over the lazy dog", string_t::basic)); toml::value("The quick brown fox jumps over the lazy dog", string_t::basic));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\'The quick brown fox jumps over the lazy dog\'", "\'The quick brown fox jumps over the lazy dog\'",
toml::value("The quick brown fox jumps over the lazy dog", string_t::literal)); toml::value("The quick brown fox jumps over the lazy dog", string_t::literal));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\"", "\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\"",
toml::value("The quick brown fox jumps over the lazy dog", string_t::basic)); toml::value("The quick brown fox jumps over the lazy dog", string_t::basic));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"'''The quick brown fox \njumps over the lazy dog'''", "'''The quick brown fox \njumps over the lazy dog'''",
toml::value("The quick brown fox \njumps over the lazy dog", string_t::literal)); toml::value("The quick brown fox \njumps over the lazy dog", string_t::literal));
} }
@@ -73,25 +73,25 @@ BOOST_AUTO_TEST_CASE(test_basic_string)
BOOST_AUTO_TEST_CASE(test_basic_string_value) BOOST_AUTO_TEST_CASE(test_basic_string_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"", "\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"",
value("GitHub Cofounder & CEO\nLikes tater tots and beer.", string_t::basic)); value("GitHub Cofounder & CEO\nLikes tater tots and beer.", string_t::basic));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"192.168.1.1\"", "\"192.168.1.1\"",
value("192.168.1.1", string_t::basic)); value("192.168.1.1", string_t::basic));
#if defined(_MSC_VER) || defined(__INTEL_COMPILER) #if defined(_MSC_VER) || defined(__INTEL_COMPILER)
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"\xE4\xB8\xAD\xE5\x9B\xBD\"", "\"\xE4\xB8\xAD\xE5\x9B\xBD\"",
value("\xE4\xB8\xAD\xE5\x9B\xBD", string_t::basic)); value("\xE4\xB8\xAD\xE5\x9B\xBD", string_t::basic));
#else #else
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"中国\"", "\"中国\"",
value("中国", string_t::basic)); value("中国", string_t::basic));
#endif #endif
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"You'll hate me after this - #\"", "\"You'll hate me after this - #\"",
value("You'll hate me after this - #", string_t::basic)); value("You'll hate me after this - #", string_t::basic));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\" And when \\\"'s are in the along with # \\\"\"", "\" And when \\\"'s are in the along with # \\\"\"",
value(" And when \"'s are in the along with # \"", string_t::basic)); value(" And when \"'s are in the along with # \"", string_t::basic));
} }
@@ -108,10 +108,10 @@ BOOST_AUTO_TEST_CASE(test_ml_basic_string)
BOOST_AUTO_TEST_CASE(test_ml_basic_string_value) BOOST_AUTO_TEST_CASE(test_ml_basic_string_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"\"\"\nThe quick brown \\\n\n fox jumps over \\\n the lazy dog.\"\"\"", "\"\"\"\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)); value("The quick brown fox jumps over the lazy dog.", string_t::basic));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"\"\"\\\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 \"\"\"",
value("The quick brown fox jumps over the lazy dog.", string_t::basic)); value("The quick brown fox jumps over the lazy dog.", string_t::basic));
} }
@@ -134,16 +134,16 @@ BOOST_AUTO_TEST_CASE(test_literal_string)
BOOST_AUTO_TEST_CASE(test_literal_string_value) BOOST_AUTO_TEST_CASE(test_literal_string_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"'C:\\Users\\nodejs\\templates'", "'C:\\Users\\nodejs\\templates'",
value("C:\\Users\\nodejs\\templates", string_t::literal)); value("C:\\Users\\nodejs\\templates", string_t::literal));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"'\\\\ServerX\\admin$\\system32\\'", "'\\\\ServerX\\admin$\\system32\\'",
value("\\\\ServerX\\admin$\\system32\\", string_t::literal)); value("\\\\ServerX\\admin$\\system32\\", string_t::literal));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"'Tom \"Dubs\" Preston-Werner'", "'Tom \"Dubs\" Preston-Werner'",
value("Tom \"Dubs\" Preston-Werner", string_t::literal)); value("Tom \"Dubs\" Preston-Werner", string_t::literal));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"'<\\i\\c*\\s*>'", "'<\\i\\c*\\s*>'",
value("<\\i\\c*\\s*>", string_t::literal)); value("<\\i\\c*\\s*>", string_t::literal));
} }
@@ -160,10 +160,10 @@ BOOST_AUTO_TEST_CASE(test_ml_literal_string)
BOOST_AUTO_TEST_CASE(test_ml_literal_string_value) BOOST_AUTO_TEST_CASE(test_ml_literal_string_value)
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"'''I [dw]on't need \\d{2} apples'''", "'''I [dw]on't need \\d{2} apples'''",
value("I [dw]on't need \\d{2} apples", string_t::literal)); value("I [dw]on't need \\d{2} apples", string_t::literal));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value, TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"'''\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'''",
value("The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n", string_t::literal)); value("The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n", string_t::literal));
} }

View File

@@ -21,13 +21,13 @@ BOOST_AUTO_TEST_CASE(test_normal_table)
); );
location<std::string> loc("test", table); location<std::string> loc("test", table);
const auto result = toml::detail::parse_ml_table(loc); const auto result = toml::detail::parse_ml_table<toml::value>(loc);
BOOST_CHECK(result.is_ok()); BOOST_TEST(result.is_ok());
const auto data = result.unwrap(); const auto data = result.unwrap();
BOOST_CHECK_EQUAL(toml::get<std::string >(data.at("key1")), "value"); BOOST_TEST(toml::get<std::string >(data.at("key1")) == "value");
BOOST_CHECK_EQUAL(toml::get<std::int64_t>(data.at("key2")), 42); BOOST_TEST(toml::get<std::int64_t>(data.at("key2")) == 42);
BOOST_CHECK_EQUAL(toml::get<double >(data.at("key3")), 3.14); BOOST_TEST(toml::get<double >(data.at("key3")) == 3.14);
} }
BOOST_AUTO_TEST_CASE(test_nested_table) BOOST_AUTO_TEST_CASE(test_nested_table)
@@ -38,13 +38,13 @@ BOOST_AUTO_TEST_CASE(test_nested_table)
); );
location<std::string> loc("test", table); location<std::string> loc("test", table);
const auto result = toml::detail::parse_ml_table(loc); const auto result = toml::detail::parse_ml_table<toml::value>(loc);
BOOST_CHECK(result.is_ok()); BOOST_TEST(result.is_ok());
const auto data = result.unwrap(); const auto data = result.unwrap();
const auto a = toml::get<toml::table>(data.at("a")); const auto a = toml::get<toml::table>(data.at("a"));
const auto c = toml::get<toml::table>(a.at("c")); const auto c = toml::get<toml::table>(a.at("c"));
BOOST_CHECK_EQUAL(toml::get<std::string >(a.at("b")), "value"); BOOST_TEST(toml::get<std::string >(a.at("b")) == "value");
BOOST_CHECK_EQUAL(toml::get<std::int64_t>(c.at("d")), 42); BOOST_TEST(toml::get<std::int64_t>(c.at("d")) == 42);
} }

View File

@@ -14,11 +14,11 @@ BOOST_AUTO_TEST_CASE(test_hard_example_unicode)
{ {
const auto data = toml::parse("toml/tests/hard_example_unicode.toml"); const auto data = toml::parse("toml/tests/hard_example_unicode.toml");
const auto the = toml::get<toml::Table>(data.at("the")); const auto the = toml::find<toml::table>(data, "the");
BOOST_CHECK_EQUAL(toml::get<std::string>(the.at("test_string")), BOOST_TEST(toml::get<std::string>(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")); 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<toml::Table>(the.at("hard")); const auto hard = toml::get<toml::table>(the.at("hard"));
const std::vector<std::string> expected_the_hard_test_array{"] ", " # "}; const std::vector<std::string> expected_the_hard_test_array{"] ", " # "};
BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array")) == BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array")) ==
expected_the_hard_test_array); expected_the_hard_test_array);
@@ -28,13 +28,13 @@ BOOST_AUTO_TEST_CASE(test_hard_example_unicode)
}; };
BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array2")) == BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array2")) ==
expected_the_hard_test_array2); expected_the_hard_test_array2);
BOOST_CHECK_EQUAL(toml::get<std::string>(hard.at("another_test_string")), BOOST_TEST(toml::get<std::string>(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")); 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_CHECK_EQUAL(toml::get<std::string>(hard.at("harder_test_string")), BOOST_TEST(toml::get<std::string>(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")); 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<toml::Table>(hard.at(std::string("\xCE\xB2\xC3\xAF\xC6\xAD\x23"))); const auto bit = toml::get<toml::table>(hard.at(std::string("\xCE\xB2\xC3\xAF\xC6\xAD\x23")));
BOOST_CHECK_EQUAL(toml::get<std::string>(bit.at(std::string("\xCF\x89\xCE\xBB\xC3\xA1\xC6\xAD\x3F"))), BOOST_TEST(toml::get<std::string>(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")); 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<std::string> expected_multi_line_array{"]"}; const std::vector<std::string> expected_multi_line_array{"]"};
BOOST_CHECK(toml::get<std::vector<std::string>>(bit.at("multi_line_array")) == BOOST_CHECK(toml::get<std::vector<std::string>>(bit.at("multi_line_array")) ==
@@ -45,11 +45,11 @@ BOOST_AUTO_TEST_CASE(test_hard_example_unicode)
{ {
const auto data = toml::parse("toml/tests/hard_example_unicode.toml"); const auto data = toml::parse("toml/tests/hard_example_unicode.toml");
const auto the = toml::get<toml::Table>(data.at("the")); const auto the = toml::find<toml::table>(data, "the");
BOOST_CHECK_EQUAL(toml::get<std::string>(the.at("test_string")), BOOST_TEST(toml::get<std::string>(the.at("test_string")) ==
std::string(u8"Ýôú' λáƭè ₥è áƒƭèř ƭλïƨ - #")); std::string(u8"Ýôú' λáƭè ₥è áƒƭèř ƭλïƨ - #"));
const auto hard = toml::get<toml::Table>(the.at("hard")); const auto hard = toml::get<toml::table>(the.at("hard"));
const std::vector<std::string> expected_the_hard_test_array{"] ", " # "}; const std::vector<std::string> expected_the_hard_test_array{"] ", " # "};
BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array")) == BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array")) ==
expected_the_hard_test_array); expected_the_hard_test_array);
@@ -58,13 +58,13 @@ BOOST_AUTO_TEST_CASE(test_hard_example_unicode)
std::string(u8"Éжƥèřï₥èñƭ #9 ωáƨ á ƨúççèƨƨ")}; std::string(u8"Éжƥèřï₥èñƭ #9 ωáƨ á ƨúççèƨƨ")};
BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array2")) == BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array2")) ==
expected_the_hard_test_array2); expected_the_hard_test_array2);
BOOST_CHECK_EQUAL(toml::get<std::string>(hard.at("another_test_string")), BOOST_TEST(toml::get<std::string>(hard.at("another_test_string")) ==
std::string(u8"§á₥è ƭλïñϱ, βúƭ ωïƭλ á ƨƭřïñϱ #")); std::string(u8"§á₥è ƭλïñϱ, βúƭ ωïƭλ á ƨƭřïñϱ #"));
BOOST_CHECK_EQUAL(toml::get<std::string>(hard.at("harder_test_string")), BOOST_TEST(toml::get<std::string>(hard.at("harder_test_string")) ==
std::string(u8" Âñδ ωλèñ \"'ƨ ářè ïñ ƭλè ƨƭřïñϱ, áℓôñϱ ωïƭλ # \"")); std::string(u8" Âñδ ωλèñ \"'ƨ ářè ïñ ƭλè ƨƭřïñϱ, áℓôñϱ ωïƭλ # \""));
const auto bit = toml::get<toml::Table>(hard.at(std::string(u8"βïƭ#"))); const auto bit = toml::get<toml::table>(hard.at(std::string(u8"βïƭ#")));
BOOST_CHECK_EQUAL(toml::get<std::string>(bit.at(std::string(u8"ωλáƭ?"))), BOOST_TEST(toml::get<std::string>(bit.at(std::string(u8"ωλáƭ?"))) ==
std::string(u8"Ýôú δôñ'ƭ ƭλïñƙ ƨô₥è úƨèř ωôñ'ƭ δô ƭλáƭ?")); std::string(u8"Ýôú δôñ'ƭ ƭλïñƙ ƨô₥è úƨèř ωôñ'ƭ δô ƭλáƭ?"));
const std::vector<std::string> expected_multi_line_array{"]"}; const std::vector<std::string> expected_multi_line_array{"]"};
BOOST_CHECK(toml::get<std::vector<std::string>>(bit.at("multi_line_array")) == BOOST_CHECK(toml::get<std::vector<std::string>>(bit.at("multi_line_array")) ==

View File

@@ -8,49 +8,49 @@ BOOST_AUTO_TEST_CASE(test_construct)
{ {
auto s = toml::ok(42); auto s = toml::ok(42);
toml::result<int, std::string> result(s); toml::result<int, std::string> result(s);
BOOST_CHECK(!!result); BOOST_TEST(!!result);
BOOST_CHECK(result.is_ok()); BOOST_TEST(result.is_ok());
BOOST_CHECK(!result.is_err()); BOOST_TEST(!result.is_err());
BOOST_CHECK_EQUAL(result.unwrap(), 42); BOOST_TEST(result.unwrap() == 42);
} }
{ {
const auto s = toml::ok(42); const auto s = toml::ok(42);
toml::result<int, std::string> result(s); toml::result<int, std::string> result(s);
BOOST_CHECK(!!result); BOOST_TEST(!!result);
BOOST_CHECK(result.is_ok()); BOOST_TEST(result.is_ok());
BOOST_CHECK(!result.is_err()); BOOST_TEST(!result.is_err());
BOOST_CHECK_EQUAL(result.unwrap(), 42); BOOST_TEST(result.unwrap() == 42);
} }
{ {
toml::result<int, std::string> result(toml::ok(42)); toml::result<int, std::string> result(toml::ok(42));
BOOST_CHECK(!!result); BOOST_TEST(!!result);
BOOST_CHECK(result.is_ok()); BOOST_TEST(result.is_ok());
BOOST_CHECK(!result.is_err()); BOOST_TEST(!result.is_err());
BOOST_CHECK_EQUAL(result.unwrap(), 42); BOOST_TEST(result.unwrap() == 42);
} }
{ {
auto f = toml::err<std::string>("foobar"); auto f = toml::err<std::string>("foobar");
toml::result<int, std::string> result(f); toml::result<int, std::string> result(f);
BOOST_CHECK(!result); BOOST_TEST(!result);
BOOST_CHECK(!result.is_ok()); BOOST_TEST(!result.is_ok());
BOOST_CHECK(result.is_err()); BOOST_TEST(result.is_err());
BOOST_CHECK_EQUAL(result.unwrap_err(), "foobar"); BOOST_TEST(result.unwrap_err() == "foobar");
} }
{ {
const auto f = toml::err<std::string>("foobar"); const auto f = toml::err<std::string>("foobar");
toml::result<int, std::string> result(f); toml::result<int, std::string> result(f);
BOOST_CHECK(!result); BOOST_TEST(!result);
BOOST_CHECK(!result.is_ok()); BOOST_TEST(!result.is_ok());
BOOST_CHECK(result.is_err()); BOOST_TEST(result.is_err());
BOOST_CHECK_EQUAL(result.unwrap_err(), "foobar"); BOOST_TEST(result.unwrap_err() == "foobar");
} }
{ {
toml::result<int, std::string> result(toml::err<std::string>("foobar")); toml::result<int, std::string> result(toml::err<std::string>("foobar"));
BOOST_CHECK(!result); BOOST_TEST(!result);
BOOST_CHECK(!result.is_ok()); BOOST_TEST(!result.is_ok());
BOOST_CHECK(result.is_err()); BOOST_TEST(result.is_err());
BOOST_CHECK_EQUAL(result.unwrap_err(), "foobar"); BOOST_TEST(result.unwrap_err() == "foobar");
} }
} }
@@ -59,54 +59,54 @@ BOOST_AUTO_TEST_CASE(test_assignment)
{ {
toml::result<int, std::string> result(toml::err<std::string>("foobar")); toml::result<int, std::string> result(toml::err<std::string>("foobar"));
result = toml::ok(42); result = toml::ok(42);
BOOST_CHECK(!!result); BOOST_TEST(!!result);
BOOST_CHECK(result.is_ok()); BOOST_TEST(result.is_ok());
BOOST_CHECK(!result.is_err()); BOOST_TEST(!result.is_err());
BOOST_CHECK_EQUAL(result.unwrap(), 42); BOOST_TEST(result.unwrap() == 42);
} }
{ {
toml::result<int, std::string> result(toml::err<std::string>("foobar")); toml::result<int, std::string> result(toml::err<std::string>("foobar"));
auto s = toml::ok(42); auto s = toml::ok(42);
result = s; result = s;
BOOST_CHECK(!!result); BOOST_TEST(!!result);
BOOST_CHECK(result.is_ok()); BOOST_TEST(result.is_ok());
BOOST_CHECK(!result.is_err()); BOOST_TEST(!result.is_err());
BOOST_CHECK_EQUAL(result.unwrap(), 42); BOOST_TEST(result.unwrap() == 42);
} }
{ {
toml::result<int, std::string> result(toml::err<std::string>("foobar")); toml::result<int, std::string> result(toml::err<std::string>("foobar"));
const auto s = toml::ok(42); const auto s = toml::ok(42);
result = s; result = s;
BOOST_CHECK(!!result); BOOST_TEST(!!result);
BOOST_CHECK(result.is_ok()); BOOST_TEST(result.is_ok());
BOOST_CHECK(!result.is_err()); BOOST_TEST(!result.is_err());
BOOST_CHECK_EQUAL(result.unwrap(), 42); BOOST_TEST(result.unwrap() == 42);
} }
{ {
toml::result<int, std::string> result(toml::err<std::string>("foobar")); toml::result<int, std::string> result(toml::err<std::string>("foobar"));
result = toml::err<std::string>("hoge"); result = toml::err<std::string>("hoge");
BOOST_CHECK(!result); BOOST_TEST(!result);
BOOST_CHECK(!result.is_ok()); BOOST_TEST(!result.is_ok());
BOOST_CHECK(result.is_err()); BOOST_TEST(result.is_err());
BOOST_CHECK_EQUAL(result.unwrap_err(), "hoge"); BOOST_TEST(result.unwrap_err() == "hoge");
} }
{ {
toml::result<int, std::string> result(toml::err<std::string>("foobar")); toml::result<int, std::string> result(toml::err<std::string>("foobar"));
auto f = toml::err<std::string>("hoge"); auto f = toml::err<std::string>("hoge");
result = f; result = f;
BOOST_CHECK(!result); BOOST_TEST(!result);
BOOST_CHECK(!result.is_ok()); BOOST_TEST(!result.is_ok());
BOOST_CHECK(result.is_err()); BOOST_TEST(result.is_err());
BOOST_CHECK_EQUAL(result.unwrap_err(), "hoge"); BOOST_TEST(result.unwrap_err() == "hoge");
} }
{ {
toml::result<int, std::string> result(toml::err<std::string>("foobar")); toml::result<int, std::string> result(toml::err<std::string>("foobar"));
const auto f = toml::err<std::string>("hoge"); const auto f = toml::err<std::string>("hoge");
result = f; result = f;
BOOST_CHECK(!result); BOOST_TEST(!result);
BOOST_CHECK(!result.is_ok()); BOOST_TEST(!result.is_ok());
BOOST_CHECK(result.is_err()); BOOST_TEST(result.is_err());
BOOST_CHECK_EQUAL(result.unwrap_err(), "hoge"); BOOST_TEST(result.unwrap_err() == "hoge");
} }
} }
@@ -119,10 +119,10 @@ BOOST_AUTO_TEST_CASE(test_map)
return i * 2; return i * 2;
}); });
BOOST_CHECK(!!mapped); BOOST_TEST(!!mapped);
BOOST_CHECK(mapped.is_ok()); BOOST_TEST(mapped.is_ok());
BOOST_CHECK(!mapped.is_err()); BOOST_TEST(!mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap(), 42 * 2); BOOST_TEST(mapped.unwrap() == 42 * 2);
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -132,10 +132,10 @@ BOOST_AUTO_TEST_CASE(test_map)
return *i; return *i;
}); });
BOOST_CHECK(!!mapped); BOOST_TEST(!!mapped);
BOOST_CHECK(mapped.is_ok()); BOOST_TEST(mapped.is_ok());
BOOST_CHECK(!mapped.is_err()); BOOST_TEST(!mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap(), 42); BOOST_TEST(mapped.unwrap() == 42);
} }
{ {
const toml::result<int, std::string> result(toml::err<std::string>("hoge")); const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
@@ -144,10 +144,10 @@ BOOST_AUTO_TEST_CASE(test_map)
return i * 2; return i * 2;
}); });
BOOST_CHECK(!mapped); BOOST_TEST(!mapped);
BOOST_CHECK(!mapped.is_ok()); BOOST_TEST(!mapped.is_ok());
BOOST_CHECK(mapped.is_err()); BOOST_TEST(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge"); BOOST_TEST(mapped.unwrap_err() == "hoge");
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -157,10 +157,10 @@ BOOST_AUTO_TEST_CASE(test_map)
return *i; return *i;
}); });
BOOST_CHECK(!mapped); BOOST_TEST(!mapped);
BOOST_CHECK(!mapped.is_ok()); BOOST_TEST(!mapped.is_ok());
BOOST_CHECK(mapped.is_err()); BOOST_TEST(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge"); BOOST_TEST(mapped.unwrap_err() == "hoge");
} }
} }
@@ -173,10 +173,10 @@ BOOST_AUTO_TEST_CASE(test_map_err)
return s + s; return s + s;
}); });
BOOST_CHECK(!!mapped); BOOST_TEST(!!mapped);
BOOST_CHECK(mapped.is_ok()); BOOST_TEST(mapped.is_ok());
BOOST_CHECK(!mapped.is_err()); BOOST_TEST(!mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap(), 42); BOOST_TEST(mapped.unwrap() == 42);
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -186,10 +186,10 @@ BOOST_AUTO_TEST_CASE(test_map_err)
return s + s; return s + s;
}); });
BOOST_CHECK(!!mapped); BOOST_TEST(!!mapped);
BOOST_CHECK(mapped.is_ok()); BOOST_TEST(mapped.is_ok());
BOOST_CHECK(!mapped.is_err()); BOOST_TEST(!mapped.is_err());
BOOST_CHECK_EQUAL(*(mapped.unwrap()), 42); BOOST_TEST(*(mapped.unwrap()) == 42);
} }
{ {
const toml::result<int, std::string> result(toml::err<std::string>("hoge")); const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
@@ -197,10 +197,10 @@ BOOST_AUTO_TEST_CASE(test_map_err)
[](const std::string s) -> std::string { [](const std::string s) -> std::string {
return s + s; return s + s;
}); });
BOOST_CHECK(!mapped); BOOST_TEST(!mapped);
BOOST_CHECK(!mapped.is_ok()); BOOST_TEST(!mapped.is_ok());
BOOST_CHECK(mapped.is_err()); BOOST_TEST(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hogehoge"); BOOST_TEST(mapped.unwrap_err() == "hogehoge");
} }
{ {
toml::result<int, std::unique_ptr<std::string>> toml::result<int, std::unique_ptr<std::string>>
@@ -210,10 +210,10 @@ BOOST_AUTO_TEST_CASE(test_map_err)
return *p; return *p;
}); });
BOOST_CHECK(!mapped); BOOST_TEST(!mapped);
BOOST_CHECK(!mapped.is_ok()); BOOST_TEST(!mapped.is_ok());
BOOST_CHECK(mapped.is_err()); BOOST_TEST(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge"); BOOST_TEST(mapped.unwrap_err() == "hoge");
} }
} }
@@ -226,7 +226,7 @@ BOOST_AUTO_TEST_CASE(test_map_or_else)
return i * 2; return i * 2;
}, 54); }, 54);
BOOST_CHECK_EQUAL(mapped, 42 * 2); BOOST_TEST(mapped == 42 * 2);
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -236,7 +236,7 @@ BOOST_AUTO_TEST_CASE(test_map_or_else)
return *i; return *i;
}, 54); }, 54);
BOOST_CHECK_EQUAL(mapped, 42); BOOST_TEST(mapped == 42);
} }
{ {
const toml::result<int, std::string> result(toml::err<std::string>("hoge")); const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
@@ -245,7 +245,7 @@ BOOST_AUTO_TEST_CASE(test_map_or_else)
return i * 2; return i * 2;
}, 54); }, 54);
BOOST_CHECK_EQUAL(mapped, 54); BOOST_TEST(mapped == 54);
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -255,7 +255,7 @@ BOOST_AUTO_TEST_CASE(test_map_or_else)
return *i; return *i;
}, 54); }, 54);
BOOST_CHECK_EQUAL(mapped, 54); BOOST_TEST(mapped == 54);
} }
} }
@@ -268,7 +268,7 @@ BOOST_AUTO_TEST_CASE(test_map_err_or_else)
return i + i; return i + i;
}, "foobar"); }, "foobar");
BOOST_CHECK_EQUAL(mapped, "foobar"); BOOST_TEST(mapped == "foobar");
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -278,7 +278,7 @@ BOOST_AUTO_TEST_CASE(test_map_err_or_else)
return i + i; return i + i;
}, "foobar"); }, "foobar");
BOOST_CHECK_EQUAL(mapped, "foobar"); BOOST_TEST(mapped == "foobar");
} }
{ {
const toml::result<int, std::string> result(toml::err<std::string>("hoge")); const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
@@ -287,7 +287,7 @@ BOOST_AUTO_TEST_CASE(test_map_err_or_else)
return i + i; return i + i;
}, "foobar"); }, "foobar");
BOOST_CHECK_EQUAL(mapped, "hogehoge"); BOOST_TEST(mapped == "hogehoge");
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -297,7 +297,7 @@ BOOST_AUTO_TEST_CASE(test_map_err_or_else)
return i + i; return i + i;
}, "foobar"); }, "foobar");
BOOST_CHECK_EQUAL(mapped, "hogehoge"); BOOST_TEST(mapped == "hogehoge");
} }
} }
@@ -311,10 +311,10 @@ BOOST_AUTO_TEST_CASE(test_and_then)
return toml::ok(i * 2); return toml::ok(i * 2);
}); });
BOOST_CHECK(!!mapped); BOOST_TEST(!!mapped);
BOOST_CHECK(mapped.is_ok()); BOOST_TEST(mapped.is_ok());
BOOST_CHECK(!mapped.is_err()); BOOST_TEST(!mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap(), 42 * 2); BOOST_TEST(mapped.unwrap() == 42 * 2);
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -324,10 +324,10 @@ BOOST_AUTO_TEST_CASE(test_and_then)
return toml::ok(*i); return toml::ok(*i);
}); });
BOOST_CHECK(!!mapped); BOOST_TEST(!!mapped);
BOOST_CHECK(mapped.is_ok()); BOOST_TEST(mapped.is_ok());
BOOST_CHECK(!mapped.is_err()); BOOST_TEST(!mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap(), 42); BOOST_TEST(mapped.unwrap() == 42);
} }
{ {
const toml::result<int, std::string> result(toml::err<std::string>("hoge")); const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
@@ -336,10 +336,10 @@ BOOST_AUTO_TEST_CASE(test_and_then)
return toml::ok(i * 2); return toml::ok(i * 2);
}); });
BOOST_CHECK(!mapped); BOOST_TEST(!mapped);
BOOST_CHECK(!mapped.is_ok()); BOOST_TEST(!mapped.is_ok());
BOOST_CHECK(mapped.is_err()); BOOST_TEST(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge"); BOOST_TEST(mapped.unwrap_err() == "hoge");
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -349,10 +349,10 @@ BOOST_AUTO_TEST_CASE(test_and_then)
return toml::ok(*i); return toml::ok(*i);
}); });
BOOST_CHECK(!mapped); BOOST_TEST(!mapped);
BOOST_CHECK(!mapped.is_ok()); BOOST_TEST(!mapped.is_ok());
BOOST_CHECK(mapped.is_err()); BOOST_TEST(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hoge"); BOOST_TEST(mapped.unwrap_err() == "hoge");
} }
} }
@@ -365,10 +365,10 @@ BOOST_AUTO_TEST_CASE(test_or_else)
return toml::err(s + s); return toml::err(s + s);
}); });
BOOST_CHECK(!!mapped); BOOST_TEST(!!mapped);
BOOST_CHECK(mapped.is_ok()); BOOST_TEST(mapped.is_ok());
BOOST_CHECK(!mapped.is_err()); BOOST_TEST(!mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap(), 42); BOOST_TEST(mapped.unwrap() == 42);
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -378,10 +378,10 @@ BOOST_AUTO_TEST_CASE(test_or_else)
return toml::err(s + s); return toml::err(s + s);
}); });
BOOST_CHECK(!!mapped); BOOST_TEST(!!mapped);
BOOST_CHECK(mapped.is_ok()); BOOST_TEST(mapped.is_ok());
BOOST_CHECK(!mapped.is_err()); BOOST_TEST(!mapped.is_err());
BOOST_CHECK_EQUAL(*mapped.unwrap(), 42); BOOST_TEST(*mapped.unwrap() == 42);
} }
{ {
const toml::result<int, std::string> result(toml::err<std::string>("hoge")); const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
@@ -390,10 +390,10 @@ BOOST_AUTO_TEST_CASE(test_or_else)
return toml::err(s + s); return toml::err(s + s);
}); });
BOOST_CHECK(!mapped); BOOST_TEST(!mapped);
BOOST_CHECK(!mapped.is_ok()); BOOST_TEST(!mapped.is_ok());
BOOST_CHECK(mapped.is_err()); BOOST_TEST(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hogehoge"); BOOST_TEST(mapped.unwrap_err() == "hogehoge");
} }
{ {
toml::result<std::unique_ptr<int>, std::string> toml::result<std::unique_ptr<int>, std::string>
@@ -403,10 +403,10 @@ BOOST_AUTO_TEST_CASE(test_or_else)
return toml::err(s + s); return toml::err(s + s);
}); });
BOOST_CHECK(!mapped); BOOST_TEST(!mapped);
BOOST_CHECK(!mapped.is_ok()); BOOST_TEST(!mapped.is_ok());
BOOST_CHECK(mapped.is_err()); BOOST_TEST(mapped.is_err());
BOOST_CHECK_EQUAL(mapped.unwrap_err(), "hogehoge"); BOOST_TEST(mapped.unwrap_err() == "hogehoge");
} }
} }
@@ -416,10 +416,10 @@ BOOST_AUTO_TEST_CASE(test_and_or_other)
const toml::result<int, std::string> r1(toml::ok(42)); const toml::result<int, std::string> r1(toml::ok(42));
const toml::result<int, std::string> r2(toml::err<std::string>("foo")); const toml::result<int, std::string> r2(toml::err<std::string>("foo"));
BOOST_CHECK_EQUAL(r1, r1.or_other(r2)); BOOST_TEST(r1 == r1.or_other(r2));
BOOST_CHECK_EQUAL(r2, r1.and_other(r2)); BOOST_TEST(r2 == r1.and_other(r2));
BOOST_CHECK_EQUAL(42, r1.or_other(r2).unwrap()); BOOST_TEST(42 == r1.or_other(r2).unwrap());
BOOST_CHECK_EQUAL("foo", r1.and_other(r2).unwrap_err()); BOOST_TEST("foo" == r1.and_other(r2).unwrap_err());
} }
{ {
auto r1_gen = []() -> toml::result<int, std::string> { auto r1_gen = []() -> toml::result<int, std::string> {
@@ -431,10 +431,10 @@ BOOST_AUTO_TEST_CASE(test_and_or_other)
const auto r3 = r1_gen(); const auto r3 = r1_gen();
const auto r4 = r2_gen(); const auto r4 = r2_gen();
BOOST_CHECK_EQUAL(r3, r1_gen().or_other (r2_gen())); BOOST_TEST(r3 == r1_gen().or_other (r2_gen()));
BOOST_CHECK_EQUAL(r4, r1_gen().and_other(r2_gen())); BOOST_TEST(r4 == r1_gen().and_other(r2_gen()));
BOOST_CHECK_EQUAL(42, r1_gen().or_other (r2_gen()).unwrap()); BOOST_TEST(42 == r1_gen().or_other (r2_gen()).unwrap());
BOOST_CHECK_EQUAL("foo", r1_gen().and_other(r2_gen()).unwrap_err()); BOOST_TEST("foo" == r1_gen().and_other(r2_gen()).unwrap_err());
} }
} }

View File

@@ -6,9 +6,43 @@
#include <boost/test/included/unit_test.hpp> #include <boost/test/included/unit_test.hpp>
#endif #endif
#include <toml.hpp> #include <toml.hpp>
#include <deque>
#include <map>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
template<typename Comment,
template<typename ...> class Table,
template<typename ...> class Array>
bool has_comment_inside(const toml::basic_value<Comment, Table, Array>& 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) BOOST_AUTO_TEST_CASE(test_example)
{ {
@@ -20,15 +54,146 @@ BOOST_AUTO_TEST_CASE(test_example)
auto serialized = toml::parse("tmp1.toml"); auto serialized = toml::parse("tmp1.toml");
{ {
auto& owner = toml::get<toml::table>(serialized.at("owner")); auto& owner = toml::find(serialized, "owner");
auto& bio = toml::get<std::string>(owner.at("bio")); auto& bio = toml::find<std::string>(owner, "bio");
const auto CR = std::find(bio.begin(), bio.end(), '\r'); const auto CR = std::find(bio.begin(), bio.end(), '\r');
if(CR != bio.end()) if(CR != bio.end())
{ {
bio.erase(CR); bio.erase(CR);
} }
} }
BOOST_CHECK(data == serialized); BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_example_map_dq)
{
const auto data = toml::parse<toml::discard_comments, std::map, std::deque>(
"toml/tests/example.toml");
{
std::ofstream ofs("tmp1_map_dq.toml");
ofs << std::setw(80) << data;
}
auto serialized = toml::parse<toml::discard_comments, std::map, std::deque>(
"tmp1_map_dq.toml");
{
auto& owner = toml::find(serialized, "owner");
auto& bio = toml::find<std::string>(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::preserve_comments>("toml/tests/example.toml");
{
std::ofstream ofs("tmp1_com.toml");
ofs << std::setw(80) << data;
}
auto serialized = toml::parse<toml::preserve_comments>("tmp1_com.toml");
{
auto& owner = toml::find(serialized, "owner");
auto& bio = toml::find<std::string>(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::preserve_comments>("toml/tests/example.toml");
{
std::ofstream ofs("tmp1_com_nocomment.toml");
ofs << std::setw(80) << toml::nocomment << data;
}
const auto serialized = toml::parse<toml::preserve_comments>("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<std::string>(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::preserve_comments, std::map, std::deque>(
"toml/tests/example.toml");
{
std::ofstream ofs("tmp1_com_map_dq.toml");
ofs << std::setw(80) << data;
}
auto serialized = toml::parse<toml::preserve_comments, std::map, std::deque>(
"tmp1_com_map_dq.toml");
{
auto& owner = toml::find(serialized, "owner");
auto& bio = toml::find<std::string>(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::preserve_comments, std::map, std::deque>("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<toml::preserve_comments, std::map, std::deque>("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<std::string>(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) BOOST_AUTO_TEST_CASE(test_fruit)
@@ -39,7 +204,43 @@ BOOST_AUTO_TEST_CASE(test_fruit)
ofs << std::setw(80) << data; ofs << std::setw(80) << data;
} }
const auto serialized = toml::parse("tmp2.toml"); const auto serialized = toml::parse("tmp2.toml");
BOOST_CHECK(data == serialized); BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_fruit_map_dq)
{
const auto data = toml::parse<toml::discard_comments, std::map, std::deque>(
"toml/tests/fruit.toml");
{
std::ofstream ofs("tmp2.toml");
ofs << std::setw(80) << data;
}
const auto serialized = toml::parse<toml::discard_comments, std::map, std::deque>(
"tmp2.toml");
BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_fruit_with_comments)
{
const auto data = toml::parse<toml::preserve_comments>("toml/tests/fruit.toml");
{
std::ofstream ofs("tmp2_com.toml");
ofs << std::setw(80) << data;
}
const auto serialized = toml::parse<toml::preserve_comments>("tmp2_com.toml");
BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_fruit_with_comments_map_dq)
{
const auto data = toml::parse<toml::preserve_comments, std::map, std::deque>(
"toml/tests/fruit.toml");
{
std::ofstream ofs("tmp2_com.toml");
ofs << std::setw(80) << data;
}
const auto serialized = toml::parse<toml::preserve_comments, std::map, std::deque>("tmp2_com.toml");
BOOST_TEST(data == serialized);
} }
BOOST_AUTO_TEST_CASE(test_hard_example) BOOST_AUTO_TEST_CASE(test_hard_example)
@@ -50,5 +251,55 @@ BOOST_AUTO_TEST_CASE(test_hard_example)
ofs << std::setw(80) << data; ofs << std::setw(80) << data;
} }
const auto serialized = toml::parse("tmp3.toml"); const auto serialized = toml::parse("tmp3.toml");
BOOST_CHECK(data == serialized); BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_hard_example_map_dq)
{
const auto data = toml::parse<toml::discard_comments, std::map, std::deque>(
"toml/tests/hard_example.toml");
{
std::ofstream ofs("tmp3.toml");
ofs << std::setw(80) << data;
}
const auto serialized = toml::parse<toml::discard_comments, std::map, std::deque>(
"tmp3.toml");
BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_hard_example_with_comment)
{
const auto data = toml::parse<toml::preserve_comments, std::map, std::deque>(
"toml/tests/hard_example.toml");
{
std::ofstream ofs("tmp3_com.toml");
ofs << std::setw(80) << data;
}
const auto serialized = toml::parse<toml::preserve_comments, std::map, std::deque>(
"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));
}
} }

113
tests/test_string.cpp Normal file
View File

@@ -0,0 +1,113 @@
#define BOOST_TEST_MODULE "test_string"
#include <boost/test/unit_test.hpp>
#include <toml.hpp>
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());
}
}

View File

@@ -37,48 +37,48 @@ typedef std::unordered_map<std::string, dummy_type> std_unordered_map_type;
BOOST_AUTO_TEST_CASE(test_has_xxx) BOOST_AUTO_TEST_CASE(test_has_xxx)
{ {
BOOST_CHECK(toml::detail::has_iterator<std::list<dummy_type>>::value); BOOST_TEST(toml::detail::has_iterator<std::list<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_iterator<std::forward_list<dummy_type>>::value); BOOST_TEST(toml::detail::has_iterator<std::forward_list<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_iterator<std::deque<dummy_type>>::value); BOOST_TEST(toml::detail::has_iterator<std::deque<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_iterator<std::vector<dummy_type>>::value); BOOST_TEST(toml::detail::has_iterator<std::vector<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_iterator<std::set<dummy_type>>::value); BOOST_TEST(toml::detail::has_iterator<std::set<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_iterator<std::unordered_set<std::string>>::value); BOOST_TEST(toml::detail::has_iterator<std::unordered_set<std::string>>::value);
BOOST_CHECK(toml::detail::has_iterator<std_array_type>::value); BOOST_TEST(toml::detail::has_iterator<std_array_type>::value);
BOOST_CHECK(toml::detail::has_iterator<std_map_type>::value); BOOST_TEST(toml::detail::has_iterator<std_map_type>::value);
BOOST_CHECK(toml::detail::has_iterator<std_unordered_map_type>::value); BOOST_TEST(toml::detail::has_iterator<std_unordered_map_type>::value);
BOOST_CHECK(toml::detail::has_iterator<dummy_container<dummy_type>>::value); BOOST_TEST(toml::detail::has_iterator<dummy_container<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_value_type<std::list<dummy_type>>::value); BOOST_TEST(toml::detail::has_value_type<std::list<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_value_type<std::forward_list<dummy_type>>::value); BOOST_TEST(toml::detail::has_value_type<std::forward_list<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_value_type<std::deque<dummy_type>>::value); BOOST_TEST(toml::detail::has_value_type<std::deque<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_value_type<std::vector<dummy_type>>::value); BOOST_TEST(toml::detail::has_value_type<std::vector<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_value_type<std_array_type>::value); BOOST_TEST(toml::detail::has_value_type<std_array_type>::value);
BOOST_CHECK(toml::detail::has_value_type<std::set<dummy_type>>::value); BOOST_TEST(toml::detail::has_value_type<std::set<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_value_type<std::unordered_set<std::string>>::value); BOOST_TEST(toml::detail::has_value_type<std::unordered_set<std::string>>::value);
BOOST_CHECK(toml::detail::has_value_type<std_map_type>::value); BOOST_TEST(toml::detail::has_value_type<std_map_type>::value);
BOOST_CHECK(toml::detail::has_value_type<std_unordered_map_type>::value); BOOST_TEST(toml::detail::has_value_type<std_unordered_map_type>::value);
BOOST_CHECK(toml::detail::has_value_type<dummy_container<dummy_type>>::value); BOOST_TEST(toml::detail::has_value_type<dummy_container<dummy_type>>::value);
BOOST_CHECK(toml::detail::has_key_type<std_map_type>::value); BOOST_TEST(toml::detail::has_key_type<std_map_type>::value);
BOOST_CHECK(toml::detail::has_key_type<std_unordered_map_type>::value); BOOST_TEST(toml::detail::has_key_type<std_unordered_map_type>::value);
BOOST_CHECK(toml::detail::has_mapped_type<std_map_type>::value); BOOST_TEST(toml::detail::has_mapped_type<std_map_type>::value);
BOOST_CHECK(toml::detail::has_mapped_type<std_unordered_map_type>::value); BOOST_TEST(toml::detail::has_mapped_type<std_unordered_map_type>::value);
} }
BOOST_AUTO_TEST_CASE(test_is_xxx) BOOST_AUTO_TEST_CASE(test_is_xxx)
{ {
BOOST_CHECK(toml::detail::is_container<std::list<dummy_type>>::value); BOOST_TEST(toml::detail::is_container<std::list<dummy_type>>::value);
BOOST_CHECK(toml::detail::is_container<std::forward_list<dummy_type>>::value); BOOST_TEST(toml::detail::is_container<std::forward_list<dummy_type>>::value);
BOOST_CHECK(toml::detail::is_container<std::deque<dummy_type>>::value); BOOST_TEST(toml::detail::is_container<std::deque<dummy_type>>::value);
BOOST_CHECK(toml::detail::is_container<std::vector<dummy_type>>::value); BOOST_TEST(toml::detail::is_container<std::vector<dummy_type>>::value);
BOOST_CHECK(toml::detail::is_container<std_array_type>::value); BOOST_TEST(toml::detail::is_container<std_array_type>::value);
BOOST_CHECK(toml::detail::is_container<std::set<dummy_type>>::value); BOOST_TEST(toml::detail::is_container<std::set<dummy_type>>::value);
BOOST_CHECK(toml::detail::is_container<std::unordered_set<std::string>>::value); BOOST_TEST(toml::detail::is_container<std::unordered_set<std::string>>::value);
BOOST_CHECK(toml::detail::is_container<dummy_container<dummy_type>>::value); BOOST_TEST(toml::detail::is_container<dummy_container<dummy_type>>::value);
BOOST_CHECK(!toml::detail::is_container<std_map_type>::value); BOOST_TEST(!toml::detail::is_container<std_map_type>::value);
BOOST_CHECK(!toml::detail::is_container<std_unordered_map_type>::value); BOOST_TEST(!toml::detail::is_container<std_unordered_map_type>::value);
BOOST_CHECK(toml::detail::is_map<std_map_type>::value); BOOST_TEST(toml::detail::is_map<std_map_type>::value);
BOOST_CHECK(toml::detail::is_map<std_unordered_map_type>::value); BOOST_TEST(toml::detail::is_map<std_unordered_map_type>::value);
} }

View File

@@ -14,69 +14,39 @@ BOOST_AUTO_TEST_CASE(test_resize)
{ {
typedef std::vector<int> resizable_type; typedef std::vector<int> resizable_type;
typedef std::array<int,1> non_resizable_type; typedef std::array<int,1> non_resizable_type;
BOOST_CHECK(toml::detail::has_resize_method<resizable_type>::value); BOOST_TEST(toml::detail::has_resize_method<resizable_type>::value);
BOOST_CHECK(!toml::detail::has_resize_method<non_resizable_type>::value); BOOST_TEST(!toml::detail::has_resize_method<non_resizable_type>::value);
} }
{ {
bool thrown = false;
std::vector<int> v; std::vector<int> v;
try toml::resize(v, 10);
{ BOOST_TEST(v.size() == 10u);
toml::resize(v, 10);
}
catch(std::exception& ex)
{
thrown = true;
}
BOOST_CHECK(!thrown);
BOOST_CHECK_EQUAL(v.size(), 10u);
} }
{ {
bool thrown = false;
std::array<int, 15> a; std::array<int, 15> a;
try toml::resize(a, 10);
{ BOOST_TEST(a.size() == 15u);
toml::resize(a, 10);
}
catch(std::exception& ex)
{
thrown = true;
}
BOOST_CHECK(!thrown);
BOOST_CHECK_EQUAL(a.size(), 15u);
} }
{ {
bool thrown = false;
std::array<int, 15> a; std::array<int, 15> a;
try BOOST_CHECK_THROW(toml::resize(a, 20), std::invalid_argument);
{
toml::resize(a, 20);
}
catch(std::exception& ex)
{
thrown = true;
}
BOOST_CHECK(thrown);
} }
} }
BOOST_AUTO_TEST_CASE(test_concat_to_string) BOOST_AUTO_TEST_CASE(test_concat_to_string)
{ {
const std::string cat = toml::concat_to_string("foo", "bar", 42); const std::string cat = toml::concat_to_string("foo", "bar", 42);
BOOST_CHECK(cat == "foobar42"); BOOST_TEST(cat == "foobar42");
} }
BOOST_AUTO_TEST_CASE(test_from_string) BOOST_AUTO_TEST_CASE(test_from_string)
{ {
{ {
const std::string str("123"); const std::string str("123");
BOOST_CHECK_EQUAL(toml::from_string<int>(str, 0), 123); BOOST_TEST(toml::from_string<int>(str, 0) == 123);
} }
{ {
const std::string str("01"); const std::string str("01");
BOOST_CHECK_EQUAL(toml::from_string<int>(str, 0), 1); BOOST_TEST(toml::from_string<int>(str, 0) == 1);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -36,7 +36,6 @@
#include "toml/parser.hpp" #include "toml/parser.hpp"
#include "toml/literal.hpp" #include "toml/literal.hpp"
#include "toml/serializer.hpp" #include "toml/serializer.hpp"
#include "toml/from_toml.hpp"
#include "toml/get.hpp" #include "toml/get.hpp"
#endif// TOML_FOR_MODERN_CPP #endif// TOML_FOR_MODERN_CPP

403
toml/comments.hpp Normal file
View File

@@ -0,0 +1,403 @@
// Copyright Toru Niina 2019.
// Distributed under the MIT License.
#ifndef TOML11_COMMENTS_HPP
#define TOML11_COMMENTS_HPP
#include <type_traits>
#include <utility>
#include <iterator>
#include <initializer_list>
#include <vector>
#include <string>
// This file provides mainly two classes, `preserve_comments` and `discard_comments`.
// Those two are a container that have the same interface as `std::vector<std::string>`
// but bahaves in the opposite way. `preserve_comments` is just the same as
// `std::vector<std::string>` 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<toml::preserve_comments> data =
// toml::parse<toml::preserve_comments>("example.toml");
//
// the interface is almost the same as std::vector<std::string>.
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<std::string>;
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<std::string>& c): comments(c){}
explicit preserve_comments(std::vector<std::string>&& c)
: comments(std::move(c))
{}
preserve_comments& operator=(const std::vector<std::string>& c)
{
comments = c;
return *this;
}
preserve_comments& operator=(std::vector<std::string>&& 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<std::string> x): comments(x) {}
template<typename InputIterator>
preserve_comments(InputIterator first, InputIterator last)
: comments(first, last)
{}
template<typename InputIterator>
void assign(InputIterator first, InputIterator last) {comments.assign(first, last);}
void assign(std::initializer_list<std::string> ini) {comments.assign(ini);}
void assign(size_type n, const std::string& val) {comments.assign(n, val);}
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<typename InputIterator>
iterator insert(const_iterator p, InputIterator first, InputIterator last)
{
return comments.insert(p, first, last);
}
iterator insert(const_iterator p, std::initializer_list<std::string> ini)
{
return comments.insert(p, ini);
}
template<typename ... Ts>
iterator emplace(const_iterator p, Ts&& ... args)
{
return comments.emplace(p, std::forward<Ts>(args)...);
}
iterator erase(const_iterator pos) {return comments.erase(pos);}
iterator erase(const_iterator first, const_iterator last)
{
return comments.erase(first, last);
}
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<typename ... Ts>
void emplace_back(Ts&& ... args) {comments.emplace_back(std::forward<Ts>(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& lhs, const preserve_comments& rhs);
friend bool operator!=(const preserve_comments& lhs, const preserve_comments& rhs);
friend bool operator< (const preserve_comments& lhs, const preserve_comments& rhs);
friend bool operator<=(const preserve_comments& lhs, const preserve_comments& rhs);
friend bool operator> (const preserve_comments& lhs, const preserve_comments& rhs);
friend bool operator>=(const preserve_comments& lhs, const preserve_comments& rhs);
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;
}
template<typename charT, typename traits>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& 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<typename T, bool is_const>
struct empty_iterator
{
using value_type = T;
using reference_type = typename std::conditional<is_const, T const&, T&>::type;
using pointer_type = typename std::conditional<is_const, T const*, T*>::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<typename T, bool C>
bool operator==(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return true;}
template<typename T, bool C>
bool operator!=(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return false;}
template<typename T, bool C>
bool operator< (const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return false;}
template<typename T, bool C>
bool operator<=(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return true;}
template<typename T, bool C>
bool operator> (const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return false;}
template<typename T, bool C>
bool operator>=(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return true;}
template<typename T, bool C>
typename empty_iterator<T, C>::difference_type
operator-(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return 0;}
template<typename T, bool C>
empty_iterator<T, C>
operator+(typename empty_iterator<T, C>::difference_type, const empty_iterator<T, C>& rhs) noexcept {return rhs;}
template<typename T, bool C>
empty_iterator<T, C>
operator+(const empty_iterator<T, C>& lhs, typename empty_iterator<T, C>::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 choosed 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<std::string, false>;
using const_iterator = detail::empty_iterator<std::string, true>;
using reverse_iterator = detail::empty_iterator<std::string, false>;
using const_reverse_iterator = detail::empty_iterator<std::string, true>;
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<std::string>&) noexcept {}
explicit discard_comments(std::vector<std::string>&&) noexcept {}
discard_comments& operator=(const std::vector<std::string>&) noexcept {return *this;}
discard_comments& operator=(std::vector<std::string>&&) 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<std::string>) noexcept {}
template<typename InputIterator>
discard_comments(InputIterator, InputIterator) noexcept {}
template<typename InputIterator>
void assign(InputIterator, InputIterator) noexcept {}
void assign(std::initializer_list<std::string>) 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<typename InputIterator>
iterator insert(const_iterator, InputIterator, InputIterator) {return iterator{};}
iterator insert(const_iterator, std::initializer_list<std::string>) {return iterator{};}
template<typename ... Ts>
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<typename ... Ts>
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<typename charT, typename traits>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const discard_comments&)
{
return os;
}
} // toml11
#endif// TOML11_COMMENTS_HPP

View File

@@ -46,7 +46,7 @@ inline std::tm localtime_s(const std::time_t* src)
#endif #endif
} // detail } // detail
enum class month_t : std::int8_t enum class month_t : std::uint8_t
{ {
Jan = 0, Jan = 0,
Feb = 1, Feb = 1,
@@ -98,9 +98,9 @@ struct local_date
t.tm_sec = 0; t.tm_sec = 0;
t.tm_min = 0; t.tm_min = 0;
t.tm_hour = 0; t.tm_hour = 0;
t.tm_mday = this->day; t.tm_mday = static_cast<int>(this->day);
t.tm_mon = this->month; t.tm_mon = static_cast<int>(this->month);
t.tm_year = this->year - 1900; t.tm_year = static_cast<int>(this->year) - 1900;
t.tm_wday = 0; // the value will be ignored t.tm_wday = 0; // the value will be ignored
t.tm_yday = 0; // the value will be ignored t.tm_yday = 0; // the value will be ignored
t.tm_isdst = -1; t.tm_isdst = -1;
@@ -188,22 +188,22 @@ struct local_time
explicit local_time(const std::chrono::duration<Rep, Period>& t) explicit local_time(const std::chrono::duration<Rep, Period>& t)
{ {
const auto h = std::chrono::duration_cast<std::chrono::hours>(t); const auto h = std::chrono::duration_cast<std::chrono::hours>(t);
this->hour = h.count(); this->hour = static_cast<std::uint8_t>(h.count());
const auto t2 = t - h; const auto t2 = t - h;
const auto m = std::chrono::duration_cast<std::chrono::minutes>(t2); const auto m = std::chrono::duration_cast<std::chrono::minutes>(t2);
this->minute = m.count(); this->minute = static_cast<std::uint8_t>(m.count());
const auto t3 = t2 - m; const auto t3 = t2 - m;
const auto s = std::chrono::duration_cast<std::chrono::seconds>(t3); const auto s = std::chrono::duration_cast<std::chrono::seconds>(t3);
this->second = s.count(); this->second = static_cast<std::uint8_t>(s.count());
const auto t4 = t3 - s; const auto t4 = t3 - s;
const auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(t4); const auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(t4);
this->millisecond = ms.count(); this->millisecond = static_cast<std::uint16_t>(ms.count());
const auto t5 = t4 - ms; const auto t5 = t4 - ms;
const auto us = std::chrono::duration_cast<std::chrono::microseconds>(t5); const auto us = std::chrono::duration_cast<std::chrono::microseconds>(t5);
this->microsecond = us.count(); this->microsecond = static_cast<std::uint16_t>(us.count());
const auto t6 = t5 - us; const auto t6 = t5 - us;
const auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(t6); const auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(t6);
this->nanosecond = ns.count(); this->nanosecond = static_cast<std::uint16_t>(ns.count());
} }
operator std::chrono::nanoseconds() const operator std::chrono::nanoseconds() const

View File

@@ -1,71 +0,0 @@
// Copyright Toru Niina 2017.
// Distributed under the MIT License.
#ifndef TOML11_FROM_TOML_HPP
#define TOML11_FROM_TOML_HPP
#include "get.hpp"
namespace toml
{
template<typename T>
void from_toml(T& x, const toml::value& v)
{
x = toml::get<typename std::remove_reference<T>::type>(v);
return;
}
namespace detail
{
template<typename T>
constexpr toml::value_t determine_castable_type()
{
return check_type<T>() != toml::value_t::Unknown ? check_type<T>() :
toml::detail::is_map<T>::value ? toml::value_t::Table :
toml::detail::is_container<T>::value ? toml::value_t::Array :
toml::value_t::Unknown;
}
template<std::size_t N, typename ... Ts>
struct from_toml_tie_impl
{
constexpr static std::size_t index = sizeof...(Ts) - N;
constexpr static toml::value_t type_index =
determine_castable_type<
typename std::tuple_element<index, std::tuple<Ts...>>::type>();
static void invoke(std::tuple<Ts& ...> tie, const toml::value& v)
{
// static_cast is needed because with intel c++ compiler, operator==
// is only defined when the two types are strictly equal, and type_index
// is const toml::value_t, while v.type() is toml::value_t.
if(static_cast<toml::value_t>(type_index) == v.type())
{
from_toml(std::get<index>(tie), v);
return;
}
return from_toml_tie_impl<N-1, Ts...>::invoke(tie, v);
}
};
template<typename ... Ts>
struct from_toml_tie_impl<0, Ts...>
{
static void invoke(std::tuple<Ts& ...>, const toml::value&)
{
return;
}
};
} // detail
template<typename ... Ts>
void from_toml(std::tuple<Ts& ...> tie, const toml::value& v)
{
detail::from_toml_tie_impl<sizeof...(Ts), Ts...>::invoke(tie, v);
return;
}
} // toml
#endif // TOML11_FROM_TOML

File diff suppressed because it is too large Load Diff

View File

@@ -53,7 +53,7 @@ inline ::toml::value operator"" _toml(const char* str, std::size_t len)
// If it is neither a table-key or a array-of-table-key, it may be a value. // 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(!is_table_key && !is_aots_key)
{ {
if(auto data = ::toml::detail::parse_value(loc)) if(auto data = ::toml::detail::parse_value<::toml::value>(loc))
{ {
return data.unwrap(); return data.unwrap();
} }
@@ -70,14 +70,9 @@ inline ::toml::value operator"" _toml(const char* str, std::size_t len)
// It is a valid toml file. // It is a valid toml file.
// It should be parsed as if we parse a file with this content. // It should be parsed as if we parse a file with this content.
if(auto data = ::toml::detail::parse_toml_file(loc)) if(auto data = ::toml::detail::parse_toml_file<::toml::value>(loc))
{ {
loc.reset(loc.begin()); // rollback to the top of the literal return data.unwrap();
// skip needless characters for error message
skip_line::invoke(loc); // skip the first several needless lines
skip_ws::invoke(loc); // skip the first several needless whitespaces
return ::toml::value(std::move(data.unwrap()),
::toml::detail::region<std::vector<char>>(std::move(loc)));
} }
else // none of them. else // none of them.
{ {

View File

@@ -253,6 +253,11 @@ std::string read_utf8_codepoint(const region<Container>& reg,
std::istringstream iss(str); std::istringstream iss(str);
iss >> std::hex >> codepoint; iss >> std::hex >> codepoint;
const auto to_char = [](const int i) noexcept -> char {
const auto uc = static_cast<unsigned char>(i);
return *reinterpret_cast<const char*>(std::addressof(uc));
};
std::string character; std::string character;
if(codepoint < 0x80) // U+0000 ... U+0079 ; just an ASCII. if(codepoint < 0x80) // U+0000 ... U+0079 ; just an ASCII.
{ {
@@ -261,8 +266,8 @@ std::string read_utf8_codepoint(const region<Container>& reg,
else if(codepoint < 0x800) //U+0080 ... U+07FF else if(codepoint < 0x800) //U+0080 ... U+07FF
{ {
// 110yyyyx 10xxxxxx; 0x3f == 0b0011'1111 // 110yyyyx 10xxxxxx; 0x3f == 0b0011'1111
character += static_cast<unsigned char>(0xC0| codepoint >> 6); character += to_char(0xC0| codepoint >> 6);
character += static_cast<unsigned char>(0x80|(codepoint & 0x3F)); character += to_char(0x80|(codepoint & 0x3F));
} }
else if(codepoint < 0x10000) // U+0800...U+FFFF else if(codepoint < 0x10000) // U+0800...U+FFFF
{ {
@@ -276,17 +281,17 @@ std::string read_utf8_codepoint(const region<Container>& reg,
} }
assert(codepoint < 0xD800 || 0xDFFF < codepoint); assert(codepoint < 0xD800 || 0xDFFF < codepoint);
// 1110yyyy 10yxxxxx 10xxxxxx // 1110yyyy 10yxxxxx 10xxxxxx
character += static_cast<unsigned char>(0xE0| codepoint >> 12); character += to_char(0xE0| codepoint >> 12);
character += static_cast<unsigned char>(0x80|(codepoint >> 6 & 0x3F)); character += to_char(0x80|(codepoint >> 6 & 0x3F));
character += static_cast<unsigned char>(0x80|(codepoint & 0x3F)); character += to_char(0x80|(codepoint & 0x3F));
} }
else if(codepoint < 0x110000) // U+010000 ... U+10FFFF else if(codepoint < 0x110000) // U+010000 ... U+10FFFF
{ {
// 11110yyy 10yyxxxx 10xxxxxx 10xxxxxx // 11110yyy 10yyxxxx 10xxxxxx 10xxxxxx
character += static_cast<unsigned char>(0xF0| codepoint >> 18); character += to_char(0xF0| codepoint >> 18);
character += static_cast<unsigned char>(0x80|(codepoint >> 12 & 0x3F)); character += to_char(0x80|(codepoint >> 12 & 0x3F));
character += static_cast<unsigned char>(0x80|(codepoint >> 6 & 0x3F)); character += to_char(0x80|(codepoint >> 6 & 0x3F));
character += static_cast<unsigned char>(0x80|(codepoint & 0x3F)); character += to_char(0x80|(codepoint & 0x3F));
} }
else // out of UTF-8 region else // out of UTF-8 region
{ {
@@ -655,9 +660,9 @@ parse_local_time(location<Container>& loc)
{{std::addressof(inner_loc), "here"}})); {{std::addressof(inner_loc), "here"}}));
} }
local_time time( local_time time(
static_cast<std::int8_t>(from_string<int>(h.unwrap().str(), 0)), from_string<int>(h.unwrap().str(), 0),
static_cast<std::int8_t>(from_string<int>(m.unwrap().str(), 0)), from_string<int>(m.unwrap().str(), 0),
static_cast<std::int8_t>(from_string<int>(s.unwrap().str(), 0)), 0, 0); from_string<int>(s.unwrap().str(), 0), 0, 0);
const auto before_secfrac = inner_loc.iter(); const auto before_secfrac = inner_loc.iter();
if(const auto secfrac = lex_time_secfrac::invoke(inner_loc)) if(const auto secfrac = lex_time_secfrac::invoke(inner_loc))
@@ -673,13 +678,13 @@ parse_local_time(location<Container>& loc)
} }
if(sf.size() >= 6) if(sf.size() >= 6)
{ {
time.millisecond = from_string<std::int16_t>(sf.substr(0, 3), 0); time.millisecond = from_string<std::uint16_t>(sf.substr(0, 3), 0u);
time.microsecond = from_string<std::int16_t>(sf.substr(3, 3), 0); time.microsecond = from_string<std::uint16_t>(sf.substr(3, 3), 0u);
} }
else if(sf.size() >= 3) else if(sf.size() >= 3)
{ {
time.millisecond = from_string<std::int16_t>(sf, 0); time.millisecond = from_string<std::uint16_t>(sf, 0u);
time.microsecond = 0; time.microsecond = 0u;
} }
} }
else else
@@ -869,13 +874,16 @@ parse_key(location<Container>& loc)
} }
// forward-decl to implement parse_array and parse_table // forward-decl to implement parse_array and parse_table
template<typename Container> template<typename Value, typename Container>
result<value, std::string> parse_value(location<Container>&); result<Value, std::string> parse_value(location<Container>&);
template<typename Container> template<typename Value, typename Container>
result<std::pair<array, region<Container>>, std::string> result<std::pair<typename Value::array_type, region<Container>>, std::string>
parse_array(location<Container>& loc) parse_array(location<Container>& loc)
{ {
using value_type = Value;
using array_type = typename value_type::array_type;
const auto first = loc.iter(); const auto first = loc.iter();
if(loc.iter() == loc.end()) if(loc.iter() == loc.end())
{ {
@@ -890,7 +898,7 @@ parse_array(location<Container>& loc)
using lex_ws_comment_newline = repeat< using lex_ws_comment_newline = repeat<
either<lex_wschar, lex_newline, lex_comment>, unlimited>; either<lex_wschar, lex_newline, lex_comment>, unlimited>;
array retval; array_type retval;
while(loc.iter() != loc.end()) while(loc.iter() != loc.end())
{ {
lex_ws_comment_newline::invoke(loc); // skip lex_ws_comment_newline::invoke(loc); // skip
@@ -902,7 +910,7 @@ parse_array(location<Container>& loc)
region<Container>(loc, first, loc.iter()))); region<Container>(loc, first, loc.iter())));
} }
if(auto val = parse_value(loc)) if(auto val = parse_value<value_type>(loc))
{ {
if(!retval.empty() && retval.front().type() != val.as_ok().type()) if(!retval.empty() && retval.front().type() != val.as_ok().type())
{ {
@@ -966,10 +974,12 @@ parse_array(location<Container>& loc)
{{std::addressof(loc), "should be closed"}})); {{std::addressof(loc), "should be closed"}}));
} }
template<typename Container> template<typename Value, typename Container>
result<std::pair<std::pair<std::vector<key>, region<Container>>, value>, std::string> result<std::pair<std::pair<std::vector<key>, region<Container>>, Value>, std::string>
parse_key_value_pair(location<Container>& loc) parse_key_value_pair(location<Container>& loc)
{ {
using value_type = Value;
const auto first = loc.iter(); const auto first = loc.iter();
auto key_reg = parse_key(loc); auto key_reg = parse_key(loc);
if(!key_reg) if(!key_reg)
@@ -1013,7 +1023,7 @@ parse_key_value_pair(location<Container>& loc)
} }
const auto after_kvsp = loc.iter(); // err msg const auto after_kvsp = loc.iter(); // err msg
auto val = parse_value(loc); auto val = parse_value<value_type>(loc);
if(!val) if(!val)
{ {
std::string msg; std::string msg;
@@ -1081,8 +1091,8 @@ parse_table_key(location<Container>& loc);
// Here, it parses region of `tab->at(k)` as a table key and check the depth // 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. // 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. // Otherwise, the key points the same node. It would be rejected.
template<typename Iterator> template<typename Value, typename Iterator>
bool is_valid_forward_table_definition(const value& fwd, bool is_valid_forward_table_definition(const Value& fwd,
Iterator key_first, Iterator key_curr, Iterator key_last) Iterator key_first, Iterator key_curr, Iterator key_last)
{ {
location<std::string> def("internal", detail::get_region(fwd).str()); location<std::string> def("internal", detail::get_region(fwd).str());
@@ -1123,9 +1133,9 @@ bool is_valid_forward_table_definition(const value& fwd,
return false; return false;
} }
template<typename InputIterator, typename Container> template<typename Value, typename InputIterator, typename Container>
result<bool, std::string> result<bool, std::string>
insert_nested_key(table& root, const toml::value& v, insert_nested_key(typename Value::table_type& root, const Value& v,
InputIterator iter, const InputIterator last, InputIterator iter, const InputIterator last,
region<Container> key_reg, region<Container> key_reg,
const bool is_array_of_table = false) const bool is_array_of_table = false)
@@ -1133,10 +1143,14 @@ insert_nested_key(table& root, const toml::value& v,
static_assert(std::is_same<key, static_assert(std::is_same<key,
typename std::iterator_traits<InputIterator>::value_type>::value,""); typename std::iterator_traits<InputIterator>::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; const auto first = iter;
assert(iter != last); assert(iter != last);
table* tab = std::addressof(root); table_type* tab = std::addressof(root);
for(; iter != last; ++iter) // search recursively for(; iter != last; ++iter) // search recursively
{ {
const key& k = *iter; const key& k = *iter;
@@ -1176,7 +1190,7 @@ insert_nested_key(table& root, const toml::value& v,
})); }));
} }
// the above if-else-if checks tab->at(k) is an array // the above if-else-if checks tab->at(k) is an array
array& a = tab->at(k).as_array(); auto& a = tab->at(k).as_array();
if(!(a.front().is_table())) if(!(a.front().is_table()))
{ {
throw syntax_error(format_underline(concat_to_string( throw syntax_error(format_underline(concat_to_string(
@@ -1223,7 +1237,7 @@ insert_nested_key(table& root, const toml::value& v,
} }
else // if not, we need to create the array of table else // if not, we need to create the array of table
{ {
toml::value aot(toml::array(1, v), key_reg); value_type aot(array_type(1, v), key_reg);
tab->insert(std::make_pair(k, aot)); tab->insert(std::make_pair(k, aot));
return ok(true); return ok(true);
} }
@@ -1298,7 +1312,7 @@ insert_nested_key(table& root, const toml::value& v,
// [x.y.z] // [x.y.z]
if(tab->count(k) == 0) if(tab->count(k) == 0)
{ {
(*tab)[k] = toml::value(toml::table{}, key_reg); (*tab)[k] = value_type(table_type{}, key_reg);
} }
// type checking... // type checking...
@@ -1308,7 +1322,7 @@ insert_nested_key(table& root, const toml::value& v,
} }
else if(tab->at(k).is_array()) // inserting to array-of-tables? else if(tab->at(k).is_array()) // inserting to array-of-tables?
{ {
array& a = (*tab)[k].as_array(); auto& a = (*tab)[k].as_array();
if(!a.back().is_table()) if(!a.back().is_table())
{ {
throw syntax_error(format_underline(concat_to_string( throw syntax_error(format_underline(concat_to_string(
@@ -1338,12 +1352,15 @@ insert_nested_key(table& root, const toml::value& v,
return err(std::string("toml::detail::insert_nested_key: never reach here")); return err(std::string("toml::detail::insert_nested_key: never reach here"));
} }
template<typename Container> template<typename Value, typename Container>
result<std::pair<table, region<Container>>, std::string> result<std::pair<typename Value::table_type, region<Container>>, std::string>
parse_inline_table(location<Container>& loc) parse_inline_table(location<Container>& loc)
{ {
using value_type = Value;
using table_type = typename value_type::table_type;
const auto first = loc.iter(); const auto first = loc.iter();
table retval; table_type retval;
if(!(loc.iter() != loc.end() && *loc.iter() == '{')) if(!(loc.iter() != loc.end() && *loc.iter() == '{'))
{ {
return err(format_underline("[error] toml::parse_inline_table: ", return err(format_underline("[error] toml::parse_inline_table: ",
@@ -1361,14 +1378,14 @@ parse_inline_table(location<Container>& loc)
retval, region<Container>(loc, first, loc.iter()))); retval, region<Container>(loc, first, loc.iter())));
} }
const auto kv_r = parse_key_value_pair(loc); const auto kv_r = parse_key_value_pair<value_type>(loc);
if(!kv_r) if(!kv_r)
{ {
return err(kv_r.unwrap_err()); return err(kv_r.unwrap_err());
} }
const std::vector<key>& keys = kv_r.unwrap().first.first; const std::vector<key>& keys = kv_r.unwrap().first.first;
const region<Container>& key_reg = kv_r.unwrap().first.second; const region<Container>& key_reg = kv_r.unwrap().first.second;
const value& val = kv_r.unwrap().second; const value_type& val = kv_r.unwrap().second;
const auto inserted = const auto inserted =
insert_nested_key(retval, val, keys.begin(), keys.end(), key_reg); insert_nested_key(retval, val, keys.begin(), keys.end(), key_reg);
@@ -1420,7 +1437,7 @@ result<value_t, std::string> guess_number_type(const location<Container>& l)
// does not parse further, those characters are always allowed to be there. // does not parse further, those characters are always allowed to be there.
location<Container> loc = l; location<Container> loc = l;
if(lex_offset_date_time::invoke(loc)) {return ok(value_t::OffsetDatetime);} if(lex_offset_date_time::invoke(loc)) {return ok(value_t::offset_datetime);}
loc.reset(l.iter()); loc.reset(l.iter());
if(lex_local_date_time::invoke(loc)) if(lex_local_date_time::invoke(loc))
@@ -1433,7 +1450,7 @@ result<value_t, std::string> guess_number_type(const location<Container>& l)
{{std::addressof(loc), "[+-]HH:MM or Z"}}, {{std::addressof(loc), "[+-]HH:MM or Z"}},
{"pass: +09:00, -05:30", "fail: +9:00, -5:30"})); {"pass: +09:00, -05:30", "fail: +9:00, -5:30"}));
} }
return ok(value_t::LocalDatetime); return ok(value_t::local_datetime);
} }
loc.reset(l.iter()); loc.reset(l.iter());
@@ -1471,11 +1488,11 @@ result<value_t, std::string> guess_number_type(const location<Container>& l)
"fail: 1979-05-27T7:32:00, 1979-05-27 7:32"})); "fail: 1979-05-27T7:32:00, 1979-05-27 7:32"}));
} }
} }
return ok(value_t::LocalDate); return ok(value_t::local_date);
} }
loc.reset(l.iter()); loc.reset(l.iter());
if(lex_local_time::invoke(loc)) {return ok(value_t::LocalTime);} if(lex_local_time::invoke(loc)) {return ok(value_t::local_time);}
loc.reset(l.iter()); loc.reset(l.iter());
if(lex_float::invoke(loc)) if(lex_float::invoke(loc))
@@ -1487,7 +1504,7 @@ result<value_t, std::string> guess_number_type(const location<Container>& l)
{"pass: +1.0, -2e-2, 3.141_592_653_589, inf, nan", {"pass: +1.0, -2e-2, 3.141_592_653_589, inf, nan",
"fail: .0, 1., _1.0, 1.0_, 1_.0, 1.0__0"})); "fail: .0, 1., _1.0, 1.0_, 1_.0, 1.0__0"}));
} }
return ok(value_t::Float); return ok(value_t::floating);
} }
loc.reset(l.iter()); loc.reset(l.iter());
@@ -1527,7 +1544,7 @@ result<value_t, std::string> guess_number_type(const location<Container>& l)
"fail: .0, 1., _1.0, 1.0_, 1_.0, 1.0__0"})); "fail: .0, 1., _1.0, 1.0_, 1_.0, 1.0__0"}));
} }
} }
return ok(value_t::Integer); return ok(value_t::integer);
} }
if(loc.iter() != loc.end() && *loc.iter() == '.') if(loc.iter() != loc.end() && *loc.iter() == '.')
{ {
@@ -1552,21 +1569,23 @@ result<value_t, std::string> guess_value_type(const location<Container>& loc)
{ {
switch(*loc.iter()) switch(*loc.iter())
{ {
case '"' : {return ok(value_t::String); } case '"' : {return ok(value_t::string); }
case '\'': {return ok(value_t::String); } case '\'': {return ok(value_t::string); }
case 't' : {return ok(value_t::Boolean);} case 't' : {return ok(value_t::boolean); }
case 'f' : {return ok(value_t::Boolean);} case 'f' : {return ok(value_t::boolean); }
case '[' : {return ok(value_t::Array); } case '[' : {return ok(value_t::array); }
case '{' : {return ok(value_t::Table); } case '{' : {return ok(value_t::table); }
case 'i' : {return ok(value_t::Float); } // inf. case 'i' : {return ok(value_t::floating);} // inf.
case 'n' : {return ok(value_t::Float); } // nan. case 'n' : {return ok(value_t::floating);} // nan.
default : {return guess_number_type(loc);} default : {return guess_number_type(loc);}
} }
} }
template<typename Container> template<typename Value, typename Container>
result<value, std::string> parse_value(location<Container>& loc) result<Value, std::string> parse_value(location<Container>& loc)
{ {
using value_type = Value;
const auto first = loc.iter(); const auto first = loc.iter();
if(first == loc.end()) if(first == loc.end())
{ {
@@ -1581,16 +1600,16 @@ result<value, std::string> parse_value(location<Container>& loc)
} }
switch(type.unwrap()) switch(type.unwrap())
{ {
case value_t::Boolean : {return parse_boolean(loc); } case value_t::boolean : {return parse_boolean(loc); }
case value_t::Integer : {return parse_integer(loc); } case value_t::integer : {return parse_integer(loc); }
case value_t::Float : {return parse_floating(loc); } case value_t::floating : {return parse_floating(loc); }
case value_t::String : {return parse_string(loc); } case value_t::string : {return parse_string(loc); }
case value_t::OffsetDatetime : {return parse_offset_datetime(loc);} case value_t::offset_datetime: {return parse_offset_datetime(loc);}
case value_t::LocalDatetime : {return parse_local_datetime(loc); } case value_t::local_datetime : {return parse_local_datetime(loc); }
case value_t::LocalDate : {return parse_local_date(loc); } case value_t::local_date : {return parse_local_date(loc); }
case value_t::LocalTime : {return parse_local_time(loc); } case value_t::local_time : {return parse_local_time(loc); }
case value_t::Array : {return parse_array(loc); } case value_t::array : {return parse_array<value_type>(loc); }
case value_t::Table : {return parse_inline_table(loc); } case value_t::table : {return parse_inline_table<value_type>(loc);}
default: default:
{ {
const auto msg = format_underline("[error] toml::parse_value: " const auto msg = format_underline("[error] toml::parse_value: "
@@ -1714,13 +1733,17 @@ parse_array_table_key(location<Container>& loc)
} }
// parse table body (key-value pairs until the iter hits the next [tablekey]) // parse table body (key-value pairs until the iter hits the next [tablekey])
template<typename Container> template<typename Value, typename Container>
result<table, std::string> parse_ml_table(location<Container>& loc) result<typename Value::table_type, std::string>
parse_ml_table(location<Container>& loc)
{ {
using value_type = Value;
using table_type = typename value_type::table_type;
const auto first = loc.iter(); const auto first = loc.iter();
if(first == loc.end()) if(first == loc.end())
{ {
return ok(toml::table{}); return ok(table_type{});
} }
// XXX at lest one newline is needed. // XXX at lest one newline is needed.
@@ -1728,7 +1751,7 @@ result<table, std::string> parse_ml_table(location<Container>& loc)
sequence<maybe<lex_ws>, maybe<lex_comment>, lex_newline>, at_least<1>>; sequence<maybe<lex_ws>, maybe<lex_comment>, lex_newline>, at_least<1>>;
skip_line::invoke(loc); skip_line::invoke(loc);
table tab; table_type tab;
while(loc.iter() != loc.end()) while(loc.iter() != loc.end())
{ {
lex_ws::invoke(loc); lex_ws::invoke(loc);
@@ -1744,11 +1767,11 @@ result<table, std::string> parse_ml_table(location<Container>& loc)
return ok(tab); return ok(tab);
} }
if(const auto kv = parse_key_value_pair(loc)) if(const auto kv = parse_key_value_pair<value_type>(loc))
{ {
const std::vector<key>& keys = kv.unwrap().first.first; const std::vector<key>& keys = kv.unwrap().first.first;
const region<Container>& key_reg = kv.unwrap().first.second; const region<Container>& key_reg = kv.unwrap().first.second;
const value& val = kv.unwrap().second; const value_type& val = kv.unwrap().second;
const auto inserted = const auto inserted =
insert_nested_key(tab, val, keys.begin(), keys.end(), key_reg); insert_nested_key(tab, val, keys.begin(), keys.end(), key_reg);
if(!inserted) if(!inserted)
@@ -1793,18 +1816,59 @@ result<table, std::string> parse_ml_table(location<Container>& loc)
return ok(tab); return ok(tab);
} }
template<typename Container> template<typename Value, typename Container>
result<table, std::string> parse_toml_file(location<Container>& loc) result<Value, std::string> parse_toml_file(location<Container>& loc)
{ {
using value_type = Value;
using table_type = typename value_type::table_type;
const auto first = loc.iter(); const auto first = loc.iter();
if(first == loc.end()) if(first == loc.end())
{ {
return ok(toml::table{}); return ok(value_type(table_type{}));
} }
table data; // put the first line as a region of a file
const region<Container> file(loc, loc.iter(),
std::find(loc.iter(), loc.end(), '\n'));
// 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<std::string> comments;
using lex_first_comments = sequence<
repeat<sequence<maybe<lex_ws>, lex_comment, lex_newline>, at_least<1>>,
sequence<maybe<lex_ws>, lex_newline>
>;
if(const auto token = lex_first_comments::invoke(loc))
{
location<std::string> inner_loc(loc.name(), token.unwrap().str());
while(inner_loc.iter() != inner_loc.end())
{
maybe<lex_ws>::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] // root object is also a table, but without [tablename]
if(auto tab = parse_ml_table(loc)) if(auto tab = parse_ml_table<value_type>(loc))
{ {
data = std::move(tab.unwrap()); data = std::move(tab.unwrap());
} }
@@ -1820,14 +1884,14 @@ result<table, std::string> parse_toml_file(location<Container>& loc)
// message. // message.
if(const auto tabkey = parse_array_table_key(loc)) if(const auto tabkey = parse_array_table_key(loc))
{ {
const auto tab = parse_ml_table(loc); const auto tab = parse_ml_table<value_type>(loc);
if(!tab){return err(tab.unwrap_err());} if(!tab){return err(tab.unwrap_err());}
const auto& keys = tabkey.unwrap().first; const auto& keys = tabkey.unwrap().first;
const auto& reg = tabkey.unwrap().second; const auto& reg = tabkey.unwrap().second;
const auto inserted = insert_nested_key(data, const auto inserted = insert_nested_key(data,
toml::value(tab.unwrap(), reg), value_type(tab.unwrap(), reg),
keys.begin(), keys.end(), reg, keys.begin(), keys.end(), reg,
/*is_array_of_table=*/ true); /*is_array_of_table=*/ true);
if(!inserted) {return err(inserted.unwrap_err());} if(!inserted) {return err(inserted.unwrap_err());}
@@ -1836,14 +1900,14 @@ result<table, std::string> parse_toml_file(location<Container>& loc)
} }
if(const auto tabkey = parse_table_key(loc)) if(const auto tabkey = parse_table_key(loc))
{ {
const auto tab = parse_ml_table(loc); const auto tab = parse_ml_table<value_type>(loc);
if(!tab){return err(tab.unwrap_err());} if(!tab){return err(tab.unwrap_err());}
const auto& keys = tabkey.unwrap().first; const auto& keys = tabkey.unwrap().first;
const auto& reg = tabkey.unwrap().second; const auto& reg = tabkey.unwrap().second;
const auto inserted = insert_nested_key(data, const auto inserted = insert_nested_key(data,
toml::value(tab.unwrap(), reg), keys.begin(), keys.end(), reg); value_type(tab.unwrap(), reg), keys.begin(), keys.end(), reg);
if(!inserted) {return err(inserted.unwrap_err());} if(!inserted) {return err(inserted.unwrap_err());}
continue; continue;
@@ -1851,13 +1915,23 @@ result<table, std::string> parse_toml_file(location<Container>& loc)
return err(format_underline("[error]: toml::parse_toml_file: " return err(format_underline("[error]: toml::parse_toml_file: "
"unknown line appeared", {{std::addressof(loc), "unknown format"}})); "unknown line appeared", {{std::addressof(loc), "unknown format"}}));
} }
return ok(data);
Value v(std::move(data), file);
v.comments() = comments;
return ok(std::move(v));
} }
} // detail } // detail
inline table parse(std::istream& is, std::string fname = "unknown file") template<typename Comment = ::toml::discard_comments,
template<typename ...> class Table = std::unordered_map,
template<typename ...> class Array = std::vector>
basic_value<Comment, Table, Array>
parse(std::istream& is, const std::string& fname = "unknown file")
{ {
using value_type = basic_value<Comment, Table, Array>;
const auto beg = is.tellg(); const auto beg = is.tellg();
is.seekg(0, std::ios::end); is.seekg(0, std::ios::end);
const auto end = is.tellg(); const auto end = is.tellg();
@@ -1865,7 +1939,8 @@ inline table parse(std::istream& is, std::string fname = "unknown file")
is.seekg(beg); is.seekg(beg);
// read whole file as a sequence of char // read whole file as a sequence of char
std::vector<char> letters(fsize); assert(fsize >= 0);
std::vector<char> letters(static_cast<std::size_t>(fsize));
is.read(letters.data(), fsize); is.read(letters.data(), fsize);
detail::location<std::vector<char>> detail::location<std::vector<char>>
@@ -1887,7 +1962,7 @@ inline table parse(std::istream& is, std::string fname = "unknown file")
} }
} }
const auto data = detail::parse_toml_file(loc); const auto data = detail::parse_toml_file<value_type>(loc);
if(!data) if(!data)
{ {
throw syntax_error(data.unwrap_err()); throw syntax_error(data.unwrap_err());
@@ -1895,14 +1970,17 @@ inline table parse(std::istream& is, std::string fname = "unknown file")
return data.unwrap(); return data.unwrap();
} }
inline table parse(const std::string& fname) template<typename Comment = ::toml::discard_comments,
template<typename ...> class Table = std::unordered_map,
template<typename ...> class Array = std::vector>
basic_value<Comment, Table, Array> parse(const std::string& fname)
{ {
std::ifstream ifs(fname.c_str(), std::ios_base::binary); std::ifstream ifs(fname.c_str(), std::ios_base::binary);
if(!ifs.good()) if(!ifs.good())
{ {
throw std::runtime_error("toml::parse: file open error -> " + fname); throw std::runtime_error("toml::parse: file open error -> " + fname);
} }
return parse(ifs, fname); return parse<Comment, Table, Array>(ifs, fname);
} }
} // toml } // toml

View File

@@ -9,6 +9,7 @@
#include <initializer_list> #include <initializer_list>
#include <iterator> #include <iterator>
#include <iomanip> #include <iomanip>
#include <cassert>
namespace toml namespace toml
{ {
@@ -53,9 +54,7 @@ struct region_base
// number of characters in the line after the region // number of characters in the line after the region
virtual std::size_t after() const noexcept {return 0;} virtual std::size_t after() const noexcept {return 0;}
virtual std::string comment_before() const {return "";} // just before virtual std::vector<std::string> comments()const {return {};}
virtual std::string comment_inline() const {return "";} // in the same line
virtual std::string comment() const {return "";} // concatenate
// ```toml // ```toml
// # comment_before // # comment_before
// key = "value" # comment_inline // key = "value" # comment_inline
@@ -70,8 +69,9 @@ struct region_base
template<typename Container> template<typename Container>
struct location final : public region_base struct location final : public region_base
{ {
using const_iterator = typename Container::const_iterator; using const_iterator = typename Container::const_iterator;
using source_ptr = std::shared_ptr<const Container>; using difference_type = typename const_iterator::difference_type;
using source_ptr = std::shared_ptr<const Container>;
static_assert(std::is_same<char, typename Container::value_type>::value,""); static_assert(std::is_same<char, typename Container::value_type>::value,"");
static_assert(std::is_same<std::random_access_iterator_tag, static_assert(std::is_same<std::random_access_iterator_tag,
@@ -104,15 +104,17 @@ struct location final : public region_base
// to the location changes the point to look. So an overload of `iter()` // to the location changes the point to look. So an overload of `iter()`
// which returns mutable reference is removed and `advance()`, `retrace()` // which returns mutable reference is removed and `advance()`, `retrace()`
// and `reset()` is added. // and `reset()` is added.
void advance(std::size_t n = 1) noexcept void advance(difference_type n = 1) noexcept
{ {
this->line_number_ += std::count(this->iter_, this->iter_ + n, '\n'); this->line_number_ += static_cast<std::size_t>(
std::count(this->iter_, std::next(this->iter_, n), '\n'));
this->iter_ += n; this->iter_ += n;
return; return;
} }
void retrace(std::size_t n = 1) noexcept void retrace(difference_type n = 1) noexcept
{ {
this->line_number_ -= std::count(this->iter_ - n, this->iter_, '\n'); this->line_number_ -= static_cast<std::size_t>(
std::count(std::prev(this->iter_, n), this->iter_, '\n'));
this->iter_ -= n; this->iter_ -= n;
return; return;
} }
@@ -122,11 +124,13 @@ struct location final : public region_base
// iterators and returns a negative value if `first > last`. // iterators and returns a negative value if `first > last`.
if(0 <= std::distance(rollback, this->iter_)) // rollback < iter if(0 <= std::distance(rollback, this->iter_)) // rollback < iter
{ {
this->line_number_ -= std::count(rollback, this->iter_, '\n'); this->line_number_ -= static_cast<std::size_t>(
std::count(rollback, this->iter_, '\n'));
} }
else // iter < rollback [[unlikely]] else // iter < rollback [[unlikely]]
{ {
this->line_number_ += std::count(this->iter_, rollback, '\n'); this->line_number_ += static_cast<std::size_t>(
std::count(this->iter_, rollback, '\n'));
} }
this->iter_ = rollback; this->iter_ = rollback;
return; return;
@@ -163,11 +167,15 @@ struct location final : public region_base
} }
std::size_t before() const noexcept override std::size_t before() const noexcept override
{ {
return std::distance(this->line_begin(), this->iter()); const auto sz = std::distance(this->line_begin(), this->iter());
assert(sz >= 0);
return static_cast<std::size_t>(sz);
} }
std::size_t after() const noexcept override std::size_t after() const noexcept override
{ {
return std::distance(this->iter(), this->line_end()); const auto sz = std::distance(this->iter(), this->line_end());
assert(sz >= 0);
return static_cast<std::size_t>(sz);
} }
source_ptr const& source() const& noexcept {return source_;} source_ptr const& source() const& noexcept {return source_;}
@@ -251,15 +259,21 @@ struct region final : public region_base
std::size_t size() const noexcept override std::size_t size() const noexcept override
{ {
return std::distance(first_, last_); const auto sz = std::distance(first_, last_);
assert(sz >= 0);
return static_cast<std::size_t>(sz);
} }
std::size_t before() const noexcept override std::size_t before() const noexcept override
{ {
return std::distance(this->line_begin(), this->first()); const auto sz = std::distance(this->line_begin(), this->first());
assert(sz >= 0);
return static_cast<std::size_t>(sz);
} }
std::size_t after() const noexcept override std::size_t after() const noexcept override
{ {
return std::distance(this->last(), this->line_end()); const auto sz = std::distance(this->last(), this->line_end());
assert(sz >= 0);
return static_cast<std::size_t>(sz);
} }
bool contain_newline() const noexcept bool contain_newline() const noexcept
@@ -288,92 +302,114 @@ struct region final : public region_base
std::string name() const override {return source_name_;} std::string name() const override {return source_name_;}
std::string comment_before() const override std::vector<std::string> comments() const override
{ {
auto iter = this->line_begin(); // points the first element // assuming the current region (`*this`) points a value.
std::vector<std::pair<decltype(iter), decltype(iter)>> comments; // ```toml
while(iter != this->begin()) // a = "value"
{ // ^^^^^^^- this region
iter = std::prev(iter); // ```
using rev_iter = std::reverse_iterator<decltype(iter)>; using rev_iter = std::reverse_iterator<const_iterator>;
auto line_before = std::find(rev_iter(iter), rev_iter(this->begin()),
'\n').base();
// range [line_before, iter) represents the previous line
auto comment_found = std::find(line_before, iter, '#'); std::vector<std::string> com{};
if(iter != comment_found && std::all_of(line_before, comment_found, {
[](const char c) noexcept -> bool { // find comments just before the current region.
return c == ' ' || c == '\t'; // ```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 == '{';}))
{ {
// the line before this range contains only a comment. auto iter = this->line_begin(); // points the first character
comments.push_back(std::make_pair(comment_found, iter)); 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 str = make_string(std::next(comment_found), iter);
if(str.back() == '\r') {str.pop_back();}
com.push_back(std::move(str));
}
else
{
break;
}
iter = line_start;
}
} }
else
{
break;
}
iter = line_before;
} }
std::string com; if(com.size() > 1)
for(auto i = comments.crbegin(), e = comments.crend(); i!=e; ++i)
{ {
if(i != comments.crbegin()) {com += '\n';} std::reverse(com.begin(), com.end());
com += std::string(i->first, i->second); }
{
// 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 str = make_string(std::next(comment_found), this->line_end());
if(str.back() == '\r') {str.pop_back();}
com.push_back(std::move(str));
}
}
} }
return com; return com;
} }
std::string comment_inline() const override
{
if(this->contain_newline())
{
std::string com;
// check both the first and the last line.
const auto first_line_end =
std::find(this->line_begin(), this->last(), '\n');
const auto first_comment_found =
std::find(this->line_begin(), first_line_end, '#');
if(first_comment_found != first_line_end)
{
com += std::string(first_comment_found, first_line_end);
}
const auto last_comment_found =
std::find(this->last(), this->line_end(), '#');
if(last_comment_found != this->line_end())
{
if(!com.empty()){com += '\n';}
com += std::string(last_comment_found, this->line_end());
}
return com;
}
const auto comment_found =
std::find(this->line_begin(), this->line_end(), '#');
return std::string(comment_found, this->line_end());
}
std::string comment() const override
{
std::string com_bef = this->comment_before();
std::string com_inl = this->comment_inline();
if(!com_bef.empty() && !com_inl.empty())
{
com_bef += '\n';
return com_bef + com_inl;
}
else if(com_bef.empty())
{
return com_inl;
}
else
{
return com_bef;
}
}
private: private:
source_ptr source_; source_ptr source_;
@@ -383,47 +419,42 @@ struct region final : public region_base
// to show a better error message. // to show a better error message.
inline std::string format_underline(const std::string& message, inline std::string format_underline(const std::string& message,
std::vector<std::pair<region_base const*, std::string>> reg_com, const std::vector<std::pair<region_base const*, std::string>>& reg_com,
std::vector<std::string> helps = {}) const std::vector<std::string>& helps = {})
{ {
assert(!reg_com.empty()); assert(!reg_com.empty());
#ifdef _WIN32 const auto line_num_width = static_cast<int>(std::max_element(
const auto newline = "\r\n"; reg_com.begin(), reg_com.end(),
#else
const char newline = '\n';
#endif
const auto line_num_width = std::max_element(reg_com.begin(), reg_com.end(),
[](std::pair<region_base const*, std::string> const& lhs, [](std::pair<region_base const*, std::string> const& lhs,
std::pair<region_base const*, std::string> const& rhs) std::pair<region_base const*, std::string> const& rhs)
{ {
return lhs.first->line_num().size() < rhs.first->line_num().size(); return lhs.first->line_num().size() < rhs.first->line_num().size();
} }
)->first->line_num().size(); )->first->line_num().size());
std::ostringstream retval; std::ostringstream retval;
retval << message << newline; retval << message << '\n';
for(std::size_t i=0; i<reg_com.size(); ++i) for(auto iter = reg_com.begin(); iter != reg_com.end(); ++iter)
{ {
if(i!=0 && reg_com.at(i-1).first->name() == reg_com.at(i).first->name()) // if the filenames are the same, print "..."
if(iter != reg_com.begin() &&
std::prev(iter)->first->name() == iter->first->name())
{ {
retval << newline << " ..." << newline; retval << "\n ...\n";
} }
else else // if filename differs, print " --> filename.toml"
{ {
if(i != 0) {retval << newline;} if(iter != reg_com.begin()) {retval << '\n';}
retval << " --> " << reg_com.at(i).first->name() << newline; retval << " --> " << iter->first->name() << '\n';
} }
const region_base* const reg = iter->first;
const region_base* const reg = reg_com.at(i).first; const std::string& comment = iter->second;
const std::string& comment = reg_com.at(i).second;
retval << ' ' << std::setw(line_num_width) << reg->line_num(); retval << ' ' << std::setw(line_num_width) << reg->line_num();
retval << " | " << reg->line() << newline; retval << " | " << reg->line() << '\n';
retval << make_string(line_num_width + 1, ' '); retval << make_string(static_cast<std::size_t>(line_num_width + 1), ' ');
retval << " | " << make_string(reg->before(), ' '); retval << " | " << make_string(reg->before(), ' ');
if(reg->size() == 1) if(reg->size() == 1)
@@ -440,20 +471,18 @@ inline std::string format_underline(const std::string& message,
const auto underline_len = std::min(reg->size(), reg->line().size()); const auto underline_len = std::min(reg->size(), reg->line().size());
retval << make_string(underline_len, '~'); retval << make_string(underline_len, '~');
} }
retval << ' '; retval << ' ';
retval << comment; retval << comment;
} }
if(helps.size() != 0) if(!helps.empty())
{ {
retval << newline; retval << '\n';
retval << make_string(line_num_width + 1, ' '); retval << make_string(static_cast<std::size_t>(line_num_width + 1), ' ');
retval << " | "; retval << " | ";
for(const auto help : helps) for(const auto help : helps)
{ {
retval << newline; retval << "\nHint: ";
retval << "Hint: ";
retval << help; retval << help;
} }
} }

View File

@@ -10,30 +10,88 @@
namespace toml 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.
inline std::string format_key(const toml::key& key)
{
detail::location<toml::key> loc(key, key);
detail::lex_unquoted_key::invoke(loc);
if(loc.iter() == loc.end())
{
return key; // all the tokens are consumed. the key is unquoted-key.
}
std::string token("\"");
for(const char c : key)
{
switch(c)
{
case '\\': {token += "\\\\"; break;}
case '\"': {token += "\\\""; break;}
case '\b': {token += "\\b"; break;}
case '\t': {token += "\\t"; break;}
case '\f': {token += "\\f"; break;}
case '\n': {token += "\\n"; break;}
case '\r': {token += "\\r"; break;}
default : {token += c; break;}
}
}
token += "\"";
return token;
}
template<typename Comment,
template<typename ...> class Table,
template<typename ...> class Array>
struct serializer struct serializer
{ {
serializer(const std::size_t w = 80, using value_type = basic_value<Comment, Table, Array>;
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<toml::floating>::max_digits10, const int float_prec = std::numeric_limits<toml::floating>::max_digits10,
const bool can_be_inlined = false, const bool can_be_inlined = false,
const bool no_comment = false,
std::vector<toml::key> ks = {}) std::vector<toml::key> ks = {})
: can_be_inlined_(can_be_inlined), float_prec_(float_prec), width_(w), : can_be_inlined_(can_be_inlined), no_comment_(no_comment),
keys_(std::move(ks)) float_prec_(float_prec), width_(w), keys_(std::move(ks))
{} {}
~serializer() = default; ~serializer() = default;
std::string operator()(const toml::boolean& b) const std::string operator()(const boolean_type& b) const
{ {
return b ? "true" : "false"; return b ? "true" : "false";
} }
std::string operator()(const integer i) const std::string operator()(const integer_type i) const
{ {
return std::to_string(i); return std::to_string(i);
} }
std::string operator()(const toml::floating f) const std::string operator()(const floating_type f) const
{ {
const auto fmt = "%.*g"; const auto fmt = "%.*g";
const auto bsz = std::snprintf(nullptr, 0, fmt, this->float_prec_, f); const auto bsz = std::snprintf(nullptr, 0, fmt, this->float_prec_, f);
std::vector<char> buf(bsz + 1, '\0'); // +1 for null character(\0) // +1 for null character(\0)
std::vector<char> buf(static_cast<std::size_t>(bsz + 1), '\0');
std::snprintf(buf.data(), buf.size(), fmt, this->float_prec_, f); std::snprintf(buf.data(), buf.size(), fmt, this->float_prec_, f);
std::string token(buf.begin(), std::prev(buf.end())); std::string token(buf.begin(), std::prev(buf.end()));
@@ -41,16 +99,27 @@ struct serializer
{ {
token += '0'; token += '0';
} }
const auto e = std::find_if(token.cbegin(), token.cend(),
[](const char c) -> bool { const auto e = std::find_if(
return c == 'E' || c == 'e'; token.cbegin(), token.cend(), [](const char c) noexcept -> bool {
return c == 'e' || c == 'E';
}); });
if(e == token.cend()) 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;
}
if(!has_exponent)
{ {
return token; // there is no exponent part. just return it. return token; // there is no exponent part. just return it.
} }
// zero-prefix in an exponent is not allowed in TOML. // zero-prefix in an exponent is NOT allowed in TOML.
// remove it if it exists. // remove it if it exists.
bool sign_exists = false; bool sign_exists = false;
std::size_t zero_prefix = 0; std::size_t zero_prefix = 0;
@@ -64,11 +133,12 @@ struct serializer
{ {
const auto offset = std::distance(token.cbegin(), e) + const auto offset = std::distance(token.cbegin(), e) +
(sign_exists ? 2 : 1); (sign_exists ? 2 : 1);
token.erase(offset, zero_prefix); token.erase(static_cast<typename std::string::size_type>(offset),
zero_prefix);
} }
return token; return token;
} }
std::string operator()(const string& s) const std::string operator()(const string_type& s) const
{ {
if(s.kind == string_t::basic) if(s.kind == string_t::basic)
{ {
@@ -130,37 +200,44 @@ struct serializer
} }
} }
std::string operator()(const local_date& d) const std::string operator()(const local_date_type& d) const
{ {
std::ostringstream oss; std::ostringstream oss;
oss << d; oss << d;
return oss.str(); return oss.str();
} }
std::string operator()(const local_time& t) const std::string operator()(const local_time_type& t) const
{ {
std::ostringstream oss; std::ostringstream oss;
oss << t; oss << t;
return oss.str(); return oss.str();
} }
std::string operator()(const local_datetime& dt) const std::string operator()(const local_datetime_type& dt) const
{ {
std::ostringstream oss; std::ostringstream oss;
oss << dt; oss << dt;
return oss.str(); return oss.str();
} }
std::string operator()(const offset_datetime& odt) const std::string operator()(const offset_datetime_type& odt) const
{ {
std::ostringstream oss; std::ostringstream oss;
oss << odt; oss << odt;
return oss.str(); return oss.str();
} }
std::string operator()(const array& v) const std::string operator()(const array_type& v) const
{ {
if(!v.empty() && v.front().is_table())// v is an array of tables if(!v.empty() && v.front().is_table())// v is an array of tables
{ {
// if it's not inlined, we need to add `[[table.key]]`. // if it's not inlined, we need to add `[[table.key]]`.
// but if it can be inlined, we need `table.key = [...]`. // but if it can be inlined,
// ```
// table.key = [
// {...},
// # comment
// {...},
// ]
// ```
if(this->can_be_inlined_) if(this->can_be_inlined_)
{ {
std::string token; std::string token;
@@ -169,37 +246,62 @@ struct serializer
token += this->serialize_key(keys_.back()); token += this->serialize_key(keys_.back());
token += " = "; token += " = ";
} }
bool width_exceeds = false; bool failed = false;
token += "[\n"; token += "[\n";
for(const auto& item : v) for(const auto& item : v)
{ {
const auto t = // if an element of the table has a comment, the table
this->make_inline_table(item.cast<value_t::Table>()); // cannot be inlined.
if(this->has_comment_inside(item.as_table()))
{
failed = true;
break;
}
if(!no_comment_)
{
for(const auto& c : item.comments())
{
token += '#';
token += c;
token += '\n';
}
}
const auto t = this->make_inline_table(item.as_table());
if(t.size() + 1 > width_ || // +1 for the last comma {...}, if(t.size() + 1 > width_ || // +1 for the last comma {...},
std::find(t.cbegin(), t.cend(), '\n') != t.cend()) std::find(t.cbegin(), t.cend(), '\n') != t.cend())
{ {
width_exceeds = true; failed = true;
break; break;
} }
token += t; token += t;
token += ",\n"; token += ",\n";
} }
if(!width_exceeds) if(!failed)
{ {
token += "]\n"; token += "]\n";
return token; return token;
} }
// if width_exceeds, serialize it as [[array.of.tables]]. // if failed, serialize them as [[array.of.tables]].
} }
std::string token; std::string token;
for(const auto& item : v) for(const auto& item : v)
{ {
if(!no_comment_)
{
for(const auto& c : item.comments())
{
token += '#';
token += c;
token += '\n';
}
}
token += "[["; token += "[[";
token += this->serialize_dotted_key(keys_); token += this->serialize_dotted_key(keys_);
token += "]]\n"; token += "]]\n";
token += this->make_multiline_table(item.cast<value_t::Table>()); token += this->make_multiline_table(item.as_table());
} }
return token; return token;
} }
@@ -208,7 +310,9 @@ struct serializer
return std::string("[]"); return std::string("[]");
} }
// not an array of tables. normal array. first, try to make it inline. // 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); const auto inl = this->make_inline_array(v);
if(inl.size() < this->width_ && if(inl.size() < this->width_ &&
@@ -218,16 +322,54 @@ struct serializer
} }
} }
// if the length exceeds this->width_, print multiline array // if the length exceeds this->width_, print multiline array.
// key = [
// # ...
// 42,
// ...
// ]
std::string token; std::string token;
std::string current_line; std::string current_line;
token += "[\n"; token += "[\n";
for(const auto& item : v) for(const auto& item : v)
{ {
auto next_elem = toml::visit(*this, item); if(!item.comments().empty() && !no_comment_)
// newline between array-value and comma is not allowed {
if(next_elem.back() == '\n'){next_elem.pop_back();} // 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.back() == '\n') {token.pop_back();}
token += ",\n";
continue;
}
std::string next_elem;
next_elem += toml::visit(*this, item);
// comma before newline.
if(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_) if(current_line.size() + next_elem.size() + 1 < this->width_)
{ {
current_line += next_elem; current_line += next_elem;
@@ -235,12 +377,13 @@ struct serializer
} }
else if(current_line.empty()) else if(current_line.empty())
{ {
// the next elem cannot be within the width. // if current line was empty, force put the next_elem because
// next_elem is not splittable
token += next_elem; token += next_elem;
token += ",\n"; token += ",\n";
// keep current line empty // current_line is kept empty
} }
else // current_line has some tokens and it exceeds width else // reset current_line
{ {
assert(current_line.back() == ','); assert(current_line.back() == ',');
token += current_line; token += current_line;
@@ -258,9 +401,12 @@ struct serializer
return token; return token;
} }
std::string operator()(const table& v) const // templatize for any table-like container
std::string operator()(const table_type& v) const
{ {
if(this->can_be_inlined_) // 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; std::string token;
if(!this->keys_.empty()) if(!this->keys_.empty())
@@ -269,7 +415,8 @@ struct serializer
token += " = "; token += " = ";
} }
token += this->make_inline_table(v); token += this->make_inline_table(v);
if(token.size() < this->width_) if(token.size() < this->width_ &&
token.end() == std::find(token.begin(), token.end(), '\n'))
{ {
return token; return token;
} }
@@ -290,16 +437,7 @@ struct serializer
std::string serialize_key(const toml::key& key) const std::string serialize_key(const toml::key& key) const
{ {
detail::location<toml::key> loc(key, key); return ::toml::format_key(key);
detail::lex_unquoted_key::invoke(loc);
if(loc.iter() == loc.end())
{
return key; // all the tokens are consumed. the key is unquoted-key.
}
std::string token("\"");
token += this->escape_basic_string(key);
token += "\"";
return token;
} }
std::string serialize_dotted_key(const std::vector<toml::key>& keys) const std::string serialize_dotted_key(const std::vector<toml::key>& keys) const
@@ -369,8 +507,33 @@ struct serializer
return retval; return retval;
} }
std::string make_inline_array(const array& v) const // 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; std::string token;
token += '['; token += '[';
bool is_first = true; bool is_first = true;
@@ -384,8 +547,9 @@ struct serializer
return token; return token;
} }
std::string make_inline_table(const table& v) const std::string make_inline_table(const table_type& v) const
{ {
assert(!has_comment_inside(v));
assert(this->can_be_inlined_); assert(this->can_be_inlined_);
std::string token; std::string token;
token += '{'; token += '{';
@@ -403,7 +567,7 @@ struct serializer
return token; return token;
} }
std::string make_multiline_table(const table& v) const std::string make_multiline_table(const table_type& v) const
{ {
std::string token; std::string token;
@@ -416,6 +580,15 @@ struct serializer
continue; continue;
} }
if(!kv.second.comments().empty() && !no_comment_)
{
for(const auto& c : kv.second.comments())
{
token += '#';
token += c;
token += '\n';
}
}
const auto key_and_sep = this->serialize_key(kv.first) + " = "; const auto key_and_sep = this->serialize_key(kv.first) + " = ";
const auto residual_width = (this->width_ > key_and_sep.size()) ? const auto residual_width = (this->width_ > key_and_sep.size()) ?
this->width_ - key_and_sep.size() : 0; this->width_ - key_and_sep.size() : 0;
@@ -446,8 +619,8 @@ struct serializer
std::vector<toml::key> ks(this->keys_); std::vector<toml::key> ks(this->keys_);
ks.push_back(kv.first); ks.push_back(kv.first);
auto tmp = visit(serializer( auto tmp = visit(serializer(this->width_, this->float_prec_,
this->width_, this->float_prec_, !multiline_table_printed, ks), !multiline_table_printed, this->no_comment_, ks),
kv.second); kv.second);
if((!multiline_table_printed) && if((!multiline_table_printed) &&
@@ -460,12 +633,22 @@ struct serializer
// still inline tables only. // still inline tables only.
tmp += '\n'; tmp += '\n';
} }
if(!kv.second.comments().empty() && !no_comment_)
{
for(const auto& c : kv.second.comments())
{
token += '#';
token += c;
token += '\n';
}
}
token += tmp; token += tmp;
} }
return token; return token;
} }
bool is_array_of_tables(const value& v) const bool is_array_of_tables(const value_type& v) const
{ {
if(!v.is_array()) {return false;} if(!v.is_array()) {return false;}
const auto& a = v.as_array(); const auto& a = v.as_array();
@@ -475,50 +658,107 @@ struct serializer
private: private:
bool can_be_inlined_; bool can_be_inlined_;
bool no_comment_;
int float_prec_; int float_prec_;
std::size_t width_; std::size_t width_;
std::vector<toml::key> keys_; std::vector<toml::key> keys_;
}; };
inline std::string template<typename C,
format(const value& v, std::size_t w = 80, template<typename ...> class M, template<typename ...> class V>
std::string
format(const basic_value<C, M, V>& v, std::size_t w = 80u,
int fprec = std::numeric_limits<toml::floating>::max_digits10, int fprec = std::numeric_limits<toml::floating>::max_digits10,
bool force_inline = false) bool no_comment = false, bool force_inline = false)
{ {
// if value is a table, it is considered to be a root object. // if value is a table, it is considered to be a root object.
// the root object can't be an inline table. so pass false. otherwise, true. // the root object can't be an inline table.
return visit(serializer(w, fprec, (!v.is_table()) || force_inline), v); 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
}
oss << visit(serializer<C, M, V>(w, fprec, no_comment, false), v);
return oss.str();
}
return visit(serializer<C, M, V>(w, fprec, force_inline), v);
} }
inline std::string
format(const table& t, std::size_t w = 80, namespace detail
int fprec = std::numeric_limits<toml::floating>::max_digits10,
bool force_inline = false)
{ {
return serializer(w, fprec, force_inline)(t); template<typename charT, typename traits>
int comment_index(std::basic_ostream<charT, traits>&)
{
static const int index = std::ios_base::xalloc();
return index;
}
} // detail
template<typename charT, typename traits>
std::basic_ostream<charT, traits>&
nocomment(std::basic_ostream<charT, traits>& os)
{
// by default, it is zero. and by defalut, it shows comments.
os.iword(detail::comment_index(os)) = 1;
return os;
} }
template<typename charT, typename traits> template<typename charT, typename traits>
std::basic_ostream<charT, traits>& std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const value& v) showcomment(std::basic_ostream<charT, traits>& os)
{ {
// get status of std::setw(). // by default, it is zero. and by defalut, it shows comments.
const std::size_t w = os.width(); os.iword(detail::comment_index(os)) = 0;
const int fprec = os.precision();
os.width(0);
// the root object can't be an inline table. so pass `false`.
os << visit(serializer(w, fprec, false), v);
return os; return os;
} }
template<typename charT, typename traits>
template<typename charT, typename traits, typename C,
template<typename ...> class M, template<typename ...> class V>
std::basic_ostream<charT, traits>& std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const table& v) operator<<(std::basic_ostream<charT, traits>& os, const basic_value<C, M, V>& v)
{ {
// get status of std::setw(). // get status of std::setw().
const std::size_t w = os.width(); const auto w = static_cast<std::size_t>(os.width());
const int fprec = os.precision(); const int fprec = static_cast<int>(os.precision());
os.width(0); os.width(0);
// by defualt, iword is initialized byl 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`. // the root object can't be an inline table. so pass `false`.
os << serializer(w, fprec, false)(v); os << visit(serializer<C, M, V>(w, fprec, false, no_comment), v);
// 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; return os;
} }

82
toml/source_location.hpp Normal file
View File

@@ -0,0 +1,82 @@
// Copyright Toru Niina 2019.
// Distributed under the MIT License.
#ifndef TOML11_SOURCE_LOCATION_HPP
#define TOML11_SOURCE_LOCATION_HPP
#include "region.hpp"
#include <cstdint>
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_(0), column_num_(0), region_size_(0),
file_name_("unknown file"), line_str_("")
{}
explicit source_location(const detail::region_base* reg)
: line_num_(0), column_num_(0), region_size_(0),
file_name_("unknown file"), line_str_("")
{
if(reg)
{
line_num_ = static_cast<std::uint_least32_t>(std::stoul(reg->line_num()));
column_num_ = static_cast<std::uint_least32_t>(reg->before() + 1);
region_size_ = static_cast<std::uint_least32_t>(reg->size());
file_name_ = reg->name();
line_str_ = reg->line();
}
}
~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_;
};
} // toml
#endif// TOML11_SOURCE_LOCATION_HPP

View File

@@ -139,9 +139,74 @@ operator>=(const char* lhs, const string& rhs) {return std::string(lhs) >= rhs.s
template<typename charT, typename traits> template<typename charT, typename traits>
std::basic_ostream<charT, traits>& std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const string& str) operator<<(std::basic_ostream<charT, traits>& os, const string& s)
{ {
os << str.str; 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; return os;
} }

View File

@@ -15,15 +15,11 @@
namespace toml namespace toml
{ {
template<typename C, template<typename ...> class T, template<typename ...> class A>
class value; // forward decl class basic_value;
namespace detail namespace detail
{ {
template<typename T>
using unwrap_t = typename std::decay<T>::type;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// check whether type T is a kind of container/map class // check whether type T is a kind of container/map class
@@ -54,12 +50,22 @@ struct has_resize_method_impl
template<typename T> static std::false_type check(...); template<typename T> static std::false_type check(...);
}; };
struct is_comparable_impl
{
template<typename T> static std::true_type check(decltype(std::declval<T>() < std::declval<T>())*);
template<typename T> static std::false_type check(...);
};
struct has_from_toml_method_impl struct has_from_toml_method_impl
{ {
template<typename T> template<typename T, typename C,
template<typename ...> class Tb, template<typename ...> class A>
static std::true_type check( static std::true_type check(
decltype(std::declval<T>().from_toml(std::declval<::toml::value>()))*); decltype(std::declval<T>().from_toml(
template<typename T> std::declval<::toml::basic_value<C, Tb, A>>()))*);
template<typename T, typename C,
template<typename ...> class Tb, template<typename ...> class A>
static std::false_type check(...); static std::false_type check(...);
}; };
struct has_into_toml_method_impl struct has_into_toml_method_impl
@@ -86,10 +92,14 @@ template<typename T>
struct has_mapped_type : decltype(has_mapped_type_impl::check<T>(nullptr)){}; struct has_mapped_type : decltype(has_mapped_type_impl::check<T>(nullptr)){};
template<typename T> template<typename T>
struct has_resize_method : decltype(has_resize_method_impl::check<T>(nullptr)){}; struct has_resize_method : decltype(has_resize_method_impl::check<T>(nullptr)){};
template<typename T> template<typename T>
struct is_comparable : decltype(is_comparable_impl::check<T>(nullptr)){};
template<typename T, typename C,
template<typename ...> class Tb, template<typename ...> class A>
struct has_from_toml_method struct has_from_toml_method
: decltype(has_from_toml_method_impl::check<T>(nullptr)){}; : decltype(has_from_toml_method_impl::check<T, C, Tb, A>(nullptr)){};
template<typename T> template<typename T>
struct has_into_toml_method struct has_into_toml_method
: decltype(has_into_toml_method_impl::check<T>(nullptr)){}; : decltype(has_into_toml_method_impl::check<T>(nullptr)){};
@@ -160,6 +170,15 @@ template<typename T> struct is_container<T const&> : is_container<T>{};
template<typename T> struct is_container<T volatile&> : is_container<T>{}; template<typename T> struct is_container<T volatile&> : is_container<T>{};
template<typename T> struct is_container<T const volatile&> : is_container<T>{}; template<typename T> struct is_container<T const volatile&> : is_container<T>{};
template<typename T>
struct is_basic_value: std::false_type{};
template<typename T> struct is_basic_value<T&> : is_basic_value<T>{};
template<typename T> struct is_basic_value<T const&> : is_basic_value<T>{};
template<typename T> struct is_basic_value<T volatile&> : is_basic_value<T>{};
template<typename T> struct is_basic_value<T const volatile&> : is_basic_value<T>{};
template<typename C, template<typename ...> class M, template<typename ...> class V>
struct is_basic_value<::toml::basic_value<C, M, V>>: std::true_type{};
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// C++14 index_sequence // C++14 index_sequence
@@ -186,6 +205,11 @@ struct index_sequence_maker<0>
template<std::size_t N> template<std::size_t N>
using make_index_sequence = typename index_sequence_maker<N-1>::type; using make_index_sequence = typename index_sequence_maker<N-1>::type;
// ---------------------------------------------------------------------------
// C++14 enable_if_t
template<bool B, typename T>
using enable_if_t = typename std::enable_if<B, T>::type;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// return_type_of_t // return_type_of_t

View File

@@ -5,50 +5,51 @@
#include "datetime.hpp" #include "datetime.hpp"
#include "string.hpp" #include "string.hpp"
#include "traits.hpp" #include "traits.hpp"
#include "comments.hpp"
#include <vector> #include <vector>
#include <unordered_map> #include <unordered_map>
namespace toml namespace toml
{ {
using character = char; template<typename Comment, // discard/preserve_comment
template<typename ...> class Table, // map-like class
template<typename ...> class Array> // vector-like class
class basic_value;
class value; using character = char;
using key = std::string; using key = std::string;
using Boolean = bool; using boolean = bool;
using Integer = std::int64_t; using integer = std::int64_t;
using Float = double; using floating = double; // "float" is a keyward, cannot use it here.
using String = ::toml::string; // the following stuffs are structs defined here, so aliases are not needed.
using Datetime = offset_datetime; // - string
using OffsetDatetime = offset_datetime; // - offset_datetime
using LocalDatetime = local_datetime; // - offset_datetime
using LocalDate = local_date; // - local_datetime
using LocalTime = local_time; // - local_date
using Array = std::vector<value>; // - local_time
using Table = std::unordered_map<key, value>;
// alias for snake_case, consistency with STL/Boost, toml::key, toml::value // default toml::value and default array/table. these are defined after defining
using boolean = Boolean; // basic_value itself.
using integer = Integer; // using value = basic_value<discard_comments, std::unordered_map, std::vector>;
using floating = Float; // XXX `float` is keyword. we can't use it here // using array = typename value::array_type;
using array = Array; // using table = typename value::table_type;
using table = Table;
enum class value_t : std::uint8_t enum class value_t : std::uint8_t
{ {
Empty = 0, empty = 0,
Boolean = 1, boolean = 1,
Integer = 2, integer = 2,
Float = 3, floating = 3,
String = 4, string = 4,
OffsetDatetime = 5, offset_datetime = 5,
LocalDatetime = 6, local_datetime = 6,
LocalDate = 7, local_date = 7,
LocalTime = 8, local_time = 8,
Array = 9, array = 9,
Table = 10, table = 10,
Unknown = 255,
}; };
template<typename charT, typename traits> template<typename charT, typename traits>
@@ -57,27 +58,27 @@ operator<<(std::basic_ostream<charT, traits>& os, value_t t)
{ {
switch(t) switch(t)
{ {
case toml::value_t::Boolean : os << "boolean"; return os; case value_t::boolean : os << "boolean"; return os;
case toml::value_t::Integer : os << "integer"; return os; case value_t::integer : os << "integer"; return os;
case toml::value_t::Float : os << "float"; return os; case value_t::floating : os << "floating"; return os;
case toml::value_t::String : os << "string"; return os; case value_t::string : os << "string"; return os;
case toml::value_t::OffsetDatetime: os << "offset_datetime"; return os; case value_t::offset_datetime : os << "offset_datetime"; return os;
case toml::value_t::LocalDatetime : os << "local_datetime"; return os; case value_t::local_datetime : os << "local_datetime"; return os;
case toml::value_t::LocalDate : os << "local_date"; return os; case value_t::local_date : os << "local_date"; return os;
case toml::value_t::LocalTime : os << "local_time"; return os; case value_t::local_time : os << "local_time"; return os;
case toml::value_t::Array : os << "array"; return os; case value_t::array : os << "array"; return os;
case toml::value_t::Table : os << "table"; return os; case value_t::table : os << "table"; return os;
case toml::value_t::Empty : os << "empty"; return os; case value_t::empty : os << "empty"; return os;
case toml::value_t::Unknown : os << "unknown"; return os; default : os << "unknown"; return os;
default : os << "nothing"; return os;
} }
} }
template<typename charT = character, typename traits = std::char_traits<charT>, template<typename charT = char,
typename traits = std::char_traits<charT>,
typename alloc = std::allocator<charT>> typename alloc = std::allocator<charT>>
inline std::basic_string<charT, traits, alloc> stringize(value_t t) inline std::basic_string<charT, traits, alloc> stringize(value_t t)
{ {
std::ostringstream oss; std::basic_ostringstream<charT, traits, alloc> oss;
oss << t; oss << t;
return oss.str(); return oss.str();
} }
@@ -85,60 +86,47 @@ inline std::basic_string<charT, traits, alloc> stringize(value_t t)
namespace detail namespace detail
{ {
template<typename T> // helper to define a type that represents a value_t value.
constexpr inline value_t check_type() template<value_t V>
{ using value_t_constant = std::integral_constant<value_t, V>;
using type = typename std::remove_cv<
typename std::remove_reference<T>::type
>::type;
return std::is_same<type, toml::boolean>::value ? value_t::Boolean :
std::is_integral<type>::value ? value_t::Integer :
std::is_floating_point<type>::value ? value_t::Float :
std::is_same<type, std::string>::value ? value_t::String :
std::is_same<type, toml::string>::value ? value_t::String :
std::is_same<type, toml::local_date>::value ? value_t::LocalDate :
std::is_same<type, toml::local_time>::value ? value_t::LocalTime :
is_chrono_duration<type>::value ? value_t::LocalTime :
std::is_same<type, toml::local_datetime>::value ? value_t::LocalDatetime :
std::is_same<type, toml::offset_datetime>::value ? value_t::OffsetDatetime :
std::is_same<type, std::chrono::system_clock::time_point>::value ? value_t::OffsetDatetime :
std::is_convertible<type, toml::array>::value ? value_t::Array :
std::is_convertible<type, toml::table>::value ? value_t::Table :
value_t::Unknown;
}
constexpr inline bool is_valid(value_t vt) // 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.
return vt != value_t::Unknown; template<value_t t, typename Value> struct enum_to_type {using type = void ;};
} template<typename Value> struct enum_to_type<value_t::empty , Value>{using type = void ;};
template<typename Value> struct enum_to_type<value_t::boolean , Value>{using type = boolean ;};
template<typename Value> struct enum_to_type<value_t::integer , Value>{using type = integer ;};
template<typename Value> struct enum_to_type<value_t::floating , Value>{using type = floating ;};
template<typename Value> struct enum_to_type<value_t::string , Value>{using type = string ;};
template<typename Value> struct enum_to_type<value_t::offset_datetime, Value>{using type = offset_datetime ;};
template<typename Value> struct enum_to_type<value_t::local_datetime , Value>{using type = local_datetime ;};
template<typename Value> struct enum_to_type<value_t::local_date , Value>{using type = local_date ;};
template<typename Value> struct enum_to_type<value_t::local_time , Value>{using type = local_time ;};
template<typename Value> struct enum_to_type<value_t::array , Value>{using type = typename Value::array_type;};
template<typename Value> struct enum_to_type<value_t::table , Value>{using type = typename Value::table_type;};
template<value_t t> struct toml_default_type; // meta-function that converts from an exact toml type to the enum that corresponds to.
template<> struct toml_default_type<value_t::Boolean > {typedef boolean type;}; template<typename T, typename Value>
template<> struct toml_default_type<value_t::Integer > {typedef integer type;}; struct type_to_enum : std::conditional<
template<> struct toml_default_type<value_t::Float > {typedef floating type;}; std::is_same<T, typename Value::array_type>::value, // if T == array_type,
template<> struct toml_default_type<value_t::String > {typedef string type;}; value_t_constant<value_t::array>, // then value_t::array
template<> struct toml_default_type<value_t::OffsetDatetime>{typedef offset_datetime type;}; typename std::conditional< // else...
template<> struct toml_default_type<value_t::LocalDatetime> {typedef local_datetime type;}; std::is_same<T, typename Value::table_type>::value, // if T == table_type
template<> struct toml_default_type<value_t::LocalDate> {typedef local_date type;}; value_t_constant<value_t::table>, // then value_t::table
template<> struct toml_default_type<value_t::LocalTime> {typedef local_time type;}; value_t_constant<value_t::empty> // else value_t::empty
template<> struct toml_default_type<value_t::Array > {typedef array type;}; >::type
template<> struct toml_default_type<value_t::Table > {typedef table type;}; >::type {};
template<> struct toml_default_type<value_t::Empty > {typedef void type;}; template<typename Value> struct type_to_enum<boolean , Value>: value_t_constant<value_t::boolean > {};
template<> struct toml_default_type<value_t::Unknown > {typedef void type;}; template<typename Value> struct type_to_enum<integer , Value>: value_t_constant<value_t::integer > {};
template<typename Value> struct type_to_enum<floating , Value>: value_t_constant<value_t::floating > {};
template<typename Value> struct type_to_enum<string , Value>: value_t_constant<value_t::string > {};
template<typename Value> struct type_to_enum<offset_datetime, Value>: value_t_constant<value_t::offset_datetime> {};
template<typename Value> struct type_to_enum<local_datetime , Value>: value_t_constant<value_t::local_datetime > {};
template<typename Value> struct type_to_enum<local_date , Value>: value_t_constant<value_t::local_date > {};
template<typename Value> struct type_to_enum<local_time , Value>: value_t_constant<value_t::local_time > {};
template<typename T> struct toml_value_t {static constexpr value_t value = value_t::Unknown ;}; // meta-function that checks the type T is the same as one of the toml::* types.
template<> struct toml_value_t<boolean >{static constexpr value_t value = value_t::Boolean ;}; template<typename T, typename Value>
template<> struct toml_value_t<integer >{static constexpr value_t value = value_t::Integer ;};
template<> struct toml_value_t<floating >{static constexpr value_t value = value_t::Float ;};
template<> struct toml_value_t<string >{static constexpr value_t value = value_t::String ;};
template<> struct toml_value_t<offset_datetime>{static constexpr value_t value = value_t::OffsetDatetime;};
template<> struct toml_value_t<local_datetime >{static constexpr value_t value = value_t::LocalDatetime ;};
template<> struct toml_value_t<local_date >{static constexpr value_t value = value_t::LocalDate ;};
template<> struct toml_value_t<local_time >{static constexpr value_t value = value_t::LocalTime ;};
template<> struct toml_value_t<array >{static constexpr value_t value = value_t::Array ;};
template<> struct toml_value_t<table >{static constexpr value_t value = value_t::Table ;};
template<typename T>
struct is_exact_toml_type : disjunction< struct is_exact_toml_type : disjunction<
std::is_same<T, boolean >, std::is_same<T, boolean >,
std::is_same<T, integer >, std::is_same<T, integer >,
@@ -148,13 +136,13 @@ struct is_exact_toml_type : disjunction<
std::is_same<T, local_datetime >, std::is_same<T, local_datetime >,
std::is_same<T, local_date >, std::is_same<T, local_date >,
std::is_same<T, local_time >, std::is_same<T, local_time >,
std::is_same<T, array >, std::is_same<T, typename Value::array_type>,
std::is_same<T, table > std::is_same<T, typename Value::table_type>
>{}; >{};
template<typename T> struct is_exact_toml_type<T&> : is_exact_toml_type<T>{}; template<typename T, typename V> struct is_exact_toml_type<T&, V> : is_exact_toml_type<T, V>{};
template<typename T> struct is_exact_toml_type<T const&> : is_exact_toml_type<T>{}; template<typename T, typename V> struct is_exact_toml_type<T const&, V> : is_exact_toml_type<T, V>{};
template<typename T> struct is_exact_toml_type<T volatile&> : is_exact_toml_type<T>{}; template<typename T, typename V> struct is_exact_toml_type<T volatile&, V> : is_exact_toml_type<T, V>{};
template<typename T> struct is_exact_toml_type<T const volatile&>: is_exact_toml_type<T>{}; template<typename T, typename V> struct is_exact_toml_type<T const volatile&, V>: is_exact_toml_type<T, V>{};
} // detail } // detail
} // toml } // toml

File diff suppressed because it is too large Load Diff