fixed some incorrect handling of vertical whitespace when printing TOML to streams

also:
- added `date_time` converting constructors from `date` and `time`
- added `is_key<>` and is_key_or_convertible<>` metafunctions
- exposed `TOML_NAMESPACE_START` and `TOML_NAMESPACE_END` macros to help with ADL specialization scenarios
- added encoder and decoder for `toml-test` (closes #125)
This commit is contained in:
Mark Gillard 2022-01-03 20:51:03 +02:00
parent 6d381b698f
commit f3bd22bff4
38 changed files with 854 additions and 145 deletions

3
.gitmodules vendored
View File

@ -13,3 +13,6 @@
[submodule "external/tloptional"]
path = external/tloptional
url = https://github.com/TartanLlama/optional.git
[submodule "external/json"]
path = external/json
url = https://github.com/nlohmann/json.git

View File

@ -28,6 +28,8 @@ code changes at callsites or in build systems are indicated with ⚠&#xFE0F;.
- fixed an illegal table redefinition edge case (#112) (@python36)
- fixed documentation issues
- fixed incorrect source position in redefinition error messages
- fixed incorrect handling of vertical whitespace in keys when printing TOML to streams
- fixed memory leak during parse failures when compiled using GCC (#123, #124) (@rsmmr, @ronalabraham)
- fixed missing `#include <initializer_list>`
- fixed missing `#include <utility>`
- fixed missing `TOML_API` on interfaces
@ -41,6 +43,7 @@ code changes at callsites or in build systems are indicated with ⚠&#xFE0F;.
- added `toml::array::prune()`
- added `toml::array::replace()` (#109) (@LebJe)
- added `toml::array::resize()` param `default_init_flags`
- added `toml::date_time` converting constructors from `toml::date` and `toml::time`
- added `toml::format_flags::allow_binary_integers`
- added `toml::format_flags::allow_hexadecimal_integers`
- added `toml::format_flags::allow_octal_integers`
@ -49,6 +52,7 @@ code changes at callsites or in build systems are indicated with ⚠&#xFE0F;.
- added `toml::format_flags::indent_sub_tables`
- added `toml::format_flags::quote_infinities_and_nans`
- added `toml::key` - provides a facility to access the source_regions of parsed keys (#82) (@vaartis)
- added `toml::is_key<>` and toml::is_key_or_convertible<>` metafunctions
- added `toml::table::at()` (same semantics as `std::map::at()`)
- added `toml::table::emplace_hint()` (same semantics as `std::map::emplace_hint()`)
- added `toml::table::lower_bound()` (same semantics as `std::map::lower_bound()`)
@ -79,6 +83,7 @@ code changes at callsites or in build systems are indicated with ⚠&#xFE0F;.
- moved all implementation headers to `/impl`
- renamed all implementation headers to `.h` and 'source' headers to `.inl`
- updated conformance tests
- exposed `TOML_NAMESPACE_START` and `TOML_NAMESPACE_END` macros to help with ADL specialization scenarios
#### Removals:
- ⚠&#xFE0F; removed `toml::format_flags::allow_value_format_flags`

View File

@ -29,7 +29,7 @@ git submodule update --init --depth 1 external/Catch2 external/tloptional
### Testing on Windows with Visual Studio
Install [Visual Studio] and [Test Adapter for Catch2], then open `vs/toml++.sln` and build the
Install [Visual Studio] and [Test Adapter for Catch2], then open `toml++.sln` and build the
projects in the `tests` solution folder. Visual Studio's Test Explorer should pick these up and
allow you to run the tests directly.
@ -64,6 +64,13 @@ cd build-gcc-debug && ninja && ninja test \
&& cd ..
```
<br>
## Testing with the [toml-test] suite
As an optional extra you may wish to test against the 'official' test TOML test suite, [BurntSushi/toml-test]. See the
instructions at [toml-test/README](./toml-test/README.md). Note that the toml++ tests already consume tests from the
offical suite via a C++ code-generation script so you are not expected to take this extra step as part of contributing
to the library.
[Visual Studio]: https://visualstudio.microsoft.com/vs/
[Test Adapter for Catch2]: https://marketplace.visualstudio.com/items?itemName=JohnnyHendriks.ext01
@ -71,3 +78,5 @@ cd build-gcc-debug && ninja && ninja test \
[Catch2]: https://github.com/catchorg/Catch2
[meson]: https://mesonbuild.com/Getting-meson.html
[ninja]: https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages
[toml-test]: https://github.com/BurntSushi/toml-test
[BurntSushi/toml-test]: https://github.com/BurntSushi/toml-test

View File

@ -132,6 +132,11 @@ FetchContent_MakeAvailable(tomlplusplus)
in the C++ ecosystem. I'm also a cmake novice, for better or worse. If there's an integration option missing be
assured that I fully support it being added, and welcome [pull requests](./CONTRIBUTING.md)!
### What about dependencies?
If you just want to consume `toml++` as a regular library then you don't have any dependencies to worry about.
There's a few test-related dependencies to be aware of if you're working on the library, though.
See [CONTRIBUTING] for information.
<br>
# Configuration

View File

@ -6,7 +6,7 @@
// This example shows the error messages the library produces by forcing a set of specific parsing
// failures and printing their results.
#include "examples.h"
#include "examples.hpp"
#define TOML_EXCEPTIONS 0
#define TOML_ENABLE_UNRELEASED_FEATURES 0

View File

@ -55,7 +55,7 @@
<Text Include="CMakeLists.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="examples.h" />
<ClInclude Include="examples.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
</Project>

View File

@ -5,7 +5,7 @@
// This example is just a short-n-shiny benchmark.
#include "examples.h"
#include "examples.hpp"
#include <toml++/toml.h>
using namespace std::string_view_literals;

View File

@ -56,7 +56,7 @@
<Text Include="CMakeLists.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="examples.h" />
<ClInclude Include="examples.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
</Project>

View File

@ -5,7 +5,7 @@
// This example demonstrates how to parse TOML from a file or stdin and re-serialize it (print it out) to stdout.
#include "examples.h"
#include "examples.hpp"
#define TOML_ENABLE_UNRELEASED_FEATURES 1
#include <toml++/toml.h>
@ -16,16 +16,16 @@ int main(int argc, char** argv)
{
const auto path = argc > 1 ? std::string_view{ argv[1] } : "example.toml"sv;
toml::table table;
toml::table tbl;
try
{
// read directly from stdin
if (path == "-"sv || path.empty())
table = toml::parse(std::cin, "stdin"sv);
tbl = toml::parse(std::cin, "stdin"sv);
// read from a file
else
table = toml::parse_file(path);
tbl = toml::parse_file(path);
}
catch (const toml::parse_error& err)
{
@ -33,6 +33,6 @@ int main(int argc, char** argv)
return 1;
}
std::cout << table << "\n";
std::cout << tbl << "\n";
return 0;
}

View File

@ -56,7 +56,7 @@
<Text Include="CMakeLists.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="examples.h" />
<ClInclude Include="examples.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
</Project>

View File

@ -5,7 +5,7 @@
// This example demonstrates the use of some more advanced features to generate a tree of random TOML data.
#include "examples.h"
#include "examples.hpp"
#define TOML_ENABLE_PARSER 0
#include <toml++/toml.h>

View File

@ -56,7 +56,7 @@
<Text Include="CMakeLists.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="examples.h" />
<ClInclude Include="examples.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
</Project>

View File

@ -5,7 +5,7 @@
// This example demonstrates how to use the toml::json_formatter to re-serialize TOML data as JSON.
#include "examples.h"
#include "examples.hpp"
#define TOML_ENABLE_UNRELEASED_FEATURES 1
#include <toml++/toml.h>

View File

@ -56,7 +56,7 @@
<Text Include="CMakeLists.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="examples.h" />
<ClInclude Include="examples.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
</Project>

1
external/json vendored Submodule

@ -0,0 +1 @@
Subproject commit cc59ab122f75448c17ac623d10306cbe19cde970

View File

@ -347,6 +347,26 @@ TOML_NAMESPACE_START
offset{} // TINAE - icc bugfix
{}
/// \brief Constructs a local date-time.
///
/// \param d The date component.
TOML_NODISCARD_CTOR
explicit constexpr date_time(const toml::date& d) noexcept //
: date{ d },
time{},
offset{} // TINAE - icc bugfix
{}
/// \brief Constructs a local date-time.
///
/// \param t The time component.
TOML_NODISCARD_CTOR
explicit constexpr date_time(const toml::time& t) noexcept //
: date{},
time{ t },
offset{} // TINAE - icc bugfix
{}
/// \brief Constructs an offset date-time.
///
/// \param d The date component.

View File

@ -130,10 +130,15 @@ TOML_IMPL_NAMESPACE_START
}
else if (decoder.has_code_point())
{
if (is_vertical_whitespace(decoder.codepoint))
if (decoder.codepoint == U'\n')
{
has_line_breaks = true;
if (!multi_line)
has_control_chars = true;
}
else if (is_nontab_control_character(decoder.codepoint)
|| (treat_raw_tab_as_control_char && decoder.codepoint == U'\t'))
|| (treat_raw_tab_as_control_char && decoder.codepoint == U'\t')
|| is_vertical_whitespace(decoder.codepoint))
has_control_chars = true;
else if (decoder.codepoint == U'\'')
has_single_quotes = true;

View File

@ -927,15 +927,21 @@ TOML_NAMESPACE_START
/// \brief Metafunction for determining if a type is, or is a reference to, a std::string or toml::value<std::string>.
template <typename T>
inline constexpr bool is_string = std::is_same_v<impl::wrap_node<impl::remove_cvref<T>>, value<std::string>>;
inline constexpr bool is_string = std::is_same_v< //
impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, //
value<std::string>>;
/// \brief Metafunction for determining if a type is, or is a reference to, a int64_t or toml::value<int64_t>.
template <typename T>
inline constexpr bool is_integer = std::is_same_v<impl::wrap_node<impl::remove_cvref<T>>, value<int64_t>>;
inline constexpr bool is_integer = std::is_same_v< //
impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, //
value<int64_t>>;
/// \brief Metafunction for determining if a type is, or is a reference to, a double or toml::value<double>.
template <typename T>
inline constexpr bool is_floating_point = std::is_same_v<impl::wrap_node<impl::remove_cvref<T>>, value<double>>;
inline constexpr bool is_floating_point = std::is_same_v< //
impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, //
value<double>>;
/// \brief Metafunction for determining if a type satisfies either toml::is_integer or toml::is_floating_point.
template <typename T>
@ -943,19 +949,27 @@ TOML_NAMESPACE_START
/// \brief Metafunction for determining if a type is, or is a reference to, a bool or toml::value<bool>.
template <typename T>
inline constexpr bool is_boolean = std::is_same_v<impl::wrap_node<impl::remove_cvref<T>>, value<bool>>;
inline constexpr bool is_boolean = std::is_same_v< //
impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, //
value<bool>>;
/// \brief Metafunction for determining if a type is, or is a reference to, a toml::date or toml::value<date>.
template <typename T>
inline constexpr bool is_date = std::is_same_v<impl::wrap_node<impl::remove_cvref<T>>, value<date>>;
inline constexpr bool is_date = std::is_same_v< //
impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, //
value<date>>;
/// \brief Metafunction for determining if a type is, or is a reference to, a toml::time or toml::value<time>.
template <typename T>
inline constexpr bool is_time = std::is_same_v<impl::wrap_node<impl::remove_cvref<T>>, value<time>>;
inline constexpr bool is_time = std::is_same_v< //
impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, //
value<time>>;
/// \brief Metafunction for determining if a type is, or is a reference to, a toml::date_time or toml::value<date_time>.
template <typename T>
inline constexpr bool is_date_time = std::is_same_v<impl::wrap_node<impl::remove_cvref<T>>, value<date_time>>;
inline constexpr bool is_date_time = std::is_same_v< //
impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, //
value<date_time>>;
/// \brief Metafunction for determining if a type satisfies any of toml::is_date, toml::is_time or toml::is_date_time.
template <typename T>

View File

@ -294,19 +294,17 @@ TOML_NAMESPACE_START
return lhs;
}
};
/// \brief Metafunction for determining if a type is, or is a reference to, a toml::key.
template <typename T>
inline constexpr bool is_key = std::is_same_v<impl::remove_cvref<T>, toml::key>;
/// \brief Metafunction for determining if a type is, or is a reference to, a toml::key,
/// or is implicitly or explicitly convertible to one.
template <typename T>
inline constexpr bool is_key_or_convertible =
is_key<T> || std::is_constructible_v<toml::key, T> || std::is_convertible_v<T, toml::key>;
}
TOML_NAMESPACE_END;
/// \cond
TOML_IMPL_NAMESPACE_START
{
template <typename T>
inline constexpr bool is_key = std::is_same_v<remove_cvref<T>, toml::key>;
template <typename T>
inline constexpr bool is_key_or_convertible = is_key<T> || std::is_constructible_v<toml::key, T>;
}
TOML_IMPL_NAMESPACE_END;
/// \endcond
#include "header_end.h"

