mirror of
https://github.com/marzer/tomlplusplus.git
synced 2025-02-23 18:40:04 +00:00
fixed potential ODR issues relating to exception mode handling (fixes #6)
also: - fixed truncation of floating-point values when using ostreams - fixed some minor documentation issues (fixes #8) - fixed missing value deduction guides for dates and times - added serialization round-trip tests (closes #9) - added node::is_number() - added node_view::is_number() - added node_view::value_or() (closes #7) - added hexfloat parsing support for all implementations, not just <charconv> ones
This commit is contained in:
parent
2219fd22bb
commit
3d653de7c9
17
README.md
17
README.md
@ -5,6 +5,13 @@
|
||||
[](https://github.com/marzer/tomlplusplus/blob/master/LICENSE)
|
||||
|
||||
`toml++` is a header-only toml parser and serializer for C++17, C++20 and whatever comes after.
|
||||
- Fully [TOML v0.5.0]-compliant
|
||||
- Modern C++17 (with some C++20 features where supported)
|
||||
- Proper UTF-8 handling (incl. BOM)
|
||||
- Works with or without exceptions
|
||||
- Doesn't require RTTI
|
||||
- First-class support for serializing to JSON
|
||||
- Supports a number of 'unreleased' TOML features (optional)
|
||||
|
||||
<br>
|
||||
|
||||
@ -25,10 +32,10 @@ Reading it in C++ is easy with `toml++`:
|
||||
auto config = toml::parse_file( "configuration.toml" );
|
||||
|
||||
// get key-value pairs
|
||||
std::string_view library_name = config["library"]["name"].as_string()->get();
|
||||
std::string_view library_version = config["library"]["version"].as_string()->get();
|
||||
std::string_view library_author = config["library"]["authors"][0].as_string()->get();
|
||||
int64_t depends_on_cpp_version = config["dependencies"]["cpp"].as_integer()->get();
|
||||
std::string_view library_name = config["library"]["name"].value_or(""sv);
|
||||
std::string_view library_version = config["library"]["version"].value_or(""sv);
|
||||
std::string_view library_author = config["library"]["authors"][0].value_or(""sv);
|
||||
int64_t depends_on_cpp_version = config["dependencies"]["cpp"].value_or(0);
|
||||
|
||||
// modify the data
|
||||
config.insert_or_assign("alternatives", toml::array{
|
||||
@ -80,7 +87,7 @@ won't need to mess with these at all, butif you do, set them before including to
|
||||
| Option | Type | Default | Description |
|
||||
|----------------------------|:--------------:|-----------------------------------|----------------------------------------------------------------------------------------------------------|
|
||||
| `TOML_ASSERT(expr)` | function macro | `assert(expr)`<br>(or undefined) | Sets the assert function used by the library. |
|
||||
| `TOML_CHAR_8_STRINGS` | boolean | `0` | Uses C++20 [char8_t]-based strings as the toml string data type. |
|
||||
| `TOML_CHAR_8_STRINGS` | boolean | `0` | Uses C++20 [char8_t]-based strings as the toml string data type. **_Experimental!_** |
|
||||
| `TOML_CONFIG_HEADER` | string literal | undefined | Includes the given header file before the rest of the library. |
|
||||
| `TOML_LARGE_FILES` | boolean | `0` | Uses 32-bit integers for line and column indices (instead of 16-bit). |
|
||||
| `TOML_SMALL_FLOAT_TYPE` | type name | undefined | If your codebase has an additional 'small' float type (e.g. half-precision), this tells toml++ about it. |
|
||||
|
@ -339,6 +339,9 @@ PREDEFINED = TOML_DOXYGEN=1 \
|
||||
TOML_ALWAYS_INLINE=inline \
|
||||
TOML_MAY_THROW= \
|
||||
TOML_NODISCARD_CTOR= \
|
||||
TOML_ASYMMETRICAL_EQUALITY_OPS= \
|
||||
TOML_START="namespace toml" \
|
||||
TOML_END= \
|
||||
__cpp_lib_char8_t=201811L
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = NO
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <toml++/toml.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <toml++/toml.h>
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
@ -22,9 +22,8 @@ int main(int argc, char** argv)
|
||||
}
|
||||
try
|
||||
{
|
||||
const auto table = toml::parse(file, std::move(path));
|
||||
|
||||
std::cout << table << std::endl;
|
||||
const auto tbl = toml::parse(file, std::move(path));
|
||||
std::cout << tbl << std::endl;
|
||||
}
|
||||
catch (const toml::parse_error& err)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <toml++/toml.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <toml++/toml.h>
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
|
@ -20,7 +20,6 @@
|
||||
|
||||
// macro hygiene
|
||||
#if TOML_UNDEF_MACROS
|
||||
#undef TOML_EXCEPTIONS
|
||||
#undef TOML_USE_STREAMS_FOR_FLOATS
|
||||
#undef TOML_GCC_ATTR
|
||||
#undef TOML_PUSH_WARNINGS
|
||||
@ -54,6 +53,10 @@
|
||||
#undef TOML_DOXYGEN
|
||||
#undef TOML_RELOPS_REORDERING
|
||||
#undef TOML_ASYMMETRICAL_EQUALITY_OPS
|
||||
#undef TOML_START
|
||||
#undef TOML_END
|
||||
#undef TOML_IMPL_START
|
||||
#undef TOML_IMPL_END
|
||||
#endif
|
||||
|
||||
/// \mainpage toml++
|
||||
@ -126,7 +129,7 @@
|
||||
///
|
||||
/// \ecpp
|
||||
///
|
||||
/// When exceptions are disabled parsing methods return a toml::parse_error and it is up to the caller
|
||||
/// When exceptions are disabled parsing methods return a toml::parse_result and it is up to the caller
|
||||
/// to check if parsing has been successful by examining the return value:
|
||||
/// \cpp
|
||||
/// #include <iostream>
|
||||
@ -151,7 +154,11 @@
|
||||
/// return 0;
|
||||
/// }
|
||||
/// \ecpp
|
||||
/// \see toml::parse_file()
|
||||
///
|
||||
/// \see
|
||||
/// - toml::parse_file()
|
||||
/// - toml::parse_result
|
||||
/// - toml::parse_error
|
||||
///
|
||||
///////////////////////////////////
|
||||
///
|
||||
@ -252,7 +259,11 @@
|
||||
/// 'dinosaurs':
|
||||
/// \eout
|
||||
///
|
||||
/// \see toml::node, toml::node_view, toml::array, toml::table
|
||||
/// \see
|
||||
/// - toml::node
|
||||
/// - toml::node_view
|
||||
/// - toml::array
|
||||
/// - toml::table
|
||||
///
|
||||
///////////////////////////////////
|
||||
///
|
||||
@ -317,7 +328,9 @@
|
||||
/// ]
|
||||
/// }
|
||||
/// \eout
|
||||
/// \see toml::default_formatter, toml::json_formatter
|
||||
/// \see
|
||||
/// - toml::default_formatter
|
||||
/// - toml::json_formatter
|
||||
///
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include "toml_value.h"
|
||||
|
||||
namespace toml::impl
|
||||
TOML_IMPL_START
|
||||
{
|
||||
template <bool is_const>
|
||||
class array_iterator final
|
||||
@ -174,8 +174,9 @@ namespace toml::impl
|
||||
}
|
||||
}
|
||||
}
|
||||
TOML_IMPL_END
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
[[nodiscard]] bool operator == (const table& lhs, const table& rhs) noexcept;
|
||||
|
||||
@ -945,3 +946,4 @@ namespace toml
|
||||
friend inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>&, const array&) TOML_MAY_THROW;
|
||||
};
|
||||
}
|
||||
TOML_END
|
||||
|
@ -229,6 +229,17 @@
|
||||
__VA_ARGS__ [[nodiscard]] friend bool operator != (RHS rhs, LHS lhs) noexcept { return !(lhs == rhs); }
|
||||
#endif
|
||||
|
||||
#if !TOML_DOXYGEN
|
||||
#if TOML_EXCEPTIONS
|
||||
#define TOML_START namespace toml { inline namespace wex
|
||||
#else
|
||||
#define TOML_START namespace toml { inline namespace woex
|
||||
#endif
|
||||
#define TOML_END }
|
||||
#endif
|
||||
#define TOML_IMPL_START TOML_START { namespace impl
|
||||
#define TOML_IMPL_END } TOML_END
|
||||
|
||||
#include "toml_version.h"
|
||||
|
||||
#define TOML_MAKE_VERSION(maj, min, rev) \
|
||||
@ -292,7 +303,9 @@ TOML_POP_WARNINGS
|
||||
// clang-format on
|
||||
|
||||
/// \brief The root namespace for all toml++ functions and types.
|
||||
namespace toml
|
||||
namespace toml { }
|
||||
|
||||
TOML_START
|
||||
{
|
||||
using namespace std::string_literals;
|
||||
using namespace std::string_view_literals;
|
||||
@ -621,9 +634,9 @@ namespace toml
|
||||
|
||||
TOML_POP_WARNINGS
|
||||
}
|
||||
TOML_END
|
||||
|
||||
/// \brief Internal implementation details. No user-serviceable parts within.
|
||||
namespace toml::impl
|
||||
TOML_IMPL_START
|
||||
{
|
||||
template <typename T>
|
||||
using string_map = std::map<string, T, std::less<>>; //heterogeneous lookup
|
||||
@ -840,8 +853,9 @@ namespace toml::impl
|
||||
|
||||
#undef TOML_P2S_DECL
|
||||
}
|
||||
TOML_IMPL_END
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
/// \brief Metafunction for determining if a type is a toml::table.
|
||||
template <typename T>
|
||||
@ -905,3 +919,4 @@ namespace toml
|
||||
}
|
||||
}
|
||||
}
|
||||
TOML_END
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include "toml_common.h"
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
/// \brief A local date.
|
||||
struct date final
|
||||
@ -301,3 +301,4 @@ namespace toml
|
||||
}
|
||||
};
|
||||
}
|
||||
TOML_END
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "toml_array.h"
|
||||
#include "toml_utf8.h"
|
||||
|
||||
namespace toml::impl
|
||||
TOML_IMPL_START
|
||||
{
|
||||
TOML_PUSH_WARNINGS
|
||||
TOML_DISABLE_ALL_WARNINGS
|
||||
@ -131,8 +131,9 @@ namespace toml::impl
|
||||
return (default_formatter_inline_columns(node) + starting_column_bias) > 120_sz;
|
||||
}
|
||||
}
|
||||
TOML_IMPL_END
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
/// \brief A wrapper for printing TOML objects out to a stream as formatted TOML.
|
||||
///
|
||||
@ -494,3 +495,4 @@ namespace toml
|
||||
return lhs << default_formatter<CHAR>{ rhs };
|
||||
}
|
||||
}
|
||||
TOML_END
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include "toml_print_to_stream.h"
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
/// \brief Format flags for modifying how TOML data is printed to streams.
|
||||
enum class format_flags : uint8_t
|
||||
@ -18,8 +18,9 @@ namespace toml
|
||||
return static_cast<format_flags>( impl::unbox_enum(lhs) | impl::unbox_enum(rhs) );
|
||||
}
|
||||
}
|
||||
TOML_END
|
||||
|
||||
namespace toml::impl
|
||||
TOML_IMPL_START
|
||||
{
|
||||
template <typename CHAR = char>
|
||||
class formatter
|
||||
@ -142,3 +143,4 @@ namespace toml::impl
|
||||
{}
|
||||
};
|
||||
}
|
||||
TOML_IMPL_END
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include "toml_formatter.h"
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
/// \brief A wrapper for printing TOML objects out to a stream as formatted JSON.
|
||||
///
|
||||
@ -160,4 +160,4 @@ namespace toml
|
||||
base::clear_naked_newline();
|
||||
}
|
||||
}
|
||||
|
||||
TOML_END
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include "toml_common.h"
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
/// \brief A TOML node.
|
||||
///
|
||||
@ -69,6 +69,8 @@ namespace toml
|
||||
[[nodiscard]] virtual bool is_integer() const noexcept { return false; }
|
||||
/// \brief Returns true if this node is an floating-point value.
|
||||
[[nodiscard]] virtual bool is_floating_point() const noexcept { return false; }
|
||||
/// \brief Returns true if this node is an integer or floating-point value.
|
||||
[[nodiscard]] virtual bool is_number() const noexcept { return false; }
|
||||
/// \brief Returns true if this node is a boolean value.
|
||||
[[nodiscard]] virtual bool is_boolean() const noexcept { return false; }
|
||||
/// \brief Returns true if this node is a local date value.
|
||||
@ -400,3 +402,4 @@ namespace toml
|
||||
}
|
||||
};
|
||||
}
|
||||
TOML_END
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "toml_array.h"
|
||||
#include "toml_value.h"
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
/// \brief A view of a node.
|
||||
///
|
||||
@ -77,31 +77,29 @@ namespace toml
|
||||
[[nodiscard]] node_type type() const noexcept { return node_ ? node_->type() : node_type::none; }
|
||||
|
||||
/// \brief Returns true if the viewed node is a toml::table.
|
||||
[[nodiscard]] bool is_table() const noexcept { return type() == node_type::table; }
|
||||
[[nodiscard]] bool is_table() const noexcept { return node_ && node_->is_table(); }
|
||||
/// \brief Returns true if the viewed node is a toml::array.
|
||||
[[nodiscard]] bool is_array() const noexcept { return type() == node_type::array; }
|
||||
[[nodiscard]] bool is_array() const noexcept { return node_ && node_->is_array(); }
|
||||
/// \brief Returns true if the viewed node is a toml::value<>.
|
||||
[[nodiscard]] bool is_value() const noexcept { return type() > node_type::array; }
|
||||
[[nodiscard]] bool is_value() const noexcept { return node_ && node_->is_value(); }
|
||||
/// \brief Returns true if the viewed node is a toml::value<string>.
|
||||
[[nodiscard]] bool is_string() const noexcept { return type() == node_type::string; }
|
||||
[[nodiscard]] bool is_string() const noexcept { return node_ && node_->is_string(); }
|
||||
/// \brief Returns true if the viewed node is a toml::value<int64_t>.
|
||||
[[nodiscard]] bool is_integer() const noexcept { return type() == node_type::integer; }
|
||||
[[nodiscard]] bool is_integer() const noexcept { return node_ && node_->is_integer(); }
|
||||
/// \brief Returns true if the viewed node is a toml::value<double>.
|
||||
[[nodiscard]] bool is_floating_point() const noexcept { return type() == node_type::floating_point; }
|
||||
[[nodiscard]] bool is_floating_point() const noexcept { return node_ && node_->is_floating_point(); }
|
||||
/// \brief Returns true if the viewed node is a toml::value<int64_t> or toml::value<double>.
|
||||
[[nodiscard]] bool is_number() const noexcept { return node_ && node_->is_number(); }
|
||||
/// \brief Returns true if the viewed node is a toml::value<bool>.
|
||||
[[nodiscard]] bool is_boolean() const noexcept { return type() == node_type::boolean; }
|
||||
[[nodiscard]] bool is_boolean() const noexcept { return node_ && node_->is_boolean(); }
|
||||
/// \brief Returns true if the viewed node is a toml::value<date>.
|
||||
[[nodiscard]] bool is_date() const noexcept { return type() == node_type::date; }
|
||||
[[nodiscard]] bool is_date() const noexcept { return node_ && node_->is_date(); }
|
||||
/// \brief Returns true if the viewed node is a toml::value<time>.
|
||||
[[nodiscard]] bool is_time() const noexcept { return type() == node_type::time; }
|
||||
[[nodiscard]] bool is_time() const noexcept { return node_ && node_->is_time(); }
|
||||
/// \brief Returns true if the viewed node is a toml::value<date_time>.
|
||||
[[nodiscard]] bool is_date_time() const noexcept { return type() == node_type::date_time; }
|
||||
|
||||
[[nodiscard]] bool is_date_time() const noexcept { return node_ && node_->is_date_time(); }
|
||||
/// \brief Returns true if the viewed node is a toml::array that contains only tables.
|
||||
[[nodiscard]] bool is_array_of_tables() const noexcept
|
||||
{
|
||||
return node_ ? node_->is_array_of_tables() : false;
|
||||
}
|
||||
[[nodiscard]] bool is_array_of_tables() const noexcept { return node_ && node_->is_array_of_tables(); }
|
||||
|
||||
/// \brief Checks if this view references a node of a specific type.
|
||||
///
|
||||
@ -178,6 +176,51 @@ namespace toml
|
||||
[[nodiscard]] const value<time>* as_time() const noexcept { return as<time>(); }
|
||||
[[nodiscard]] const value<date_time>* as_date_time() const noexcept { return as<date_time>(); }
|
||||
|
||||
/// \brief Gets the raw value represented by the viewed value node, or a default.
|
||||
///
|
||||
/// \detail The underlying node is retrieved as if it were a value of the input default value's
|
||||
/// type. For example, if you specify an integral default value, you'll only get
|
||||
/// a non-default return value if the underlying node existed _and_ was an integer:\cpp
|
||||
/// auto tbl = toml::parse(R"(
|
||||
/// int = 42
|
||||
/// flt = 420.0
|
||||
/// bln = false
|
||||
/// )"sv);
|
||||
///
|
||||
/// std::cout << "accessing 'int' as an integer: "sv << tbl["int"].value_or(-1) << std::endl;
|
||||
/// std::cout << "accessing 'int' as a float: "sv << tbl["int"].value_or(-1.0) << std::endl;
|
||||
/// std::cout << "accessing 'flt' as a float: "sv << tbl["flt"].value_or(-1.0f) << std::endl;
|
||||
/// \ecpp
|
||||
///
|
||||
/// \out
|
||||
/// accessing 'int' as an integer: 42
|
||||
/// accessing 'int' as a float: -1.0
|
||||
/// accessing 'flt' as a float: 420.0
|
||||
/// \eout
|
||||
///
|
||||
/// \tparam U Default value type. Must be (or be promotable to) one of the TOML value types.
|
||||
/// \param default_value The default value to return if no matching node was found.
|
||||
///
|
||||
/// \returns The selected value, or the default if no match was found.
|
||||
template <typename U>
|
||||
[[nodiscard]] auto value_or(U&& default_value) const noexcept
|
||||
{
|
||||
static_assert(
|
||||
impl::is_value_or_promotable<impl::remove_cvref_t<U>>,
|
||||
"Default value type must be (or be promotable to) one of the TOML value types"
|
||||
);
|
||||
|
||||
using value_type = impl::promoted<impl::remove_cvref_t<U>>;
|
||||
using return_type = std::conditional_t<
|
||||
std::is_same_v<value_type, string>,
|
||||
std::conditional_t<std::is_same_v<impl::remove_cvref_t<U>, string>, string, string_view>,
|
||||
value_type
|
||||
>;
|
||||
if (auto val = node_ ? node_->template as<value_type>() : nullptr)
|
||||
return return_type{ **val };
|
||||
return return_type{ std::forward<U>(default_value) };
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template <typename N, typename FUNC>
|
||||
@ -348,3 +391,4 @@ namespace toml
|
||||
return { this->get(key) };
|
||||
}
|
||||
}
|
||||
TOML_END
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "toml_array.h"
|
||||
#include "toml_value.h"
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
#if TOML_DOXYGEN || !TOML_EXCEPTIONS
|
||||
|
||||
@ -181,8 +181,9 @@ namespace toml
|
||||
|
||||
#endif
|
||||
}
|
||||
TOML_END
|
||||
|
||||
namespace toml::impl
|
||||
TOML_IMPL_START
|
||||
{
|
||||
#if TOML_EXCEPTIONS
|
||||
#define TOML_ERROR_CHECK(...) (void)0
|
||||
@ -315,6 +316,7 @@ namespace toml::impl
|
||||
#if TOML_USE_STREAMS_FOR_FLOATS
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss.precision(std::numeric_limits<arg_t>::digits10 + 1);
|
||||
oss << arg;
|
||||
const auto str = oss.str();
|
||||
std::memcpy(ptr, str.c_str(), str.length());
|
||||
@ -1200,7 +1202,7 @@ namespace toml::impl
|
||||
TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
#if !TOML_USE_STREAMS_FOR_FLOATS && TOML_LANG_HIGHER_THAN(0, 5, 0) // toml/issues/562
|
||||
#if TOML_LANG_HIGHER_THAN(0, 5, 0) // toml/issues/562
|
||||
|
||||
[[nodiscard]]
|
||||
double parse_hex_float() TOML_MAY_THROW
|
||||
@ -1342,38 +1344,62 @@ namespace toml::impl
|
||||
|
||||
// convert to double
|
||||
TOML_GCC_ATTR(uninitialized) double result;
|
||||
auto fc_result = std::from_chars(chars, chars + length, result, std::chars_format::hex);
|
||||
switch (fc_result.ec)
|
||||
#if TOML_USE_STREAMS_FOR_FLOATS
|
||||
{
|
||||
case std::errc{}: //ok
|
||||
return result;
|
||||
std::string str;
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss.write("0x", 2_sz);
|
||||
ss.write(chars, static_cast<std::streamsize>(length));
|
||||
str = ss.str();
|
||||
}
|
||||
|
||||
case std::errc::invalid_argument:
|
||||
char* end = {};
|
||||
result = std::strtod(str.c_str(), &end);
|
||||
if (result == 0.0 && end == str.c_str())
|
||||
abort_with_error(
|
||||
"Error parsing hexadecimal "sv, node_type::floating_point,
|
||||
"; '"sv, std::string_view{ chars, length }, "' could not be interpreted as a value"sv
|
||||
);
|
||||
break;
|
||||
|
||||
case std::errc::result_out_of_range:
|
||||
abort_with_error(
|
||||
"Error parsing hexadecimal "sv, node_type::floating_point,
|
||||
"; '"sv, std::string_view{ chars, length }, "' is not representable in 64 bits"sv
|
||||
);
|
||||
break;
|
||||
|
||||
default: //??
|
||||
abort_with_error(
|
||||
"Error parsing hexadecimal "sv, node_type::floating_point,
|
||||
"; an unspecified error occurred while trying to interpret '",
|
||||
std::string_view{ chars, length }, "' as a value"sv
|
||||
);
|
||||
else
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
{
|
||||
auto fc_result = std::from_chars(chars, chars + length, result, std::chars_format::hex);
|
||||
switch (fc_result.ec)
|
||||
{
|
||||
case std::errc{}: //ok
|
||||
return result;
|
||||
|
||||
case std::errc::invalid_argument:
|
||||
abort_with_error(
|
||||
"Error parsing hexadecimal "sv, node_type::floating_point,
|
||||
"; '"sv, std::string_view{ chars, length }, "' could not be interpreted as a value"sv
|
||||
);
|
||||
break;
|
||||
|
||||
case std::errc::result_out_of_range:
|
||||
abort_with_error(
|
||||
"Error parsing hexadecimal "sv, node_type::floating_point,
|
||||
"; '"sv, std::string_view{ chars, length }, "' is not representable in 64 bits"sv
|
||||
);
|
||||
break;
|
||||
|
||||
default: //??
|
||||
abort_with_error(
|
||||
"Error parsing hexadecimal "sv, node_type::floating_point,
|
||||
"; an unspecified error occurred while trying to interpret '",
|
||||
std::string_view{ chars, length }, "' as a value"sv
|
||||
);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
TOML_ERROR_CHECK({});
|
||||
TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
#endif //!TOML_USE_STREAMS_FOR_FLOATS && TOML_LANG_HIGHER_THAN(0, 5, 0)
|
||||
#endif //TOML_LANG_HIGHER_THAN(0, 5, 0)
|
||||
|
||||
template <int base>
|
||||
[[nodiscard]]
|
||||
@ -2181,14 +2207,6 @@ namespace toml::impl
|
||||
begin_pos,
|
||||
reader.source_path()
|
||||
);
|
||||
#elif TOML_USE_STREAMS_FOR_FLOATS
|
||||
TOML_ERROR(
|
||||
"Hexadecimal floating-point values are not "
|
||||
"supported when streams are used to interpret floats "
|
||||
"(TOML_USE_STREAMS_FOR_FLOATS = 1).",
|
||||
begin_pos,
|
||||
reader.source_path()
|
||||
);
|
||||
#else
|
||||
val = std::make_unique<value<double>>(parse_hex_float());
|
||||
break;
|
||||
@ -3061,8 +3079,9 @@ namespace toml::impl
|
||||
#undef TOML_ERROR
|
||||
#undef TOML_NORETURN
|
||||
}
|
||||
TOML_IMPL_END
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
/// \brief Parses a TOML document from a string view.
|
||||
///
|
||||
@ -3277,8 +3296,22 @@ namespace toml
|
||||
|
||||
/// \brief Convenience literal operators for working with TOML++.
|
||||
///
|
||||
/// \remark This namespace exists so you can safely hoist the UDL operators into another scope
|
||||
/// without dragging in everything in the toml namespace.
|
||||
/// \detail This namespace exists so you can safely hoist the UDL operators into another scope
|
||||
/// without dragging in everything in the toml namespace: \cpp
|
||||
///
|
||||
/// #include <toml++/toml.h>
|
||||
/// using namespace toml_literals;
|
||||
///
|
||||
/// int main()
|
||||
/// {
|
||||
/// auto tbl = "vals = [1, 2, 3]"_toml;
|
||||
/// /*
|
||||
/// ... do stuff with the table generated by the "_toml" UDL
|
||||
/// */
|
||||
/// return 0;
|
||||
/// }
|
||||
/// \ecpp
|
||||
///
|
||||
inline namespace literals
|
||||
{
|
||||
/// \brief Parses TOML data from a string.
|
||||
@ -3339,3 +3372,4 @@ namespace toml
|
||||
|
||||
}
|
||||
}
|
||||
TOML_END
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include "toml_date_time.h"
|
||||
|
||||
namespace toml::impl
|
||||
TOML_IMPL_START
|
||||
{
|
||||
// Q: "why does print_to_stream() exist? why not just use ostream::write(), ostream::put() etc?"
|
||||
// A: - I'm supporting C++20's char8_t as well; wrapping streams allows switching string modes transparently.
|
||||
@ -115,7 +115,7 @@ namespace toml::impl
|
||||
#undef TOML_P2S_OVERLOAD
|
||||
|
||||
template <typename T, typename CHAR>
|
||||
inline void print_floating_point_to_stream(T val, std::basic_ostream<CHAR>& stream) TOML_MAY_THROW
|
||||
inline void print_floating_point_to_stream(T val, std::basic_ostream<CHAR>& stream, bool hexfloat = false) TOML_MAY_THROW
|
||||
{
|
||||
static_assert(
|
||||
sizeof(CHAR) == 1,
|
||||
@ -133,6 +133,9 @@ namespace toml::impl
|
||||
#if TOML_USE_STREAMS_FOR_FLOATS
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss.precision(std::numeric_limits<T>::digits10 + 1);
|
||||
if (hexfloat)
|
||||
oss << std::hexfloat;
|
||||
oss << val;
|
||||
const auto str = oss.str();
|
||||
print_to_stream(str, stream);
|
||||
@ -142,7 +145,9 @@ namespace toml::impl
|
||||
#else
|
||||
{
|
||||
TOML_GCC_ATTR(uninitialized) char buf[charconv_buffer_length<T>];
|
||||
const auto res = std::to_chars(buf, buf + sizeof(buf), val);
|
||||
const auto res = hexfloat
|
||||
? std::to_chars(buf, buf + sizeof(buf), val, std::chars_format::hex)
|
||||
: std::to_chars(buf, buf + sizeof(buf), val);
|
||||
const auto str = std::string_view{ buf, static_cast<size_t>(res.ptr - buf) };
|
||||
print_to_stream(str, stream);
|
||||
if (needs_decimal_point(str))
|
||||
@ -283,8 +288,9 @@ namespace toml::impl
|
||||
|
||||
TOML_POP_WARNINGS
|
||||
}
|
||||
TOML_IMPL_END
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
template <typename CHAR>
|
||||
std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const source_position& rhs)
|
||||
@ -319,3 +325,4 @@ namespace toml
|
||||
return lhs;
|
||||
}
|
||||
}
|
||||
TOML_END
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include "toml_array.h"
|
||||
|
||||
namespace toml::impl
|
||||
TOML_IMPL_START
|
||||
{
|
||||
template <bool is_const>
|
||||
struct table_proxy_pair final
|
||||
@ -109,8 +109,9 @@ namespace toml::impl
|
||||
{}
|
||||
};
|
||||
}
|
||||
TOML_IMPL_END
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
/// \brief A TOML table.
|
||||
///
|
||||
@ -778,3 +779,4 @@ namespace toml
|
||||
friend inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>&, const table&) TOML_MAY_THROW;
|
||||
};
|
||||
}
|
||||
TOML_END
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "toml_utf8_generated.h"
|
||||
#endif // TOML_LANG_HIGHER_THAN(0, 5, 0)
|
||||
|
||||
namespace toml::impl
|
||||
TOML_IMPL_START
|
||||
{
|
||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||
constexpr bool is_ascii_whitespace(char32_t codepoint) noexcept
|
||||
@ -603,4 +603,4 @@ namespace toml::impl
|
||||
#undef TOML_ERROR_CHECK
|
||||
#undef TOML_ERROR
|
||||
}
|
||||
|
||||
TOML_IMPL_END
|
||||
|
@ -6,7 +6,7 @@
|
||||
TOML_ASSUME(codepoint >= first); \
|
||||
TOML_ASSUME(codepoint <= last)
|
||||
|
||||
namespace toml::impl
|
||||
TOML_IMPL_START
|
||||
{
|
||||
//# Returns true if a codepoint belongs to any of these categories: Ll, Lm, Lo, Lt, Lu
|
||||
[[nodiscard]]
|
||||
@ -981,5 +981,6 @@ namespace toml::impl
|
||||
// chunk summary: 2255 codepoints from 282 ranges (spanning a search area of 917232)
|
||||
}
|
||||
}
|
||||
TOML_IMPL_END
|
||||
|
||||
#undef TOML_ASSUME_CODEPOINT_BETWEEN
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "toml_node.h"
|
||||
#include "toml_print_to_stream.h"
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
/// \brief A TOML value.
|
||||
///
|
||||
@ -92,6 +92,7 @@ namespace toml
|
||||
[[nodiscard]] bool is_string() const noexcept override { return std::is_same_v<T, string>; }
|
||||
[[nodiscard]] bool is_integer() const noexcept override { return std::is_same_v<T, int64_t>; }
|
||||
[[nodiscard]] bool is_floating_point() const noexcept override { return std::is_same_v<T, double>; }
|
||||
[[nodiscard]] bool is_number() const noexcept override { return impl::is_one_of<T, int64_t, double>; }
|
||||
[[nodiscard]] bool is_boolean() const noexcept override { return std::is_same_v<T, bool>; }
|
||||
[[nodiscard]] bool is_date() const noexcept override { return std::is_same_v<T, date>; }
|
||||
[[nodiscard]] bool is_time() const noexcept override { return std::is_same_v<T, time>; }
|
||||
@ -326,6 +327,9 @@ namespace toml
|
||||
value(uint8_t) -> value<int64_t>;
|
||||
value(uint16_t) -> value<int64_t>;
|
||||
value(uint32_t) -> value<int64_t>;
|
||||
value(date) -> value<date>;
|
||||
value(time) -> value<time>;
|
||||
value(date_time) -> value<date_time>;
|
||||
#ifdef TOML_SMALL_FLOAT_TYPE
|
||||
value(TOML_SMALL_FLOAT_TYPE) -> value<double>;
|
||||
#endif
|
||||
@ -333,3 +337,4 @@ namespace toml
|
||||
value(TOML_SMALL_INT_TYPE) -> value<int64_t>;
|
||||
#endif
|
||||
}
|
||||
TOML_END
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#define TOML_LIB_MAJOR 0
|
||||
#define TOML_LIB_MINOR 1
|
||||
#define TOML_LIB_MINOR 2
|
||||
#define TOML_LIB_PATCH 0
|
||||
|
||||
#define TOML_LANG_MAJOR 0
|
||||
|
@ -504,11 +504,11 @@ def main():
|
||||
print('#pragma once', file=output_file)
|
||||
print('#include "toml_common.h"', file=output_file)
|
||||
print('\n#define TOML_ASSUME_CODEPOINT_BETWEEN(first, last)\t\\\n\tTOML_ASSUME(codepoint >= first);\t\t\t\t\\\n\tTOML_ASSUME(codepoint <= last)', file=output_file)
|
||||
print('\nnamespace toml::impl\n{', file=output_file, end='')
|
||||
print('\nTOML_IMPL_START\n{', file=output_file, end='')
|
||||
emit_function('is_unicode_letter', ('Ll', 'Lm', 'Lo', 'Lt', 'Lu'), output_file, codepoints)
|
||||
emit_function('is_unicode_number', ('Nd', 'Nl'), output_file, codepoints)
|
||||
emit_function('is_unicode_combining_mark', ('Mn', 'Mc'), output_file, codepoints)
|
||||
print('}\n\n#undef TOML_ASSUME_CODEPOINT_BETWEEN', file=output_file)
|
||||
print('}\nTOML_IMPL_END\n\n#undef TOML_ASSUME_CODEPOINT_BETWEEN', file=output_file)
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
|
@ -103,14 +103,14 @@ flt8 = 224_617.445_991_228
|
||||
parse_expected_value( "1.112_650_06e-17"sv, 1.11265006e-17 );
|
||||
|
||||
//toml/issues/562 - hexfloat literals
|
||||
#if TOML_LANG_HIGHER_THAN(0, 5, 0) && !TOML_USE_STREAMS_FOR_FLOATS
|
||||
#if TOML_LANG_HIGHER_THAN(0, 5, 0)
|
||||
parse_expected_value(" 0x10.1p0"sv, 0x10.1p0 );
|
||||
parse_expected_value(" 0x0.3p10"sv, 0x0.3p10 );
|
||||
parse_expected_value(" 0x12.2P2"sv, 0x12.2P2 );
|
||||
#else
|
||||
parsing_should_fail(S("flt = 0x10.1p0"sv));
|
||||
parsing_should_fail(S("flt = 0x0.3p10"sv));
|
||||
parsing_should_fail(S("flt = 0x12.2P2"sv));
|
||||
parsing_should_fail(S("val = 0x10.1p0"sv));
|
||||
parsing_should_fail(S("val = 0x0.3p10"sv));
|
||||
parsing_should_fail(S("val = 0x12.2P2"sv));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -152,11 +152,11 @@ void parsing_should_fail(std::basic_string_view<CHAR> toml_str) noexcept
|
||||
template <typename T>
|
||||
void parse_expected_value(std::string_view value_str, const T& expected) noexcept
|
||||
{
|
||||
std::string value;
|
||||
static constexpr auto value_key = "val = "sv;
|
||||
value.reserve(value_key.length() + value_str.length());
|
||||
value.append(value_key);
|
||||
value.append(value_str);
|
||||
std::string val;
|
||||
static constexpr auto key = "val = "sv;
|
||||
val.reserve(key.length() + value_str.length());
|
||||
val.append(key);
|
||||
val.append(value_str);
|
||||
|
||||
static constexpr auto is_val = [](char32_t codepoint) noexcept
|
||||
{
|
||||
@ -166,7 +166,7 @@ void parse_expected_value(std::string_view value_str, const T& expected) noexcep
|
||||
return !impl::is_whitespace(codepoint);
|
||||
};
|
||||
|
||||
source_position pos{ 1, static_cast<source_index>(value_key.length()) };
|
||||
source_position pos{ 1, static_cast<source_index>(key.length()) };
|
||||
source_position begin{}, end{};
|
||||
impl::utf8_decoder decoder;
|
||||
for (auto c : value_str)
|
||||
@ -198,31 +198,73 @@ void parse_expected_value(std::string_view value_str, const T& expected) noexcep
|
||||
end = begin;
|
||||
end.column++;
|
||||
|
||||
parsing_should_succeed(std::string_view{ value }, [&](table&& tbl) noexcept
|
||||
using value_type = impl::promoted<impl::remove_cvref_t<T>>;
|
||||
value<value_type> val_parsed;
|
||||
|
||||
parsing_should_succeed(std::string_view{ val }, [&](table&& tbl) noexcept
|
||||
{
|
||||
INFO("String being parsed: '"sv << val << "'"sv);
|
||||
|
||||
CHECK(tbl.size() == 1);
|
||||
const auto nv = tbl[S("val"sv)];
|
||||
auto nv = tbl[S("val"sv)];
|
||||
REQUIRE(nv);
|
||||
REQUIRE(nv.as<impl::promoted<T>>());
|
||||
REQUIRE(nv.as<value_type>());
|
||||
REQUIRE(nv.get()->type() == impl::node_type_of<T>);
|
||||
|
||||
//check the raw value
|
||||
CHECK(nv.as<impl::promoted<T>>()->get() == expected);
|
||||
// check the raw value
|
||||
CHECK(nv.as<value_type>()->get() == expected);
|
||||
CHECK(nv.value_or(T{}) == expected);
|
||||
|
||||
//check the value relops
|
||||
CHECK(*nv.as<impl::promoted<T>>() == expected);
|
||||
CHECK(expected == *nv.as<impl::promoted<T>>());
|
||||
CHECK(!(*nv.as<impl::promoted<T>>() != expected));
|
||||
CHECK(!(expected != *nv.as<impl::promoted<T>>()));
|
||||
// check the table relops
|
||||
CHECK(tbl == table{ { { S("val"sv), expected } } });
|
||||
CHECK(!(tbl != table{ { { S("val"sv), expected } } }));
|
||||
|
||||
//check the node_view relops
|
||||
// check the value relops
|
||||
CHECK(*nv.as<value_type>() == expected);
|
||||
CHECK(expected == *nv.as<value_type>());
|
||||
CHECK(!(*nv.as<value_type>() != expected));
|
||||
CHECK(!(expected != *nv.as<value_type>()));
|
||||
|
||||
// check the node_view relops
|
||||
CHECK(nv == expected);
|
||||
CHECK(expected == nv);
|
||||
CHECK(!(nv != expected));
|
||||
CHECK(!(expected != nv));
|
||||
|
||||
//make sure source info is correct
|
||||
// make sure source info is correct
|
||||
CHECK(nv.get()->source().begin == begin);
|
||||
CHECK(nv.get()->source().end == end);
|
||||
|
||||
// steal the val for round-trip tests
|
||||
val_parsed = std::move(*nv.as<value_type>());
|
||||
});
|
||||
|
||||
// check round-tripping
|
||||
value<value_type> val_reparsed;
|
||||
{
|
||||
std::string str;
|
||||
{
|
||||
auto tbl = table{ { { S("val"sv), *val_parsed } } };
|
||||
std::stringstream ss;
|
||||
ss << tbl;
|
||||
str = ss.str();
|
||||
}
|
||||
|
||||
parsing_should_succeed(std::string_view{ str }, [&](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl.size() == 1);
|
||||
auto nv = tbl[S("val"sv)];
|
||||
REQUIRE(nv);
|
||||
REQUIRE(nv.as<value_type>());
|
||||
REQUIRE(nv.get()->type() == impl::node_type_of<T>);
|
||||
|
||||
CHECK(nv.as<value_type>()->get() == expected);
|
||||
CHECK(nv.value_or(T{}) == expected);
|
||||
|
||||
val_reparsed = std::move(*nv.as<value_type>());
|
||||
});
|
||||
}
|
||||
CHECK(val_reparsed == val_parsed);
|
||||
CHECK(val_reparsed == expected);
|
||||
|
||||
}
|
||||
|
227
toml.hpp
227
toml.hpp
@ -1,6 +1,6 @@
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// toml++ v0.1.0
|
||||
// toml++ v0.2.0
|
||||
// https://github.com/marzer/tomlplusplus
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
@ -293,8 +293,19 @@
|
||||
__VA_ARGS__ [[nodiscard]] friend bool operator != (RHS rhs, LHS lhs) noexcept { return !(lhs == rhs); }
|
||||
#endif
|
||||
|
||||
#if !TOML_DOXYGEN
|
||||
#if TOML_EXCEPTIONS
|
||||
#define TOML_START namespace toml { inline namespace wex
|
||||
#else
|
||||
#define TOML_START namespace toml { inline namespace woex
|
||||
#endif
|
||||
#define TOML_END }
|
||||
#endif
|
||||
#define TOML_IMPL_START TOML_START { namespace impl
|
||||
#define TOML_IMPL_END } TOML_END
|
||||
|
||||
#define TOML_LIB_MAJOR 0
|
||||
#define TOML_LIB_MINOR 1
|
||||
#define TOML_LIB_MINOR 2
|
||||
#define TOML_LIB_PATCH 0
|
||||
|
||||
#define TOML_LANG_MAJOR 0
|
||||
@ -355,7 +366,9 @@ TOML_POP_WARNINGS
|
||||
#define TOML_STRING_PREFIX(S) S
|
||||
#endif
|
||||
|
||||
namespace toml
|
||||
namespace toml { }
|
||||
|
||||
TOML_START
|
||||
{
|
||||
using namespace std::string_literals;
|
||||
using namespace std::string_view_literals;
|
||||
@ -558,8 +571,9 @@ namespace toml
|
||||
|
||||
TOML_POP_WARNINGS
|
||||
}
|
||||
TOML_END
|
||||
|
||||
namespace toml::impl
|
||||
TOML_IMPL_START
|
||||
{
|
||||
template <typename T>
|
||||
using string_map = std::map<string, T, std::less<>>; //heterogeneous lookup
|
||||
@ -775,8 +789,9 @@ namespace toml::impl
|
||||
|
||||
#undef TOML_P2S_DECL
|
||||
}
|
||||
TOML_IMPL_END
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
template <typename T>
|
||||
inline constexpr bool is_table = std::is_same_v<impl::remove_cvref_t<T>, table>;
|
||||
@ -815,6 +830,7 @@ namespace toml
|
||||
}
|
||||
}
|
||||
}
|
||||
TOML_END
|
||||
|
||||
#pragma endregion
|
||||
//----------------- ↑ toml_common.h ----------------------------------------------------------------------------------
|
||||
@ -822,7 +838,7 @@ namespace toml
|
||||
//---------------------------------------- ↓ toml_date_time.h --------------------------------------------------------
|
||||
#pragma region
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
struct date final
|
||||
{
|
||||
@ -977,6 +993,7 @@ namespace toml
|
||||
}
|
||||
};
|
||||
}
|
||||
TOML_END
|
||||
|
||||
#pragma endregion
|
||||
//---------------------------------------- ↑ toml_date_time.h --------------------------------------------------------
|
||||
@ -984,7 +1001,7 @@ namespace toml
|
||||
//-------------------------------------------------------------- ↓ toml_print_to_stream.h ----------------------------
|
||||
#pragma region
|
||||
|
||||
namespace toml::impl
|
||||
TOML_IMPL_START
|
||||
{
|
||||
// Q: "why does print_to_stream() exist? why not just use ostream::write(), ostream::put() etc?"
|
||||
// A: - I'm supporting C++20's char8_t as well; wrapping streams allows switching string modes transparently.
|
||||
@ -1098,7 +1115,7 @@ namespace toml::impl
|
||||
#undef TOML_P2S_OVERLOAD
|
||||
|
||||
template <typename T, typename CHAR>
|
||||
inline void print_floating_point_to_stream(T val, std::basic_ostream<CHAR>& stream) TOML_MAY_THROW
|
||||
inline void print_floating_point_to_stream(T val, std::basic_ostream<CHAR>& stream, bool hexfloat = false) TOML_MAY_THROW
|
||||
{
|
||||
static_assert(
|
||||
sizeof(CHAR) == 1,
|
||||
@ -1116,6 +1133,9 @@ namespace toml::impl
|
||||
#if TOML_USE_STREAMS_FOR_FLOATS
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss.precision(std::numeric_limits<T>::digits10 + 1);
|
||||
if (hexfloat)
|
||||
oss << std::hexfloat;
|
||||
oss << val;
|
||||
const auto str = oss.str();
|
||||
print_to_stream(str, stream);
|
||||
@ -1125,7 +1145,9 @@ namespace toml::impl
|
||||
#else
|
||||
{
|
||||
TOML_GCC_ATTR(uninitialized) char buf[charconv_buffer_length<T>];
|
||||
const auto res = std::to_chars(buf, buf + sizeof(buf), val);
|
||||
const auto res = hexfloat
|
||||
? std::to_chars(buf, buf + sizeof(buf), val, std::chars_format::hex)
|
||||
: std::to_chars(buf, buf + sizeof(buf), val);
|
||||
const auto str = std::string_view{ buf, static_cast<size_t>(res.ptr - buf) };
|
||||
print_to_stream(str, stream);
|
||||
if (needs_decimal_point(str))
|
||||
@ -1266,8 +1288,9 @@ namespace toml::impl
|
||||
|
||||
TOML_POP_WARNINGS
|
||||
}
|
||||
TOML_IMPL_END
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
template <typename CHAR>
|
||||
std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const source_position& rhs)
|
||||
@ -1302,6 +1325,7 @@ namespace toml
|
||||
return lhs;
|
||||
}
|
||||
}
|
||||
TOML_END
|
||||
|
||||
#pragma endregion
|
||||
//-------------------------------------------------------------- ↑ toml_print_to_stream.h ----------------------------
|
||||
@ -1309,7 +1333,7 @@ namespace toml
|
||||
//--------------------------------------------------------------------------------------------- ↓ toml_node.h --------
|
||||
#pragma region
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
class TOML_INTERFACE node
|
||||
{
|
||||
@ -1364,6 +1388,7 @@ namespace toml
|
||||
[[nodiscard]] virtual bool is_string() const noexcept { return false; }
|
||||
[[nodiscard]] virtual bool is_integer() const noexcept { return false; }
|
||||
[[nodiscard]] virtual bool is_floating_point() const noexcept { return false; }
|
||||
[[nodiscard]] virtual bool is_number() const noexcept { return false; }
|
||||
[[nodiscard]] virtual bool is_boolean() const noexcept { return false; }
|
||||
[[nodiscard]] virtual bool is_date() const noexcept { return false; }
|
||||
[[nodiscard]] virtual bool is_time() const noexcept { return false; }
|
||||
@ -1619,6 +1644,7 @@ namespace toml
|
||||
}
|
||||
};
|
||||
}
|
||||
TOML_END
|
||||
|
||||
#pragma endregion
|
||||
//--------------------------------------------------------------------------------------------- ↑ toml_node.h --------
|
||||
@ -1626,7 +1652,7 @@ namespace toml
|
||||
//----------------- ↓ toml_value.h -----------------------------------------------------------------------------------
|
||||
#pragma region
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
template <typename T>
|
||||
class value final : public node
|
||||
@ -1684,6 +1710,7 @@ namespace toml
|
||||
[[nodiscard]] bool is_string() const noexcept override { return std::is_same_v<T, string>; }
|
||||
[[nodiscard]] bool is_integer() const noexcept override { return std::is_same_v<T, int64_t>; }
|
||||
[[nodiscard]] bool is_floating_point() const noexcept override { return std::is_same_v<T, double>; }
|
||||
[[nodiscard]] bool is_number() const noexcept override { return impl::is_one_of<T, int64_t, double>; }
|
||||
[[nodiscard]] bool is_boolean() const noexcept override { return std::is_same_v<T, bool>; }
|
||||
[[nodiscard]] bool is_date() const noexcept override { return std::is_same_v<T, date>; }
|
||||
[[nodiscard]] bool is_time() const noexcept override { return std::is_same_v<T, time>; }
|
||||
@ -1833,6 +1860,9 @@ namespace toml
|
||||
value(uint8_t) -> value<int64_t>;
|
||||
value(uint16_t) -> value<int64_t>;
|
||||
value(uint32_t) -> value<int64_t>;
|
||||
value(date) -> value<date>;
|
||||
value(time) -> value<time>;
|
||||
value(date_time) -> value<date_time>;
|
||||
#ifdef TOML_SMALL_FLOAT_TYPE
|
||||
value(TOML_SMALL_FLOAT_TYPE) -> value<double>;
|
||||
#endif
|
||||
@ -1840,6 +1870,7 @@ namespace toml
|
||||
value(TOML_SMALL_INT_TYPE) -> value<int64_t>;
|
||||
#endif
|
||||
}
|
||||
TOML_END
|
||||
|
||||
#pragma endregion
|
||||
//----------------- ↑ toml_value.h -----------------------------------------------------------------------------------
|
||||
@ -1847,7 +1878,7 @@ namespace toml
|
||||
//------------------------------------------ ↓ toml_array.h ----------------------------------------------------------
|
||||
#pragma region
|
||||
|
||||
namespace toml::impl
|
||||
TOML_IMPL_START
|
||||
{
|
||||
template <bool is_const>
|
||||
class array_iterator final
|
||||
@ -2020,8 +2051,9 @@ namespace toml::impl
|
||||
}
|
||||
}
|
||||
}
|
||||
TOML_IMPL_END
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
[[nodiscard]] bool operator == (const table& lhs, const table& rhs) noexcept;
|
||||
|
||||
@ -2429,6 +2461,7 @@ namespace toml
|
||||
friend inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>&, const array&) TOML_MAY_THROW;
|
||||
};
|
||||
}
|
||||
TOML_END
|
||||
|
||||
#pragma endregion
|
||||
//------------------------------------------ ↑ toml_array.h ----------------------------------------------------------
|
||||
@ -2436,7 +2469,7 @@ namespace toml
|
||||
//------------------------------------------------------------------- ↓ toml_table.h ---------------------------------
|
||||
#pragma region
|
||||
|
||||
namespace toml::impl
|
||||
TOML_IMPL_START
|
||||
{
|
||||
template <bool is_const>
|
||||
struct table_proxy_pair final
|
||||
@ -2544,8 +2577,9 @@ namespace toml::impl
|
||||
{}
|
||||
};
|
||||
}
|
||||
TOML_IMPL_END
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
class table final
|
||||
: public node
|
||||
@ -2792,6 +2826,7 @@ namespace toml
|
||||
friend inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>&, const table&) TOML_MAY_THROW;
|
||||
};
|
||||
}
|
||||
TOML_END
|
||||
|
||||
#pragma endregion
|
||||
//------------------------------------------------------------------- ↑ toml_table.h ---------------------------------
|
||||
@ -2799,7 +2834,7 @@ namespace toml
|
||||
//------------------------------------------------------------------------------------------ ↓ toml_node_view.h ------
|
||||
#pragma region
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
template <typename T>
|
||||
class node_view final
|
||||
@ -2824,20 +2859,18 @@ namespace toml
|
||||
[[nodiscard]] const viewed_type* get() const noexcept { return node_; }
|
||||
|
||||
[[nodiscard]] node_type type() const noexcept { return node_ ? node_->type() : node_type::none; }
|
||||
[[nodiscard]] bool is_table() const noexcept { return type() == node_type::table; }
|
||||
[[nodiscard]] bool is_array() const noexcept { return type() == node_type::array; }
|
||||
[[nodiscard]] bool is_value() const noexcept { return type() > node_type::array; }
|
||||
[[nodiscard]] bool is_string() const noexcept { return type() == node_type::string; }
|
||||
[[nodiscard]] bool is_integer() const noexcept { return type() == node_type::integer; }
|
||||
[[nodiscard]] bool is_floating_point() const noexcept { return type() == node_type::floating_point; }
|
||||
[[nodiscard]] bool is_boolean() const noexcept { return type() == node_type::boolean; }
|
||||
[[nodiscard]] bool is_date() const noexcept { return type() == node_type::date; }
|
||||
[[nodiscard]] bool is_time() const noexcept { return type() == node_type::time; }
|
||||
[[nodiscard]] bool is_date_time() const noexcept { return type() == node_type::date_time; }
|
||||
[[nodiscard]] bool is_array_of_tables() const noexcept
|
||||
{
|
||||
return node_ ? node_->is_array_of_tables() : false;
|
||||
}
|
||||
[[nodiscard]] bool is_table() const noexcept { return node_ && node_->is_table(); }
|
||||
[[nodiscard]] bool is_array() const noexcept { return node_ && node_->is_array(); }
|
||||
[[nodiscard]] bool is_value() const noexcept { return node_ && node_->is_value(); }
|
||||
[[nodiscard]] bool is_string() const noexcept { return node_ && node_->is_string(); }
|
||||
[[nodiscard]] bool is_integer() const noexcept { return node_ && node_->is_integer(); }
|
||||
[[nodiscard]] bool is_floating_point() const noexcept { return node_ && node_->is_floating_point(); }
|
||||
[[nodiscard]] bool is_number() const noexcept { return node_ && node_->is_number(); }
|
||||
[[nodiscard]] bool is_boolean() const noexcept { return node_ && node_->is_boolean(); }
|
||||
[[nodiscard]] bool is_date() const noexcept { return node_ && node_->is_date(); }
|
||||
[[nodiscard]] bool is_time() const noexcept { return node_ && node_->is_time(); }
|
||||
[[nodiscard]] bool is_date_time() const noexcept { return node_ && node_->is_date_time(); }
|
||||
[[nodiscard]] bool is_array_of_tables() const noexcept { return node_ && node_->is_array_of_tables(); }
|
||||
|
||||
template <typename U>
|
||||
[[nodiscard]]
|
||||
@ -2889,6 +2922,25 @@ namespace toml
|
||||
[[nodiscard]] const value<time>* as_time() const noexcept { return as<time>(); }
|
||||
[[nodiscard]] const value<date_time>* as_date_time() const noexcept { return as<date_time>(); }
|
||||
|
||||
template <typename U>
|
||||
[[nodiscard]] auto value_or(U&& default_value) const noexcept
|
||||
{
|
||||
static_assert(
|
||||
impl::is_value_or_promotable<impl::remove_cvref_t<U>>,
|
||||
"Default value type must be (or be promotable to) one of the TOML value types"
|
||||
);
|
||||
|
||||
using value_type = impl::promoted<impl::remove_cvref_t<U>>;
|
||||
using return_type = std::conditional_t<
|
||||
std::is_same_v<value_type, string>,
|
||||
std::conditional_t<std::is_same_v<impl::remove_cvref_t<U>, string>, string, string_view>,
|
||||
value_type
|
||||
>;
|
||||
if (auto val = node_ ? node_->template as<value_type>() : nullptr)
|
||||
return return_type{ **val };
|
||||
return return_type{ std::forward<U>(default_value) };
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template <typename N, typename FUNC>
|
||||
@ -3025,6 +3077,7 @@ namespace toml
|
||||
return { this->get(key) };
|
||||
}
|
||||
}
|
||||
TOML_END
|
||||
|
||||
#pragma endregion
|
||||
//------------------------------------------------------------------------------------------ ↑ toml_node_view.h ------
|
||||
@ -3038,7 +3091,7 @@ namespace toml
|
||||
TOML_ASSUME(codepoint >= first); \
|
||||
TOML_ASSUME(codepoint <= last)
|
||||
|
||||
namespace toml::impl
|
||||
TOML_IMPL_START
|
||||
{
|
||||
[[nodiscard]]
|
||||
constexpr bool is_unicode_letter(char32_t codepoint) noexcept
|
||||
@ -4010,12 +4063,13 @@ namespace toml::impl
|
||||
// chunk summary: 2255 codepoints from 282 ranges (spanning a search area of 917232)
|
||||
}
|
||||
}
|
||||
TOML_IMPL_END
|
||||
|
||||
#undef TOML_ASSUME_CODEPOINT_BETWEEN
|
||||
|
||||
#endif // TOML_LANG_HIGHER_THAN(0, 5, 0)
|
||||
|
||||
namespace toml::impl
|
||||
TOML_IMPL_START
|
||||
{
|
||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||
constexpr bool is_ascii_whitespace(char32_t codepoint) noexcept
|
||||
@ -4611,6 +4665,7 @@ namespace toml::impl
|
||||
#undef TOML_ERROR_CHECK
|
||||
#undef TOML_ERROR
|
||||
}
|
||||
TOML_IMPL_END
|
||||
|
||||
#pragma endregion
|
||||
//------------------ ↑ toml_utf8.h -----------------------------------------------------------------------------------
|
||||
@ -4618,7 +4673,7 @@ namespace toml::impl
|
||||
//------------------------------------------ ↓ toml_parser.h ---------------------------------------------------------
|
||||
#pragma region
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
#if TOML_DOXYGEN || !TOML_EXCEPTIONS
|
||||
|
||||
@ -4740,8 +4795,9 @@ namespace toml
|
||||
|
||||
#endif
|
||||
}
|
||||
TOML_END
|
||||
|
||||
namespace toml::impl
|
||||
TOML_IMPL_START
|
||||
{
|
||||
#if TOML_EXCEPTIONS
|
||||
#define TOML_ERROR_CHECK(...) (void)0
|
||||
@ -4874,6 +4930,7 @@ namespace toml::impl
|
||||
#if TOML_USE_STREAMS_FOR_FLOATS
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss.precision(std::numeric_limits<arg_t>::digits10 + 1);
|
||||
oss << arg;
|
||||
const auto str = oss.str();
|
||||
std::memcpy(ptr, str.c_str(), str.length());
|
||||
@ -5759,7 +5816,7 @@ namespace toml::impl
|
||||
TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
#if !TOML_USE_STREAMS_FOR_FLOATS && TOML_LANG_HIGHER_THAN(0, 5, 0) // toml/issues/562
|
||||
#if TOML_LANG_HIGHER_THAN(0, 5, 0) // toml/issues/562
|
||||
|
||||
[[nodiscard]]
|
||||
double parse_hex_float() TOML_MAY_THROW
|
||||
@ -5901,38 +5958,62 @@ namespace toml::impl
|
||||
|
||||
// convert to double
|
||||
TOML_GCC_ATTR(uninitialized) double result;
|
||||
auto fc_result = std::from_chars(chars, chars + length, result, std::chars_format::hex);
|
||||
switch (fc_result.ec)
|
||||
#if TOML_USE_STREAMS_FOR_FLOATS
|
||||
{
|
||||
case std::errc{}: //ok
|
||||
return result;
|
||||
std::string str;
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss.write("0x", 2_sz);
|
||||
ss.write(chars, static_cast<std::streamsize>(length));
|
||||
str = ss.str();
|
||||
}
|
||||
|
||||
case std::errc::invalid_argument:
|
||||
char* end = {};
|
||||
result = std::strtod(str.c_str(), &end);
|
||||
if (result == 0.0 && end == str.c_str())
|
||||
abort_with_error(
|
||||
"Error parsing hexadecimal "sv, node_type::floating_point,
|
||||
"; '"sv, std::string_view{ chars, length }, "' could not be interpreted as a value"sv
|
||||
);
|
||||
break;
|
||||
|
||||
case std::errc::result_out_of_range:
|
||||
abort_with_error(
|
||||
"Error parsing hexadecimal "sv, node_type::floating_point,
|
||||
"; '"sv, std::string_view{ chars, length }, "' is not representable in 64 bits"sv
|
||||
);
|
||||
break;
|
||||
|
||||
default: //??
|
||||
abort_with_error(
|
||||
"Error parsing hexadecimal "sv, node_type::floating_point,
|
||||
"; an unspecified error occurred while trying to interpret '",
|
||||
std::string_view{ chars, length }, "' as a value"sv
|
||||
);
|
||||
else
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
{
|
||||
auto fc_result = std::from_chars(chars, chars + length, result, std::chars_format::hex);
|
||||
switch (fc_result.ec)
|
||||
{
|
||||
case std::errc{}: //ok
|
||||
return result;
|
||||
|
||||
case std::errc::invalid_argument:
|
||||
abort_with_error(
|
||||
"Error parsing hexadecimal "sv, node_type::floating_point,
|
||||
"; '"sv, std::string_view{ chars, length }, "' could not be interpreted as a value"sv
|
||||
);
|
||||
break;
|
||||
|
||||
case std::errc::result_out_of_range:
|
||||
abort_with_error(
|
||||
"Error parsing hexadecimal "sv, node_type::floating_point,
|
||||
"; '"sv, std::string_view{ chars, length }, "' is not representable in 64 bits"sv
|
||||
);
|
||||
break;
|
||||
|
||||
default: //??
|
||||
abort_with_error(
|
||||
"Error parsing hexadecimal "sv, node_type::floating_point,
|
||||
"; an unspecified error occurred while trying to interpret '",
|
||||
std::string_view{ chars, length }, "' as a value"sv
|
||||
);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
TOML_ERROR_CHECK({});
|
||||
TOML_UNREACHABLE;
|
||||
}
|
||||
|
||||
#endif //!TOML_USE_STREAMS_FOR_FLOATS && TOML_LANG_HIGHER_THAN(0, 5, 0)
|
||||
#endif //TOML_LANG_HIGHER_THAN(0, 5, 0)
|
||||
|
||||
template <int base>
|
||||
[[nodiscard]]
|
||||
@ -6738,14 +6819,6 @@ namespace toml::impl
|
||||
begin_pos,
|
||||
reader.source_path()
|
||||
);
|
||||
#elif TOML_USE_STREAMS_FOR_FLOATS
|
||||
TOML_ERROR(
|
||||
"Hexadecimal floating-point values are not "
|
||||
"supported when streams are used to interpret floats "
|
||||
"(TOML_USE_STREAMS_FOR_FLOATS = 1).",
|
||||
begin_pos,
|
||||
reader.source_path()
|
||||
);
|
||||
#else
|
||||
val = std::make_unique<value<double>>(parse_hex_float());
|
||||
break;
|
||||
@ -7617,8 +7690,9 @@ namespace toml::impl
|
||||
#undef TOML_ERROR
|
||||
#undef TOML_NORETURN
|
||||
}
|
||||
TOML_IMPL_END
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
[[nodiscard]]
|
||||
inline parse_result parse(std::string_view doc, std::string_view source_path = {}) TOML_MAY_THROW
|
||||
@ -7711,6 +7785,7 @@ namespace toml
|
||||
|
||||
}
|
||||
}
|
||||
TOML_END
|
||||
|
||||
#pragma endregion
|
||||
//------------------------------------------ ↑ toml_parser.h ---------------------------------------------------------
|
||||
@ -7718,7 +7793,7 @@ namespace toml
|
||||
//----------------------------------------------------------------- ↓ toml_formatter.h -------------------------------
|
||||
#pragma region
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
enum class format_flags : uint8_t
|
||||
{
|
||||
@ -7734,8 +7809,9 @@ namespace toml
|
||||
return static_cast<format_flags>( impl::unbox_enum(lhs) | impl::unbox_enum(rhs) );
|
||||
}
|
||||
}
|
||||
TOML_END
|
||||
|
||||
namespace toml::impl
|
||||
TOML_IMPL_START
|
||||
{
|
||||
template <typename CHAR = char>
|
||||
class formatter
|
||||
@ -7856,6 +7932,7 @@ namespace toml::impl
|
||||
{}
|
||||
};
|
||||
}
|
||||
TOML_IMPL_END
|
||||
|
||||
#pragma endregion
|
||||
//----------------------------------------------------------------- ↑ toml_formatter.h -------------------------------
|
||||
@ -7863,7 +7940,7 @@ namespace toml::impl
|
||||
//-------------------------------------------------------------------------------------- ↓ toml_default_formatter.h --
|
||||
#pragma region
|
||||
|
||||
namespace toml::impl
|
||||
TOML_IMPL_START
|
||||
{
|
||||
TOML_PUSH_WARNINGS
|
||||
TOML_DISABLE_ALL_WARNINGS
|
||||
@ -7990,8 +8067,9 @@ namespace toml::impl
|
||||
return (default_formatter_inline_columns(node) + starting_column_bias) > 120_sz;
|
||||
}
|
||||
}
|
||||
TOML_IMPL_END
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
template <typename CHAR = char>
|
||||
class default_formatter final : impl::formatter<CHAR>
|
||||
@ -8317,6 +8395,7 @@ namespace toml
|
||||
return lhs << default_formatter<CHAR>{ rhs };
|
||||
}
|
||||
}
|
||||
TOML_END
|
||||
|
||||
#pragma endregion
|
||||
//-------------------------------------------------------------------------------------- ↑ toml_default_formatter.h --
|
||||
@ -8324,7 +8403,7 @@ namespace toml
|
||||
//------------- ↓ toml_json_formatter.h ------------------------------------------------------------------------------
|
||||
#pragma region
|
||||
|
||||
namespace toml
|
||||
TOML_START
|
||||
{
|
||||
template <typename CHAR = char>
|
||||
class json_formatter final : impl::formatter<CHAR>
|
||||
@ -8443,13 +8522,13 @@ namespace toml
|
||||
base::clear_naked_newline();
|
||||
}
|
||||
}
|
||||
TOML_END
|
||||
|
||||
#pragma endregion
|
||||
//------------- ↑ toml_json_formatter.h ------------------------------------------------------------------------------
|
||||
|
||||
// macro hygiene
|
||||
#if TOML_UNDEF_MACROS
|
||||
#undef TOML_EXCEPTIONS
|
||||
#undef TOML_USE_STREAMS_FOR_FLOATS
|
||||
#undef TOML_GCC_ATTR
|
||||
#undef TOML_PUSH_WARNINGS
|
||||
@ -8483,6 +8562,10 @@ namespace toml
|
||||
#undef TOML_DOXYGEN
|
||||
#undef TOML_RELOPS_REORDERING
|
||||
#undef TOML_ASYMMETRICAL_EQUALITY_OPS
|
||||
#undef TOML_START
|
||||
#undef TOML_END
|
||||
#undef TOML_IMPL_START
|
||||
#undef TOML_IMPL_END
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
Loading…
x
Reference in New Issue
Block a user