minor refactoring to better enable explicit instantiations

This commit is contained in:
Mark Gillard 2020-03-03 10:10:07 +02:00
parent d874264432
commit 14249f4e66
17 changed files with 533 additions and 335 deletions

View File

@ -23,7 +23,7 @@ Given a TOML file `configuration.toml` containing the following:
```toml ```toml
[library] [library]
name = "toml++" name = "toml++"
version = "0.1.0" version = "0.3.2"
authors = ["Mark Gillard <mark@notarealwebsite.com>"] authors = ["Mark Gillard <mark@notarealwebsite.com>"]
[dependencies] [dependencies]
@ -89,7 +89,7 @@ won't need to mess with these at all, but if you do, set them before including t
| Option | Type | Default | Description | | Option | Type | Default | Description |
|----------------------------|:--------------:|-----------------------------------|------------------------------------------------------------------------------------------------------------| |----------------------------|:--------------:|-----------------------------------|------------------------------------------------------------------------------------------------------------|
| `TOML_ALL_INLINE` | boolean | `1` | Disable this to explicitly control where toml++'s implementation is compiled (e.g. as part of a library). | | `TOML_ALL_INLINE` | boolean | `1` | Disable this to explicitly control where toml++'s implementation is compiled (e.g. as part of a library). |
| `TOML_API` | define | undefined | API annotation to add to public symbols (e.g. `__declspec(dllexport) on Windows)`. | | `TOML_API` | define | undefined | API annotation to add to public symbols (e.g. `__declspec(dllexport)` on Windows). |
| `TOML_ASSERT(expr)` | function macro | `assert(expr)`<br>(or undefined) | Sets the assert function used by the library. | | `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. **_Experimental!_** | | `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_CONFIG_HEADER` | string literal | undefined | Includes the given header file before the rest of the library. |

View File

@ -21,8 +21,8 @@
#if TOML_IMPLEMENTATION #if TOML_IMPLEMENTATION
#include "toml_instantiations.h"
#include "toml_node_impl.h" #include "toml_node_impl.h"
#include "toml_value_impl.h"
#include "toml_array_impl.h" #include "toml_array_impl.h"
#include "toml_table_impl.h" #include "toml_table_impl.h"
#include "toml_parser_impl.h" #include "toml_parser_impl.h"

View File

@ -358,10 +358,12 @@ TOML_START
struct date_time; struct date_time;
class node; class node;
template <typename T> class node_view;
template <typename T> class value;
class array; class array;
class table; class table;
template <typename> class node_view;
template <typename> class value;
template <typename> class default_formatter;
template <typename> class json_formatter;
/// \brief TOML node type identifiers. /// \brief TOML node type identifiers.
enum class node_type : uint8_t enum class node_type : uint8_t

View File

@ -70,6 +70,7 @@ TOML_START
{ {
return pack(lhs) >= pack(rhs); return pack(lhs) >= pack(rhs);
} }
};
/// \brief Prints a date out to a stream as `YYYY-MM-DD` (per RFC 3339). /// \brief Prints a date out to a stream as `YYYY-MM-DD` (per RFC 3339).
/// \detail \cpp /// \detail \cpp
@ -80,13 +81,11 @@ TOML_START
/// 1987-03-16 /// 1987-03-16
/// \eout /// \eout
template <typename CHAR> template <typename CHAR>
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const date& rhs) inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const date& rhs) TOML_MAY_THROW
TOML_MAY_THROW
{ {
impl::print_to_stream(rhs, lhs); impl::print_to_stream(rhs, lhs);
return lhs; return lhs;
} }
};
/// \brief A local time-of-day. /// \brief A local time-of-day.
struct time final struct time final
@ -157,6 +156,7 @@ TOML_START
{ {
return pack(lhs) >= pack(rhs); return pack(lhs) >= pack(rhs);
} }
};
/// \brief Prints a time out to a stream as `HH:MM:SS.FFFFFF` (per RFC 3339). /// \brief Prints a time out to a stream as `HH:MM:SS.FFFFFF` (per RFC 3339).
/// \detail \cpp /// \detail \cpp
@ -169,13 +169,11 @@ TOML_START
/// 10:20:34.5 /// 10:20:34.5
/// \eout /// \eout
template <typename CHAR> template <typename CHAR>
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const time& rhs) inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const time& rhs) TOML_MAY_THROW
TOML_MAY_THROW
{ {
impl::print_to_stream(rhs, lhs); impl::print_to_stream(rhs, lhs);
return lhs; return lhs;
} }
};
/// \brief A timezone offset. /// \brief A timezone offset.
struct time_offset final struct time_offset final
@ -254,6 +252,7 @@ TOML_START
{ {
return lhs.minutes >= rhs.minutes; return lhs.minutes >= rhs.minutes;
} }
};
/// \brief Prints a time_offset out to a stream as `+-HH:MM or Z` (per RFC 3339). /// \brief Prints a time_offset out to a stream as `+-HH:MM or Z` (per RFC 3339).
/// \detail \cpp /// \detail \cpp
@ -272,13 +271,11 @@ TOML_START
/// -02:30 /// -02:30
/// \eout /// \eout
template <typename CHAR> template <typename CHAR>
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const time_offset& rhs) inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const time_offset& rhs) TOML_MAY_THROW
TOML_MAY_THROW
{ {
impl::print_to_stream(rhs, lhs); impl::print_to_stream(rhs, lhs);
return lhs; return lhs;
} }
};
/// \brief A date-time. /// \brief A date-time.
struct date_time final struct date_time final
@ -379,6 +376,7 @@ TOML_START
{ {
return !(lhs < rhs); return !(lhs < rhs);
} }
};
/// \brief Prints a date_time out to a stream in RFC 3339 format. /// \brief Prints a date_time out to a stream in RFC 3339 format.
/// \detail \cpp /// \detail \cpp
@ -393,12 +391,10 @@ TOML_START
/// 1987-03-16T10:20:34Z /// 1987-03-16T10:20:34Z
/// \eout /// \eout
template <typename CHAR> template <typename CHAR>
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const date_time& rhs) inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const date_time& rhs) TOML_MAY_THROW
TOML_MAY_THROW
{ {
impl::print_to_stream(rhs, lhs); impl::print_to_stream(rhs, lhs);
return lhs; return lhs;
} }
};
} }
TOML_END TOML_END

View File

@ -151,6 +151,11 @@ TOML_IMPL_END
TOML_START TOML_START
{ {
template <typename T, typename U>
std::basic_ostream<T>& operator << (std::basic_ostream<T>&, default_formatter<U>&) TOML_MAY_THROW;
template <typename T, typename U>
std::basic_ostream<T>& operator << (std::basic_ostream<T>&, default_formatter<U>&&) TOML_MAY_THROW;
/// \brief A wrapper for printing TOML objects out to a stream as formatted TOML. /// \brief A wrapper for printing TOML objects out to a stream as formatted TOML.
/// ///
/// \remarks You generally don't need to create an instance of this class explicitly; the stream /// \remarks You generally don't need to create an instance of this class explicitly; the stream
@ -444,25 +449,10 @@ TOML_START
: base{ source, flags } : base{ source, flags }
{} {}
/// \brief Prints the bound TOML object out to the stream as formatted TOML. template <typename T, typename U>
template <typename T> friend std::basic_ostream<T>& operator << (std::basic_ostream<T>&, default_formatter<U>&) TOML_MAY_THROW;
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<T>& lhs, default_formatter& rhs) template <typename T, typename U>
TOML_MAY_THROW friend std::basic_ostream<T>& operator << (std::basic_ostream<T>&, default_formatter<U>&&) TOML_MAY_THROW;
{
rhs.attach(lhs);
rhs.key_path.clear();
rhs.print();
rhs.detach();
return lhs;
}
/// \brief Prints the bound TOML object out to the stream as formatted TOML (rvalue overload).
template <typename T>
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<T>& lhs, default_formatter&& rhs)
TOML_MAY_THROW
{
return lhs << rhs; //as lvalue
}
}; };
template <typename CHAR> template <typename CHAR>
@ -499,6 +489,24 @@ TOML_START
base::clear_naked_newline(); base::clear_naked_newline();
} }
/// \brief Prints the bound TOML object out to the stream as formatted TOML.
template <typename T, typename U>
inline std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, default_formatter<U>& rhs) TOML_MAY_THROW
{
rhs.attach(lhs);
rhs.key_path.clear();
rhs.print();
rhs.detach();
return lhs;
}
/// \brief Prints the bound TOML object out to the stream as formatted TOML (rvalue overload).
template <typename T, typename U>
inline std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, default_formatter<U>&& rhs) TOML_MAY_THROW
{
return lhs << rhs; //as lvalue
}
template <typename CHAR> template <typename CHAR>
inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const table& rhs) TOML_MAY_THROW inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const table& rhs) TOML_MAY_THROW
{ {

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "toml_value.h" #include "toml_value.h"
#include "toml_node_view.h"
TOML_START TOML_START
{ {
@ -10,5 +11,8 @@ TOML_START
template class TOML_API value<date>; template class TOML_API value<date>;
template class TOML_API value<time>; template class TOML_API value<time>;
template class TOML_API value<date_time>; template class TOML_API value<date_time>;
template class TOML_API node_view<node>;
template class TOML_API node_view<const node>;
} }
TOML_END TOML_END

View File

@ -3,6 +3,11 @@
TOML_START TOML_START
{ {
template <typename T, typename U>
std::basic_ostream<T>& operator << (std::basic_ostream<T>&, json_formatter<U>&) TOML_MAY_THROW;
template <typename T, typename U>
std::basic_ostream<T>& operator << (std::basic_ostream<T>&, json_formatter<U>&&) TOML_MAY_THROW;
/// \brief A wrapper for printing TOML objects out to a stream as formatted JSON. /// \brief A wrapper for printing TOML objects out to a stream as formatted JSON.
/// ///
/// \detail \cpp /// \detail \cpp
@ -100,25 +105,10 @@ TOML_START
: base{ source, flags } : base{ source, flags }
{} {}
template <typename T, typename U>
/// \brief Prints the bound TOML object out to the stream as JSON. friend std::basic_ostream<T>& operator << (std::basic_ostream<T>&, json_formatter<U>&) TOML_MAY_THROW;
template <typename T> template <typename T, typename U>
friend std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, json_formatter& rhs) friend std::basic_ostream<T>& operator << (std::basic_ostream<T>&, json_formatter<U>&&) TOML_MAY_THROW;
TOML_MAY_THROW
{
rhs.attach(lhs);
rhs.print();
rhs.detach();
return lhs;
}
/// \brief Prints the bound TOML object out to the stream as JSON (rvalue overload).
template <typename T>
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<T>& lhs, json_formatter&& rhs)
TOML_MAY_THROW
{
return lhs << rhs; //as lvalue
}
}; };
template <typename CHAR> template <typename CHAR>
@ -159,5 +149,22 @@ TOML_START
} }
base::clear_naked_newline(); base::clear_naked_newline();
} }
/// \brief Prints the bound TOML object out to the stream as JSON.
template <typename T, typename U>
inline std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, json_formatter<U>& rhs) TOML_MAY_THROW
{
rhs.attach(lhs);
rhs.print();
rhs.detach();
return lhs;
}
/// \brief Prints the bound TOML object out to the stream as JSON (rvalue overload).
template <typename T, typename U>
inline std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, json_formatter<U>&& rhs) TOML_MAY_THROW
{
return lhs << rhs; //as lvalue
}
} }
TOML_END TOML_END

View File

@ -5,6 +5,9 @@
TOML_START TOML_START
{ {
template <typename CHAR, typename T>
inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>&, const node_view<T>&) TOML_MAY_THROW;
/// \brief A view of a node. /// \brief A view of a node.
/// ///
/// \detail A node_view is like a std::optional<toml::node> with lots of toml-specific stuff built-in. /// \detail A node_view is like a std::optional<toml::node> with lots of toml-specific stuff built-in.
@ -49,13 +52,14 @@ TOML_START
/// product[2]: /// product[2]:
/// \eout /// \eout
template <typename T> template <typename T>
class node_view final class TOML_API node_view final
{ {
public: public:
using viewed_type = T; using viewed_type = T;
private: private:
friend class toml::table; friend class toml::table;
template <typename U> friend class toml::node_view;
viewed_type* node_; viewed_type* node_;
@ -331,7 +335,15 @@ TOML_START
/// ///
/// \returns A view of the selected node if this node represented a table and it contained a /// \returns A view of the selected node if this node represented a table and it contained a
/// value at the given key, or an empty view. /// value at the given key, or an empty view.
[[nodiscard]] node_view<viewed_type> operator[] (string_view key) noexcept [[nodiscard]] node_view operator[] (string_view key) noexcept
{
if (auto tbl = this->as_table())
return { tbl->get(key) };
return { nullptr };
}
/// \brief Returns a view of the selected subnode (const overload).
[[nodiscard]] node_view<const viewed_type> operator[] (string_view key) const noexcept
{ {
if (auto tbl = this->as_table()) if (auto tbl = this->as_table())
return { tbl->get(key) }; return { tbl->get(key) };
@ -344,32 +356,33 @@ TOML_START
/// ///
/// \returns A view of the selected node if this node represented an array and it contained a /// \returns A view of the selected node if this node represented an array and it contained a
/// value at the given index, or an empty view. /// value at the given index, or an empty view.
[[nodiscard]] node_view<viewed_type> operator[] (size_t index) noexcept [[nodiscard]] node_view operator[] (size_t index) noexcept
{ {
if (auto tbl = this->as_array()) if (auto arr = this->as_array())
return { tbl->get(index) }; return { arr->get(index) };
return { nullptr };
}
/// \brief Returns a view of the selected subnode (const overload).
[[nodiscard]] node_view<const viewed_type> operator[] (string_view key) const noexcept
{
if (auto tbl = this->as_table())
return { tbl->get(key) };
return { nullptr }; return { nullptr };
} }
/// \brief Returns a view of the selected subnode (const overload). /// \brief Returns a view of the selected subnode (const overload).
[[nodiscard]] node_view<const viewed_type> operator[] (size_t index) const noexcept [[nodiscard]] node_view<const viewed_type> operator[] (size_t index) const noexcept
{ {
if (auto tbl = this->as_array()) if (auto arr = this->as_array())
return { tbl->get(index) }; return { arr->get(index) };
return { nullptr }; return { nullptr };
} }
template <typename CHAR, typename U>
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>&, const node_view<U>&) TOML_MAY_THROW;
};
#if !TOML_ALL_INLINE
extern template class TOML_API node_view<node>;
extern template class TOML_API node_view<const node>;
#endif
/// \brief Prints the viewed node out to a stream. /// \brief Prints the viewed node out to a stream.
template <typename CHAR> template <typename CHAR, typename T>
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& os, const node_view& nv) TOML_MAY_THROW inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& os, const node_view<T>& nv) TOML_MAY_THROW
{ {
if (nv.node_) if (nv.node_)
{ {
@ -380,6 +393,5 @@ TOML_START
} }
return os; return os;
} }
};
} }
TOML_END TOML_END

View File

@ -4,6 +4,9 @@
TOML_START TOML_START
{ {
template <typename CHAR, typename T>
std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>&, const value<T>&) TOML_MAY_THROW;
/// \brief A TOML value. /// \brief A TOML value.
/// ///
/// \tparam T The value's data type. Can be one of: /// \tparam T The value's data type. Can be one of:
@ -160,23 +163,8 @@ TOML_START
/// \brief Returns a reference to the underlying value (const overload). /// \brief Returns a reference to the underlying value (const overload).
[[nodiscard]] explicit operator const T& () const& noexcept { return val_; } [[nodiscard]] explicit operator const T& () const& noexcept { return val_; }
template <typename CHAR> template <typename CHAR, typename U>
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const value& rhs) TOML_MAY_THROW friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const value<U>& rhs) TOML_MAY_THROW;
{
// this is the same behaviour as default_formatter, but it's so simple that there's
// no need to spin up a new instance of it just for individual values.
if constexpr (std::is_same_v<T, string>)
{
impl::print_to_stream('"', lhs);
impl::print_to_stream_with_escapes(rhs.val_, lhs);
impl::print_to_stream('"', lhs);
}
else
impl::print_to_stream(rhs.val_, lhs);
return lhs;
}
/// \brief Value-assignment operator. /// \brief Value-assignment operator.
value& operator= (value_arg rhs) noexcept value& operator= (value_arg rhs) noexcept
@ -309,6 +297,16 @@ TOML_START
} }
}; };
#if !TOML_ALL_INLINE
extern template class TOML_API value<string>;
extern template class TOML_API value<int64_t>;
extern template class TOML_API value<double>;
extern template class TOML_API value<bool>;
extern template class TOML_API value<date>;
extern template class TOML_API value<time>;
extern template class TOML_API value<date_time>;
#endif
template <size_t N> value(const string_char(&)[N]) -> value<string>; template <size_t N> value(const string_char(&)[N]) -> value<string>;
template <size_t N> value(const string_char(&&)[N]) -> value<string>; template <size_t N> value(const string_char(&&)[N]) -> value<string>;
value(const string_char*) -> value<string>; value(const string_char*) -> value<string>;
@ -337,15 +335,24 @@ TOML_START
value(TOML_SMALL_INT_TYPE) -> value<int64_t>; value(TOML_SMALL_INT_TYPE) -> value<int64_t>;
#endif #endif
#if !TOML_ALL_INLINE /// \brief Prints the value out to a stream.
extern template class TOML_API value<string>; template <typename CHAR, typename T>
extern template class TOML_API value<int64_t>; inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const value<T>& rhs) TOML_MAY_THROW
extern template class TOML_API value<double>; {
extern template class TOML_API value<bool>; // this is the same behaviour as default_formatter, but it's so simple that there's
extern template class TOML_API value<date>; // no need to spin up a new instance of it just for individual values.
extern template class TOML_API value<time>;
extern template class TOML_API value<date_time>; if constexpr (std::is_same_v<T, string>)
#endif {
impl::print_to_stream('"', lhs);
impl::print_to_stream_with_escapes(rhs.val_, lhs);
impl::print_to_stream('"', lhs);
}
else
impl::print_to_stream(rhs.val_, lhs);
return lhs;
}
template <typename T> template <typename T>
inline std::optional<T> node::value() const noexcept inline std::optional<T> node::value() const noexcept

View File

@ -2,7 +2,7 @@
#define TOML_LIB_MAJOR 0 #define TOML_LIB_MAJOR 0
#define TOML_LIB_MINOR 3 #define TOML_LIB_MINOR 3
#define TOML_LIB_PATCH 1 #define TOML_LIB_PATCH 2
#define TOML_LANG_MAJOR 0 #define TOML_LANG_MAJOR 0
#define TOML_LANG_MINOR 5 #define TOML_LANG_MINOR 5

View File

@ -1,7 +1,7 @@
project( project(
'tomlplusplus', 'tomlplusplus',
'cpp', 'cpp',
version : '0.3.0', version : '0.3.2',
license : 'MIT', license : 'MIT',
default_options : [ default_options : [
'cpp_std=c++17', 'cpp_std=c++17',
@ -30,6 +30,7 @@ if compiler.get_id() == 'clang'
'-g0', '-g0',
'-ferror-limit=5', '-ferror-limit=5',
'-fchar8_t', '-fchar8_t',
# '-Weverything',
'-Wno-c++98-compat', '-Wno-c++98-compat',
'-Wno-c++98-compat-pedantic', '-Wno-c++98-compat-pedantic',
'-Wno-float-equal', '-Wno-float-equal',
@ -38,7 +39,7 @@ if compiler.get_id() == 'clang'
'-Wno-padded', '-Wno-padded',
'-Wno-weak-vtables', '-Wno-weak-vtables',
'-Wno-double-promotion' '-Wno-double-promotion'
#, '-Weverything' #, '-ftime-trace'
], ],
language : 'cpp' language : 'cpp'
) )

View File

@ -11,7 +11,8 @@ test_sources = [
'parsing_strings.cpp', 'parsing_strings.cpp',
'parsing_tables.cpp', 'parsing_tables.cpp',
'manipulating_arrays.cpp', 'manipulating_arrays.cpp',
'manipulating_tables.cpp' 'manipulating_tables.cpp',
'tests.cpp'
] ]
disable_exceptions = 'cpp_eh=none' disable_exceptions = 'cpp_eh=none'

View File

@ -1,3 +1,61 @@
#include "tests.h" #include "tests.h"
// this file is a no-op. it's only here for PCH on MSVC. #if TESTS_MANUAL_INSTANTIATIONS
template void parse_expected_value(std::string_view, const int&) noexcept;
template void parse_expected_value(std::string_view, const unsigned int&) noexcept;
template void parse_expected_value(std::string_view, const bool&) noexcept;
template void parse_expected_value(std::string_view, const float&) noexcept;
template void parse_expected_value(std::string_view, const double&) noexcept;
template void parse_expected_value(std::string_view, const toml::string_view&) noexcept;
TOML_IMPL_START
{
template class formatter<char>;
}
TOML_IMPL_END
TOML_START
{
template class default_formatter<char>;
template std::ostream& operator<< (std::ostream&, const table&) TOML_MAY_THROW;
template std::ostream& operator<< (std::ostream&, const array&) TOML_MAY_THROW;
template std::ostream& operator<< (std::ostream&, const value<string>&) TOML_MAY_THROW;
template std::ostream& operator<< (std::ostream&, const value<int64_t>&) TOML_MAY_THROW;
template std::ostream& operator<< (std::ostream&, const value<double>&) TOML_MAY_THROW;
template std::ostream& operator<< (std::ostream&, const value<bool>&) TOML_MAY_THROW;
template std::ostream& operator<< (std::ostream&, const value<date>&) TOML_MAY_THROW;
template std::ostream& operator<< (std::ostream&, const value<time>&) TOML_MAY_THROW;
template std::ostream& operator<< (std::ostream&, const value<date_time>&) TOML_MAY_THROW;
template std::ostream& operator<< (std::ostream&, const node_view<node>&) TOML_MAY_THROW;
template std::ostream& operator<< (std::ostream&, const node_view<const node>&) TOML_MAY_THROW;
template std::ostream& operator<< (std::ostream&, node_type) TOML_MAY_THROW;
template std::ostream& operator<< (std::ostream&, const source_region&) TOML_MAY_THROW;
template std::ostream& operator<< (std::ostream&, const source_position&) TOML_MAY_THROW;
template std::ostream& operator<< (std::ostream&, const parse_error&) TOML_MAY_THROW;
template std::ostream& operator<< (std::ostream&, const date&) TOML_MAY_THROW;
template std::ostream& operator<< (std::ostream&, const time&) TOML_MAY_THROW;
template std::ostream& operator<< (std::ostream&, const time_offset&) TOML_MAY_THROW;
template std::ostream& operator<< (std::ostream&, const date_time&) TOML_MAY_THROW;
template std::ostream& operator<< (std::ostream&, default_formatter<char>&) TOML_MAY_THROW;
template std::ostream& operator<< (std::ostream&, default_formatter<char>&&) TOML_MAY_THROW;
}
TOML_END
template class std::unique_ptr<const Catch::IExceptionTranslator>;
namespace Catch
{
template struct StringMaker<node_view<node>>;
template struct StringMaker<node_view<const node>>;
template ReusableStringStream& ReusableStringStream::operator << (toml::node_view<toml::node> const&);
template ReusableStringStream& ReusableStringStream::operator << (toml::node_view<const toml::node> const&);
namespace Detail
{
template std::string stringify(const node_view<node>&);
template std::string stringify(const node_view<const node>&);
}
}
#endif // TESTS_MANUAL_INSTANTIATIONS

View File

@ -13,7 +13,7 @@ TOML_POP_WARNINGS
#define S(str) TOML_STRING_PREFIX(str) #define S(str) TOML_STRING_PREFIX(str)
template <typename CHAR, typename FUNC> template <typename CHAR, typename FUNC>
void parsing_should_succeed(std::basic_string_view<CHAR> toml_str, FUNC&& func, std::string_view source_path = {}) noexcept inline void parsing_should_succeed(std::basic_string_view<CHAR> toml_str, FUNC&& func, std::string_view source_path = {}) noexcept
{ {
INFO("String being parsed: '"sv << std::string_view( reinterpret_cast<const char*>(toml_str.data()), toml_str.length() ) << "'"sv) INFO("String being parsed: '"sv << std::string_view( reinterpret_cast<const char*>(toml_str.data()), toml_str.length() ) << "'"sv)
@ -29,7 +29,6 @@ void parsing_should_succeed(std::basic_string_view<CHAR> toml_str, FUNC&& func,
REQUIRE(tabl.source().path != nullptr); REQUIRE(tabl.source().path != nullptr);
CHECK(*tabl.source().path == path); CHECK(*tabl.source().path == path);
} }
return std::move(tabl); return std::move(tabl);
}; };
@ -48,7 +47,7 @@ void parsing_should_succeed(std::basic_string_view<CHAR> toml_str, FUNC&& func,
std::forward<FUNC>(func)(validate_table(toml::parse(ss, source_path), source_path)); std::forward<FUNC>(func)(validate_table(toml::parse(ss, source_path), source_path));
} }
} }
catch (const toml::parse_error& err) catch (const parse_error& err)
{ {
FAIL( FAIL(
"Parse error on line "sv << err.source().begin.line "Parse error on line "sv << err.source().begin.line
@ -61,7 +60,7 @@ void parsing_should_succeed(std::basic_string_view<CHAR> toml_str, FUNC&& func,
{ {
INFO("Parsing string directly"sv) INFO("Parsing string directly"sv)
toml::parse_result result = toml::parse(toml_str, source_path); parse_result result = toml::parse(toml_str, source_path);
if (result) if (result)
std::forward<FUNC>(func)(validate_table(std::move(result), source_path)); std::forward<FUNC>(func)(validate_table(std::move(result), source_path));
else else
@ -79,7 +78,7 @@ void parsing_should_succeed(std::basic_string_view<CHAR> toml_str, FUNC&& func,
INFO("Parsing from a string stream"sv) INFO("Parsing from a string stream"sv)
std::basic_stringstream<CHAR, std::char_traits<CHAR>, std::allocator<CHAR>> ss; std::basic_stringstream<CHAR, std::char_traits<CHAR>, std::allocator<CHAR>> ss;
ss.write(toml_str.data(), static_cast<std::streamsize>(toml_str.length())); ss.write(toml_str.data(), static_cast<std::streamsize>(toml_str.length()));
toml::parse_result result = toml::parse(ss, source_path); parse_result result = toml::parse(ss, source_path);
if (result) if (result)
std::forward<FUNC>(func)(validate_table(std::move(result), source_path)); std::forward<FUNC>(func)(validate_table(std::move(result), source_path));
else else
@ -97,7 +96,7 @@ void parsing_should_succeed(std::basic_string_view<CHAR> toml_str, FUNC&& func,
} }
template <typename CHAR> template <typename CHAR>
void parsing_should_fail(std::basic_string_view<CHAR> toml_str) noexcept inline void parsing_should_fail(std::basic_string_view<CHAR> toml_str) noexcept
{ {
#if TOML_EXCEPTIONS #if TOML_EXCEPTIONS
@ -107,9 +106,9 @@ void parsing_should_fail(std::basic_string_view<CHAR> toml_str) noexcept
{ {
fn(); fn();
} }
catch (const toml::parse_error&) catch (const parse_error&)
{ {
SUCCEED("toml::parse_error thrown OK"sv); SUCCEED("parse_error thrown OK"sv);
return true; return true;
} }
catch (const std::exception& exc) catch (const std::exception& exc)
@ -135,7 +134,7 @@ void parsing_should_fail(std::basic_string_view<CHAR> toml_str) noexcept
static constexpr auto run_tests = [](auto&& fn) noexcept static constexpr auto run_tests = [](auto&& fn) noexcept
{ {
toml::parse_result result = fn(); parse_result result = fn();
if (result) if (result)
{ {
FAIL("Expected parsing failure"sv); FAIL("Expected parsing failure"sv);
@ -143,7 +142,7 @@ void parsing_should_fail(std::basic_string_view<CHAR> toml_str) noexcept
} }
else else
{ {
SUCCEED("toml::parse_error returned OK"sv); SUCCEED("parse_error returned OK"sv);
return true; return true;
} }
}; };
@ -160,7 +159,7 @@ void parsing_should_fail(std::basic_string_view<CHAR> toml_str) noexcept
} }
template <typename T> template <typename T>
void parse_expected_value(std::string_view value_str, const T& expected) noexcept inline void parse_expected_value(std::string_view value_str, const T& expected) noexcept
{ {
std::string val; std::string val;
static constexpr auto key = "val = "sv; static constexpr auto key = "val = "sv;
@ -277,5 +276,66 @@ void parse_expected_value(std::string_view value_str, const T& expected) noexcep
} }
CHECK(val_reparsed == val_parsed); CHECK(val_reparsed == val_parsed);
CHECK(val_reparsed == expected); CHECK(val_reparsed == expected);
} }
// manually instantiate some templates to reduce test compilation time (chosen using ClangBuildAnalyzer)
#define TESTS_MANUAL_INSTANTIATIONS 1
#if TESTS_MANUAL_INSTANTIATIONS
extern template void parse_expected_value(std::string_view, const int&) noexcept;
extern template void parse_expected_value(std::string_view, const unsigned int&) noexcept;
extern template void parse_expected_value(std::string_view, const bool&) noexcept;
extern template void parse_expected_value(std::string_view, const float&) noexcept;
extern template void parse_expected_value(std::string_view, const double&) noexcept;
extern template void parse_expected_value(std::string_view, const toml::string_view&) noexcept;
TOML_IMPL_START
{
extern template class formatter<char>;
}
TOML_IMPL_END
TOML_START
{
extern template class default_formatter<char>;
extern template std::ostream& operator<< (std::ostream&, const table&) TOML_MAY_THROW;
extern template std::ostream& operator<< (std::ostream&, const array&) TOML_MAY_THROW;
extern template std::ostream& operator<< (std::ostream&, const value<string>&) TOML_MAY_THROW;
extern template std::ostream& operator<< (std::ostream&, const value<int64_t>&) TOML_MAY_THROW;
extern template std::ostream& operator<< (std::ostream&, const value<double>&) TOML_MAY_THROW;
extern template std::ostream& operator<< (std::ostream&, const value<bool>&) TOML_MAY_THROW;
extern template std::ostream& operator<< (std::ostream&, const value<date>&) TOML_MAY_THROW;
extern template std::ostream& operator<< (std::ostream&, const value<time>&) TOML_MAY_THROW;
extern template std::ostream& operator<< (std::ostream&, const value<date_time>&) TOML_MAY_THROW;
extern template std::ostream& operator<< (std::ostream&, const node_view<node>&) TOML_MAY_THROW;
extern template std::ostream& operator<< (std::ostream&, const node_view<const node>&) TOML_MAY_THROW;
extern template std::ostream& operator<< (std::ostream&, node_type) TOML_MAY_THROW;
extern template std::ostream& operator<< (std::ostream&, const source_region&) TOML_MAY_THROW;
extern template std::ostream& operator<< (std::ostream&, const source_position&) TOML_MAY_THROW;
extern template std::ostream& operator<< (std::ostream&, const parse_error&) TOML_MAY_THROW;
extern template std::ostream& operator<< (std::ostream&, const date&) TOML_MAY_THROW;
extern template std::ostream& operator<< (std::ostream&, const time&) TOML_MAY_THROW;
extern template std::ostream& operator<< (std::ostream&, const time_offset&) TOML_MAY_THROW;
extern template std::ostream& operator<< (std::ostream&, const date_time&) TOML_MAY_THROW;
extern template std::ostream& operator<< (std::ostream&, default_formatter<char>&) TOML_MAY_THROW;
extern template std::ostream& operator<< (std::ostream&, default_formatter<char>&&) TOML_MAY_THROW;
}
TOML_END
extern template class std::unique_ptr<const Catch::IExceptionTranslator>;
namespace Catch
{
extern template struct StringMaker<node_view<node>>;
extern template struct StringMaker<node_view<const node>>;
extern template ReusableStringStream& ReusableStringStream::operator << (node_view<node> const&);
extern template ReusableStringStream& ReusableStringStream::operator << (node_view<const node> const&);
namespace Detail
{
extern template std::string stringify(const node_view<node>&);
extern template std::string stringify(const node_view<const node>&);
}
}
#endif // TESTS_MANUAL_INSTANTIATIONS

257
toml.hpp
View File

@ -1,6 +1,6 @@
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// //
// toml++ v0.3.1 // toml++ v0.3.2
// https://github.com/marzer/tomlplusplus // https://github.com/marzer/tomlplusplus
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
@ -303,7 +303,7 @@
#define TOML_LIB_MAJOR 0 #define TOML_LIB_MAJOR 0
#define TOML_LIB_MINOR 3 #define TOML_LIB_MINOR 3
#define TOML_LIB_PATCH 1 #define TOML_LIB_PATCH 2
#define TOML_LANG_MAJOR 0 #define TOML_LANG_MAJOR 0
#define TOML_LANG_MINOR 5 #define TOML_LANG_MINOR 5
@ -413,10 +413,12 @@ TOML_START
struct time_offset; struct time_offset;
struct date_time; struct date_time;
class node; class node;
template <typename T> class node_view;
template <typename T> class value;
class array; class array;
class table; class table;
template <typename> class node_view;
template <typename> class value;
template <typename> class default_formatter;
template <typename> class json_formatter;
enum class node_type : uint8_t enum class node_type : uint8_t
{ {
@ -918,15 +920,14 @@ TOML_START
{ {
return pack(lhs) >= pack(rhs); return pack(lhs) >= pack(rhs);
} }
};
template <typename CHAR> template <typename CHAR>
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const date& rhs) inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const date& rhs) TOML_MAY_THROW
TOML_MAY_THROW
{ {
impl::print_to_stream(rhs, lhs); impl::print_to_stream(rhs, lhs);
return lhs; return lhs;
} }
};
struct time final struct time final
{ {
@ -986,15 +987,14 @@ TOML_START
{ {
return pack(lhs) >= pack(rhs); return pack(lhs) >= pack(rhs);
} }
};
template <typename CHAR> template <typename CHAR>
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const time& rhs) inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const time& rhs) TOML_MAY_THROW
TOML_MAY_THROW
{ {
impl::print_to_stream(rhs, lhs); impl::print_to_stream(rhs, lhs);
return lhs; return lhs;
} }
};
struct time_offset final struct time_offset final
{ {
@ -1045,15 +1045,14 @@ TOML_START
{ {
return lhs.minutes >= rhs.minutes; return lhs.minutes >= rhs.minutes;
} }
};
template <typename CHAR> template <typename CHAR>
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const time_offset& rhs) inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const time_offset& rhs) TOML_MAY_THROW
TOML_MAY_THROW
{ {
impl::print_to_stream(rhs, lhs); impl::print_to_stream(rhs, lhs);
return lhs; return lhs;
} }
};
struct date_time final struct date_time final
{ {
@ -1131,15 +1130,14 @@ TOML_START
{ {
return !(lhs < rhs); return !(lhs < rhs);
} }
};
template <typename CHAR> template <typename CHAR>
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const date_time& rhs) inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const date_time& rhs) TOML_MAY_THROW
TOML_MAY_THROW
{ {
impl::print_to_stream(rhs, lhs); impl::print_to_stream(rhs, lhs);
return lhs; return lhs;
} }
};
} }
TOML_END TOML_END
@ -1822,6 +1820,9 @@ TOML_END
TOML_START TOML_START
{ {
template <typename CHAR, typename T>
std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>&, const value<T>&) TOML_MAY_THROW;
template <typename T> template <typename T>
class TOML_API value final : public node class TOML_API value final : public node
{ {
@ -1912,24 +1913,8 @@ TOML_START
[[nodiscard]] explicit operator T&& () && noexcept { return std::move(val_); } [[nodiscard]] explicit operator T&& () && noexcept { return std::move(val_); }
[[nodiscard]] explicit operator const T& () const& noexcept { return val_; } [[nodiscard]] explicit operator const T& () const& noexcept { return val_; }
template <typename CHAR> template <typename CHAR, typename U>
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const value& rhs) TOML_MAY_THROW friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const value<U>& rhs) TOML_MAY_THROW;
{
// this is the same behaviour as default_formatter, but it's so simple that there's
// no need to spin up a new instance of it just for individual values.
if constexpr (std::is_same_v<T, string>)
{
impl::print_to_stream('"', lhs);
impl::print_to_stream_with_escapes(rhs.val_, lhs);
impl::print_to_stream('"', lhs);
}
else
impl::print_to_stream(rhs.val_, lhs);
return lhs;
}
value& operator= (value_arg rhs) noexcept value& operator= (value_arg rhs) noexcept
{ {
if constexpr (std::is_same_v<T, string>) if constexpr (std::is_same_v<T, string>)
@ -2009,6 +1994,16 @@ TOML_START
} }
}; };
#if !TOML_ALL_INLINE
extern template class TOML_API value<string>;
extern template class TOML_API value<int64_t>;
extern template class TOML_API value<double>;
extern template class TOML_API value<bool>;
extern template class TOML_API value<date>;
extern template class TOML_API value<time>;
extern template class TOML_API value<date_time>;
#endif
template <size_t N> value(const string_char(&)[N]) -> value<string>; template <size_t N> value(const string_char(&)[N]) -> value<string>;
template <size_t N> value(const string_char(&&)[N]) -> value<string>; template <size_t N> value(const string_char(&&)[N]) -> value<string>;
value(const string_char*) -> value<string>; value(const string_char*) -> value<string>;
@ -2037,15 +2032,23 @@ TOML_START
value(TOML_SMALL_INT_TYPE) -> value<int64_t>; value(TOML_SMALL_INT_TYPE) -> value<int64_t>;
#endif #endif
#if !TOML_ALL_INLINE template <typename CHAR, typename T>
extern template class TOML_API value<string>; inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const value<T>& rhs) TOML_MAY_THROW
extern template class TOML_API value<int64_t>; {
extern template class TOML_API value<double>; // this is the same behaviour as default_formatter, but it's so simple that there's
extern template class TOML_API value<bool>; // no need to spin up a new instance of it just for individual values.
extern template class TOML_API value<date>;
extern template class TOML_API value<time>; if constexpr (std::is_same_v<T, string>)
extern template class TOML_API value<date_time>; {
#endif impl::print_to_stream('"', lhs);
impl::print_to_stream_with_escapes(rhs.val_, lhs);
impl::print_to_stream('"', lhs);
}
else
impl::print_to_stream(rhs.val_, lhs);
return lhs;
}
template <typename T> template <typename T>
inline std::optional<T> node::value() const noexcept inline std::optional<T> node::value() const noexcept
@ -2941,14 +2944,18 @@ TOML_END
TOML_START TOML_START
{ {
template <typename CHAR, typename T>
inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>&, const node_view<T>&) TOML_MAY_THROW;
template <typename T> template <typename T>
class node_view final class TOML_API node_view final
{ {
public: public:
using viewed_type = T; using viewed_type = T;
private: private:
friend class toml::table; friend class toml::table;
template <typename U> friend class toml::node_view;
viewed_type* node_; viewed_type* node_;
@ -3131,20 +3138,14 @@ TOML_START
return arr && *arr == rhs; return arr && *arr == rhs;
} }
TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, const std::vector<U>&, template <typename U>) TOML_ASYMMETRICAL_EQUALITY_OPS(const node_view&, const std::vector<U>&, template <typename U>)
[[nodiscard]] node_view<viewed_type> operator[] (string_view key) noexcept
[[nodiscard]] node_view operator[] (string_view key) noexcept
{ {
if (auto tbl = this->as_table()) if (auto tbl = this->as_table())
return { tbl->get(key) }; return { tbl->get(key) };
return { nullptr }; return { nullptr };
} }
[[nodiscard]] node_view<viewed_type> operator[] (size_t index) noexcept
{
if (auto tbl = this->as_array())
return { tbl->get(index) };
return { nullptr };
}
[[nodiscard]] node_view<const viewed_type> operator[] (string_view key) const noexcept [[nodiscard]] node_view<const viewed_type> operator[] (string_view key) const noexcept
{ {
if (auto tbl = this->as_table()) if (auto tbl = this->as_table())
@ -3152,15 +3153,31 @@ TOML_START
return { nullptr }; return { nullptr };
} }
[[nodiscard]] node_view<const viewed_type> operator[] (size_t index) const noexcept [[nodiscard]] node_view operator[] (size_t index) noexcept
{ {
if (auto tbl = this->as_array()) if (auto arr = this->as_array())
return { tbl->get(index) }; return { arr->get(index) };
return { nullptr }; return { nullptr };
} }
template <typename CHAR> [[nodiscard]] node_view<const viewed_type> operator[] (size_t index) const noexcept
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& os, const node_view& nv) TOML_MAY_THROW {
if (auto arr = this->as_array())
return { arr->get(index) };
return { nullptr };
}
template <typename CHAR, typename U>
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>&, const node_view<U>&) TOML_MAY_THROW;
};
#if !TOML_ALL_INLINE
extern template class TOML_API node_view<node>;
extern template class TOML_API node_view<const node>;
#endif
template <typename CHAR, typename T>
inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& os, const node_view<T>& nv) TOML_MAY_THROW
{ {
if (nv.node_) if (nv.node_)
{ {
@ -3171,7 +3188,6 @@ TOML_START
} }
return os; return os;
} }
};
} }
TOML_END TOML_END
@ -5282,6 +5298,11 @@ TOML_IMPL_END
TOML_START TOML_START
{ {
template <typename T, typename U>
std::basic_ostream<T>& operator << (std::basic_ostream<T>&, default_formatter<U>&) TOML_MAY_THROW;
template <typename T, typename U>
std::basic_ostream<T>& operator << (std::basic_ostream<T>&, default_formatter<U>&&) TOML_MAY_THROW;
template <typename CHAR = char> template <typename CHAR = char>
class default_formatter final : impl::formatter<CHAR> class default_formatter final : impl::formatter<CHAR>
{ {
@ -5541,23 +5562,10 @@ TOML_START
: base{ source, flags } : base{ source, flags }
{} {}
template <typename T> template <typename T, typename U>
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<T>& lhs, default_formatter& rhs) friend std::basic_ostream<T>& operator << (std::basic_ostream<T>&, default_formatter<U>&) TOML_MAY_THROW;
TOML_MAY_THROW template <typename T, typename U>
{ friend std::basic_ostream<T>& operator << (std::basic_ostream<T>&, default_formatter<U>&&) TOML_MAY_THROW;
rhs.attach(lhs);
rhs.key_path.clear();
rhs.print();
rhs.detach();
return lhs;
}
template <typename T>
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<T>& lhs, default_formatter&& rhs)
TOML_MAY_THROW
{
return lhs << rhs; //as lvalue
}
}; };
template <typename CHAR> template <typename CHAR>
@ -5594,6 +5602,22 @@ TOML_START
base::clear_naked_newline(); base::clear_naked_newline();
} }
template <typename T, typename U>
inline std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, default_formatter<U>& rhs) TOML_MAY_THROW
{
rhs.attach(lhs);
rhs.key_path.clear();
rhs.print();
rhs.detach();
return lhs;
}
template <typename T, typename U>
inline std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, default_formatter<U>&& rhs) TOML_MAY_THROW
{
return lhs << rhs; //as lvalue
}
template <typename CHAR> template <typename CHAR>
inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const table& rhs) TOML_MAY_THROW inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const table& rhs) TOML_MAY_THROW
{ {
@ -5616,6 +5640,11 @@ TOML_END
TOML_START TOML_START
{ {
template <typename T, typename U>
std::basic_ostream<T>& operator << (std::basic_ostream<T>&, json_formatter<U>&) TOML_MAY_THROW;
template <typename T, typename U>
std::basic_ostream<T>& operator << (std::basic_ostream<T>&, json_formatter<U>&&) TOML_MAY_THROW;
template <typename CHAR = char> template <typename CHAR = char>
class json_formatter final : impl::formatter<CHAR> class json_formatter final : impl::formatter<CHAR>
{ {
@ -5676,22 +5705,10 @@ TOML_START
: base{ source, flags } : base{ source, flags }
{} {}
template <typename T> template <typename T, typename U>
friend std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, json_formatter& rhs) friend std::basic_ostream<T>& operator << (std::basic_ostream<T>&, json_formatter<U>&) TOML_MAY_THROW;
TOML_MAY_THROW template <typename T, typename U>
{ friend std::basic_ostream<T>& operator << (std::basic_ostream<T>&, json_formatter<U>&&) TOML_MAY_THROW;
rhs.attach(lhs);
rhs.print();
rhs.detach();
return lhs;
}
template <typename T>
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<T>& lhs, json_formatter&& rhs)
TOML_MAY_THROW
{
return lhs << rhs; //as lvalue
}
}; };
template <typename CHAR> template <typename CHAR>
@ -5732,6 +5749,21 @@ TOML_START
} }
base::clear_naked_newline(); base::clear_naked_newline();
} }
template <typename T, typename U>
inline std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, json_formatter<U>& rhs) TOML_MAY_THROW
{
rhs.attach(lhs);
rhs.print();
rhs.detach();
return lhs;
}
template <typename T, typename U>
inline std::basic_ostream<T>& operator << (std::basic_ostream<T>& lhs, json_formatter<U>&& rhs) TOML_MAY_THROW
{
return lhs << rhs; //as lvalue
}
} }
TOML_END TOML_END
@ -5740,7 +5772,28 @@ TOML_END
#if TOML_IMPLEMENTATION #if TOML_IMPLEMENTATION
//----------------------------------------------------------------- ↓ toml_node_impl.h ------------------------------- //--------------------------------------------------------------- ↓ toml_instantiations.h ----------------------------
#pragma region
TOML_START
{
template class TOML_API value<string>;
template class TOML_API value<int64_t>;
template class TOML_API value<double>;
template class TOML_API value<bool>;
template class TOML_API value<date>;
template class TOML_API value<time>;
template class TOML_API value<date_time>;
template class TOML_API node_view<node>;
template class TOML_API node_view<const node>;
}
TOML_END
#pragma endregion
//--------------------------------------------------------------- ↑ toml_instantiations.h ----------------------------
//------------------------------------------------------------------------------------------ ↓ toml_node_impl.h ------
#pragma region #pragma region
TOML_START TOML_START
@ -5797,25 +5850,7 @@ TOML_START
TOML_END TOML_END
#pragma endregion #pragma endregion
//----------------------------------------------------------------- ↑ toml_node_impl.h ------------------------------- //------------------------------------------------------------------------------------------ ↑ toml_node_impl.h ------
//------------------------------------------------------------------------------------------ ↓ toml_value_impl.h -----
#pragma region
TOML_START
{
template class TOML_API value<string>;
template class TOML_API value<int64_t>;
template class TOML_API value<double>;
template class TOML_API value<bool>;
template class TOML_API value<date>;
template class TOML_API value<time>;
template class TOML_API value<date_time>;
}
TOML_END
#pragma endregion
//------------------------------------------------------------------------------------------ ↑ toml_value_impl.h -----
//--------------- ↓ toml_array_impl.h -------------------------------------------------------------------------------- //--------------- ↓ toml_array_impl.h --------------------------------------------------------------------------------
#pragma region #pragma region

View File

@ -75,8 +75,9 @@
<ClInclude Include="..\include\toml++\toml_table.h" /> <ClInclude Include="..\include\toml++\toml_table.h" />
<ClInclude Include="..\include\toml++\toml_utf8.h" /> <ClInclude Include="..\include\toml++\toml_utf8.h" />
<ClInclude Include="..\include\toml++\toml_value.h" /> <ClInclude Include="..\include\toml++\toml_value.h" />
<ClInclude Include="..\include\toml++\toml_value_impl.h" /> <ClInclude Include="..\include\toml++\toml_instantiations.h" />
<ClInclude Include="..\include\toml++\toml_version.h" /> <ClInclude Include="..\include\toml++\toml_version.h" />
<ClInclude Include="..\tests\catch2.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\.editorconfig" /> <None Include="..\.editorconfig" />

View File

@ -58,12 +58,15 @@
<ClInclude Include="..\include\toml++\toml_table_impl.h"> <ClInclude Include="..\include\toml++\toml_table_impl.h">
<Filter>include</Filter> <Filter>include</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\include\toml++\toml_value_impl.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="..\include\toml++\toml_parser_impl.h"> <ClInclude Include="..\include\toml++\toml_parser_impl.h">
<Filter>include</Filter> <Filter>include</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\include\toml++\toml_instantiations.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="..\tests\catch2.h">
<Filter>extern</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\.editorconfig" /> <None Include="..\.editorconfig" />
@ -105,5 +108,8 @@
<Filter Include="doc"> <Filter Include="doc">
<UniqueIdentifier>{5ed0949f-6855-4664-ad86-2b38ceeb400b}</UniqueIdentifier> <UniqueIdentifier>{5ed0949f-6855-4664-ad86-2b38ceeb400b}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="extern">
<UniqueIdentifier>{b838dba3-02f6-446f-840e-6b4c62d2fb0c}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
</Project> </Project>