View File

@ -346,6 +346,20 @@
#endif
//#====================================================================================================================
//# CPP VERSION
//#====================================================================================================================
#ifndef TOML_CPP_VERSION
#define TOML_CPP_VERSION __cplusplus
#endif
#if TOML_CPP_VERSION < 201103L
#error toml++ requires C++17 or higher. For a TOML library supporting pre-C++11 see https://github.com/ToruNiina/Boost.toml
#elif TOML_CPP_VERSION < 201703L
#error toml++ requires C++17 or higher. For a TOML library supporting C++11 see https://github.com/ToruNiina/toml11
#endif
#undef TOML_CPP_VERSION
//#====================================================================================================================
//# USER CONFIGURATION
//#====================================================================================================================
@ -453,10 +467,34 @@
#define TOML_HAS_CUSTOM_OPTIONAL_TYPE 0
#endif
// exceptions (compiler support)
#ifndef TOML_COMPILER_EXCEPTIONS
#if defined(__EXCEPTIONS) || defined(__cpp_exceptions)
#define TOML_COMPILER_EXCEPTIONS 1
#else
#define TOML_COMPILER_EXCEPTIONS 0
#endif
#endif
// exceptions (library use)
#if TOML_COMPILER_EXCEPTIONS
#if !defined(TOML_EXCEPTIONS) || (defined(TOML_EXCEPTIONS) && TOML_EXCEPTIONS)
#undef TOML_EXCEPTIONS
#define TOML_EXCEPTIONS 1
#endif
#else
#if defined(TOML_EXCEPTIONS) && TOML_EXCEPTIONS
#error TOML_EXCEPTIONS was explicitly enabled but exceptions are disabled/unsupported by the compiler.
#endif
#undef TOML_EXCEPTIONS
#define TOML_EXCEPTIONS 0
#endif
#ifndef TOML_UNDEF_MACROS
#define TOML_UNDEF_MACROS 1
#endif
#ifndef TOML_MAX_NESTED_VALUES
#define TOML_MAX_NESTED_VALUES 256
// this refers to the depth of nested values, e.g. inline tables and arrays.
@ -479,35 +517,8 @@
//# ATTRIBUTES, UTILITY MACROS ETC
//#====================================================================================================================
#ifndef TOML_CPP_VERSION
#define TOML_CPP_VERSION __cplusplus
#endif
#if TOML_CPP_VERSION < 201103L
#error toml++ requires C++17 or higher. For a TOML library supporting pre-C++11 see https://github.com/ToruNiina/Boost.toml
#elif TOML_CPP_VERSION < 201703L
#error toml++ requires C++17 or higher. For a TOML library supporting C++11 see https://github.com/ToruNiina/toml11
#endif
#undef TOML_CPP_VERSION
#ifndef TOML_COMPILER_EXCEPTIONS
#if defined(__EXCEPTIONS) || defined(__cpp_exceptions)
#define TOML_COMPILER_EXCEPTIONS 1
#else
#define TOML_COMPILER_EXCEPTIONS 0
#endif
#endif
#if TOML_COMPILER_EXCEPTIONS
#if !defined(TOML_EXCEPTIONS) || (defined(TOML_EXCEPTIONS) && TOML_EXCEPTIONS)
#undef TOML_EXCEPTIONS
#define TOML_EXCEPTIONS 1
#endif
#else
#if defined(TOML_EXCEPTIONS) && TOML_EXCEPTIONS
#error TOML_EXCEPTIONS was explicitly enabled but exceptions are disabled/unsupported by the compiler.
#endif
#undef TOML_EXCEPTIONS
#define TOML_EXCEPTIONS 0
#endif
#if TOML_GCC || TOML_CLANG || (TOML_ICC && !TOML_ICC_CL)
// not supported by any version of GCC or Clang as of 26/11/2020

