diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 51ca609..e2056a1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,6 +1,7 @@ set(TEST_NAMES test_traits test_utility + test_result test_value test_to_toml test_from_toml diff --git a/tests/test_parser.cpp b/tests/test_parser.cpp index 3a04c13..32ca96f 100644 --- a/tests/test_parser.cpp +++ b/tests/test_parser.cpp @@ -19,22 +19,22 @@ BOOST_AUTO_TEST_CASE(test_parse_basic_inline_string) const std::string source("\"simple\""); const std::string expected("simple"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("\"I'm a string. \\\"You can quote me\\\". Name\\tJos\\u00E9\\nLocation\\tSF.\""); const std::string expected("I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF."); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("dummy"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(!result.first.is_ok()); BOOST_CHECK(result.second == source.begin()); } } @@ -48,30 +48,30 @@ BOOST_AUTO_TEST_CASE(test_parse_basic_multiline_string) const std::string source("\"\"\"\nRoses are red\nViolets are blue\"\"\""); const std::string expected("Roses are red\nViolets are blue"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("\"\"\"\nThe quick brown \\\n\n fox jumps over \\\n the lazy dog.\"\"\""); const std::string expected("The quick brown fox jumps over the lazy dog."); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("\"\"\"\nThe quick brown \\\n fox jumps over \\\n the lazy dog.\\\n \"\"\""); const std::string expected("The quick brown fox jumps over the lazy dog."); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("dummy"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(!result.first.is_ok()); BOOST_CHECK(result.second == source.begin()); } } @@ -84,38 +84,38 @@ BOOST_AUTO_TEST_CASE(test_parse_literal_inline_string) const std::string source("'C:\\Users\\nodejs\\templates'"); const std::string expected("C:\\Users\\nodejs\\templates"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("'\\\\ServerX\\admin$\\system32\\'"); const std::string expected("\\\\ServerX\\admin$\\system32\\"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("'Tom \"Dubs\" Preston-Werner'"); const std::string expected("Tom \"Dubs\" Preston-Werner"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("'<\\i\\c*\\s*>'"); const std::string expected("<\\i\\c*\\s*>"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("dummy"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(!result.first.is_ok()); BOOST_CHECK(result.second == source.begin()); } } @@ -128,22 +128,22 @@ BOOST_AUTO_TEST_CASE(test_parse_literal_multiline_string) const std::string source("'''I [dw]on't need \\d{2} apples'''"); const std::string expected("I [dw]on't need \\d{2} apples"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("'''\nThe first newline is \ntrimmed in raw strings.\n All other whitespace\n is preserved.'''"); const std::string expected("The first newline is \ntrimmed in raw strings.\n All other whitespace\n is preserved."); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("dummy"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(!result.first.is_ok()); BOOST_CHECK(result.second == source.begin()); } } @@ -156,38 +156,38 @@ BOOST_AUTO_TEST_CASE(test_parse_string) const std::string source("\"string\""); const std::string expected("string"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("\"\"\"string\"\"\""); const std::string expected("string"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("'string'"); const std::string expected("string"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("'''string'''"); const std::string expected("string"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("dummy"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(!result.first.is_ok()); BOOST_CHECK(result.second == source.begin()); } } @@ -200,38 +200,38 @@ BOOST_AUTO_TEST_CASE(test_integer) const std::string source("42"); const toml::Integer expected(42); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("+42"); const toml::Integer expected(42); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("-42"); const toml::Integer expected(-42); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("-4_2"); const toml::Integer expected(-42); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("dummy"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(!result.first.is_ok()); BOOST_CHECK(result.second == source.begin()); } } @@ -244,60 +244,60 @@ BOOST_AUTO_TEST_CASE(test_float) const std::string source("42.0"); const toml::Float expected(42.0); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("+42.0"); const toml::Float expected(42.0); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("-42.0"); const toml::Float expected(-42.0); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("-4_2.0"); const toml::Float expected(-42.0); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("-42e0"); const toml::Float expected(-42.0); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("-42.0e0"); const toml::Float expected(-42.0); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("dummy"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(!result.first.is_ok()); BOOST_CHECK(result.second == source.begin()); } { const std::string source("42"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(!result.first.is_ok()); BOOST_CHECK(result.second == source.begin()); } } @@ -310,22 +310,22 @@ BOOST_AUTO_TEST_CASE(test_parse_boolean) const std::string source("true"); const toml::Boolean expected(true); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("false"); const toml::Boolean expected(false); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("dummy"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(!result.first.is_ok()); BOOST_CHECK(result.second == source.begin()); } } @@ -340,30 +340,30 @@ BOOST_AUTO_TEST_CASE(test_parse_local_time) const std::string source("12:34:56"); const toml::Datetime expected(12, 34, 56, 0, 0); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("12:34:56.7"); const toml::Datetime expected(12, 34, 56, 700, 0); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("12:34:56.7891"); const toml::Datetime expected(12, 34, 56, 789, 100); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("10"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(!result.first.is_ok()); BOOST_CHECK(result.second == source.begin()); } } @@ -376,14 +376,14 @@ BOOST_AUTO_TEST_CASE(test_parse_local_date) const std::string source("1979-09-27"); const toml::Datetime expected(1979, 9, 27); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("10"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(!result.first.is_ok()); BOOST_CHECK(result.second == source.begin()); } } @@ -396,22 +396,22 @@ BOOST_AUTO_TEST_CASE(test_parse_local_date_time) const std::string source("1979-09-27T12:34:56"); const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("1979-09-27T12:34:56.789000"); const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 789, 0); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("1000-11-11"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(!result.first.is_ok()); BOOST_CHECK(result.second == source.begin()); } } @@ -424,16 +424,16 @@ BOOST_AUTO_TEST_CASE(test_parse_offset_date_time) const std::string source("1979-09-27T12:34:56Z"); const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0, 0, 0); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("1979-09-27T12:34:56.789000Z"); const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 789, 0, 0, 0); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } @@ -441,16 +441,16 @@ BOOST_AUTO_TEST_CASE(test_parse_offset_date_time) const std::string source("1979-09-27T12:34:56+07:30"); const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0, 7, 30); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("1979-09-27T12:34:56.789000+07:30"); const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 789, 0, 7, 30); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } @@ -458,22 +458,22 @@ BOOST_AUTO_TEST_CASE(test_parse_offset_date_time) const std::string source("1979-09-27T12:34:56-07:30"); const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0, -7, -30); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("1979-09-27T12:34:56.789000-07:30"); const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 789, 0, -7, -30); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("1000-11-11"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(!result.first.is_ok()); BOOST_CHECK(result.second == source.begin()); } } @@ -486,38 +486,38 @@ BOOST_AUTO_TEST_CASE(test_parse_datetime) const std::string source("1979-09-27T12:34:56Z"); const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0, 0, 0); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("1979-09-27T12:34:56"); const toml::Datetime expected(1979, 9, 27, 12, 34, 56, 0, 0); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("1979-09-27"); const toml::Datetime expected(1979, 9, 27); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("12:34:56"); const toml::Datetime expected(12, 34, 56, 0, 0); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK_EQUAL(result.first.get(), expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK_EQUAL(result.first.unwrap(), expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("12"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(!result.first.is_ok()); BOOST_CHECK(result.second == source.begin()); } } @@ -531,56 +531,56 @@ BOOST_AUTO_TEST_CASE(test_parse_array) const std::string source("[1,2,3]"); const toml::Array expected{1, 2, 3}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("[1, 2, 3]"); const toml::Array expected{1, 2, 3}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("[ 1,2,3 ]"); const toml::Array expected{1, 2, 3}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("[ 1 , 2 , 3 ]"); const toml::Array expected{1, 2, 3}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("[ 1 \n,#comment\n 2 ,\n 3\n ]"); const toml::Array expected{1, 2, 3}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("[ # empty array\n ]"); const toml::Array expected{}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("[ \"] \", ' # ', \n']', # ] \n]"); const toml::Array expected{"] ", " # ", "]"}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } @@ -588,8 +588,8 @@ BOOST_AUTO_TEST_CASE(test_parse_array) const std::string source("[ \"Test #11 ]proved that\", 'Experiment #9 was a success' ]"); const toml::Array expected{"Test #11 ]proved that", "Experiment #9 was a success"}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } @@ -597,8 +597,8 @@ BOOST_AUTO_TEST_CASE(test_parse_array) const std::string source("[ \"Test #11 ]proved that\", 'Experiment #9 was a success' ]"); const toml::Array expected{"Test #11 ]proved that", "Experiment #9 was a success"}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } @@ -606,8 +606,8 @@ BOOST_AUTO_TEST_CASE(test_parse_array) const std::string source("[ [1,2,3] , ['a', 'b', 'c'] ]"); const toml::Array expected{{1,2,3}, {"a", "b", "c"}}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } @@ -615,14 +615,14 @@ BOOST_AUTO_TEST_CASE(test_parse_array) const std::string source("[ {foo=1}, {foo=1, bar=2.0}, {foo=1, bar=2.0, baz='str'} ]"); const toml::Array expected{{{"foo", 1}}, {{"foo", 1}, {"bar", 2.0}}, {{"foo", 1}, {"bar", 2.0}, {"baz", "str"}}}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("[dummy]"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(!result.first.is_ok()); BOOST_CHECK(result.second == source.begin()); } } @@ -636,24 +636,24 @@ BOOST_AUTO_TEST_CASE(test_parse_inline_table) const std::string source("{foo=1,bar=2.0,baz='str'}"); const toml::Table expected{{"foo", 1}, {"bar", 2.0}, {"baz", "str"}}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("{ foo=1, bar=2.0, baz='str' }"); const toml::Table expected{{"foo", 1}, {"bar", 2.0}, {"baz", "str"}}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("{ foo = 1, bar = 2.0, baz = 'str' }"); const toml::Table expected{{"foo", 1}, {"bar", 2.0}, {"baz", "str"}}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } @@ -664,14 +664,14 @@ BOOST_AUTO_TEST_CASE(test_parse_inline_table) {"s", "str"}, {"a", {1, 2, 3}}, {"t", {{"foo", 1}}}}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("{dummy}"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(!result.first.ok()); + BOOST_CHECK(!result.first.is_ok()); BOOST_CHECK(result.second == source.begin()); } } @@ -684,32 +684,32 @@ BOOST_AUTO_TEST_CASE(test_parse_barekey) const std::string source("hoge"); const toml::key expected("hoge"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("bare-key"); const toml::key expected("bare-key"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("bare_key"); const toml::key expected("bare_key"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("42"); const toml::key expected("42"); const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } } @@ -724,64 +724,64 @@ BOOST_AUTO_TEST_CASE(test_key_value_pair) const std::string source("key=1"); const std::pair expected{"key", 1}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("key =\t1"); const std::pair expected{"key", 1}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("key = true"); const std::pair expected{"key", true}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("key = -42"); const std::pair expected{"key", -42}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("key = -42.0"); const std::pair expected{"key", -42.}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("key = \"string\""); const std::pair expected{"key", "string"}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("key = 1901-01-01T00:00:00"); const std::pair expected{"key", toml::Datetime(1901, 1,1,0,0,0,0,0)}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("key = [1,2,3]"); const std::pair expected{"key", {1,2,3}}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { @@ -789,8 +789,8 @@ BOOST_AUTO_TEST_CASE(test_key_value_pair) const std::pair expected{"key", {{"foo", 1}, {"bar", 2.0}, {"baz", "3"}}}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } } @@ -803,40 +803,40 @@ BOOST_AUTO_TEST_CASE(test_table_definition) const std::string source("[foo]"); const std::vector expected{"foo"}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("[foo.bar.baz]"); const std::vector expected{"foo", "bar", "baz"}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("[foo . bar. baz]"); const std::vector expected{"foo", "bar", "baz"}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("[foo . \"bar\" . baz]"); const std::vector expected{"foo", "bar", "baz"}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("[foo . \"b\\tar\" . baz]"); const std::vector expected{"foo", "b\tar", "baz"}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } } @@ -849,40 +849,40 @@ BOOST_AUTO_TEST_CASE(test_array_of_table_definition) const std::string source("[[foo]]"); const std::vector expected{"foo"}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("[[foo.bar.baz]]"); const std::vector expected{"foo", "bar", "baz"}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("[[foo . bar. baz]]"); const std::vector expected{"foo", "bar", "baz"}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("[[foo . \"bar\" . baz]]"); const std::vector expected{"foo", "bar", "baz"}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } { const std::string source("[[foo . \"b\\tar\" . baz]]"); const std::vector expected{"foo", "b\tar", "baz"}; const auto result = parser::invoke(source.cbegin(), source.cend()); - BOOST_CHECK(result.first.ok()); - BOOST_CHECK(result.first.get() == expected); + BOOST_CHECK(result.first.is_ok()); + BOOST_CHECK(result.first.unwrap() == expected); BOOST_CHECK(result.second == acceptor::invoke(source.begin(), source.end())); } } diff --git a/tests/test_result.cpp b/tests/test_result.cpp new file mode 100644 index 0000000..fcc0ddd --- /dev/null +++ b/tests/test_result.cpp @@ -0,0 +1,111 @@ +#define BOOST_TEST_MODULE "test_result" +#include +#include +#include + +BOOST_AUTO_TEST_CASE(test_construct) +{ + { + auto s = toml::ok(42); + toml::result result(s); + BOOST_TEST(!!result); + BOOST_TEST(result.is_ok()); + BOOST_TEST(!result.is_err()); + BOOST_TEST(result.unwrap() == 42); + } + { + const auto s = toml::ok(42); + toml::result result(s); + BOOST_TEST(!!result); + BOOST_TEST(result.is_ok()); + BOOST_TEST(!result.is_err()); + BOOST_TEST(result.unwrap() == 42); + } + { + toml::result result(toml::ok(42)); + BOOST_TEST(!!result); + BOOST_TEST(result.is_ok()); + BOOST_TEST(!result.is_err()); + BOOST_TEST(result.unwrap() == 42); + } + + { + auto f = toml::err("foobar"); + toml::result result(f); + BOOST_TEST(!result); + BOOST_TEST(!result.is_ok()); + BOOST_TEST(result.is_err()); + BOOST_TEST(result.unwrap_err() == "foobar"); + } + { + const auto f = toml::err("foobar"); + toml::result result(f); + BOOST_TEST(!result); + BOOST_TEST(!result.is_ok()); + BOOST_TEST(result.is_err()); + BOOST_TEST(result.unwrap_err() == "foobar"); + } + { + toml::result result(toml::err("foobar")); + BOOST_TEST(!result); + BOOST_TEST(!result.is_ok()); + BOOST_TEST(result.is_err()); + BOOST_TEST(result.unwrap_err() == "foobar"); + } +} + +BOOST_AUTO_TEST_CASE(test_assignment) +{ + { + toml::result result(toml::err("foobar")); + result = toml::ok(42); + BOOST_TEST(!!result); + BOOST_TEST(result.is_ok()); + BOOST_TEST(!result.is_err()); + BOOST_TEST(result.unwrap() == 42); + } + { + toml::result result(toml::err("foobar")); + auto s = toml::ok(42); + result = s; + BOOST_TEST(!!result); + BOOST_TEST(result.is_ok()); + BOOST_TEST(!result.is_err()); + BOOST_TEST(result.unwrap() == 42); + } + { + toml::result result(toml::err("foobar")); + const auto s = toml::ok(42); + result = s; + BOOST_TEST(!!result); + BOOST_TEST(result.is_ok()); + BOOST_TEST(!result.is_err()); + BOOST_TEST(result.unwrap() == 42); + } + { + toml::result result(toml::err("foobar")); + result = toml::err("hoge"); + BOOST_TEST(!result); + BOOST_TEST(!result.is_ok()); + BOOST_TEST(result.is_err()); + BOOST_TEST(result.unwrap_err() == "hoge"); + } + { + toml::result result(toml::err("foobar")); + auto f = toml::err("hoge"); + result = f; + BOOST_TEST(!result); + BOOST_TEST(!result.is_ok()); + BOOST_TEST(result.is_err()); + BOOST_TEST(result.unwrap_err() == "hoge"); + } + { + toml::result result(toml::err("foobar")); + const auto f = toml::err("hoge"); + result = f; + BOOST_TEST(!result); + BOOST_TEST(!result.is_ok()); + BOOST_TEST(result.is_err()); + BOOST_TEST(result.unwrap_err() == "hoge"); + } +} diff --git a/toml/parser.hpp b/toml/parser.hpp index f470330..478078a 100644 --- a/toml/parser.hpp +++ b/toml/parser.hpp @@ -2,6 +2,7 @@ #define TOML11_PARSER #include "value.hpp" #include "acceptor.hpp" +#include "result.hpp" #include #include #include @@ -11,54 +12,11 @@ namespace toml { -namespace detail -{ - -// it is just an inferior vertion of boost/std::optional -template -struct result -{ - result() : ok_(false){} - ~result() = default; - result(const result& rhs) = default; - result(result&& rhs) = default; - result& operator=(const result& rhs) = default; - result& operator=(result&& rhs) = default; - - result(const T& v) : ok_(true), value_(v){} - result(T&& v) : ok_(true), value_(std::move(v)){} - result& operator=(const T& rhs){ok_ = true; value_ = rhs; return *this;} - result& operator=(T&& rhs) {ok_ = true; value_ = rhs; return *this;} - - template - result& operator=(const result& u) {ok_ = u.ok(); if(ok_)value_ = u.move(); return *this;} - template - result& operator=(result&& u) {ok_ = u.ok(); if(ok_)value_ = u.move(); return *this;} - template - result(const result& u): ok_(u.ok()){if(ok_)value_ = u.get();} - template - result(result&& u): ok_(u.ok()){if(ok_)value_ = u.move();} - - bool ok() const {return ok_;} - operator bool() const {return ok_;} - - T& get() {if(!ok_) throw std::logic_error("result::get"); return value_;} - T const& get() const {if(!ok_) throw std::logic_error("result::get"); return value_;} - T&& move() - {if(!ok_) throw std::logic_error("result::move"); ok_ = false; return std::move(value_);} - - private: - bool ok_; - T value_; -}; - -}//detail - struct parse_escape_sequence { typedef toml::character value_type; typedef toml::String string_type; - typedef detail::result result_type; + typedef result result_type; template::value_type, @@ -67,32 +25,34 @@ struct parse_escape_sequence { const auto beg = iter; if(iter == end || *iter != '\\') - return std::make_pair(result_type{}, iter); + return std::make_pair(err("not an escape sequence"), iter); ++iter; switch(*iter) { - case '\\': return std::make_pair(string_type("\\"), std::next(iter)); - case '"' : return std::make_pair(string_type("\""), std::next(iter)); - case 'b' : return std::make_pair(string_type("\b"), std::next(iter)); - case 't' : return std::make_pair(string_type("\t"), std::next(iter)); - case 'n' : return std::make_pair(string_type("\n"), std::next(iter)); - case 'f' : return std::make_pair(string_type("\f"), std::next(iter)); - case 'r' : return std::make_pair(string_type("\r"), std::next(iter)); + case '\\': return std::make_pair(ok(string_type("\\")), std::next(iter)); + case '"' : return std::make_pair(ok(string_type("\"")), std::next(iter)); + case 'b' : return std::make_pair(ok(string_type("\b")), std::next(iter)); + case 't' : return std::make_pair(ok(string_type("\t")), std::next(iter)); + case 'n' : return std::make_pair(ok(string_type("\n")), std::next(iter)); + case 'f' : return std::make_pair(ok(string_type("\f")), std::next(iter)); + case 'r' : return std::make_pair(ok(string_type("\r")), std::next(iter)); case 'u' : { if(std::distance(iter, end) < 5) throw std::make_pair(iter, syntax_error( "invalid escape sequence: " + std::string(beg, end))); - return std::make_pair(utf8_to_char(make_codepoint( - string_type(iter+1, iter+5))), iter+5); + return std::make_pair(ok( + utf8_to_char(make_codepoint(string_type(iter+1, iter+5)))), + iter+5); } case 'U': { if(std::distance(iter, end) < 8) throw std::make_pair(iter, syntax_error( "invalid escape sequence: " + std::string(beg, end))); - return std::make_pair(utf8_to_char(make_codepoint( - string_type(iter+1, iter+9))), iter+9); + return std::make_pair(ok( + utf8_to_char(make_codepoint(string_type(iter+1, iter+9)))), + iter+9); } default: throw std::make_pair(iter, syntax_error( "unkwnon escape sequence: " + std::string(iter, end))); @@ -139,7 +99,7 @@ struct parse_escape_sequence struct parse_basic_inline_string { typedef toml::character value_type; - typedef detail::result result_type; + typedef result result_type; template::value_type, @@ -149,7 +109,7 @@ struct parse_basic_inline_string { const Iterator end = is_basic_inline_string::invoke(iter, range_end); - if(iter == end) return std::make_pair(result_type{}, iter); + if(iter == end) return std::make_pair(err("input is empty"), iter); if(std::distance(iter, end) < 2) throw internal_error("is_basic_inline_string"); @@ -161,9 +121,9 @@ struct parse_basic_inline_string if(*iter == '\\') { auto r = parse_escape_sequence::invoke(iter, last); - if(!r.first.ok()) + if(!r.first.is_ok()) throw internal_error("parse_basic_inline_string"); - result += r.first.move(); + result += r.first.unwrap(); iter = r.second; } else @@ -172,7 +132,7 @@ struct parse_basic_inline_string ++iter; } } - return std::make_pair(result, end); + return std::make_pair(ok(result), end); } }; @@ -180,7 +140,7 @@ struct parse_basic_multiline_string { typedef toml::character value_type; typedef toml::String string_type; - typedef detail::result result_type; + typedef result result_type; typedef is_chain_of, is_newline> is_line_ending_backslash; @@ -195,7 +155,7 @@ struct parse_basic_multiline_string { const Iterator end = is_basic_multiline_string::invoke(iter, range_end); - if(iter == end) return std::make_pair(result_type{}, iter); + if(iter == end) return std::make_pair(err("input is empty"), iter); if(std::distance(iter, end) < 6) throw internal_error("is_basic_inline_string"); @@ -214,9 +174,9 @@ struct parse_basic_multiline_string else { auto r = parse_escape_sequence::invoke(iter, last); - if(!r.first.ok()) + if(!r.first.is_ok()) throw internal_error("parse_basic_inline_string"); - result += r.first.move(); + result += r.first.unwrap(); iter = r.second; } } @@ -226,14 +186,14 @@ struct parse_basic_multiline_string ++iter; } } - return std::make_pair(result, end); + return std::make_pair(ok(result), end); } }; struct parse_literal_inline_string { typedef toml::character value_type; - typedef detail::result result_type; + typedef result result_type; template::value_type, @@ -243,7 +203,7 @@ struct parse_literal_inline_string { const Iterator end = is_literal_inline_string::invoke(iter, range_end); - if(iter == end) return std::make_pair(result_type{}, iter); + if(iter == end) return std::make_pair(err("input is empty"), iter); if(std::distance(iter, end) < 2) throw internal_error("is_literal_inline_string"); @@ -255,14 +215,14 @@ struct parse_literal_inline_string result.push_back(*iter); ++iter; } - return std::make_pair(result, end); + return std::make_pair(ok(result), end); } }; struct parse_literal_multiline_string { typedef toml::character value_type; - typedef detail::result result_type; + typedef result result_type; typedef is_chain_of, is_newline> is_line_ending_backslash; @@ -277,7 +237,7 @@ struct parse_literal_multiline_string { const Iterator end = is_literal_multiline_string::invoke(iter, range_end); - if(iter == end) return std::make_pair(result_type{}, iter); + if(iter == end) return std::make_pair(err("input is empty"), iter); if(std::distance(iter, end) < 6) throw internal_error("is_literal_multiline_string"); @@ -290,14 +250,14 @@ struct parse_literal_multiline_string result.push_back(*iter); ++iter; } - return std::make_pair(result, end); + return std::make_pair(ok(result), end); } }; struct parse_string { typedef toml::character value_type; - typedef detail::result result_type; + typedef result result_type; template::value_type, @@ -305,17 +265,17 @@ struct parse_string static std::pair invoke(Iterator iter, Iterator range_end) { - std::pair result; - if((result = parse_basic_inline_string::invoke(iter, range_end)).first.ok()) + std::pair result(err(""), Iterator()); + if((result = parse_basic_inline_string::invoke(iter, range_end)).first.is_ok()) return result; - else if((result = parse_basic_multiline_string::invoke(iter, range_end)).first.ok()) + else if((result = parse_basic_multiline_string::invoke(iter, range_end)).first.is_ok()) return result; - else if((result = parse_literal_inline_string::invoke(iter, range_end)).first.ok()) + else if((result = parse_literal_inline_string::invoke(iter, range_end)).first.is_ok()) return result; - else if((result = parse_literal_multiline_string::invoke(iter, range_end)).first.ok()) + else if((result = parse_literal_multiline_string::invoke(iter, range_end)).first.is_ok()) return result; else - return std::make_pair(result_type{}, iter); + return std::make_pair(err("does not match anything"), iter); } }; @@ -323,7 +283,7 @@ struct parse_integer { typedef toml::character value_type; typedef std::basic_string string_type; - typedef detail::result result_type; + typedef result result_type; template::value_type, @@ -331,11 +291,11 @@ struct parse_integer static std::pair invoke(Iterator iter, Iterator range_end) { const Iterator end = is_integer::invoke(iter, range_end); - if(iter == end) return std::make_pair(result_type{}, iter); + if(iter == end) return std::make_pair(err("input is empty"), iter); 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::stoll(result), end); + return std::make_pair(ok(std::stoll(result)), end); } }; @@ -343,7 +303,7 @@ struct parse_float { typedef toml::character value_type; typedef std::basic_string string_type; - typedef detail::result result_type; + typedef result result_type; template::value_type, @@ -352,18 +312,18 @@ struct parse_float invoke(Iterator iter, Iterator range_end) { const Iterator end = is_float::invoke(iter, range_end); - if(iter == end) return std::make_pair(result_type{}, iter); + if(iter == end) return std::make_pair(err("input is empty"), iter); string_type result; result.resize(std::distance(iter, end)); std::copy_if(iter, end, result.begin(), [](value_type c){return c != '_';}); try{ - return std::make_pair(std::stod(result), end); + return std::make_pair(ok(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); + return std::make_pair(ok(0.0), end); } } }; @@ -371,7 +331,7 @@ struct parse_float struct parse_boolean { typedef toml::character value_type; - typedef detail::result result_type; + typedef result result_type; template::value_type, @@ -380,8 +340,8 @@ struct parse_boolean invoke(Iterator iter, Iterator range_end) { const Iterator end = is_boolean::invoke(iter, range_end); - if(iter == end) return std::make_pair(result_type{}, iter); - return std::make_pair((std::distance(iter, end) == 4), end); + if(iter == end) return std::make_pair(err("input is empty"), iter); + return std::make_pair(ok(std::distance(iter, end) == 4), end); } }; @@ -389,7 +349,7 @@ struct parse_local_time { typedef toml::character value_type; typedef std::basic_string string_type; - typedef detail::result result_type; + typedef result result_type; typedef typename toml::Datetime::number_type number_type; template using nums = is_repeat_of, N>; @@ -403,7 +363,7 @@ struct parse_local_time invoke(Iterator iter, Iterator range_end) { const Iterator end = is_local_time::invoke(iter, range_end); - if(iter == end) return std::make_pair(result_type{}, iter); + if(iter == end) return std::make_pair(err("input is empty"), iter); toml::Datetime result; result.hour = std::stoi(string_type(iter, nums<2>::invoke(iter, end))); @@ -432,7 +392,7 @@ struct parse_local_time result.year = toml::Datetime::undef; result.month = toml::Datetime::undef; result.day = toml::Datetime::undef; - return std::make_pair(result, end); + return std::make_pair(ok(result), end); } template string_type; - typedef detail::result result_type; + typedef result result_type; template using nums = is_repeat_of, N>; typedef is_character delim; @@ -463,7 +423,7 @@ struct parse_local_date invoke(Iterator iter, Iterator range_end) { const Iterator end = is_local_date::invoke(iter, range_end); - if(iter == end) return std::make_pair(result_type{}, iter); + if(iter == end) return std::make_pair(err("input is empty"), iter); toml::Datetime result; result.year = std::stoi(string_type(iter, nums<4>::invoke(iter, end))); @@ -479,7 +439,7 @@ struct parse_local_date result.second = toml::Datetime::undef; result.millisecond = toml::Datetime::undef; result.microsecond = toml::Datetime::undef; - return std::make_pair(result, end); + return std::make_pair(ok(result), end); } }; @@ -487,7 +447,7 @@ struct parse_local_date_time { typedef toml::character value_type; typedef std::basic_string string_type; - typedef detail::result result_type; + typedef result result_type; template using nums = is_repeat_of, N>; typedef is_character delim; @@ -500,23 +460,23 @@ struct parse_local_date_time { const Iterator end = is_local_date_time::invoke(iter, range_end); - if(iter == end) return std::make_pair(result_type{}, iter); + if(iter == end) return std::make_pair(err("input is empty"), iter); auto ld = parse_local_date::invoke(iter, end); - if(!ld.first.ok()) + if(!ld.first.is_ok()) throw std::make_pair(iter, syntax_error("invalid local datetime")); - toml::Datetime result(ld.first.move()); + toml::Datetime result(ld.first.unwrap()); iter = delim::invoke(ld.second, end);// 'T' const auto time = parse_local_time::invoke(iter, end); - result.hour = time.first.get().hour; - result.minute = time.first.get().minute; - result.second = time.first.get().second; - result.millisecond = time.first.get().millisecond; - result.microsecond = time.first.get().microsecond; + result.hour = time.first.unwrap().hour; + result.minute = time.first.unwrap().minute; + result.second = time.first.unwrap().second; + result.millisecond = time.first.unwrap().millisecond; + result.microsecond = time.first.unwrap().microsecond; result.offset_hour = toml::Datetime::nooffset; result.offset_minute = toml::Datetime::nooffset; - return std::make_pair(result, end); + return std::make_pair(ok(result), end); } }; @@ -524,7 +484,7 @@ struct parse_offset_date_time { typedef toml::character value_type; typedef std::basic_string string_type; - typedef detail::result result_type; + typedef result result_type; template using nums = is_repeat_of, N>; typedef is_character delim; @@ -537,12 +497,12 @@ struct parse_offset_date_time { const Iterator end = is_offset_date_time::invoke(iter, range_end); - if(iter == end) return std::make_pair(result_type{}, iter); + if(iter == end) return std::make_pair(err("input is empty"), iter); auto ldt = parse_local_date_time::invoke(iter, end); - if(!ldt.first.ok()) + if(!ldt.first.is_ok()) throw std::make_pair(iter, syntax_error("invalid offset datetime")); - toml::Datetime result(ldt.first.move()); + toml::Datetime result(ldt.first.unwrap()); iter = ldt.second; if(*iter == 'Z') { @@ -561,14 +521,14 @@ struct parse_offset_date_time result.offset_minute = sign * std::stoi(string_type(iter, nums<2>::invoke(iter, end))); } - return std::make_pair(result, end); + return std::make_pair(ok(result), end); } }; struct parse_datetime { typedef toml::character value_type; - typedef detail::result result_type; + typedef result result_type; template::value_type, @@ -576,17 +536,17 @@ struct parse_datetime static std::pair invoke(Iterator iter, Iterator range_end) { - std::pair result; - if((result = parse_offset_date_time::invoke(iter, range_end)).first.ok()) + std::pair result(err(""), Iterator()); + if((result = parse_offset_date_time::invoke(iter, range_end)).first.is_ok()) return result; - else if((result = parse_local_date_time::invoke(iter, range_end)).first.ok()) + else if((result = parse_local_date_time::invoke(iter, range_end)).first.is_ok()) return result; - else if((result = parse_local_date::invoke(iter, range_end)).first.ok()) + else if((result = parse_local_date::invoke(iter, range_end)).first.is_ok()) return result; - else if((result = parse_local_time::invoke(iter, range_end)).first.ok()) + else if((result = parse_local_time::invoke(iter, range_end)).first.is_ok()) return result; else - return std::make_pair(result_type{}, iter); + return std::make_pair(err("does not match anything"), iter); } }; @@ -594,7 +554,7 @@ template struct parse_fixed_type_array { typedef toml::character value_type; - typedef detail::result result_type; + typedef result result_type; typedef acceptorT acceptor_type; typedef parserT parser_type; typedef is_skippable_in_array skippable; @@ -606,7 +566,7 @@ struct parse_fixed_type_array { const Iterator end = is_fixed_type_array::invoke(iter, range_end); - if(iter == end) return std::make_pair(result_type{}, iter); + if(iter == end) return std::make_pair(err("input is empty"), iter); toml::Array result; const Iterator last = std::prev(end); @@ -617,15 +577,15 @@ struct parse_fixed_type_array if(tmp == iter) throw std::make_pair(iter, syntax_error("parse_array")); auto next = parser_type::invoke(iter, last); - if(!next.first.ok()) + if(!next.first.is_ok()) throw std::make_pair(iter, syntax_error("parse_array")); - result.emplace_back(next.first.move()); + result.emplace_back(next.first.unwrap()); iter = tmp; iter = skippable::invoke(iter, last); iter = is_character::invoke(iter, last); iter = skippable::invoke(iter, last); } - return std::make_pair(result, end); + return std::make_pair(ok(result), end); } }; @@ -637,7 +597,7 @@ struct parse_array { typedef charT value_type; static_assert(std::is_same::value, ""); - typedef detail::result result_type; + typedef result result_type; typedef is_skippable_in_array skippable; template::invoke(iter, range_end)) - return std::make_pair(result_type{}, iter); + return std::make_pair(err("input is not an array"), iter); - std::pair result; + std::pair result(err(""), Iterator()); if((result = parse_fixed_type_array, - parse_boolean>::invoke(iter, range_end)).first.ok()) return result; + parse_boolean>::invoke(iter, range_end)).first.is_ok()) return result; else if((result = parse_fixed_type_array, - parse_string>::invoke(iter, range_end)).first.ok()) return result; + parse_string>::invoke(iter, range_end)).first.is_ok()) return result; else if((result = parse_fixed_type_array, - parse_datetime>::invoke(iter, range_end)).first.ok()) return result; + parse_datetime>::invoke(iter, range_end)).first.is_ok()) return result; else if((result = parse_fixed_type_array, - parse_float>::invoke(iter, range_end)).first.ok()) return result; + parse_float>::invoke(iter, range_end)).first.is_ok()) return result; else if((result = parse_fixed_type_array, - parse_integer>::invoke(iter, range_end)).first.ok()) return result; + parse_integer>::invoke(iter, range_end)).first.is_ok()) return result; else if((result = parse_fixed_type_array, - parse_array>::invoke(iter, range_end)).first.ok()) return result; + parse_array>::invoke(iter, range_end)).first.is_ok()) return result; else if((result = parse_fixed_type_array, - parse_inline_table>::invoke(iter, range_end)).first.ok()) + parse_inline_table>::invoke(iter, range_end)).first.is_ok()) return result; else if(skippable::invoke(std::next(iter), range_end) == // empty std::prev(is_array::invoke(iter, range_end)) ) return std::make_pair( - toml::Array{}, is_array::invoke(iter, range_end)); + ok(toml::Array{}), is_array::invoke(iter, range_end)); else throw std::make_pair(iter, syntax_error("no valid array here")); } }; @@ -678,7 +638,7 @@ struct parse_value { typedef charT value_type; static_assert(std::is_same::value, ""); - typedef detail::result result_type; + typedef result result_type; template::value_type, @@ -686,30 +646,30 @@ struct parse_value static std::pair invoke(Iterator iter, Iterator range_end) { - std::pair result; - if((result = parse_boolean::invoke(iter, range_end)).first.ok()) + std::pair result(err(""), Iterator()); + if((result = parse_boolean::invoke(iter, range_end)).first.is_ok()) return result; - else if((result = parse_string::invoke(iter, range_end)).first.ok()) + else if((result = parse_string::invoke(iter, range_end)).first.is_ok()) return result; - else if((result = parse_datetime::invoke(iter, range_end)).first.ok()) + else if((result = parse_datetime::invoke(iter, range_end)).first.is_ok()) return result; - else if((result = parse_float::invoke(iter, range_end)).first.ok()) + else if((result = parse_float::invoke(iter, range_end)).first.is_ok()) return result; - else if((result = parse_integer::invoke(iter, range_end)).first.ok()) + else if((result = parse_integer::invoke(iter, range_end)).first.is_ok()) return result; - else if((result = parse_array::invoke(iter, range_end)).first.ok()) + else if((result = parse_array::invoke(iter, range_end)).first.is_ok()) return result; - else if((result = parse_inline_table::invoke(iter, range_end)).first.ok()) + else if((result = parse_inline_table::invoke(iter, range_end)).first.is_ok()) return result; else - return std::make_pair(result_type{}, iter); + return std::make_pair(err("does not match any value type"), iter); } }; struct parse_barekey { typedef toml::character value_type; - typedef detail::result result_type; + typedef result result_type; template::value_type, @@ -718,15 +678,15 @@ struct parse_barekey invoke(Iterator iter, Iterator range_end) { const Iterator end = is_barekey::invoke(iter, range_end); - if(iter == end) return std::make_pair(result_type{}, iter); - return std::make_pair(toml::key(iter, end), end); + if(iter == end) return std::make_pair(err("input is empty"), iter); + return std::make_pair(ok(toml::key(iter, end)), end); } }; struct parse_key { typedef toml::character value_type; - typedef detail::result result_type; + typedef result result_type; template::value_type, @@ -734,12 +694,12 @@ struct parse_key static std::pair invoke(Iterator iter, Iterator range_end) { - std::pair result; - if((result = parse_barekey::invoke(iter, range_end)).first.ok()) + std::pair result(err(""), Iterator()); + if((result = parse_barekey::invoke(iter, range_end)).first.is_ok()) return result; - else if((result = parse_string::invoke(iter, range_end)).first.ok()) + else if((result = parse_string::invoke(iter, range_end)).first.is_ok()) return result; - else return std::make_pair(result_type{}, iter); + else return std::make_pair(err("does not match anything"), iter); } }; @@ -748,7 +708,7 @@ struct parse_key_value_pair { typedef charT value_type; static_assert(std::is_same::value, ""); - typedef detail::result> result_type; + typedef result, std::string> result_type; template::value_type, @@ -757,21 +717,21 @@ struct parse_key_value_pair invoke(Iterator iter, Iterator range_end) { auto tmp_key = parse_key::invoke(iter, range_end); - if(!tmp_key.first.ok()) - return std::make_pair(result_type{}, iter); + if(!tmp_key.first.is_ok()) + return std::make_pair(err(tmp_key.first.unwrap_err()), iter); iter = is_any_num_of_ws::invoke(tmp_key.second, range_end); if(*iter != '=') throw std::make_pair(iter, syntax_error("invalid key value pair")); iter = is_any_num_of_ws::invoke(std::next(iter), range_end); auto tmp_value = parse_value::invoke(iter, range_end); - if(!tmp_value.first.ok()) + if(!tmp_value.first.is_ok()) throw std::make_pair(iter, syntax_error("invalid key value pair")); iter = tmp_value.second; - return std::make_pair(std::make_pair( - tmp_key.first.move(), tmp_value.first.move()), + return std::make_pair(ok(std::make_pair( + tmp_key.first.unwrap(), tmp_value.first.unwrap())), is_any_num_of_ws::invoke(tmp_value.second, range_end)); } }; @@ -781,7 +741,7 @@ struct parse_inline_table { typedef charT value_type; static_assert(std::is_same::value, ""); - typedef detail::result result_type; + typedef result result_type; template::value_type, @@ -790,7 +750,7 @@ struct parse_inline_table invoke(Iterator iter, Iterator range_end) { const Iterator end = is_inline_table::invoke(iter, range_end); - if(iter == end) return std::make_pair(result_type{}, iter); + if(iter == end) return std::make_pair(err("input is empty"), iter); iter = is_any_num_of_ws::invoke(std::next(iter), range_end); @@ -799,24 +759,24 @@ struct parse_inline_table while(iter != last) { auto tmp = parse_key_value_pair::invoke(iter, last); - if(!tmp.first.ok()) + if(!tmp.first.is_ok()) throw std::make_pair(iter, syntax_error("parse_inline_table")); - result.emplace(tmp.first.move()); + result.emplace(tmp.first.unwrap()); iter = tmp.second; iter = is_any_num_of_ws::invoke(iter, last); iter = is_character::invoke(iter, last); iter = is_any_num_of_ws::invoke(iter, last); } - return std::make_pair(result, end); + return std::make_pair(ok(result), end); } }; struct parse_table_definition { typedef toml::character value_type; - typedef detail::result> result_type; + typedef result, std::string> result_type; template::value_type, @@ -826,7 +786,7 @@ struct parse_table_definition { const Iterator end = is_table_definition::invoke(iter, range_end); - if(iter == end) return std::make_pair(result_type{}, iter); + if(iter == end) return std::make_pair(err("input is empty"), iter); std::vector result; result.reserve(std::count(iter, end, '.')+1); @@ -836,9 +796,9 @@ struct parse_table_definition iter = is_any_num_of_ws::invoke(std::next(iter), last); auto tmp = parse_key::invoke(iter, last); - if(!tmp.first.ok()) + if(!tmp.first.is_ok()) throw std::make_pair(iter, syntax_error("table definition")); - result.emplace_back(tmp.first.move()); + result.emplace_back(tmp.first.unwrap()); iter = is_any_num_of_ws::invoke(tmp.second, last); while(iter != last) @@ -847,19 +807,19 @@ struct parse_table_definition iter = is_any_num_of_ws::invoke(iter, last); tmp = parse_key::invoke(iter, last); - if(!tmp.first.ok()) + if(!tmp.first.is_ok()) throw std::make_pair(iter, syntax_error("table definition")); - result.emplace_back(tmp.first.move()); + result.emplace_back(tmp.first.unwrap()); iter = is_any_num_of_ws::invoke(tmp.second, last); } - return std::make_pair(result, end); + return std::make_pair(ok(result), end); } }; struct parse_array_of_table_definition { typedef toml::character value_type; - typedef detail::result> result_type; + typedef result, std::string> result_type; template::value_type, @@ -869,7 +829,7 @@ struct parse_array_of_table_definition { const Iterator end = is_array_of_table_definition::invoke(iter, range_end); - if(iter == end) return std::make_pair(result_type{}, iter); + if(iter == end) return std::make_pair(err("input is empty"), iter); if(std::distance(iter, end) < 5) throw std::make_pair(iter, syntax_error("invalid array_of_table definition")); @@ -882,9 +842,9 @@ struct parse_array_of_table_definition iter = is_any_num_of_ws::invoke(iter, last); auto tmp = parse_key::invoke(iter, last); - if(!tmp.first.ok()) + if(!tmp.first.is_ok()) throw std::make_pair(iter, syntax_error("array of table definition")); - result.emplace_back(tmp.first.move()); + result.emplace_back(tmp.first.unwrap()); iter = is_any_num_of_ws::invoke(tmp.second, last); while(iter != last) @@ -893,12 +853,12 @@ struct parse_array_of_table_definition iter = is_any_num_of_ws::invoke(iter, last); tmp = parse_key::invoke(iter, last); - if(!tmp.first.ok()) + if(!tmp.first.is_ok()) throw std::make_pair(iter, syntax_error("array of table definition")); - result.emplace_back(tmp.first.move()); + result.emplace_back(tmp.first.unwrap()); iter = is_any_num_of_ws::invoke(tmp.second, last); } - return std::make_pair(result, end); + return std::make_pair(ok(result), end); } }; @@ -920,19 +880,20 @@ struct parse_data while(iter != end) { iter = skip_empty(iter, end); - std::pair>, Iterator> tabname; - if((tabname = parse_table_definition::invoke(iter, end)).first.ok()) + std::pair<::toml::result, std::string>, Iterator> + tabname(err(""), Iterator()); + if((tabname = parse_table_definition::invoke(iter, end)).first.is_ok()) { auto contents = parse_table_contents(tabname.second, end); push_table(result, std::move(contents.first), - tabname.first.get().begin(), tabname.first.get().end()); + tabname.first.unwrap().begin(), tabname.first.unwrap().end()); iter = contents.second; } - else if((tabname = parse_array_of_table_definition::invoke(iter, end)).first.ok()) + else if((tabname = parse_array_of_table_definition::invoke(iter, end)).first.is_ok()) { auto contents = parse_table_contents(tabname.second, end); push_array_of_table(result, std::move(contents.first), - tabname.first.get().begin(), tabname.first.get().end()); + tabname.first.unwrap().begin(), tabname.first.unwrap().end()); iter = contents.second; } else @@ -978,9 +939,9 @@ struct parse_data while(iter != end) { auto kv = parse_key_value_pair::invoke(iter, end); - if(!kv.first.ok()) return std::make_pair(table, iter); + if(!kv.first.is_ok()) return std::make_pair(table, iter); - table.emplace(kv.first.move()); + table.emplace(kv.first.unwrap()); iter = kv.second; iter = skip_empty(iter, end); } @@ -1124,7 +1085,5 @@ inline toml::Table parse(const std::basic_string& filename) return parse(ifs); } - - }// toml #endif// TOML11_PARSER diff --git a/toml/result.hpp b/toml/result.hpp new file mode 100644 index 0000000..a6276ef --- /dev/null +++ b/toml/result.hpp @@ -0,0 +1,414 @@ +#ifndef TOML11_RESULT_H +#define TOML11_RESULT_H +#include +#include +#include +#include + +namespace toml +{ + +template +struct success +{ + using value_type = T; + value_type value; + + explicit success(const value_type& v) + noexcept(std::is_nothrow_copy_constructible::value) + : value(v) + {} + explicit success(value_type&& v) + noexcept(std::is_nothrow_move_constructible::value) + : value(std::move(v)) + {} + + template + explicit success(U&& v): value(std::forward(v)) {} + + template + explicit success(const success& v): value(v.value) {} + template + explicit success(success&& v): value(std::move(v.value)) {} + + ~success() = default; + success(const success&) = default; + success(success&&) = default; + success& operator=(const success&) = default; + success& operator=(success&&) = default; +}; + +template +struct failure +{ + using value_type = T; + value_type value; + + explicit failure(const value_type& v) + noexcept(std::is_nothrow_copy_constructible::value) + : value(v) + {} + explicit failure(value_type&& v) + noexcept(std::is_nothrow_move_constructible::value) + : value(std::move(v)) + {} + + template + explicit failure(U&& v): value(std::forward(v)) {} + + template + explicit failure(const failure& v): value(v.value) {} + template + explicit failure(failure&& v): value(std::move(v.value)) {} + + ~failure() = default; + failure(const failure&) = default; + failure(failure&&) = default; + failure& operator=(const failure&) = default; + failure& operator=(failure&&) = default; +}; + +template +success::type>::type> +ok(T&& v) +{ + return success< + typename std::remove_cv::type>::type + >(std::forward(v)); +} +template +failure::type>::type> +err(T&& v) +{ + return failure< + typename std::remove_cv::type>::type + >(std::forward(v)); +} + +inline success ok(const char* literal) +{ + return success(std::string(literal)); +} +inline failure err(const char* literal) +{ + return failure(std::string(literal)); +} + + +template +struct result +{ + using value_type = T; + using error_type = E; + using success_type = success; + using failure_type = failure; + + result(const success_type& s): is_ok_(true) + { + auto tmp = ::new(std::addressof(this->succ)) success_type(s); + assert(tmp == std::addressof(this->succ)); + } + result(const failure_type& f): is_ok_(false) + { + auto tmp = ::new(std::addressof(this->fail)) failure_type(f); + assert(tmp == std::addressof(this->fail)); + } + result(success_type&& s): is_ok_(true) + { + auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s)); + assert(tmp == std::addressof(this->succ)); + } + result(failure_type&& f): is_ok_(false) + { + auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f)); + assert(tmp == std::addressof(this->fail)); + } + + template + result(const success& s): is_ok_(true) + { + auto tmp = ::new(std::addressof(this->succ)) success_type(s.value); + assert(tmp == std::addressof(this->succ)); + } + template + result(const failure& f): is_ok_(false) + { + auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value); + assert(tmp == std::addressof(this->fail)); + } + template + result(success&& s): is_ok_(true) + { + auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value)); + assert(tmp == std::addressof(this->succ)); + } + template + result(failure&& f): is_ok_(false) + { + auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value)); + assert(tmp == std::addressof(this->fail)); + } + + result& operator=(const success_type& s) + { + this->cleanup(); + this->is_ok_ = true; + auto tmp = ::new(std::addressof(this->succ)) success_type(s); + assert(tmp == std::addressof(this->succ)); + return *this; + } + result& operator=(const failure_type& f) + { + this->cleanup(); + this->is_ok_ = false; + auto tmp = ::new(std::addressof(this->fail)) failure_type(f); + assert(tmp == std::addressof(this->fail)); + return *this; + } + result& operator=(success_type&& s) + { + this->cleanup(); + this->is_ok_ = true; + auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s)); + assert(tmp == std::addressof(this->succ)); + return *this; + } + result& operator=(failure_type&& f) + { + this->cleanup(); + this->is_ok_ = false; + auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f)); + assert(tmp == std::addressof(this->fail)); + return *this; + } + + template + result& operator=(const success& s) + { + this->cleanup(); + this->is_ok_ = true; + auto tmp = ::new(std::addressof(this->succ)) success_type(s.value); + assert(tmp == std::addressof(this->succ)); + return *this; + } + template + result& operator=(const failure& f) + { + this->cleanup(); + this->is_ok_ = false; + auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value); + assert(tmp == std::addressof(this->fail)); + return *this; + } + template + result& operator=(success&& s) + { + this->cleanup(); + this->is_ok_ = true; + auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value)); + assert(tmp == std::addressof(this->succ)); + return *this; + } + template + result& operator=(failure&& f) + { + this->cleanup(); + this->is_ok_ = false; + auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value)); + assert(tmp == std::addressof(this->fail)); + return *this; + } + + ~result() noexcept {this->cleanup();} + + result(const result& other): is_ok_(other.is_ok()) + { + if(other.is_ok()) + { + auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok()); + assert(tmp == std::addressof(this->succ)); + } + else + { + auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err()); + assert(tmp == std::addressof(this->fail)); + } + } + result(result&& other): is_ok_(other.is_ok()) + { + if(other.is_ok()) + { + auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok()); + assert(tmp == std::addressof(this->succ)); + } + else + { + auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err()); + assert(tmp == std::addressof(this->fail)); + } + } + + template + result(const result& other): is_ok_(other.is_ok()) + { + if(other.is_ok()) + { + auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok()); + assert(tmp == std::addressof(this->succ)); + } + else + { + auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err()); + assert(tmp == std::addressof(this->fail)); + } + } + template + result(result&& other): is_ok_(other.is_ok()) + { + if(other.is_ok()) + { + auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok()); + assert(tmp == std::addressof(this->succ)); + } + else + { + auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err()); + assert(tmp == std::addressof(this->fail)); + } + } + + result& operator=(const result& other) + { + this->cleanup(); + if(other.is_ok()) + { + auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok()); + assert(tmp == std::addressof(this->succ)); + } + else + { + auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err()); + assert(tmp == std::addressof(this->fail)); + } + is_ok_ = other.is_ok(); + return *this; + } + result& operator=(result&& other) + { + this->cleanup(); + if(other.is_ok()) + { + auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok())); + assert(tmp == std::addressof(this->succ)); + } + else + { + auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err())); + assert(tmp == std::addressof(this->fail)); + } + is_ok_ = other.is_ok(); + return *this; + } + + template + result& operator=(const result& other) + { + this->cleanup(); + if(other.is_ok()) + { + auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok()); + assert(tmp == std::addressof(this->succ)); + } + else + { + auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err()); + assert(tmp == std::addressof(this->fail)); + } + is_ok_ = other.is_ok(); + return *this; + } + template + result& operator=(result&& other) + { + this->cleanup(); + if(other.is_ok()) + { + auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok())); + assert(tmp == std::addressof(this->succ)); + } + else + { + auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err())); + assert(tmp == std::addressof(this->fail)); + } + is_ok_ = other.is_ok(); + return *this; + } + + bool is_ok() const noexcept {return is_ok_;} + bool is_err() const noexcept {return !is_ok_;} + + operator bool() const noexcept {return is_ok_;} + + value_type& unwrap() & + { + if(is_err()) {throw std::runtime_error("result: bad unwrap");} + return this->succ.value; + } + value_type const& unwrap() const& + { + if(is_err()) {throw std::runtime_error("result: bad unwrap");} + return this->succ.value; + } + value_type&& unwrap() && + { + if(is_err()) {throw std::runtime_error("result: bad unwrap");} + return std::move(this->succ.value); + } + + error_type& unwrap_err() & + { + if(is_ok()) {throw std::runtime_error("result: bad unwrap_err");} + return this->fail.value; + } + error_type const& unwrap_err() const& + { + if(is_ok()) {throw std::runtime_error("result: bad unwrap_err");} + return this->fail.value; + } + error_type&& unwrap_err() && + { + if(is_ok()) {throw std::runtime_error("result: bad unwrap_err");} + return std::move(this->fail.value); + } + + value_type& as_ok() & noexcept {return this->succ.value;} + value_type const& as_ok() const& noexcept {return this->succ.value;} + value_type&& as_ok() && noexcept {return std::move(this->succ.value);} + + error_type& as_err() & noexcept {return this->fail.value;} + error_type const& as_err() const& noexcept {return this->fail.value;} + error_type&& as_err() && noexcept {return std::move(this->fail.value);} + + private: + + void cleanup() noexcept + { + if(this->is_ok_) {this->succ.~success_type();} + else {this->fail.~failure_type();} + return; + } + + private: + + bool is_ok_; + union + { + success_type succ; + failure_type fail; + }; +}; + + +} // toml11 +#endif// TOML11_RESULT_H