diff --git a/examples/error_printer.cpp b/examples/error_printer.cpp index 9b126d9..6c00fc7 100644 --- a/examples/error_printer.cpp +++ b/examples/error_printer.cpp @@ -2,26 +2,21 @@ // Copyright (c) Mark Gillard // See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. // SPDX-License-Identifier: MIT -/* - This example is one of diagnostics; it forces a set of specific parsing - failures and prints their error messages to stdout so you can see what the - default error messages look like. +// This example shows the error messages the library produces by forcing a set of specific parsing +// failures and printing their results. -*/ -#include -#include "utf8_console.h" +#include "examples.h" #define TOML_EXCEPTIONS 0 #define TOML_UNRELEASED_FEATURES 0 #include using namespace std::string_view_literals; -using toml::operator""_sz; namespace { - inline constexpr std::string_view invalid_parses[] = + inline constexpr auto invalid_parses = std::array { "########## comments"sv, "# bar\rkek"sv, @@ -104,44 +99,36 @@ namespace "########## floats"sv, R"(val = 9999999999999999999999999999999999999999999999999999999999999995.0)"sv, }; + + inline constexpr auto divider = + "################################################################################"sv; } - -int main(int /*argc*/, char** /*argv*/) +int main() { - std::ios_base::sync_with_stdio(false); - init_utf8_console(); + examples::init(); for (auto str : invalid_parses) { if (str.empty()) continue; - if (str.substr(0_sz, 10_sz) == "##########"sv) + // section headings + if (str.substr(0, 10) == "##########"sv) { - const auto substr = str.substr(11_sz); - size_t cols = 80_sz; - for (size_t i = (cols - substr.length()) / 2_sz - 1_sz; i-- > 0_sz; ) - { - std::cout.put('#'); - cols--; - } - std::cout.put(' '); - std::cout << substr; - std::cout.put(' '); - cols -= substr.length() + 2_sz; - while (cols--) - std::cout.put('#'); - - std::cout << "\n\n"sv; + std::cout << divider << '\n'; + std::cout << "# "sv << str.substr(11) << '\n'; + std::cout << divider << "\n\n"sv; } + + // error messages else { toml::parse_result result; if (str == "PATHOLOGICALLY_NESTED"sv) { - std::string s(1000_sz, '['); + std::string s(1000u, '['); constexpr auto start = "array = "sv; memcpy(s.data(), start.data(), start.length()); result = toml::parse(s); @@ -150,10 +137,7 @@ int main(int /*argc*/, char** /*argv*/) result = toml::parse(str); if (!result) - { - std::cout << result.error(); - std::cout << "\n\n"sv; - } + std::cout << result.error() << "\n\n"sv; } } return 0; diff --git a/examples/error_printer.vcxproj b/examples/error_printer.vcxproj index f4aa10a..0036138 100644 --- a/examples/error_printer.vcxproj +++ b/examples/error_printer.vcxproj @@ -51,5 +51,11 @@ + + + + + + - + \ No newline at end of file diff --git a/examples/examples.h b/examples/examples.h new file mode 100644 index 0000000..f028e74 --- /dev/null +++ b/examples/examples.h @@ -0,0 +1,52 @@ +//# This file is a part of toml++ and is subject to the the terms of the MIT license. +//# Copyright (c) 2019-2020 Mark Gillard +//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. +// SPDX-License-Identifier: MIT + +// this file is for boilerplate unrelated to the toml++ example learning outcomes. + +#ifdef __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Weverything" +#elif defined (__GNUC__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wall" + #pragma GCC diagnostic ignored "-Wextra" +#elif defined(_MSC_VER) + #pragma warning(push, 0) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _WIN32 + #include +#endif + +#ifdef __clang__ + #pragma clang diagnostic pop +#elif defined(__GNUC__) + #pragma GCC diagnostic pop +#elif defined(_MSC_VER) + #pragma warning(pop) +#endif + +namespace examples +{ + inline void init() noexcept + { + #ifdef _WIN32 + SetConsoleOutputCP(65001); //CP_UTF8 + #endif + + std::ios_base::sync_with_stdio(false); + std::cout << std::boolalpha; + + srand(static_cast(time(nullptr))); + } +} diff --git a/examples/simple_parser.cpp b/examples/simple_parser.cpp index 67d44c5..7c7453a 100644 --- a/examples/simple_parser.cpp +++ b/examples/simple_parser.cpp @@ -2,14 +2,10 @@ // Copyright (c) Mark Gillard // See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. // SPDX-License-Identifier: MIT -/* - This example demonstrates how to parse TOML from a file and - re-serialize it (print it out) to stdout. +// This example demonstrates how to parse TOML from a file and re-serialize it (print it out) to stdout. -*/ -#include -#include "utf8_console.h" +#include "examples.h" #define TOML_UNRELEASED_FEATURES 1 #include @@ -18,14 +14,13 @@ using namespace std::string_view_literals; int main(int argc, char** argv) { - std::ios_base::sync_with_stdio(false); - init_utf8_console(); + examples::init(); - auto path = std::string{ argc > 1 ? argv[1] : "example.toml" }; + const auto path = argc > 1 ? std::string_view{ argv[1] } : "example.toml"sv; try { - const auto tbl = toml::parse_file(path); - std::cout << tbl << "\n"; + const auto table = toml::parse_file(path); + std::cout << table << "\n"; } catch (const toml::parse_error& err) { diff --git a/examples/simple_parser.vcxproj b/examples/simple_parser.vcxproj index e1f67f1..29ea77f 100644 --- a/examples/simple_parser.vcxproj +++ b/examples/simple_parser.vcxproj @@ -52,5 +52,11 @@ + + + + + + - + \ No newline at end of file diff --git a/examples/toml_generator.cpp b/examples/toml_generator.cpp index 37abc2d..89d2997 100644 --- a/examples/toml_generator.cpp +++ b/examples/toml_generator.cpp @@ -2,17 +2,10 @@ // Copyright (c) Mark Gillard // See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. // SPDX-License-Identifier: MIT -/* - This example demonstrates some slightly advanced techniques - being used to randomly generate a tree of TOML data. +// This example demonstrates the use of some more advanced features to generate a tree of random TOML data. -*/ -#include -#include -#include -#include -#include "utf8_console.h" +#include "examples.h" #define TOML_PARSER 0 #include @@ -63,7 +56,7 @@ namespace [[nodiscard]] static T rand(T excl_max) noexcept { - return static_cast(static_cast(::rand()) % excl_max); + return static_cast(static_cast(std::rand()) % excl_max); } template @@ -107,12 +100,9 @@ namespace } } - int main(int argc, char** argv) { - std::ios_base::sync_with_stdio(false); - init_utf8_console(); - srand(static_cast(time(nullptr))); + examples::init(); int node_budget{}; for (int i = 1; i < argc; i++) @@ -132,34 +122,48 @@ int main(int argc, char** argv) int container_min_values = 10; bool in_arr = false; - const auto add = [&](auto&& obj) noexcept -> toml::node& + const auto add = [&](auto&& val) noexcept -> auto& { + using value_ref = decltype(val); + using value_type = std::remove_reference_t; + using node_type = toml::inserted_type_of; + toml::node* new_node{}; + // we're adding an element to an array if (auto arr = tree.back()->as_array()) { - arr->push_back(std::forward(obj)); + arr->push_back(std::forward(val)); new_node = &arr->back(); } - else - new_node = &(*tree.back()->ref().insert_or_assign( - rand_string(rand(1u, 4u), '-'), - std::forward(obj) - ).first).second; - if constexpr (toml::is_array || toml::is_table) + // we're adding a new kvp to a table + else + { + auto& table = tree.back()->ref(); + + const auto it = table.insert_or_assign( + rand_string(rand(1u, 4u), '-'), + std::forward(val) + ); + + new_node = &it.first->second; + } + + // we added a new array or table, so now we need to step into it + if constexpr (toml::is_container) { tree.push_back(new_node); container_min_values = rand(1, 4); - in_arr = toml::is_array; - if constexpr (toml::is_array) + in_arr = toml::is_array; + if constexpr (toml::is_array) tree.back()->as_array()->reserve(static_cast(container_min_values)); } else container_min_values--; node_budget--; - return *new_node; + return *new_node->as(); }; while (node_budget) @@ -167,7 +171,7 @@ int main(int argc, char** argv) if (!in_arr && rand(100) >= 75) { if (container_min_values <= 0 && tree.size() < max_depth) - add(toml::table{}).ref().is_inline(tree.size() >= max_depth - 2u && rand(100) >= 85); + add(toml::table{}).is_inline(tree.size() >= max_depth - 2u && rand(100) >= 85); } else { @@ -179,41 +183,41 @@ int main(int argc, char** argv) switch (new_node_type) { - case toml::node_type::array: - if (container_min_values <= 0 && tree.size() < max_depth) - add(toml::array{}); - break; + case toml::node_type::array: + if (container_min_values <= 0 && tree.size() < max_depth) + add(toml::array{}); + break; - case toml::node_type::string: - add(rand_string(rand(8u))); - break; + case toml::node_type::string: + add(rand_string(rand(8u))); + break; - case toml::node_type::integer: - add(rand()); - break; + case toml::node_type::integer: + add(rand()); + break; - case toml::node_type::floating_point: - add(rand(10001u) / 10000.0); - break; + case toml::node_type::floating_point: + add(rand(10001u) / 10000.0); + break; - case toml::node_type::boolean: - add(!rand(2u)); - break; + case toml::node_type::boolean: + add(!rand(2u)); + break; - case toml::node_type::date: - add(rand_date()); - break; + case toml::node_type::date: + add(rand_date()); + break; - case toml::node_type::time: - add(rand_time()); - break; + case toml::node_type::time: + add(rand_time()); + break; - case toml::node_type::date_time: - add(rand(100) >= 75 - ? toml::date_time{ rand_date(), rand_time() } - : toml::date_time{ rand_date(), rand_time(), toml::time_offset{ rand(-11, 12), rand(-45, +46) } } - ); - break; + case toml::node_type::date_time: + add(rand(100) >= 75 + ? toml::date_time{ rand_date(), rand_time() } + : toml::date_time{ rand_date(), rand_time(), toml::time_offset{ rand(-11, 12), rand(-45, +46) } } + ); + break; } if (container_min_values <= 0 && tree.size() >= 2u && rand(100) >= 85) { diff --git a/examples/toml_generator.vcxproj b/examples/toml_generator.vcxproj index 56e3274..84afd8f 100644 --- a/examples/toml_generator.vcxproj +++ b/examples/toml_generator.vcxproj @@ -52,5 +52,11 @@ + + + + + + - + \ No newline at end of file diff --git a/examples/toml_to_json_transcoder.cpp b/examples/toml_to_json_transcoder.cpp index 6832d13..175432c 100644 --- a/examples/toml_to_json_transcoder.cpp +++ b/examples/toml_to_json_transcoder.cpp @@ -2,14 +2,10 @@ // Copyright (c) Mark Gillard // See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. // SPDX-License-Identifier: MIT -/* - This example demonstrates how to use the toml::json_formatter to - re-serialize TOML data as JSON. +// This example demonstrates how to use the toml::json_formatter to re-serialize TOML data as JSON. -*/ -#include -#include "utf8_console.h" +#include "examples.h" #define TOML_UNRELEASED_FEATURES 1 #include @@ -18,38 +14,28 @@ using namespace std::string_view_literals; int main(int argc, char** argv) { - std::ios_base::sync_with_stdio(false); - init_utf8_console(); + examples::init(); - // read from a file if a path argument is given - if (argc > 1) + toml::table table; + try { - try - { - const auto table = toml::parse_file(argv[1]); - std::cout << toml::json_formatter{ table } << "\n"; - } - catch (const toml::parse_error& err) - { - std::cerr << err << "\n"; - return 1; - } - } - - // otherwise read directly from stdin - else - { - try - { - const auto table = toml::parse(std::cin, "stdin"sv); - std::cout << toml::json_formatter{ table } << "\n"; - } - catch (const toml::parse_error& err) - { - std::cerr << err << "\n"; - return 1; - } + + // read from a file if a path argument is given + if (argc > 1) + table = toml::parse_file(argv[1]); + + // otherwise read directly from stdin + else + table = toml::parse(std::cin, "stdin"sv); + + std::cout << toml::json_formatter{ table } << "\n"; + } + catch (const toml::parse_error& err) + { + std::cerr << err << "\n"; + return 1; } + std::cout << toml::json_formatter{ table } << "\n"; return 0; } diff --git a/examples/toml_to_json_transcoder.vcxproj b/examples/toml_to_json_transcoder.vcxproj index d785569..daff5d7 100644 --- a/examples/toml_to_json_transcoder.vcxproj +++ b/examples/toml_to_json_transcoder.vcxproj @@ -52,5 +52,11 @@ + + + + + + - + \ No newline at end of file diff --git a/examples/utf8_console.h b/examples/utf8_console.h deleted file mode 100644 index 2087edf..0000000 --- a/examples/utf8_console.h +++ /dev/null @@ -1,18 +0,0 @@ -//# This file is a part of toml++ and is subject to the the terms of the MIT license. -//# Copyright (c) 2019-2020 Mark Gillard -//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. -// SPDX-License-Identifier: MIT - -#include -#ifdef _WIN32 -#include -#endif - -inline void init_utf8_console() noexcept -{ - #ifdef _WIN32 - SetConsoleOutputCP(65001); //CP_UTF8 - #endif - - std::cout << std::boolalpha; -} diff --git a/include/toml++/toml_array.h b/include/toml++/toml_array.h index 311360d..6c73a8e 100644 --- a/include/toml++/toml_array.h +++ b/include/toml++/toml_array.h @@ -176,78 +176,6 @@ TOML_IMPL_NAMESPACE_START TOML_ENABLE_WARNINGS; }; - - template - [[nodiscard]] - TOML_ATTR(returns_nonnull) - auto* make_node_specialized(T&& val) noexcept - { - using type = unwrap_node>; - static_assert(!std::is_same_v); - static_assert(!is_node_view); - - if constexpr (is_one_of) - { - return new type{ static_cast(val) }; - } - else if constexpr (is_native && !std::is_same_v, type>) - { - return new value{ static_cast(val) }; - } - else - { - static_assert( - !is_wide_string || TOML_WINDOWS_COMPAT, - "Instantiating values from wide-character strings is only " - "supported on Windows with TOML_WINDOWS_COMPAT enabled." - ); - static_assert( - is_native || is_losslessly_convertible_to_native, - "Value initializers must be (or be promotable to) one of the TOML value types" - ); - - using value_type = native_type_of>; - if constexpr (is_wide_string) - { - #if TOML_WINDOWS_COMPAT - return new value{ narrow(static_cast(val)) }; - #else - static_assert(dependent_false, "Evaluated unreachable branch!"); - #endif - } - else - return new value{ static_cast(val) }; - } - } - - template - [[nodiscard]] - auto* make_node(T&& val) noexcept - { - using type = unwrap_node>; - if constexpr (std::is_same_v || is_node_view) - { - if constexpr (is_node_view) - { - if (!val) - return static_cast(nullptr); - } - - return static_cast(val).visit([](auto&& concrete) noexcept - { - return static_cast(make_node_specialized(std::forward(concrete))); - }); - } - else - return make_node_specialized(static_cast(val)); - } - - template - [[nodiscard]] - auto* make_node(inserter&& val) noexcept - { - return make_node(std::move(val.value)); - } } TOML_IMPL_NAMESPACE_END; /// \endcond @@ -330,7 +258,7 @@ TOML_NAMESPACE_START if (!val) return; } - elements.emplace_back(impl::make_node(std::forward(val))); + elements.emplace_back(impl::make_node(static_cast(val))); } #if TOML_LIFETIME_HOOKS @@ -418,11 +346,11 @@ TOML_NAMESPACE_START explicit array(ElemType&& val, ElemTypes&&... vals) { elements.reserve(sizeof...(ElemTypes) + 1_sz); - emplace_back_if_not_empty_view(std::forward(val)); + emplace_back_if_not_empty_view(static_cast(val)); if constexpr (sizeof...(ElemTypes) > 0) { ( - emplace_back_if_not_empty_view(std::forward(vals)), + emplace_back_if_not_empty_view(static_cast(vals)), ... ); } @@ -544,7 +472,7 @@ TOML_NAMESPACE_START if (!val) return end(); } - return { elements.emplace(pos.raw_, impl::make_node(std::forward(val))) }; + return { elements.emplace(pos.raw_, impl::make_node(static_cast(val))) }; } /// \brief Repeatedly inserts a new element starting at a specific position in the array. @@ -595,7 +523,7 @@ TOML_NAMESPACE_START switch (count) { case 0: return { elements.begin() + (pos.raw_ - elements.cbegin()) }; - case 1: return insert(pos, std::forward(val)); + case 1: return insert(pos, static_cast(val)); default: { const auto start_idx = static_cast(pos.raw_ - elements.cbegin()); @@ -605,7 +533,7 @@ TOML_NAMESPACE_START elements[i].reset(impl::make_node(val)); //# potentially move the initial value into the last element - elements[i].reset(impl::make_node(std::forward(val))); + elements[i].reset(impl::make_node(static_cast(val))); return { elements.begin() + static_cast(start_idx) }; } } @@ -714,7 +642,7 @@ TOML_NAMESPACE_START TOML_SA_UNWRAPPED_NODE_TYPE_LIST ); - return { elements.emplace(pos.raw_, new impl::wrap_node{ std::forward(args)...} ) }; + return { elements.emplace(pos.raw_, new impl::wrap_node{ static_cast(args)...} ) }; } /// \brief Removes the specified element from the array. @@ -800,7 +728,7 @@ TOML_NAMESPACE_START else if (new_size < elements.size()) elements.resize(new_size); else if (new_size > elements.size()) - insert(cend(), new_size - elements.size(), std::forward(default_init_val)); + insert(cend(), new_size - elements.size(), static_cast(default_init_val)); } /// \brief Shrinks the array to the given size. @@ -851,7 +779,7 @@ TOML_NAMESPACE_START template void push_back(ElemType&& val) noexcept { - emplace_back_if_not_empty_view(std::forward(val)); + emplace_back_if_not_empty_view(static_cast(val)); } /// \brief Emplaces a new element at the end of the array. @@ -885,7 +813,7 @@ TOML_NAMESPACE_START TOML_SA_UNWRAPPED_NODE_TYPE_LIST ); - auto nde = new impl::wrap_node{ std::forward(args)... }; + auto nde = new impl::wrap_node{ static_cast(args)... }; elements.emplace_back(nde); return *nde; } diff --git a/include/toml++/toml_common.h b/include/toml++/toml_common.h index a53f3f5..55372f1 100644 --- a/include/toml++/toml_common.h +++ b/include/toml++/toml_common.h @@ -549,47 +549,64 @@ TOML_IMPL_NAMESPACE_END; TOML_NAMESPACE_START { - /// \brief Metafunction for determining if a type is a toml::table. + /// \brief Metafunction for determining if a type is, or is a reference to, a toml::table. template inline constexpr bool is_table = std::is_same_v, table>; - /// \brief Metafunction for determining if a type is a toml::array. + /// \brief Metafunction for determining if a type is, or is a reference to, a toml::array. template inline constexpr bool is_array = std::is_same_v, array>; - /// \brief Metafunction for determining if a type is a std::string or toml::value. + /// \brief Metafunction for determining if a type satisfies either toml::is_table or toml::is_array. + template + inline constexpr bool is_container = is_table || is_array; + + /// \brief Metafunction for determining if a type is, or is a reference to, a std::string or toml::value. template inline constexpr bool is_string = std::is_same_v>, value>; - /// \brief Metafunction for determining if a type is an int64_t or toml::value. + /// \brief Metafunction for determining if a type is, or is a reference to, a int64_t or toml::value. template inline constexpr bool is_integer = std::is_same_v>, value>; - /// \brief Metafunction for determining if a type is a double or toml::value. + /// \brief Metafunction for determining if a type is, or is a reference to, a double or toml::value. template inline constexpr bool is_floating_point = std::is_same_v>, value>; - /// \brief Metafunction for determining if a type satisfies `toml::is_integer || toml::is_floating_point`. + /// \brief Metafunction for determining if a type satisfies either toml::is_integer or toml::is_floating_point. template inline constexpr bool is_number = is_integer || is_floating_point; - /// \brief Metafunction for determining if a type is a bool toml::value. + /// \brief Metafunction for determining if a type is, or is a reference to, a bool or toml::value. template inline constexpr bool is_boolean = std::is_same_v>, value>; - /// \brief Metafunction for determining if a type is a toml::date or toml::value. + /// \brief Metafunction for determining if a type is, or is a reference to, a toml::date or toml::value. template inline constexpr bool is_date = std::is_same_v>, value>; - /// \brief Metafunction for determining if a type is a toml::time or toml::value