From 1c26ffe3aeb8b5c99114c0b8b9c023f8005f2804 Mon Sep 17 00:00:00 2001 From: ToruNiina Date: Fri, 12 May 2017 20:49:47 +0900 Subject: [PATCH] add parse() function --- tests/test_parse_file.cpp | 107 ++++++++++++++++++++++++++++++++++++++ toml/parser.hpp | 40 ++++++++++++-- 2 files changed, 142 insertions(+), 5 deletions(-) create mode 100644 tests/test_parse_file.cpp diff --git a/tests/test_parse_file.cpp b/tests/test_parse_file.cpp new file mode 100644 index 0000000..b3b1bbc --- /dev/null +++ b/tests/test_parse_file.cpp @@ -0,0 +1,107 @@ +#define BOOST_TEST_MODULE "test_parse_file" +#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST +#include +#else +#define BOOST_TEST_NO_LIB +#include +#endif +#include +#include +#include + + +BOOST_AUTO_TEST_CASE(test_example) +{ + const auto data = toml::parse("toml/tests/example.toml"); + + BOOST_CHECK_EQUAL(toml::get(data.at("title")), "TOML Example"); + toml::Table owner = toml::get(data.at("owner")); + { + BOOST_CHECK_EQUAL(toml::get(owner.at("name")), "Tom Preston-Werner"); + BOOST_CHECK_EQUAL(toml::get(owner.at("organization")), "GitHub"); + BOOST_CHECK_EQUAL(toml::get(owner.at("bio")), + "GitHub Cofounder & CEO\nLikes tater tots and beer."); + BOOST_CHECK_EQUAL(toml::get(owner.at("dob")), + toml::Datetime(1979, 5, 27, 7, 32, 0, 0, 0, 0, 0)); + } + + toml::Table database = toml::get(data.at("database")); + { + BOOST_CHECK_EQUAL(toml::get(database.at("server")), "192.168.1.1"); + const std::vector expected_ports{8001, 8001, 8002}; + BOOST_CHECK(toml::get>(database.at("ports")) == expected_ports); + BOOST_CHECK_EQUAL(toml::get(database.at("connection_max")), 5000); + BOOST_CHECK_EQUAL(toml::get(database.at("enabled")), true); + } + + toml::Table servers = toml::get(data.at("servers")); + { + toml::Table alpha = toml::get(servers.at("alpha")); + BOOST_CHECK_EQUAL(toml::get(alpha.at("ip")), "10.0.0.1"); + BOOST_CHECK_EQUAL(toml::get(alpha.at("dc")), "eqdc10"); + + toml::Table beta = toml::get(servers.at("beta")); + BOOST_CHECK_EQUAL(toml::get(beta.at("ip")), "10.0.0.2"); + BOOST_CHECK_EQUAL(toml::get(beta.at("dc")), "eqdc10"); + BOOST_CHECK_EQUAL(toml::get(beta.at("country")), "中国"); + } + + toml::Table clients = toml::get(data.at("clients")); + { + toml::Array clients_data = toml::get(clients.at("data")); + std::vector expected_name{"gamma", "delta"}; + BOOST_CHECK(toml::get>(clients_data.at(0)) == + expected_name); + std::vector expected_number{1, 2}; + BOOST_CHECK(toml::get>(clients_data.at(1)) == + expected_number); + std::vector expected_hosts{"alpha", "omega"}; + BOOST_CHECK(toml::get>(clients.at("hosts")) == + expected_hosts); + } + + std::vector products = + toml::get>(data.at("products")); + { + BOOST_CHECK_EQUAL(toml::get(products.at(0).at("name")), + "Hammer"); + BOOST_CHECK_EQUAL(toml::get(products.at(0).at("sku")), + 738594937); + + BOOST_CHECK_EQUAL(toml::get(products.at(1).at("name")), + "Nail"); + BOOST_CHECK_EQUAL(toml::get(products.at(1).at("sku")), + 284758393); + BOOST_CHECK_EQUAL(toml::get(products.at(1).at("color")), + "gray"); + } +} + +BOOST_AUTO_TEST_CASE(test_fruit) +{ + const auto data = toml::parse("toml/tests/fruit.toml"); + const auto blah = toml::get>( + toml::get(data.at("fruit")).at("blah")); + BOOST_CHECK_EQUAL(toml::get(blah.at(0).at("name")), "apple"); + BOOST_CHECK_EQUAL(toml::get(blah.at(1).at("name")), "banana"); + { + const auto physical = toml::get(blah.at(0).at("physical")); + BOOST_CHECK_EQUAL(toml::get(physical.at("color")), "red"); + BOOST_CHECK_EQUAL(toml::get(physical.at("shape")), "round"); + } + { + const auto physical = toml::get(blah.at(1).at("physical")); + BOOST_CHECK_EQUAL(toml::get(physical.at("color")), "yellow"); + BOOST_CHECK_EQUAL(toml::get(physical.at("shape")), "bent"); + } +} + +// BOOST_AUTO_TEST_CASE(test_hard_example) +// { +// +// } +// +// BOOST_AUTO_TEST_CASE(test_hard_example_unicode) +// { +// ; +// } diff --git a/toml/parser.hpp b/toml/parser.hpp index cb0e919..3422264 100644 --- a/toml/parser.hpp +++ b/toml/parser.hpp @@ -4,6 +4,7 @@ #include "acceptor.hpp" #include #include +#include namespace toml { @@ -329,7 +330,15 @@ struct parse_float string_type result; result.resize(std::distance(iter, end)); std::copy_if(iter, end, result.begin(), [](value_type c){return c != '_';}); - return std::make_pair(std::stod(result), end); + try{ + return std::make_pair(std::stod(result), end); + } + catch(std::out_of_range& oor) + { + std::cout << "extremely large Float value appeared: " + << result << "; it is negrected" << std::endl; + return std::make_pair(0, end); + } } }; @@ -929,7 +938,7 @@ struct parse_data if(iter == std::prev(end)) { if(data.count(*iter) == 1) - throw syntax_error("duplicate key"); + throw syntax_error("duplicate key: " + *iter); data.emplace(*iter, std::move(v)); return; } @@ -937,7 +946,7 @@ struct parse_data if(data.count(*iter) == 0) data.emplace(*iter, toml::Table()); else if(data[*iter].type() != value_t::Table) - throw syntax_error("duplicate key"); + throw syntax_error("duplicate key: " + *iter); return push_table(data[*iter].template cast(), std::move(v), std::next(iter), end); @@ -955,7 +964,7 @@ struct parse_data if(data.count(*iter) == 0) data.emplace(*iter, toml::Array()); else if(data.at(*iter).type() != value_t::Array) - throw syntax_error("duplicate key"); + throw syntax_error("duplicate key: " + *iter); data[*iter].template cast().emplace_back(std::move(v)); return; @@ -964,7 +973,7 @@ struct parse_data if(data.count(*iter) == 0) data.emplace(*iter, toml::Table()); else if(data[*iter].type() != value_t::Table) - throw syntax_error("duplicate key"); + throw syntax_error("duplicate key: " + *iter); return push_array_of_table(data[*iter].template cast(), std::move(v), std::next(iter), end); @@ -972,5 +981,26 @@ struct parse_data }; +template> +toml::Table parse(std::basic_istream& is) +{ + const auto initial = is.tellg(); + is.seekg(0, std::ios::end); + const auto eofpos = is.tellg(); + const std::size_t size = eofpos - initial; + is.seekg(initial); + std::vector contents(size); + is.read(contents.data(), size); + return parse_data::invoke(contents.cbegin(), contents.cend()); +} + +toml::Table parse(const std::string& filename) +{ + std::ifstream ifs(filename); + if(!ifs.good()) throw std::runtime_error("file open error: " + filename); + return parse(ifs); +} + + }// toml #endif// TOML11_PARSER