View File

@ -1181,7 +1181,7 @@ TOML_NAMESPACE_START
/// \returns An iterator to the emplacement position (or the position of the value that prevented emplacement)
///
/// \note This function has exactly the same semantics as [std::map::emplace_hint()](https://en.cppreference.com/w/cpp/container/map/emplace_hint).
TOML_CONSTRAINED_TEMPLATE((impl::is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>),
TOML_CONSTRAINED_TEMPLATE((is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>),
typename ValueType,
typename KeyType,
typename... ValueArgs)
@ -1297,7 +1297,7 @@ TOML_NAMESPACE_START
/// \attention The return value will always be `{ end(), false }` if the input value was an
/// null toml::node_view, because no insertion can take place. This is the only circumstance
/// in which this can occur.
TOML_CONSTRAINED_TEMPLATE((impl::is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>),
TOML_CONSTRAINED_TEMPLATE((is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>),
typename KeyType,
typename ValueType)
std::pair<iterator, bool> insert(KeyType&& key,
@ -1376,7 +1376,7 @@ TOML_NAMESPACE_START
/// \remarks This function is morally equivalent to calling `insert(key, value)` for each
/// key-value pair covered by the iterator range, so any values with keys already found in the
/// table will not be replaced.
TOML_CONSTRAINED_TEMPLATE((!impl::is_key_or_convertible<Iter> && !impl::is_wide_string<Iter>), typename Iter)
TOML_CONSTRAINED_TEMPLATE((!is_key_or_convertible<Iter> && !impl::is_wide_string<Iter>), typename Iter)
void insert(Iter begin, Iter end, value_flags flags = preserve_source_value_flags)
{
if (begin == end)
@ -1442,7 +1442,7 @@ TOML_NAMESPACE_START
/// \attention The return value will always be `{ end(), false }` if the input value was
/// a null toml::node_view, because no insertion or assignment can take place.
/// This is the only circumstance in which this can occur.
TOML_CONSTRAINED_TEMPLATE((impl::is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>),
TOML_CONSTRAINED_TEMPLATE((is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>),
typename KeyType,
typename ValueType)
std::pair<iterator, bool> insert_or_assign(KeyType&& key,
@ -1525,7 +1525,7 @@ TOML_NAMESPACE_START
/// - A boolean indicating if the emplacement was successful.
///
/// \remark There is no difference between insert() and emplace() for trivial value types (floats, ints, bools).
TOML_CONSTRAINED_TEMPLATE((impl::is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>),
TOML_CONSTRAINED_TEMPLATE((is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>),
typename ValueType,
typename KeyType,
typename... ValueArgs)

View File

@ -88,8 +88,6 @@ TOML_POP_WARNINGS;
#undef TOML_CLOSED_ENUM
#undef TOML_CLOSED_FLAGS_ENUM
#undef TOML_COMPILER_EXCEPTIONS
#undef TOML_CONCAT
#undef TOML_CONCAT_1
#undef TOML_CONST_GETTER
#undef TOML_CONST_INLINE_GETTER
#undef TOML_CONSTRAINED_TEMPLATE
@ -143,8 +141,6 @@ TOML_POP_WARNINGS;
#undef TOML_MAKE_VERSION
#undef TOML_MSVC
#undef TOML_NAMESPACE
#undef TOML_NAMESPACE_END
#undef TOML_NAMESPACE_START
#undef TOML_NEVER_INLINE
#undef TOML_NODISCARD
#undef TOML_NODISCARD_CTOR

View File

@ -496,6 +496,11 @@ if build_examples
subdir('examples')
endif
build_tt = (get_option('build_tt_encoder') or get_option('build_tt_encoder')) and not is_subproject
if build_tt
subdir('toml-test')
endif
if not is_subproject
install_subdir('include'/'toml++',
strip_directory: true,

View File

@ -5,4 +5,6 @@ option('pedantic', type: 'boolean', value: false, description: 'Enable as man
option('time_trace', type: 'boolean', value: false, description: 'Enable the -ftime-trace option (Clang only)')
option('asan_examples', type: 'boolean', value: false)
option('asan_tests', type: 'boolean', value: false)
option('build_tt_encoder', type: 'boolean', value: false, description: 'Enable to build the toml-test encoder.')
option('build_tt_decoder', type: 'boolean', value: false, description: 'Enable to build the toml-test decoder.')

View File

@ -395,16 +395,16 @@ zyx = 42)"sv;
zyx = 42)"sv;
static constexpr auto table_quoted_no_close = R"(["where will it end]
name = value)"sv;
static constexpr auto table_redefine = R"(# Define b as int, and try to use it as a table: error
static constexpr auto table_redefine = R"(# Define b as int, and try to use it as a table: error
[a]
b = 1
[a.b]
c = 2)"sv;
static constexpr auto table_rrbrace = R"([[table] ])"sv;
static constexpr auto table_text_after_table = R"([error] this shouldn't be here)"sv;
static constexpr auto table_whitespace = R"([invalid key])"sv;
static constexpr auto table_with_pound = R"([key#group]
static constexpr auto table_rrbrace = R"([[table] ])"sv;
static constexpr auto table_text_after_table = R"([error] this shouldn't be here)"sv;
static constexpr auto table_whitespace = R"([invalid key])"sv;
static constexpr auto table_with_pound = R"([key#group]
answer = 42)"sv;
}

View File

@ -433,6 +433,19 @@ hosts = [
static constexpr auto string_double_quote_escape = R"(test = "\"one\"")"sv;
static constexpr auto string_empty = R"(answer = "")"sv;
static constexpr auto string_escaped_escape = R"(answer = "\\x64")"sv;
static constexpr auto string_escapes = R"(backspace = "This string has a \b backspace character."
tab = "This string has a \t tab character."
newline = "This string has a \n new line character."
formfeed = "This string has a \f form feed character."
carriage = "This string has a \r carriage return character."
quote = "This string has a \" quote character."
backslash = "This string has a \\ backslash character."
notunicode1 = "This string does not have a unicode \\u escape."
notunicode2 = "This string does not have a unicode \u005Cu escape."
notunicode3 = "This string does not have a unicode \\u0075 escape."
notunicode4 = "This string does not have a unicode \\\u0075 escape."
delete = "This string has a \u007F delete control code."
unitseparator = "This string has a \u001F unit separator control code.")"sv;
static constexpr auto string_multiline_quotes =
R"(# Make sure that quotes inside multiline strings are allowed, including right
# after the opening '''/""" and before the closing '''/"""
@ -2119,6 +2132,29 @@ another line)"sv },
REQUIRE(tbl == expected);
});
parsing_should_succeed(FILE_LINE_ARGS,
string_escapes,
[](toml::table&& tbl) // string-escapes
{
const auto expected = toml::table{
{ R"(backslash)"sv, R"(This string has a \ backslash character.)"sv },
{ R"(backspace)"sv, "This string has a \x08 backspace character."sv },
{ R"(carriage)"sv, "This string has a \r carriage return character."sv },
{ R"(delete)"sv, "This string has a \x7F delete control code."sv },
{ R"(formfeed)"sv, "This string has a \x0C form feed character."sv },
{ R"(newline)"sv, R"(This string has a
new line character.)"sv },
{ R"(notunicode1)"sv, R"(This string does not have a unicode \u escape.)"sv },
{ R"(notunicode2)"sv, R"(This string does not have a unicode \u escape.)"sv },
{ R"(notunicode3)"sv, R"(This string does not have a unicode \u0075 escape.)"sv },
{ R"(notunicode4)"sv, R"(This string does not have a unicode \u escape.)"sv },
{ R"(quote)"sv, R"(This string has a " quote character.)"sv },
{ R"(tab)"sv, R"(This string has a tab character.)"sv },
{ R"(unitseparator)"sv, "This string has a \x1F unit separator control code."sv },
};
REQUIRE(tbl == expected);
});
parsing_should_succeed(
FILE_LINE_ARGS,
string_multiline_quotes,

View File

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29519.161
# Visual Studio Version 17
VisualStudioVersion = 17.1.31911.260
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "toml++", "toml++.vcxproj", "{0E287B5A-1168-43FD-B067-F6BE8E182A57}"
EndProject
@ -83,6 +83,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_release_x86_unrel", "t
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "parse_benchmark", "examples\parse_benchmark.vcxproj", "{407FCAA8-FC2C-424D-B44B-C6A1AFAD757A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "toml-test", "toml-test", "{5DE43BF4-4EDD-4A7A-A422-764415BB3224}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tt_decoder", "toml-test\tt_decoder.vcxproj", "{8D19DE49-9687-4305-B59E-21F398415F5A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tt_encoder", "toml-test\tt_encoder.vcxproj", "{8F673261-5DFE-4B67-937A-61FC3F0082A2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@ -239,6 +245,14 @@ Global
{407FCAA8-FC2C-424D-B44B-C6A1AFAD757A}.Debug|x64.Build.0 = Debug|x64
{407FCAA8-FC2C-424D-B44B-C6A1AFAD757A}.Release|x64.ActiveCfg = Release|x64
{407FCAA8-FC2C-424D-B44B-C6A1AFAD757A}.Release|x64.Build.0 = Release|x64
{8D19DE49-9687-4305-B59E-21F398415F5A}.Debug|x64.ActiveCfg = Debug|x64
{8D19DE49-9687-4305-B59E-21F398415F5A}.Debug|x64.Build.0 = Debug|x64
{8D19DE49-9687-4305-B59E-21F398415F5A}.Release|x64.ActiveCfg = Release|x64
{8D19DE49-9687-4305-B59E-21F398415F5A}.Release|x64.Build.0 = Release|x64
{8F673261-5DFE-4B67-937A-61FC3F0082A2}.Debug|x64.ActiveCfg = Debug|x64
{8F673261-5DFE-4B67-937A-61FC3F0082A2}.Debug|x64.Build.0 = Debug|x64
{8F673261-5DFE-4B67-937A-61FC3F0082A2}.Release|x64.ActiveCfg = Release|x64
{8F673261-5DFE-4B67-937A-61FC3F0082A2}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -281,6 +295,8 @@ Global
{151E9E68-E325-5B08-8722-257F2B083BAD} = {4E25CF88-D7D8-4A9C-A52E-0D78281E82EC}
{B3077FF1-FC90-5C14-A69F-3524F62167B1} = {4E25CF88-D7D8-4A9C-A52E-0D78281E82EC}
{407FCAA8-FC2C-424D-B44B-C6A1AFAD757A} = {412816A5-9D22-4A30-BCDF-ABFB54BB3735}
{8D19DE49-9687-4305-B59E-21F398415F5A} = {5DE43BF4-4EDD-4A7A-A422-764415BB3224}
{8F673261-5DFE-4B67-937A-61FC3F0082A2} = {5DE43BF4-4EDD-4A7A-A422-764415BB3224}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0926DDCC-88CD-4839-A82D-D9B99E02A0B1}

50
toml-test/README.md Normal file
View File

@ -0,0 +1,50 @@
# Encoder and Decoder for [toml-test]
> &#xFE0F; _The contents of this directory relate to testing with the [toml-test] suite, **not** anything to do with running the library's unit-tests.
> For information about running the unit-tests see [CONTRIBUTING](../CONTRIBUTING.md)._
<br>
## Prequisites
For this document to make sense, you will need to:
1. Install some recent version of Go
2. Follow the installation instructions from the [toml-test] README to compile the `toml-test` runner
3. Add `toml-test` as an alias or have it on the system PATH
4. Clone the toml++ repository's [nlohmann/json] submodule:
```bash
git submodule update --init --depth 1 external/json
```
5. **Linux only:** Install `ninja` and `meson`:
```bash
sudo apt update && sudo apt install -y locales python3 python3-pip ninja-build
sudo pip3 install meson
```
<br>
## Building and Testing the Encoder and Decoder
> &#xFE0F; _Commands in this section assume the starting directory is the toml++ repository root directory._
### Windows with Visual Studio
Open `toml++.sln` and build the two projects in the `toml-test` solution folder. They'll be compiled in some target-specific subfolder under `/bin` in the repo root. Then run `toml-test` against them:
```bash
toml-test ./bin/win64_vc143_Release_Application/tt_decoder.exe
toml-test ./bin/win64_vc143_Release_Application/tt_encoder.exe --encoder
```
### Linux (and WSL)
```bash
# create the meson build target folder (first time only)
meson build_tt --buildtype=release -Dbuild_tt_encoder=true -Dbuild_tt_decoder=true -Dgenerate_cmake_config=false
# build and run
cd build_tt
ninja && toml-test ./toml-test/tt_decoder && toml-test ./toml-test/tt_encoder --encoder
```
[toml-test]: https://github.com/BurntSushi/toml-test
[CONTRIBUTING]: ../CONTRIBUTING.md
[nlohmann/json]: https://github.com/nlohmann/json
[meson]: https://mesonbuild.com/

15
toml-test/meson.build Normal file
View File

@ -0,0 +1,15 @@
if get_option('build_tt_encoder')
executable(
'tt_encoder',
'tt_encoder.cpp',
include_directories: include_dirs
)
endif
if get_option('build_tt_decoder')
executable(
'tt_decoder',
'tt_decoder.cpp',
include_directories: include_dirs
)
endif

39
toml-test/tt.hpp Normal file
View File

@ -0,0 +1,39 @@
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
//# Copyright (c) 2019-2020 Mark Gillard <mark.gillard@outlook.com.au>
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
// SPDX-License-Identifier: MIT
#pragma once
#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
#if __has_include(<json/single_include/nlohmann/json.hpp>)
#include <json/single_include/nlohmann/json.hpp>
#else
#error nlohmann/json is missing! You probably need to fetch submodules ("git submodule update --init --depth 1 external/json")
#endif
#include <string>
#include <string_view>
#include <iostream>
#include <sstream>
#ifdef __clang__
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#elif defined(_MSC_VER)
#pragma warning(pop)
#endif
#define TOML_ENABLE_UNRELEASED_FEATURES 0
#define TOML_EXCEPTIONS 1
#include <toml++/toml.h>

114
toml-test/tt_decoder.cpp Normal file
View File

@ -0,0 +1,114 @@
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
//# Copyright (c) 2019-2020 Mark Gillard <mark.gillard@outlook.com.au>
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
// SPDX-License-Identifier: MIT
#include "tt.hpp"
using nlohmann::json;
using namespace std::string_view_literals;
TOML_NAMESPACE_START
{
void to_json(json & j, const value<std::string>& val)
{
j["type"] = "string";
j["value"] = *val;
}
template <typename T>
static void to_json_via_stream(json & j, const value<T>& val)
{
static constexpr auto flags = toml_formatter::default_flags
& ~(format_flags::allow_binary_integers //
| format_flags::allow_hexadecimal_integers //
| format_flags::allow_octal_integers);
std::ostringstream ss;
ss << toml_formatter{ val, flags };
j["value"] = ss.str();
}
void to_json(json & j, const value<int64_t>& val)
{
j["type"] = "integer";
to_json_via_stream(j, val);
}
void to_json(json & j, const value<double>& val)
{
j["type"] = "float";
to_json_via_stream(j, val);
}
void to_json(json & j, const value<bool>& val)
{
j["type"] = "bool";
to_json_via_stream(j, val);
}
void to_json(json & j, const value<date>& val)
{
j["type"] = "date-local";
to_json_via_stream(j, val);
}
void to_json(json & j, const value<time>& val)
{
j["type"] = "time-local";
to_json_via_stream(j, val);
}
void to_json(json & j, const value<date_time>& val)
{
j["type"] = val->is_local() ? "datetime-local" : "datetime";
to_json_via_stream(j, val);
}
void to_json(json&, const array&);
void to_json(json & j, const table& tbl)
{
j = json::object();
for (auto& [k_, v_] : tbl)
v_.visit([&, k = &k_](auto& v) { j[std::string{ k->str() }] = v; });
}
void to_json(json & j, const array& arr)
{
j = json::array();
for (auto& v_ : arr)
v_.visit([&](auto& v) { j.push_back(v); });
}
}
TOML_NAMESPACE_END;
int main()
{
json j;
try
{
const std::string str(std::istreambuf_iterator<char>{ std::cin }, std::istreambuf_iterator<char>{});
j = toml::parse(str, "stdin"sv);
}
catch (const toml::parse_error& err)
{
std::cerr << err << "\n";
return 1;
}
catch (const std::exception& exc)
{
std::cerr << exc.what() << "\n";
return 1;
}
catch (...)
{
std::cerr << "An unspecified error occurred.\n";
return 1;
}
std::cout << j << "\n";
return 0;
}

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{8D19DE49-9687-4305-B59E-21F398415F5A}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<Import Project="..\toml++.props" />
<ItemDefinitionGroup>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<PropertyGroup>
<LocalDebuggerWorkingDirectory>..\toml-test</LocalDebuggerWorkingDirectory>
</PropertyGroup>
<ItemGroup>
<Natvis Include="..\toml++.natvis" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="tt_decoder.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="meson.build" />
<None Include="README.md" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="tt.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

215
toml-test/tt_encoder.cpp Normal file
View File

@ -0,0 +1,215 @@
//# This file is a part of toml++ and is subject to the the terms of the MIT license.
//# Copyright (c) 2019-2020 Mark Gillard <mark.gillard@outlook.com.au>
//# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text.
// SPDX-License-Identifier: MIT
#include "tt.hpp"
using nlohmann::json;
using namespace std::string_view_literals;
[[nodiscard]] static bool is_tt_value(const json& j) noexcept
{
return j.is_object() //
&& j.size() == 2u //
&& j.contains("type") //
&& j["type"].is_string() //
&& j.contains("value") //
&& j["value"].is_string();
}
TOML_NAMESPACE_START
{
void from_json(const json& j, value<std::string>& val)
{
assert(is_tt_value(j));
assert(j["type"] == "string");
*val = j["value"];
}
template <typename T>
static void from_json_via_parse(const json& j, value<T>& val)
{
assert(is_tt_value(j));
std::stringstream ss;
ss.imbue(std::locale::classic());
ss << "value = " << j["value"].get_ref<const std::string&>();
auto tbl = toml::parse(ss);
tbl["value"sv].visit(
[&](auto& v)
{
if constexpr (is_value<decltype(v)>)
{
using value_type = typename std::remove_cv_t<std::remove_reference_t<decltype(v)>>::value_type;
if constexpr (std::is_same_v<T, value_type>)
val = std::move(v);
else if constexpr (std::is_constructible_v<T, value_type>)
*val = T(*v);
else if constexpr (std::is_convertible_v<value_type, T>)
*val = static_cast<T>(*v);
}
});
}
void from_json(const json& j, value<int64_t>& val)
{
assert(is_tt_value(j));
assert(j["type"] == "integer");
from_json_via_parse(j, val);
}
void from_json(const json& j, value<double>& val)
{
assert(is_tt_value(j));
assert(j["type"] == "float");
from_json_via_parse(j, val);
}
void from_json(const json& j, value<bool>& val)
{
assert(is_tt_value(j));
assert(j["type"] == "bool");
from_json_via_parse(j, val);
}
void from_json(const json& j, value<date>& val)
{
assert(is_tt_value(j));
assert(j["type"] == "date-local");
from_json_via_parse(j, val);
}
void from_json(const json& j, value<time>& val)
{
assert(is_tt_value(j));
assert(j["type"] == "time-local");
from_json_via_parse(j, val);
}
void from_json(const json& j, value<date_time>& val)
{
assert(is_tt_value(j));
assert(j["type"] == "datetime-local" || j["type"] == "datetime");
from_json_via_parse(j, val);
}
void from_json(const json&, array&);
template <typename T, typename Key>
static void insert_from_json(table & tbl, Key && key, const json& val)
{
T v;
from_json(val, v);
tbl.insert_or_assign(static_cast<Key&&>(key), std::move(v));
}
template <typename T>
static void insert_from_json(array & arr, const json& val)
{
T v;
from_json(val, v);
arr.push_back(std::move(v));
}
void from_json(const json& j, table& tbl)
{
assert(j.is_object());
assert(!is_tt_value(j));
for (auto& [k, v] : j.items())
{
if (v.is_object())
{
if (is_tt_value(v))
{
if (v["type"] == "string")
insert_from_json<toml::value<std::string>>(tbl, k, v);
else if (v["type"] == "integer")
insert_from_json<toml::value<int64_t>>(tbl, k, v);
else if (v["type"] == "float")
insert_from_json<toml::value<double>>(tbl, k, v);
else if (v["type"] == "bool")
insert_from_json<toml::value<bool>>(tbl, k, v);
else if (v["type"] == "date-local")
insert_from_json<toml::value<date>>(tbl, k, v);
else if (v["type"] == "time-local")
insert_from_json<toml::value<time>>(tbl, k, v);
else if (v["type"] == "datetime-local" || v["type"] == "datetime")
insert_from_json<toml::value<date_time>>(tbl, k, v);
}
else
insert_from_json<toml::table>(tbl, k, v);
}
if (v.is_array())
insert_from_json<toml::array>(tbl, k, v);
}
}
void from_json(const json& j, array& arr)
{
assert(j.is_array());
for (auto& v : j)
{
if (v.is_object())
{
if (is_tt_value(v))
{
if (v["type"] == "string")
insert_from_json<toml::value<std::string>>(arr, v);
else if (v["type"] == "integer")
insert_from_json<toml::value<int64_t>>(arr, v);
else if (v["type"] == "float")
insert_from_json<toml::value<double>>(arr, v);
else if (v["type"] == "bool")
insert_from_json<toml::value<bool>>(arr, v);
else if (v["type"] == "date-local")
insert_from_json<toml::value<date>>(arr, v);
else if (v["type"] == "time-local")
insert_from_json<toml::value<time>>(arr, v);
else if (v["type"] == "datetime-local" || v["type"] == "datetime")
insert_from_json<toml::value<date_time>>(arr, v);
}
else
insert_from_json<toml::table>(arr, v);
}
if (v.is_array())
insert_from_json<toml::array>(arr, v);
}
}
}
TOML_NAMESPACE_END;
int main()
{
toml::table tbl;
try
{
const std::string str(std::istreambuf_iterator<char>{ std::cin }, std::istreambuf_iterator<char>{});
tbl = json::parse(str);
}
catch (const std::exception& exc)
{
std::cerr << exc.what() << "\n";
return 1;
}
catch (...)
{
std::cerr << "An unspecified error occurred.\n";
return 1;
}
std::cout << tbl << "\n";
return 0;
}

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{8F673261-5DFE-4B67-937A-61FC3F0082A2}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<Import Project="..\toml++.props" />
<ItemDefinitionGroup>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<PropertyGroup>
<LocalDebuggerWorkingDirectory>..\toml-test</LocalDebuggerWorkingDirectory>
</PropertyGroup>
<ItemGroup>
<Natvis Include="..\toml++.natvis" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="tt_encoder.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="meson.build" />
<None Include="README.md" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="tt.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

145
toml.hpp
View File

@ -369,6 +369,16 @@
#endif
#ifndef TOML_CPP_VERSION
#define TOML_CPP_VERSION __cplusplus
#endif
#if TOML_CPP_VERSION < 201103L
#error toml++ requires C++17 or higher. For a TOML library supporting pre-C++11 see https://github.com/ToruNiina/Boost.toml
#elif TOML_CPP_VERSION < 201703L
#error toml++ requires C++17 or higher. For a TOML library supporting C++11 see https://github.com/ToruNiina/toml11
#endif
#undef TOML_CPP_VERSION
#ifdef TOML_CONFIG_HEADER
#include TOML_CONFIG_HEADER
#endif
@ -472,6 +482,29 @@
#define TOML_HAS_CUSTOM_OPTIONAL_TYPE 0
#endif
// exceptions (compiler support)
#ifndef TOML_COMPILER_EXCEPTIONS
#if defined(__EXCEPTIONS) || defined(__cpp_exceptions)
#define TOML_COMPILER_EXCEPTIONS 1
#else
#define TOML_COMPILER_EXCEPTIONS 0
#endif
#endif
// exceptions (library use)
#if TOML_COMPILER_EXCEPTIONS
#if !defined(TOML_EXCEPTIONS) || (defined(TOML_EXCEPTIONS) && TOML_EXCEPTIONS)
#undef TOML_EXCEPTIONS
#define TOML_EXCEPTIONS 1
#endif
#else
#if defined(TOML_EXCEPTIONS) && TOML_EXCEPTIONS
#error TOML_EXCEPTIONS was explicitly enabled but exceptions are disabled/unsupported by the compiler.
#endif
#undef TOML_EXCEPTIONS
#define TOML_EXCEPTIONS 0
#endif
#ifndef TOML_UNDEF_MACROS
#define TOML_UNDEF_MACROS 1
#endif
@ -494,36 +527,6 @@
#endif
#endif
#ifndef TOML_CPP_VERSION
#define TOML_CPP_VERSION __cplusplus
#endif
#if TOML_CPP_VERSION < 201103L
#error toml++ requires C++17 or higher. For a TOML library supporting pre-C++11 see https://github.com/ToruNiina/Boost.toml
#elif TOML_CPP_VERSION < 201703L
#error toml++ requires C++17 or higher. For a TOML library supporting C++11 see https://github.com/ToruNiina/toml11
#endif
#undef TOML_CPP_VERSION
#ifndef TOML_COMPILER_EXCEPTIONS
#if defined(__EXCEPTIONS) || defined(__cpp_exceptions)
#define TOML_COMPILER_EXCEPTIONS 1
#else
#define TOML_COMPILER_EXCEPTIONS 0
#endif
#endif
#if TOML_COMPILER_EXCEPTIONS
#if !defined(TOML_EXCEPTIONS) || (defined(TOML_EXCEPTIONS) && TOML_EXCEPTIONS)
#undef TOML_EXCEPTIONS
#define TOML_EXCEPTIONS 1
#endif
#else
#if defined(TOML_EXCEPTIONS) && TOML_EXCEPTIONS
#error TOML_EXCEPTIONS was explicitly enabled but exceptions are disabled/unsupported by the compiler.
#endif
#undef TOML_EXCEPTIONS
#define TOML_EXCEPTIONS 0
#endif
#if TOML_GCC || TOML_CLANG || (TOML_ICC && !TOML_ICC_CL)
// not supported by any version of GCC or Clang as of 26/11/2020
// not supported by any version of ICC on Linux as of 11/01/2021
@ -1840,28 +1843,42 @@ TOML_NAMESPACE_START
inline constexpr bool is_container = is_table<T> || is_array<T>;
template <typename T>
inline constexpr bool is_string = std::is_same_v<impl::wrap_node<impl::remove_cvref<T>>, value<std::string>>;
inline constexpr bool is_string = std::is_same_v< //
impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, //
value<std::string>>;
template <typename T>
inline constexpr bool is_integer = std::is_same_v<impl::wrap_node<impl::remove_cvref<T>>, value<int64_t>>;
inline constexpr bool is_integer = std::is_same_v< //
impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, //
value<int64_t>>;
template <typename T>
inline constexpr bool is_floating_point = std::is_same_v<impl::wrap_node<impl::remove_cvref<T>>, value<double>>;
inline constexpr bool is_floating_point = std::is_same_v< //
impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, //
value<double>>;
template <typename T>
inline constexpr bool is_number = is_integer<T> || is_floating_point<T>;
template <typename T>
inline constexpr bool is_boolean = std::is_same_v<impl::wrap_node<impl::remove_cvref<T>>, value<bool>>;
inline constexpr bool is_boolean = std::is_same_v< //
impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, //
value<bool>>;
template <typename T>
inline constexpr bool is_date = std::is_same_v<impl::wrap_node<impl::remove_cvref<T>>, value<date>>;
inline constexpr bool is_date = std::is_same_v< //
impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, //
value<date>>;
template <typename T>
inline constexpr bool is_time = std::is_same_v<impl::wrap_node<impl::remove_cvref<T>>, value<time>>;
inline constexpr bool is_time = std::is_same_v< //
impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, //
value<time>>;
template <typename T>
inline constexpr bool is_date_time = std::is_same_v<impl::wrap_node<impl::remove_cvref<T>>, value<date_time>>;
inline constexpr bool is_date_time = std::is_same_v< //
impl::remove_cvref<impl::wrap_node<impl::remove_cvref<T>>>, //
value<date_time>>;
template <typename T>
inline constexpr bool is_chronological = is_date<T> || is_time<T> || is_date_time<T>;
@ -2430,6 +2447,20 @@ TOML_NAMESPACE_START
offset{} // TINAE - icc bugfix
{}
TOML_NODISCARD_CTOR
explicit constexpr date_time(const toml::date& d) noexcept //
: date{ d },
time{},
offset{} // TINAE - icc bugfix
{}
TOML_NODISCARD_CTOR
explicit constexpr date_time(const toml::time& t) noexcept //
: date{},
time{ t },
offset{} // TINAE - icc bugfix
{}
TOML_NODISCARD_CTOR
constexpr date_time(const toml::date& d, const toml::time& t, const toml::time_offset& off) noexcept
: date{ d },
@ -6069,19 +6100,16 @@ TOML_NAMESPACE_START
return lhs;
}
};
template <typename T>
inline constexpr bool is_key = std::is_same_v<impl::remove_cvref<T>, toml::key>;
template <typename T>
inline constexpr bool is_key_or_convertible =
is_key<T> || std::is_constructible_v<toml::key, T> || std::is_convertible_v<T, toml::key>;
}
TOML_NAMESPACE_END;
TOML_IMPL_NAMESPACE_START
{
template <typename T>
inline constexpr bool is_key = std::is_same_v<remove_cvref<T>, toml::key>;
template <typename T>
inline constexpr bool is_key_or_convertible = is_key<T> || std::is_constructible_v<toml::key, T>;
}
TOML_IMPL_NAMESPACE_END;
#ifdef _MSC_VER
#pragma pop_macro("min")
#pragma pop_macro("max")
@ -6831,7 +6859,7 @@ TOML_NAMESPACE_START
public:
TOML_CONSTRAINED_TEMPLATE((impl::is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>),
TOML_CONSTRAINED_TEMPLATE((is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>),
typename ValueType,
typename KeyType,
typename... ValueArgs)
@ -6896,7 +6924,7 @@ TOML_NAMESPACE_START
}
}
TOML_CONSTRAINED_TEMPLATE((impl::is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>),
TOML_CONSTRAINED_TEMPLATE((is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>),
typename KeyType,
typename ValueType)
std::pair<iterator, bool> insert(KeyType&& key,
@ -6936,7 +6964,7 @@ TOML_NAMESPACE_START
}
}
TOML_CONSTRAINED_TEMPLATE((!impl::is_key_or_convertible<Iter> && !impl::is_wide_string<Iter>), typename Iter)
TOML_CONSTRAINED_TEMPLATE((!is_key_or_convertible<Iter> && !impl::is_wide_string<Iter>), typename Iter)
void insert(Iter begin, Iter end, value_flags flags = preserve_source_value_flags)
{
if (begin == end)
@ -6950,7 +6978,7 @@ TOML_NAMESPACE_START
}
}
TOML_CONSTRAINED_TEMPLATE((impl::is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>),
TOML_CONSTRAINED_TEMPLATE((is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>),
typename KeyType,
typename ValueType)
std::pair<iterator, bool> insert_or_assign(KeyType&& key,
@ -6996,7 +7024,7 @@ TOML_NAMESPACE_START
}
}
TOML_CONSTRAINED_TEMPLATE((impl::is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>),
TOML_CONSTRAINED_TEMPLATE((is_key_or_convertible<KeyType&&> || impl::is_wide_string<KeyType>),
typename ValueType,
typename KeyType,
typename... ValueArgs)
@ -14415,10 +14443,15 @@ TOML_IMPL_NAMESPACE_START
}
else if (decoder.has_code_point())
{
if (is_vertical_whitespace(decoder.codepoint))
if (decoder.codepoint == U'\n')
{
has_line_breaks = true;
if (!multi_line)
has_control_chars = true;
}
else if (is_nontab_control_character(decoder.codepoint)
|| (treat_raw_tab_as_control_char && decoder.codepoint == U'\t'))
|| (treat_raw_tab_as_control_char && decoder.codepoint == U'\t')
|| is_vertical_whitespace(decoder.codepoint))
has_control_chars = true;
else if (decoder.codepoint == U'\'')
has_single_quotes = true;
@ -15306,8 +15339,6 @@ TOML_POP_WARNINGS;
#undef TOML_CLOSED_ENUM
#undef TOML_CLOSED_FLAGS_ENUM
#undef TOML_COMPILER_EXCEPTIONS
#undef TOML_CONCAT
#undef TOML_CONCAT_1
#undef TOML_CONST_GETTER
#undef TOML_CONST_INLINE_GETTER
#undef TOML_CONSTRAINED_TEMPLATE
@ -15361,8 +15392,6 @@ TOML_POP_WARNINGS;
#undef TOML_MAKE_VERSION
#undef TOML_MSVC
#undef TOML_NAMESPACE
#undef TOML_NAMESPACE_END
#undef TOML_NAMESPACE_START
#undef TOML_NEVER_INLINE
#undef TOML_NODISCARD
#undef TOML_NODISCARD_CTOR

View File

@ -438,7 +438,6 @@ def add_condition(tests, condition, names):
def load_valid_inputs(tests, extern_root):
tests['valid']['burntsushi'] = load_tests(Path(extern_root, 'toml-test', 'tests', 'valid'), True, (
# broken by the json reader
'string-escapes',
'key-alphanum',
))
add_condition(tests['valid']['burntsushi'], '!TOML_MSVC', (

View File

@ -185,11 +185,12 @@ def main():
if m:
defines[m.group(1)] = defined
ignore_list = ( # macros that are meant to stay public (user configs etc)
r'TOMLPLUSPLUS_H',
r'INCLUDE_TOMLPLUSPLUS_H',
r'POXY_IMPLEMENTATION_DETAIL',
r'TOML_ALL_INLINE',
r'TOML_API',
r'TOML_CONCAT',
r'TOML_CONCAT_1',
r'TOML_CONFIG_HEADER',
r'TOML_ENABLE_FORMATTERS',
r'TOML_ENABLE_PARSER',
@ -207,10 +208,13 @@ def main():
r'TOML_LIB_PATCH',
r'TOML_LIB_SINGLE_HEADER',
r'TOML_MAX_NESTED_VALUES',
r'TOML_NAMESPACE_END',
r'TOML_NAMESPACE_START',
r'TOML_OPTIONAL_TYPE',
r'TOML_SMALL_FLOAT_TYPE',
r'TOML_SMALL_INT_TYPE',
r'TOML_UNDEF_MACROS',
r'TOMLPLUSPLUS_H',
)
set_defines = []
for define, currently_set in defines.items():