mirror of
https://github.com/boostorg/leaf.git
synced 2026-01-19 04:22:08 +00:00
Serialization refactoring
This commit is contained in:
517
doc/leaf.adoc
517
doc/leaf.adoc
@@ -1740,85 +1740,12 @@ LEAF provides a serialization API that enables exporting error information into
|
||||
* <<diagnostic_details>>
|
||||
* <<result>>
|
||||
|
||||
==== Custom Writers
|
||||
LEAF serialization is defined in terms of `write` and `write_nested` function calls, found via ADL:
|
||||
|
||||
To support different serialization formats, users can define custom writer types that derive from `leaf::serialization::writer`:
|
||||
* `write(w, x)` serializes `x` directly to writer `w`.
|
||||
* `write_nested(w, x, name)` serializes `x` to writer `w` as a named field.
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
#include <boost/leaf/serialization/writer.hpp>
|
||||
|
||||
class my_writer: public leaf::serialization::writer
|
||||
{
|
||||
public:
|
||||
|
||||
my_writer() noexcept:
|
||||
writer(this)
|
||||
{
|
||||
}
|
||||
|
||||
template <class E>
|
||||
void write(E const & e)
|
||||
{
|
||||
.... // Serialize e
|
||||
}
|
||||
};
|
||||
----
|
||||
|
||||
LEAF does not define a specific API for user-defined writer types; for example, a writer could provide a `write` member function as shown above.
|
||||
|
||||
To enable serialization of error objects to custom writer types, define a `serialize` function template in the `boost::leaf::serialization` namespace:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization {
|
||||
|
||||
template <class E>
|
||||
void serialize(writer & w, E const & e)
|
||||
{
|
||||
if( my_writer * mw = w.get<my_writer>() )
|
||||
mw->write(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} }
|
||||
----
|
||||
|
||||
The `serialize` function receives a polymorphic `writer &` reference. Use the `get<Derived>()` member function to check for a specific writer type. If the cast succeeds (returns non-null), call member functions as needed (e.g. `write`) to serialize the error object. To support multiple output formats, this user-defined `serialize` function should check for each writer type accordingly.
|
||||
|
||||
==== JSON Serialization
|
||||
|
||||
LEAF provides `json_writer`, a writer class template for JSON serialization:
|
||||
|
||||
.#include <boost/leaf/serialization/json_writer.hpp>
|
||||
[source,c++]
|
||||
----
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization {
|
||||
|
||||
template <class Json>
|
||||
class json_writer: public writer
|
||||
{
|
||||
public:
|
||||
|
||||
explicit json_writer(Json &) noexcept;
|
||||
|
||||
template <class E>
|
||||
void write(E const &);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} }
|
||||
----
|
||||
|
||||
The `json_writer::write` member function serializes error objects by calling `to_json(Json &, E const &)`, found via ADL. These overloads use `operator[](char const *)` and `to_json` to serialize member values.
|
||||
|
||||
LEAF provides `to_json` overloads for:
|
||||
LEAF provides generic `write` overloads for the following types:
|
||||
|
||||
* `error_id`
|
||||
* `e_source_location`
|
||||
@@ -1827,35 +1754,109 @@ LEAF provides `to_json` overloads for:
|
||||
* `std::error_condition`
|
||||
* `std::exception`
|
||||
* `std::exception_ptr`
|
||||
* any type with a `.value` member for which `to_json` can be found via ADL
|
||||
* any type with a `.value` member for which a suitable `write` can be found via ADL
|
||||
|
||||
This interface is compatible with https://github.com/nlohmann/json[nlohmann/json]:
|
||||
[[custom-writers]]
|
||||
==== Custom Writers
|
||||
|
||||
To support exporting to a specific format, users define a writer class with associated `write` and `write_nested` function templates specific to that writer:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
#include <boost/leaf/diagnostics.hpp>
|
||||
#include <boost/leaf/serialization/json_writer.hpp>
|
||||
struct my_writer
|
||||
{
|
||||
std::ostream & os;
|
||||
|
||||
template <class T>
|
||||
friend void write(my_writer & w, T const & x)
|
||||
{
|
||||
// write x to w
|
||||
}
|
||||
|
||||
template <class T>
|
||||
friend void write_nested(my_writer & w, T const & x, char const * name)
|
||||
{
|
||||
// write x to w as a named field
|
||||
}
|
||||
};
|
||||
----
|
||||
|
||||
The `write` function outputs a value. The `write_nested` function typically creates a nested scope (e.g. a JSON object or XML element) and then makes an unqualified call to `write` to output the value. This will call any compatible overload found via ADL.
|
||||
|
||||
TIP: The `write` function may need to use SFINAE to avoid ambiguities with the generic `write` overloads provided by LEAF. Custom writers must also handle types that do not provide ADL `write` overloads, including built-in types like `int` and `std::string`.
|
||||
|
||||
To enable serialization to a custom writer type, define a `serialize` function template in the `boost::leaf::serialization` namespace:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization {
|
||||
|
||||
template <class Handle, class E>
|
||||
void serialize(Handle & h, E const & e, char const * name)
|
||||
{
|
||||
h.dispatch([&](my_writer & mw) {
|
||||
write_nested(mw, e, name);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} }
|
||||
----
|
||||
|
||||
The `serialize` function template takes a handle reference `h` (of unspecified type) that holds a writer, the error object to be serialized, and its type name. Call `h.dispatch` with a single-argument function F to detect the writer type based on F's argument type; F is called only if the handle contains a writer of that type.
|
||||
|
||||
To support multiple output formats, pass multiple functions to `h.dispatch`:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
h.dispatch(
|
||||
[&](nlohmann_writer & nw) { write_nested(nw, e, name); },
|
||||
[&](xml_writer & xw) { write_nested(xw, e, name); }
|
||||
);
|
||||
----
|
||||
|
||||
==== JSON Serialization
|
||||
|
||||
LEAF provides `nlohmann_writer`, a class template for JSON serialization. The `nlohmann_writer` class defines `write` and `write_nested` friend functions (see <<tutorial-serialization>>) that work with:
|
||||
|
||||
* Types for which `to_json` overloads can be found via ADL
|
||||
* Types for which a `write` overload can be found via ADL (e.g. LEAF types)
|
||||
|
||||
This interface is compatible with https://github.com/nlohmann/json[nlohmann/json], we just need to define the required `serialize` function template (see <<custom-writers>>):
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
#include <boost/leaf/serialization/nlohmann_writer.hpp>
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
namespace leaf = boost::leaf;
|
||||
|
||||
using nlohmann_writer = leaf::serialization::json_writer<nlohmann::json>;
|
||||
using nlohmann_writer = leaf::serialization::nlohmann_writer<nlohmann::json>;
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization {
|
||||
|
||||
template <class E>
|
||||
void serialize(writer & w, E const & e)
|
||||
{
|
||||
if( nlohmann_writer * nw = w.get<nlohmann_writer>() )
|
||||
nw->write(e);
|
||||
}
|
||||
template <class Handle, class E>
|
||||
void serialize(Handle & h, E const & e, char const * name)
|
||||
{
|
||||
h.dispatch([&](nlohmann_writer & nw) {
|
||||
write_nested(nw, e, name);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} }
|
||||
----
|
||||
|
||||
With this in place, we can easily (for example) serialize <<diagnostic_details>> to JSON:
|
||||
|
||||
[source,c++]
|
||||
----
|
||||
struct e_api_response
|
||||
{
|
||||
int status;
|
||||
@@ -1900,9 +1901,7 @@ leaf::try_handle_all(
|
||||
"status": 403,
|
||||
"message": "Access denied"
|
||||
},
|
||||
"e_request_url": {
|
||||
"value": "/api/admin/settings"
|
||||
}
|
||||
"e_request_url": "/api/admin/settings"
|
||||
}
|
||||
----
|
||||
|
||||
@@ -1912,7 +1911,7 @@ leaf::try_handle_all(
|
||||
'''
|
||||
|
||||
[[tutorial-std_error_code]]
|
||||
=== Working with `std::error_code`, `std::error_condition`
|
||||
=== Working with `std::error_code` and `std::error_condition`
|
||||
|
||||
==== Introduction
|
||||
|
||||
@@ -2868,98 +2867,11 @@ Reference: <<to_variant>>
|
||||
|
||||
=== Serialization
|
||||
|
||||
[[type_name.hpp]]
|
||||
==== `type_name.hpp`
|
||||
[[nlohmann_writer.hpp]]
|
||||
==== `nlohmann_writer.hpp`
|
||||
|
||||
====
|
||||
.#include <boost/leaf/serialization/type_name.hpp>
|
||||
[source,c++]
|
||||
----
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
|
||||
struct type_name
|
||||
{
|
||||
char const * name_not_zero_terminated_at_length;
|
||||
std::size_t length;
|
||||
std::size_t hash;
|
||||
|
||||
friend bool operator==( type_name const &, type_name const & ) noexcept;
|
||||
friend bool operator!=( type_name const &, type_name const & ) noexcept;
|
||||
friend bool operator<( type_name const &, type_name const & ) noexcept;
|
||||
|
||||
template <class CharT, class Traits>
|
||||
friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> &, type_name const & );
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
friend std::string_view to_string_view( type_name const & ) noexcept;
|
||||
#endif
|
||||
|
||||
#if BOOST_LEAF_CFG_STD_STRING
|
||||
friend std::string to_string( type_name const & );
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class T>
|
||||
type_name get_type_name() noexcept;
|
||||
|
||||
} // namespace serialization
|
||||
|
||||
} }
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <> struct hash<boost::leaf::serialization::type_name>;
|
||||
}
|
||||
----
|
||||
|
||||
[.text-right]
|
||||
Reference: <<type_name>> | <<get_type_name>>
|
||||
====
|
||||
|
||||
[[writer.hpp]]
|
||||
==== `writer.hpp`
|
||||
|
||||
====
|
||||
.#include <boost/leaf/serialization/writer.hpp>
|
||||
[source,c++]
|
||||
----
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
|
||||
class writer
|
||||
{
|
||||
protected:
|
||||
|
||||
template <class Derived>
|
||||
explicit writer( Derived * ) noexcept;
|
||||
|
||||
~writer() noexcept;
|
||||
|
||||
public:
|
||||
|
||||
template <class Derived>
|
||||
Derived * get() noexcept;
|
||||
};
|
||||
|
||||
} // namespace serialization
|
||||
|
||||
} }
|
||||
----
|
||||
|
||||
[.text-right]
|
||||
Reference: <<writer>> | <<serialize>>
|
||||
====
|
||||
|
||||
[[json_writer.hpp]]
|
||||
==== `json_writer.hpp`
|
||||
|
||||
====
|
||||
.#include <boost/leaf/serialization/json_writer.hpp>
|
||||
.#include <boost/leaf/serialization/nlohmann_writer.hpp>
|
||||
[source,c++]
|
||||
----
|
||||
namespace boost { namespace leaf {
|
||||
@@ -2967,49 +2879,24 @@ namespace boost { namespace leaf {
|
||||
namespace serialization
|
||||
{
|
||||
template <class Json>
|
||||
void to_json( Json &, error_id );
|
||||
|
||||
template <class Json>
|
||||
void to_json( Json &, e_source_location const & );
|
||||
|
||||
template <class Json>
|
||||
void to_json( Json &, e_errno const & );
|
||||
|
||||
template <class Json>
|
||||
void to_json( Json &, std::error_code const & );
|
||||
|
||||
template <class Json>
|
||||
void to_json( Json &, std::error_condition const & );
|
||||
|
||||
template <class Json>
|
||||
void to_json( Json &, std::exception const & );
|
||||
|
||||
template <class Json>
|
||||
void to_json( Json &, std::exception_ptr const & );
|
||||
|
||||
// SFINAE: any type E with a .value member for which to_json can be bound via ADL.
|
||||
template <class Json, class E>
|
||||
auto to_json( Json &, E const & ) ->
|
||||
decltype(to_json(std::declval<Json &>(), std::declval<E const &>().value), void());
|
||||
|
||||
template <class Json>
|
||||
class json_writer: public writer
|
||||
struct nlohmann_writer
|
||||
{
|
||||
public:
|
||||
Json & j_;
|
||||
|
||||
explicit json_writer( Json & ) noexcept;
|
||||
template <class T>
|
||||
friend auto write( nlohmann_writer &, T const & x )
|
||||
-> decltype(to_json(std::declval<Json &>(), x));
|
||||
|
||||
template <class E>
|
||||
void write( E const & );
|
||||
template <class T>
|
||||
friend void write_nested( nlohmann_writer &, T const &, char const * name );
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} }
|
||||
----
|
||||
|
||||
[.text-right]
|
||||
Reference: <<to_json>> | <<json_writer>>
|
||||
Reference: <<nlohmann_writer>>
|
||||
====
|
||||
|
||||
[[functions]]
|
||||
@@ -3196,27 +3083,6 @@ TIP: See also <<tutorial-exception_to_result>> from the tutorial.
|
||||
|
||||
'''
|
||||
|
||||
[[get_type_name]]
|
||||
=== `get_type_name`
|
||||
|
||||
.#include <boost/leaf/serialization/type_name.hpp>
|
||||
[source,c++]
|
||||
----
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
template <class T>
|
||||
type_name get_type_name() noexcept;
|
||||
}
|
||||
|
||||
} }
|
||||
----
|
||||
|
||||
Returns a <<type_name>> object representing the type `T`. The type name is extracted automatically in constant time.
|
||||
|
||||
'''
|
||||
|
||||
[[make_context]]
|
||||
=== `make_context`
|
||||
|
||||
@@ -3330,21 +3196,20 @@ TIP: See <<tutorial-on_error>> from the Tutorial.
|
||||
[[serialize]]
|
||||
=== `serialize`
|
||||
|
||||
.#include <boost/leaf/serialization/writer.hpp>
|
||||
[source,c++]
|
||||
----
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
template <class E>
|
||||
void serialize( writer &, E const & );
|
||||
template <class Handle, class E>
|
||||
void serialize( Handle &, E const &, char const * name );
|
||||
}
|
||||
|
||||
} }
|
||||
----
|
||||
|
||||
The `serialize` function template is a user-defined customization point. If defined, it is called by the serialization system to serialize error objects to a writer; see <<tutorial-serialization>>.
|
||||
The `serialize` function template is a user-defined customization point. If provided, it is called by the serialization system to output error objects; see <<custom-writers>>.
|
||||
|
||||
'''
|
||||
|
||||
@@ -3424,52 +3289,6 @@ NOTE: To automatically capture `pass:[__FILE__]`, `pass:[__LINE__]` and `pass:[_
|
||||
|
||||
'''
|
||||
|
||||
[[to_json]]
|
||||
=== `to_json`
|
||||
|
||||
.#include <boost/leaf/serialization/json_writer.hpp>
|
||||
[source,c++]
|
||||
----
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
template <class Json>
|
||||
void to_json( Json &, error_id );
|
||||
|
||||
template <class Json>
|
||||
void to_json( Json &, e_source_location const & );
|
||||
|
||||
template <class Json>
|
||||
void to_json( Json &, e_errno const & );
|
||||
|
||||
template <class Json>
|
||||
void to_json( Json &, std::error_code const & );
|
||||
|
||||
template <class Json>
|
||||
void to_json( Json &, std::error_condition const & );
|
||||
|
||||
template <class Json>
|
||||
void to_json( Json &, std::exception const & );
|
||||
|
||||
template <class Json>
|
||||
void to_json( Json &, std::exception_ptr const & );
|
||||
|
||||
// SFINAE: any type E with a .value member for which to_json can be bound via ADL.
|
||||
template <class Json, class E>
|
||||
auto to_json( Json &, E const & ) ->
|
||||
decltype(to_json(std::declval<Json &>(), std::declval<E const &>().value), void());
|
||||
}
|
||||
|
||||
} }
|
||||
----
|
||||
|
||||
The `to_json` function is used by <<json_writer>> to serialize error objects to a JSON object. Users can define `to_json` overloads for their own error types, which will be found via ADL. These overloads should use `operator[]` to create JSON object fields and call `to_json` to serialize member values.
|
||||
|
||||
NOTE: This interface is compatible with https://github.com/nlohmann/json[nlohmann/json].
|
||||
|
||||
'''
|
||||
|
||||
[[to_variant]]
|
||||
=== `to_variant`
|
||||
|
||||
@@ -4623,10 +4442,10 @@ The `write_to` member function is used with the serialization system; see <<tuto
|
||||
|
||||
'''
|
||||
|
||||
[[json_writer]]
|
||||
=== `json_writer`
|
||||
[[nlohmann_writer]]
|
||||
=== `nlohmann_writer`
|
||||
|
||||
.#include <boost/leaf/serialization/json_writer.hpp>
|
||||
.#include <boost/leaf/serialization/nlohmann_writer.hpp>
|
||||
[source,c++]
|
||||
----
|
||||
namespace boost { namespace leaf {
|
||||
@@ -4634,25 +4453,25 @@ namespace boost { namespace leaf {
|
||||
namespace serialization
|
||||
{
|
||||
template <class Json>
|
||||
class json_writer: public writer
|
||||
struct nlohmann_writer
|
||||
{
|
||||
public:
|
||||
Json & j_;
|
||||
|
||||
explicit json_writer( Json & ) noexcept;
|
||||
// Enabled for types for which a suitable to_json overload
|
||||
// can be found via ADL, but a suitable write overload cannot.
|
||||
template <class T>
|
||||
friend auto write( nlohmann_writer &, T const & x )
|
||||
-> decltype(to_json(std::declval<Json &>(), x));
|
||||
|
||||
template <class E>
|
||||
void write( E const & );
|
||||
template <class T>
|
||||
friend void write_nested( nlohmann_writer &, T const &, char const * name );
|
||||
};
|
||||
}
|
||||
|
||||
} }
|
||||
----
|
||||
|
||||
The `json_writer` class template is used to serialize error objects to a JSON object. The `Json` template parameter is the type of the JSON object, for example https://github.com/nlohmann/json[nlohmann/json].
|
||||
|
||||
The constructor takes a reference to a JSON object, which will be populated with serialized error data.
|
||||
|
||||
The `write` member function serializes an error object by calling `<<to_json>>(json, e)`, found via ADL; see <<tutorial-serialization>>.
|
||||
The `nlohmann_writer` class template serializes error objects to JSON format using unqualified calls to `to_json`. This is compatible with https://github.com/nlohmann/json[nlohmann/json]; See <<tutorial-serialization>>.
|
||||
|
||||
'''
|
||||
|
||||
@@ -5155,106 +4974,6 @@ namespace boost { namespace leaf {
|
||||
} }
|
||||
----
|
||||
|
||||
'''
|
||||
|
||||
[[type_name]]
|
||||
=== `type_name`
|
||||
|
||||
.#include <boost/leaf/serialization/type_name.hpp>
|
||||
[source,c++]
|
||||
----
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
|
||||
struct type_name
|
||||
{
|
||||
char const * name_not_zero_terminated_at_length;
|
||||
std::size_t length;
|
||||
std::size_t hash;
|
||||
|
||||
friend bool operator==( type_name const &, type_name const & ) noexcept;
|
||||
friend bool operator!=( type_name const &, type_name const & ) noexcept;
|
||||
friend bool operator<( type_name const &, type_name const & ) noexcept;
|
||||
|
||||
template <class CharT, class Traits>
|
||||
friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> &, type_name const & );
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
friend std::string_view to_string_view( type_name const & ) noexcept;
|
||||
#endif
|
||||
|
||||
#if BOOST_LEAF_CFG_STD_STRING
|
||||
friend std::string to_string( type_name const & );
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace serialization
|
||||
|
||||
} }
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <> struct hash<boost::leaf::serialization::type_name>;
|
||||
}
|
||||
----
|
||||
|
||||
The `type_name` struct represents a type name, extracted automatically in constant time. It contains a pointer to the type name string, its length, and a precomputed hash for efficient comparison.
|
||||
|
||||
Two `type_name` objects compare equal if they represent the same type. The `operator<` provides alphabetical ordering. A `std::hash` specialization is provided for use with `std::unordered_map`. See <<get_type_name>>.
|
||||
|
||||
The type names are not mangled.
|
||||
|
||||
.Example:
|
||||
[source,c++]
|
||||
----
|
||||
namespace app
|
||||
{
|
||||
struct my_error { };
|
||||
}
|
||||
|
||||
using leaf::serialization::get_type_name;
|
||||
|
||||
assert(to_string_view(get_type_name<int>()) == "int");
|
||||
assert(to_string_view(get_type_name<app::my_error>()) == "app::my_error");
|
||||
----
|
||||
|
||||
'''
|
||||
|
||||
[[writer]]
|
||||
=== `writer`
|
||||
|
||||
.#include <boost/leaf/serialization/writer.hpp>
|
||||
[source,c++]
|
||||
----
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
class writer
|
||||
{
|
||||
protected:
|
||||
|
||||
template <class Derived>
|
||||
explicit writer( Derived * ) noexcept;
|
||||
|
||||
~writer() noexcept;
|
||||
|
||||
public:
|
||||
|
||||
template <class Derived>
|
||||
Derived * get() noexcept;
|
||||
};
|
||||
}
|
||||
|
||||
} }
|
||||
----
|
||||
|
||||
The `writer` class is the base class for custom serialization writers. The constructor takes a pointer to the derived class, which is used by the `get` member function to recognize writer types at runtime.
|
||||
|
||||
The `get` member function returns a pointer to the derived class if the type matches, or `nullptr` otherwise. This allows the <<serialize>> function to dispatch to the correct writer type; see <<tutorial-serialization>>.
|
||||
|
||||
[[predicates]]
|
||||
== Reference: Predicates
|
||||
|
||||
|
||||
@@ -452,11 +452,11 @@ code{font-family:"Anonymous Pro","DejaVu Sans Mono",monospace;font-weight:400;co
|
||||
pre,pre>code{line-height:1.45;color:rgba(255,255,255,.67);font-family:"Anonymous Pro","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeLegibility;font-size:1.05em;background-color:#101010}
|
||||
a:not(pre)>code:hover {color:#00cc99}
|
||||
kbd{font-family:"Anonymous Pro","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
|
||||
h1 code{color:#00cc99; font-size:113%}
|
||||
h2 code{color:#00cc99; font-size:113%}
|
||||
h3 code{color:#00cc99; font-size:113%}
|
||||
h4 code{color:#00cc99; font-size:113%}
|
||||
h5 code{color:#00cc99; font-size:113%}
|
||||
h1 code{color:#00cc99; font-size:104%}
|
||||
h2 code{color:#00cc99; font-size:104%}
|
||||
h3 code{color:#00cc99; font-size:104%}
|
||||
h4 code{color:#00cc99; font-size:104%}
|
||||
h5 code{color:#00cc99; font-size:104%}
|
||||
#header>h1:first-child{font-family:"Poiret One";color:#00cc99;margin-top:2.25rem;margin-bottom:0;letter-spacing:-.07em}
|
||||
#author{color:#a366ff}
|
||||
#toc ul{font-family:"Quicksand","DejaVu Sans",sans-serif;list-style-type:none}
|
||||
|
||||
@@ -446,11 +446,11 @@ code{font-family:"Anonymous Pro","DejaVu Sans Mono",monospace;font-weight:400;co
|
||||
pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Anonymous Pro","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeLegibility;font-size:1.05em;background-color:#f7f8f7}
|
||||
a:not(pre)>code:hover {color:#4101a7}
|
||||
kbd{font-family:"Anonymous Pro","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
|
||||
h1 code{color:#4101a7; font-size:113%}
|
||||
h2 code{color:#4101a7; font-size:113%}
|
||||
h3 code{color:#4101a7; font-size:113%}
|
||||
h4 code{color:#4101a7; font-size:113%}
|
||||
h5 code{color:#4101a7; font-size:113%}
|
||||
h1 code{color:#4101a7; font-size:104%}
|
||||
h2 code{color:#4101a7; font-size:104%}
|
||||
h3 code{color:#4101a7; font-size:104%}
|
||||
h4 code{color:#4101a7; font-size:104%}
|
||||
h5 code{color:#4101a7; font-size:104%}
|
||||
#header>h1:first-child{font-family:"Poiret One";color:#ff5100;margin-top:2.25rem;margin-bottom:0;letter-spacing:-.07em}
|
||||
#author{color: #4101a7;}
|
||||
#toc ul{font-family:"Quicksand","DejaVu Sans",sans-serif;list-style-type:none}
|
||||
|
||||
@@ -57,6 +57,13 @@ struct e_errno
|
||||
{
|
||||
return os << err.value << ", \"" << std::strerror(err.value) << '"';
|
||||
}
|
||||
|
||||
template <class Writer>
|
||||
friend void write( Writer & w, e_errno const & e )
|
||||
{
|
||||
write_nested(w, e.value, "errno");
|
||||
write_nested(w, std::strerror(e.value), "strerror");
|
||||
}
|
||||
};
|
||||
|
||||
struct e_type_info_name { char const * value; };
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/leaf/config.hpp>
|
||||
#include <boost/leaf/serialization/diagnostics_writer.hpp>
|
||||
#include <boost/leaf/detail/diagnostics_writer.hpp>
|
||||
#include <boost/leaf/error.hpp>
|
||||
|
||||
#if !defined(BOOST_LEAF_NO_THREADS) && !defined(NDEBUG)
|
||||
@@ -204,7 +204,7 @@ namespace detail
|
||||
tuple_for_each<I-1,Tup>::unload(tup, err_id);
|
||||
}
|
||||
|
||||
static void write_to(serialization::writer & w, void const * tup, error_id id)
|
||||
static void write_to(writer & w, void const * tup, error_id id)
|
||||
{
|
||||
BOOST_LEAF_ASSERT(tup != nullptr);
|
||||
tuple_for_each<I-1,Tup>::write_to(w, tup, id);
|
||||
@@ -218,11 +218,11 @@ namespace detail
|
||||
BOOST_LEAF_CONSTEXPR static void activate( Tup & ) noexcept { }
|
||||
BOOST_LEAF_CONSTEXPR static void deactivate( Tup & ) noexcept { }
|
||||
BOOST_LEAF_CONSTEXPR static void unload( Tup &, int ) noexcept { }
|
||||
BOOST_LEAF_CONSTEXPR static void write_to(serialization::writer &, void const *, error_id) { }
|
||||
BOOST_LEAF_CONSTEXPR static void write_to(writer &, void const *, error_id) { }
|
||||
};
|
||||
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR void serialize_tuple_contents(serialization::writer & w, void const * tup, error_id id)
|
||||
void serialize_tuple_contents(writer & w, void const * tup, error_id id)
|
||||
{
|
||||
tuple_for_each<std::tuple_size<Tup>::value, Tup>::write_to(w, tup, id);
|
||||
}
|
||||
@@ -368,7 +368,7 @@ public:
|
||||
return is_active_;
|
||||
}
|
||||
|
||||
void write_to( serialization::writer & w ) const
|
||||
void write_to( detail::diagnostics_writer & w ) const
|
||||
{
|
||||
detail::serialize_tuple_contents<Tup>(w, &tup_, error_id());
|
||||
}
|
||||
@@ -376,7 +376,7 @@ public:
|
||||
template <class CharT, class Traits>
|
||||
friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, context const & ctx )
|
||||
{
|
||||
serialization::diagnostics_writer w(os);
|
||||
detail::diagnostics_writer w(os);
|
||||
w.set_prefix("Contents:");
|
||||
ctx.write_to(w);
|
||||
return os;
|
||||
|
||||
@@ -11,7 +11,5 @@
|
||||
#include <boost/leaf/on_error.hpp>
|
||||
#include <boost/leaf/pred.hpp>
|
||||
#include <boost/leaf/result.hpp>
|
||||
#include <boost/leaf/serialization/diagnostics_writer.hpp>
|
||||
#include <boost/leaf/serialization/json_writer.hpp>
|
||||
#include <boost/leaf/serialization/writer.hpp>
|
||||
#include <boost/leaf/serialization/nlohmann_writer.hpp>
|
||||
#include <boost/leaf/to_variant.hpp>
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
class error_id;
|
||||
namespace serialization { class writer; }
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class writer;
|
||||
|
||||
class capture_list
|
||||
{
|
||||
@@ -29,7 +29,7 @@ namespace detail
|
||||
friend class capture_list;
|
||||
|
||||
virtual void unload( int err_id ) = 0;
|
||||
virtual void write_to(serialization::writer &, error_id const &) const = 0;
|
||||
virtual void write_to(writer &, error_id const &) const = 0;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace detail
|
||||
} );
|
||||
}
|
||||
|
||||
void write_to(serialization::writer & w, error_id const & id) const
|
||||
void write_to(writer & w, error_id const & id) const
|
||||
{
|
||||
if( first_ )
|
||||
{
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#ifndef BOOST_LEAF_SERIALIZATION_DIAGNOSTICS_WRITER_HPP_INCLUDED
|
||||
#define BOOST_LEAF_SERIALIZATION_DIAGNOSTICS_WRITER_HPP_INCLUDED
|
||||
#ifndef BOOST_LEAF_DETAIL_DIAGNOSTICS_WRITER_HPP_INCLUDED
|
||||
#define BOOST_LEAF_DETAIL_DIAGNOSTICS_WRITER_HPP_INCLUDED
|
||||
|
||||
// Copyright 2018-2026 Emil Dotchevski and Reverge Studios, Inc.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/leaf/config.hpp>
|
||||
#include <boost/leaf/serialization/writer.hpp>
|
||||
#include <boost/leaf/detail/writer.hpp>
|
||||
#include <boost/leaf/detail/exception_base.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
@@ -28,7 +28,7 @@ struct show_in_diagnostics: std::integral_constant<bool, BOOST_LEAF_CFG_DIAGNOST
|
||||
{
|
||||
};
|
||||
|
||||
namespace serialization
|
||||
namespace detail
|
||||
{
|
||||
template <class T, class E = void>
|
||||
struct is_printable: std::false_type
|
||||
@@ -50,16 +50,6 @@ namespace serialization
|
||||
{
|
||||
};
|
||||
|
||||
template <class T, class E = void>
|
||||
struct has_member_value: std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct has_member_value<T, decltype((void)std::declval<T const &>().value)>: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
class diagnostics_writer: public writer
|
||||
@@ -79,7 +69,7 @@ namespace serialization
|
||||
BOOST_LEAF_ASSERT(delimiter);
|
||||
char const * p = prefix;
|
||||
prefix = nullptr;
|
||||
os << (p ? p : delimiter) << get_type_name<T>();
|
||||
os << (p ? p : delimiter) << detail::get_type_name<T>();
|
||||
}
|
||||
|
||||
template <class T, class PrintableInfo, class CharT, class Traits>
|
||||
@@ -171,10 +161,10 @@ namespace serialization
|
||||
delimiter_ = delimiter;
|
||||
}
|
||||
|
||||
template <class E>
|
||||
void write(E const & e)
|
||||
template <class T>
|
||||
void write(T const & x)
|
||||
{
|
||||
diagnostic<E>::print(os_, prefix_, delimiter_, e);
|
||||
diagnostic<T>::print(os_, prefix_, delimiter_, x);
|
||||
}
|
||||
}; // class diagnostics_writer
|
||||
|
||||
@@ -245,8 +235,8 @@ namespace serialization
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace serialization
|
||||
} // namespace detail
|
||||
|
||||
} } // namespace boost::leaf
|
||||
|
||||
#endif // #ifndef BOOST_LEAF_SERIALIZATION_DIAGNOSTICS_WRITER_HPP_INCLUDED
|
||||
#endif // #ifndef BOOST_LEAF_DETAIL_DIAGNOSTICS_WRITER_HPP_INCLUDED
|
||||
@@ -6,7 +6,6 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/leaf/config.hpp>
|
||||
#include <boost/leaf/serialization/type_name.hpp>
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
@@ -14,11 +13,13 @@ class error_id;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct type_name;
|
||||
|
||||
class exception_base
|
||||
{
|
||||
public:
|
||||
virtual error_id get_error_id() const noexcept = 0;
|
||||
virtual serialization::type_name get_type_name() const = 0;
|
||||
virtual type_name get_type_name() const = 0;
|
||||
protected:
|
||||
exception_base() noexcept { }
|
||||
~exception_base() noexcept { }
|
||||
|
||||
57
include/boost/leaf/detail/type_name.hpp
Normal file
57
include/boost/leaf/detail/type_name.hpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#ifndef BOOST_LEAF_DETAIL_TYPE_NAME_HPP_INCLUDED
|
||||
#define BOOST_LEAF_DETAIL_TYPE_NAME_HPP_INCLUDED
|
||||
|
||||
// Copyright 2018-2026 Emil Dotchevski and Reverge Studios, Inc.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/leaf/detail/demangle.hpp>
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct type_name
|
||||
{
|
||||
char const * name_not_zero_terminated_at_length;
|
||||
std::size_t length;
|
||||
std::size_t hash;
|
||||
|
||||
friend bool operator==(type_name const & a, type_name const & b) noexcept
|
||||
{
|
||||
BOOST_LEAF_ASSERT((a.hash == b.hash) == (a.length == b.length && std::memcmp(a.name_not_zero_terminated_at_length, b.name_not_zero_terminated_at_length, a.length) == 0));
|
||||
return a.hash == b.hash;
|
||||
}
|
||||
|
||||
friend bool operator!=(type_name const & a, type_name const & b) noexcept
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
friend std::ostream & operator<<(std::basic_ostream<CharT, Traits> & os, type_name const & x)
|
||||
{
|
||||
return os.write(x.name_not_zero_terminated_at_length, x.length);
|
||||
}
|
||||
|
||||
template <std::size_t S>
|
||||
friend char * to_zstr(char (&zstr)[S], type_name const & x) noexcept
|
||||
{
|
||||
std::size_t n = x.length < S - 1 ? x.length : S - 1;
|
||||
std::memcpy(zstr, x.name_not_zero_terminated_at_length, n);
|
||||
zstr[n] = 0;
|
||||
return zstr;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
type_name get_type_name()
|
||||
{
|
||||
n::r parsed = n::p<T>();
|
||||
return { parsed.name_not_zero_terminated_at_length, parsed.length, parsed.hash };
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
} } // namespace boost::leaf
|
||||
|
||||
#endif // #ifndef BOOST_LEAF_DETAIL_TYPE_NAME_HPP_INCLUDED
|
||||
92
include/boost/leaf/detail/writer.hpp
Normal file
92
include/boost/leaf/detail/writer.hpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#ifndef BOOST_LEAF_DETAIL_WRITER_HPP_INCLUDED
|
||||
#define BOOST_LEAF_DETAIL_WRITER_HPP_INCLUDED
|
||||
|
||||
// Copyright 2018-2026 Emil Dotchevski and Reverge Studios, Inc.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/leaf/config.hpp>
|
||||
#include <boost/leaf/detail/type_name.hpp>
|
||||
#include <boost/leaf/detail/function_traits.hpp>
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
struct writer_adl {};
|
||||
|
||||
template <class Writer, class E>
|
||||
auto write(Writer & w, E const & e) -> decltype(write(w, e.value))
|
||||
{
|
||||
write(w, e.value);
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class writer:
|
||||
serialization::writer_adl
|
||||
{
|
||||
writer(writer const &) = delete;
|
||||
writer & operator=(writer const &) = delete;
|
||||
|
||||
type_name const type_;
|
||||
void * const w_;
|
||||
|
||||
bool dispatch_()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class F1, class... Fn>
|
||||
bool dispatch_(F1 && f1, Fn && ... fn)
|
||||
{
|
||||
using writer_type = typename std::decay<fn_arg_type<F1, 0>>::type;
|
||||
if (writer_type * w = get<writer_type>())
|
||||
{
|
||||
std::forward<F1>(f1)(*w);
|
||||
return true;
|
||||
}
|
||||
return dispatch_(std::forward<Fn>(fn)...);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
template <class Writer>
|
||||
explicit writer(Writer * w) noexcept:
|
||||
type_(get_type_name<Writer>()),
|
||||
w_(w)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
template <class Writer>
|
||||
Writer * get() noexcept
|
||||
{
|
||||
return type_ == get_type_name<Writer>() ? static_cast<Writer *>(w_) : nullptr;
|
||||
}
|
||||
|
||||
template <class... Fn>
|
||||
bool dispatch(Fn && ... fn)
|
||||
{
|
||||
using writer_types = leaf_detail_mp11::mp_list<typename std::decay<fn_arg_type<Fn, 0>>::type...>;
|
||||
static_assert(std::is_same<writer_types, leaf_detail_mp11::mp_unique<writer_types>>::value, "Duplicate writer types in dispatch");
|
||||
return dispatch_(std::forward<Fn>(fn)...);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Writer>
|
||||
struct writer_adaptor:
|
||||
writer
|
||||
{
|
||||
explicit writer_adaptor(Writer & w) noexcept:
|
||||
writer(&w)
|
||||
{
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
} } // namespace boost::leaf
|
||||
|
||||
#endif // #ifndef BOOST_LEAF_DETAIL_WRITER_HPP_INCLUDED
|
||||
@@ -6,7 +6,6 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/leaf/config.hpp>
|
||||
#include <boost/leaf/context.hpp>
|
||||
#include <boost/leaf/handle_errors.hpp>
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
@@ -14,7 +13,7 @@ namespace boost { namespace leaf {
|
||||
class diagnostic_info: public error_info
|
||||
{
|
||||
void const * tup_;
|
||||
void (*serialize_tuple_contents_)(serialization::writer &, void const *, error_id);
|
||||
void (*serialize_tuple_contents_)(detail::writer &, void const *, error_id);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -31,6 +30,7 @@ protected:
|
||||
template <class Writer>
|
||||
void write_to_(Writer & w) const
|
||||
{
|
||||
static_assert(std::is_base_of<detail::writer, Writer>::value, "Writer must derive from detail::writer");
|
||||
serialize_tuple_contents_(w, tup_, error());
|
||||
}
|
||||
|
||||
@@ -39,14 +39,15 @@ public:
|
||||
template <class Writer>
|
||||
void write_to(Writer & w) const
|
||||
{
|
||||
error_info::write_to(w);
|
||||
write_to_(w);
|
||||
detail::writer_adaptor<Writer> wa(w);
|
||||
error_info::write_to_(wa);
|
||||
write_to_(wa);
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, diagnostic_info const & x )
|
||||
{
|
||||
serialization::diagnostics_writer w(os, x.error(), x.source_location(), x.exception());
|
||||
detail::diagnostics_writer w(os, x.error(), x.source_location(), x.exception());
|
||||
#if BOOST_LEAF_CFG_DIAGNOSTICS
|
||||
x.write_to_(w);
|
||||
#else
|
||||
@@ -100,6 +101,7 @@ protected:
|
||||
template <class Writer>
|
||||
void write_to_(Writer & w) const
|
||||
{
|
||||
static_assert(std::is_base_of<detail::writer, Writer>::value, "Writer must derive from detail::writer");
|
||||
if( da_ )
|
||||
da_->write_to(w, error());
|
||||
}
|
||||
@@ -109,14 +111,16 @@ public:
|
||||
template <class Writer>
|
||||
void write_to(Writer & w) const
|
||||
{
|
||||
diagnostic_info::write_to(w);
|
||||
write_to_(w);
|
||||
detail::writer_adaptor<Writer> wa(w);
|
||||
error_info::write_to_(wa);
|
||||
diagnostic_info::write_to_(wa);
|
||||
write_to_(wa);
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, diagnostic_details const & x )
|
||||
{
|
||||
serialization::diagnostics_writer w(os, x.error(), x.source_location(), x.exception());
|
||||
detail::diagnostics_writer w(os, x.error(), x.source_location(), x.exception());
|
||||
#if BOOST_LEAF_CFG_DIAGNOSTICS
|
||||
x.diagnostic_info::write_to_(w);
|
||||
w.set_prefix("\nDiagnostic details:" BOOST_LEAF_CFG_DIAGNOSTICS_FIRST_DELIMITER);
|
||||
@@ -170,13 +174,15 @@ public:
|
||||
template <class Writer>
|
||||
void write_to(Writer & w) const
|
||||
{
|
||||
diagnostic_info::write_to(w);
|
||||
detail::writer_adaptor<Writer> wa(w);
|
||||
error_info::write_to_(wa);
|
||||
diagnostic_info::write_to_(wa);
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, diagnostic_details const & x )
|
||||
{
|
||||
serialization::diagnostics_writer w(os, x.error(), x.source_location(), x.exception());
|
||||
detail::diagnostics_writer w(os, x.error(), x.source_location(), x.exception());
|
||||
#if BOOST_LEAF_CFG_DIAGNOSTICS
|
||||
x.diagnostic_info::write_to_(w);
|
||||
os << "\nboost::leaf::diagnostic_details N/A due to BOOST_LEAF_CFG_CAPTURE=0";
|
||||
|
||||
@@ -9,12 +9,41 @@
|
||||
#include <boost/leaf/detail/optional.hpp>
|
||||
#include <boost/leaf/detail/function_traits.hpp>
|
||||
#include <boost/leaf/detail/capture_list.hpp>
|
||||
#include <boost/leaf/serialization/diagnostics_writer.hpp>
|
||||
#include <boost/leaf/detail/diagnostics_writer.hpp>
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
#if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
|
||||
# include <system_error>
|
||||
|
||||
#include <system_error>
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
template <class Writer>
|
||||
void write(Writer & w, std::error_code const & ec)
|
||||
{
|
||||
write_nested(w, ec.category().name(), "category");
|
||||
write_nested(w, ec.value(), "value");
|
||||
write_nested(w, ec.message(), "message");
|
||||
}
|
||||
|
||||
template <class Writer>
|
||||
void write(Writer & w, std::error_condition const & ec)
|
||||
{
|
||||
write_nested(w, ec.category().name(), "category");
|
||||
write_nested(w, ec.value(), "value");
|
||||
write_nested(w, ec.message(), "message");
|
||||
}
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
#define BOOST_LEAF_TOKEN_PASTE(x, y) x ## y
|
||||
#define BOOST_LEAF_TOKEN_PASTE2(x, y) BOOST_LEAF_TOKEN_PASTE(x, y)
|
||||
#define BOOST_LEAF_TMP BOOST_LEAF_TOKEN_PASTE2(boost_leaf_tmp_, __LINE__)
|
||||
@@ -32,26 +61,26 @@
|
||||
|
||||
#if BOOST_LEAF_CFG_GNUC_STMTEXPR
|
||||
|
||||
#define BOOST_LEAF_CHECK(r)\
|
||||
({\
|
||||
auto && BOOST_LEAF_TMP = (r);\
|
||||
static_assert(::boost::leaf::is_result_type<typename std::decay<decltype(BOOST_LEAF_TMP)>::type>::value,\
|
||||
"BOOST_LEAF_CHECK requires a result object (see is_result_type)");\
|
||||
if( !BOOST_LEAF_TMP )\
|
||||
return BOOST_LEAF_TMP.error();\
|
||||
std::move(BOOST_LEAF_TMP);\
|
||||
}).value()
|
||||
# define BOOST_LEAF_CHECK(r)\
|
||||
({\
|
||||
auto && BOOST_LEAF_TMP = (r);\
|
||||
static_assert(::boost::leaf::is_result_type<typename std::decay<decltype(BOOST_LEAF_TMP)>::type>::value,\
|
||||
"BOOST_LEAF_CHECK requires a result object (see is_result_type)");\
|
||||
if( !BOOST_LEAF_TMP )\
|
||||
return BOOST_LEAF_TMP.error();\
|
||||
std::move(BOOST_LEAF_TMP);\
|
||||
}).value()
|
||||
|
||||
#else // #if BOOST_LEAF_CFG_GNUC_STMTEXPR
|
||||
|
||||
#define BOOST_LEAF_CHECK(r)\
|
||||
{\
|
||||
auto && BOOST_LEAF_TMP = (r);\
|
||||
static_assert(::boost::leaf::is_result_type<typename std::decay<decltype(BOOST_LEAF_TMP)>::type>::value,\
|
||||
"BOOST_LEAF_CHECK requires a result object (see is_result_type)");\
|
||||
if( !BOOST_LEAF_TMP )\
|
||||
return BOOST_LEAF_TMP.error();\
|
||||
}
|
||||
# define BOOST_LEAF_CHECK(r)\
|
||||
{\
|
||||
auto && BOOST_LEAF_TMP = (r);\
|
||||
static_assert(::boost::leaf::is_result_type<typename std::decay<decltype(BOOST_LEAF_TMP)>::type>::value,\
|
||||
"BOOST_LEAF_CHECK requires a result object (see is_result_type)");\
|
||||
if( !BOOST_LEAF_TMP )\
|
||||
return BOOST_LEAF_TMP.error();\
|
||||
}
|
||||
|
||||
#endif // #else (#if BOOST_LEAF_CFG_GNUC_STMTEXPR)
|
||||
|
||||
@@ -70,6 +99,14 @@ struct e_source_location
|
||||
{
|
||||
return os << x.file << '(' << x.line << ") in function " << x.function;
|
||||
}
|
||||
|
||||
template <class Writer>
|
||||
friend void write( Writer & w, e_source_location const & x )
|
||||
{
|
||||
write_nested(w, x.file, "file");
|
||||
write_nested(w, x.line, "line");
|
||||
write_nested(w, x.function, "function");
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
@@ -79,16 +116,32 @@ struct show_in_diagnostics<e_source_location>: std::false_type
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
|
||||
template <class Writer, class T, class... Unused>
|
||||
typename std::enable_if<std::is_base_of<detail::writer, Writer>::value>::type
|
||||
serialize(Writer &, T const &, char const *, Unused && ...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class Writer, class E>
|
||||
void serialize_(Writer & w, E const & e)
|
||||
template <class T>
|
||||
void serialize_(diagnostics_writer & w, T const & x)
|
||||
{
|
||||
w.write(x);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void serialize_(writer & w, T const & x)
|
||||
{
|
||||
using namespace serialization;
|
||||
typename dependent_writer<Writer>::type & wr = w;
|
||||
serialize(wr, e);
|
||||
if( diagnostics_writer * dw = w.template get<diagnostics_writer>() )
|
||||
dw->write(e);
|
||||
char zstr[1024];
|
||||
serialize(w, x, to_zstr(zstr, get_type_name<T>()));
|
||||
if( diagnostics_writer * dw = w.get<diagnostics_writer>() )
|
||||
dw->write(x);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,9 +201,10 @@ namespace detail
|
||||
|
||||
void unload( int err_id ) noexcept(!BOOST_LEAF_CFG_CAPTURE);
|
||||
|
||||
template <class ErrorID>
|
||||
void write_to(serialization::writer & w, ErrorID id) const
|
||||
template <class Writer,class ErrorID>
|
||||
void write_to(Writer & w, ErrorID id) const
|
||||
{
|
||||
static_assert(std::is_base_of<writer, Writer>::value, "Writer must derive from detail::writer");
|
||||
if( int k = this->key() )
|
||||
{
|
||||
if( id && id.value() != k )
|
||||
@@ -217,7 +271,7 @@ namespace detail
|
||||
{
|
||||
impl::unload(err_id);
|
||||
}
|
||||
void write_to(serialization::writer & w, error_id const & id) const override
|
||||
void write_to(writer & w, error_id const & id) const override
|
||||
{
|
||||
impl::write_to(w, id);
|
||||
}
|
||||
@@ -252,7 +306,7 @@ namespace detail
|
||||
{
|
||||
std::rethrow_exception(ex_);
|
||||
}
|
||||
void write_to(serialization::writer &, error_id const &) const override
|
||||
void write_to(writer &, error_id const &) const override
|
||||
{
|
||||
}
|
||||
std::exception_ptr const ex_;
|
||||
@@ -428,7 +482,7 @@ namespace detail
|
||||
}
|
||||
|
||||
template <class ErrorID>
|
||||
void write_to(serialization::writer &, ErrorID) const
|
||||
void write_to(writer &, ErrorID) const
|
||||
{
|
||||
}
|
||||
}; // slot specialization for dynamic_allocator
|
||||
@@ -784,6 +838,12 @@ public:
|
||||
return os << (x.value_ / 4);
|
||||
}
|
||||
|
||||
template <class Writer>
|
||||
friend void write( Writer & w, error_id x )
|
||||
{
|
||||
write(w, x.value_ / 4);
|
||||
}
|
||||
|
||||
BOOST_LEAF_CONSTEXPR void load_source_location_( char const * file, int line, char const * function ) const noexcept(!BOOST_LEAF_CFG_CAPTURE)
|
||||
{
|
||||
BOOST_LEAF_ASSERT(file&&*file);
|
||||
|
||||
@@ -9,6 +9,59 @@
|
||||
#include <boost/leaf/error.hpp>
|
||||
#include <boost/leaf/detail/exception_base.hpp>
|
||||
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
# include <typeinfo>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
template <class Writer>
|
||||
void write(Writer & w, std::exception const & ex)
|
||||
{
|
||||
char const dynamic_type[] = "dynamic_type";
|
||||
char const what[] = "what";
|
||||
#ifdef BOOST_LEAF_NO_EXCEPTIONS
|
||||
write_nested(w, "<<unknown>>", dynamic_type);
|
||||
#else
|
||||
write_nested(w, detail::demangler(typeid(ex).name()).get(), dynamic_type);
|
||||
#endif
|
||||
if( char const * wh = ex.what() )
|
||||
write_nested(w, wh, what);
|
||||
else
|
||||
write_nested(w, "<<nullptr>>", what);
|
||||
}
|
||||
|
||||
template <class Writer>
|
||||
void write(Writer & w, std::exception_ptr const & ep)
|
||||
{
|
||||
if( ep )
|
||||
{
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
std::rethrow_exception(ep);
|
||||
}
|
||||
catch( std::exception const & ex )
|
||||
{
|
||||
write(w, ex);
|
||||
return;
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
}
|
||||
#endif
|
||||
write_nested(w, "<<unknown>>", "dynamic_type");
|
||||
}
|
||||
else
|
||||
write_nested(w, "<<empty>>", "dynamic_type");
|
||||
write_nested(w, "N/A", "what");
|
||||
}
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
#define BOOST_LEAF_THROW_EXCEPTION ::boost::leaf::detail::throw_with_loc{__FILE__,__LINE__,__FUNCTION__}+::boost::leaf::detail::make_exception
|
||||
@@ -57,9 +110,9 @@ namespace detail
|
||||
return *this;
|
||||
}
|
||||
|
||||
serialization::type_name get_type_name() const override
|
||||
detail::type_name get_type_name() const override
|
||||
{
|
||||
return serialization::get_type_name<Ex>();
|
||||
return detail::get_type_name<Ex>();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include <boost/leaf/config.hpp>
|
||||
#include <boost/leaf/context.hpp>
|
||||
#include <boost/leaf/serialization/diagnostics_writer.hpp>
|
||||
#include <boost/leaf/detail/diagnostics_writer.hpp>
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
@@ -45,6 +45,17 @@ protected:
|
||||
|
||||
error_info( error_info const & ) noexcept = default;
|
||||
|
||||
template <class Writer>
|
||||
void write_to_(Writer & w) const
|
||||
{
|
||||
static_assert(std::is_base_of<detail::writer, Writer>::value, "Writer must derive from detail::writer");
|
||||
detail::serialize_(w, err_id_);
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
if( ex_ )
|
||||
detail::serialize_(w, *ex_);
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
BOOST_LEAF_CONSTEXPR error_info(error_id id, std::exception * ex, e_source_location const * loc) noexcept:
|
||||
@@ -79,17 +90,14 @@ public:
|
||||
template <class Writer>
|
||||
void write_to(Writer & w) const
|
||||
{
|
||||
detail::serialize_(w, err_id_);
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
if( ex_ )
|
||||
detail::serialize_(w, *ex_);
|
||||
#endif
|
||||
detail::writer_adaptor<Writer> wa(w);
|
||||
write_to_(wa);
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
friend std::ostream & operator<<(std::basic_ostream<CharT, Traits> & os, error_info const & x)
|
||||
{
|
||||
serialization::diagnostics_writer w(os, x.error(), x.source_location(), x.exception());
|
||||
detail::diagnostics_writer w(os, x.error(), x.source_location(), x.exception());
|
||||
return os;
|
||||
}
|
||||
}; // class error_info
|
||||
@@ -804,6 +812,10 @@ try_capture_all( TryBlock && try_block ) noexcept
|
||||
|
||||
} } // namespace boost::leaf
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
|
||||
// Boost Exception Integration
|
||||
|
||||
namespace boost { class exception; }
|
||||
@@ -866,4 +878,6 @@ namespace detail
|
||||
|
||||
} } // namespace boost::leaf
|
||||
|
||||
#endif
|
||||
|
||||
#endif // #ifndef BOOST_LEAF_HANDLE_ERRORS_HPP_INCLUDED
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include <boost/leaf/config.hpp>
|
||||
#include <boost/leaf/exception.hpp>
|
||||
#include <boost/leaf/serialization/diagnostics_writer.hpp>
|
||||
#include <boost/leaf/detail/diagnostics_writer.hpp>
|
||||
#include <boost/leaf/detail/capture_list.hpp>
|
||||
|
||||
#include <functional>
|
||||
@@ -299,6 +299,7 @@ protected:
|
||||
template <class Writer>
|
||||
error_id write_error_to(Writer & w) const
|
||||
{
|
||||
static_assert(std::is_base_of<detail::writer, Writer>::value, "Writer must derive from detail::writer");
|
||||
result_discriminant const what = what_;
|
||||
BOOST_LEAF_ASSERT(what.kind() != result_discriminant::val);
|
||||
error_id const err_id = what.get_error_id();
|
||||
@@ -309,6 +310,7 @@ protected:
|
||||
template <class Writer>
|
||||
void write_capture_to(Writer & w, error_id err_id) const
|
||||
{
|
||||
static_assert(std::is_base_of<detail::writer, Writer>::value, "Writer must derive from detail::writer");
|
||||
if( what_.kind() == result_discriminant::err_id_capture_list )
|
||||
{
|
||||
#if BOOST_LEAF_CFG_CAPTURE
|
||||
@@ -322,6 +324,7 @@ protected:
|
||||
template <class Writer>
|
||||
void print_error( Writer & w ) const
|
||||
{
|
||||
static_assert(std::is_base_of<detail::writer, Writer>::value, "Writer must derive from detail::writer");
|
||||
error_id err_id = write_error_to(w);
|
||||
w.set_prefix(", captured -> ");
|
||||
w.set_delimiter(", ");
|
||||
@@ -576,16 +579,17 @@ public:
|
||||
template <class Writer>
|
||||
void write_to(Writer & w) const
|
||||
{
|
||||
detail::writer_adaptor<Writer> wa(w);
|
||||
if( what_.kind() == result_discriminant::val )
|
||||
detail::serialize_(w, value());
|
||||
detail::serialize_(wa, value());
|
||||
else
|
||||
write_capture_to(w, write_error_to(w));
|
||||
write_capture_to(wa, write_error_to(wa));
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, result const & r )
|
||||
{
|
||||
serialization::diagnostics_writer w(os);
|
||||
detail::diagnostics_writer w(os);
|
||||
w.set_prefix(": ");
|
||||
if( r )
|
||||
{
|
||||
@@ -695,7 +699,10 @@ public:
|
||||
void write_to(Writer & w) const
|
||||
{
|
||||
if( !*this )
|
||||
write_error_to(w);
|
||||
{
|
||||
detail::writer_adaptor<Writer> wa(w);
|
||||
write_error_to(wa);
|
||||
}
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
@@ -705,7 +712,7 @@ public:
|
||||
os << "Success";
|
||||
else
|
||||
{
|
||||
serialization::diagnostics_writer w(os);
|
||||
detail::diagnostics_writer w(os);
|
||||
w.set_prefix(": ");
|
||||
os << "Failure";
|
||||
r.print_error(w);
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
#ifndef BOOST_LEAF_SERIALIZATION_JSON_WRITER_HPP_INCLUDED
|
||||
#define BOOST_LEAF_SERIALIZATION_JSON_WRITER_HPP_INCLUDED
|
||||
|
||||
// Copyright 2018-2026 Emil Dotchevski and Reverge Studios, Inc.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/leaf/config.hpp>
|
||||
#include <boost/leaf/serialization/writer.hpp>
|
||||
#include <boost/leaf/detail/exception_base.hpp>
|
||||
#include <boost/leaf/error.hpp>
|
||||
#include <boost/leaf/common.hpp>
|
||||
|
||||
#if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
|
||||
# include <system_error>
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
# include <typeinfo>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
template <class Json>
|
||||
void to_json(Json & j, error_id x)
|
||||
{
|
||||
to_json(j, x.value() / 4);
|
||||
}
|
||||
|
||||
template <class Json>
|
||||
void to_json(Json & j, e_source_location const & x)
|
||||
{
|
||||
to_json(j["file"], x.file);
|
||||
to_json(j["line"], x.line);
|
||||
to_json(j["function"], x.function);
|
||||
}
|
||||
|
||||
template <class Json>
|
||||
void to_json(Json & j, e_errno const & e)
|
||||
{
|
||||
to_json(j["value"], e.value);
|
||||
to_json(j["message"], std::strerror(e.value));
|
||||
}
|
||||
|
||||
#if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
|
||||
template <class Json>
|
||||
void to_json(Json & j, std::error_code const & ec)
|
||||
{
|
||||
to_json(j["category"], ec.category().name());
|
||||
to_json(j["value"], ec.value());
|
||||
to_json(j["message"], ec.message());
|
||||
}
|
||||
|
||||
template <class Json>
|
||||
void to_json(Json & j, std::error_condition const & ec)
|
||||
{
|
||||
to_json(j["category"], ec.category().name());
|
||||
to_json(j["value"], ec.value());
|
||||
to_json(j["message"], ec.message());
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class Json>
|
||||
void to_json(Json & j, detail::exception_base const & eb)
|
||||
{
|
||||
char zstr[1024];
|
||||
to_json(j["type"], to_zstr(zstr, eb.get_type_name()));
|
||||
char const * what = "N/A";
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
if( std::exception const * ex = dynamic_cast<std::exception const *>(&eb) )
|
||||
what = ex->what();
|
||||
#endif
|
||||
to_json(j["what"], what ? what : "<<nullptr>>");
|
||||
}
|
||||
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
template <class Json>
|
||||
void to_json(Json & j, std::exception const & ex)
|
||||
{
|
||||
if( detail::exception_base const * eb = dynamic_cast<detail::exception_base const *>(&ex) )
|
||||
{
|
||||
char zstr[1024];
|
||||
to_json(j["type"], to_zstr(zstr, eb->get_type_name()));
|
||||
}
|
||||
else
|
||||
to_json(j["type"], detail::demangler(typeid(ex).name()).get());
|
||||
if( char const * w = ex.what() )
|
||||
to_json(j["what"], w);
|
||||
else
|
||||
to_json(j["what"], "<<nullptr>>");
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class Json>
|
||||
void to_json(Json & j, std::exception_ptr const & ep)
|
||||
{
|
||||
if( ep )
|
||||
{
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
std::rethrow_exception(ep);
|
||||
}
|
||||
catch( detail::exception_base const & eb )
|
||||
{
|
||||
to_json(j, eb);
|
||||
return;
|
||||
}
|
||||
catch( std::exception const & ex )
|
||||
{
|
||||
to_json(j, ex);
|
||||
return;
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
}
|
||||
#endif
|
||||
to_json(j["type"], "<<unknown>>");
|
||||
}
|
||||
else
|
||||
to_json(j["type"], "<<empty>>");
|
||||
to_json(j["what"], "N/A");
|
||||
}
|
||||
|
||||
template <class Json, class E>
|
||||
auto to_json(Json & j, E const & e) -> decltype(to_json(j, e.value), void())
|
||||
{
|
||||
to_json(j["value"], e.value);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
template <class Json>
|
||||
class json_writer: public writer
|
||||
{
|
||||
Json & j_;
|
||||
|
||||
public:
|
||||
|
||||
explicit json_writer(Json & j) noexcept:
|
||||
writer(this),
|
||||
j_(j)
|
||||
{
|
||||
}
|
||||
|
||||
template <class E>
|
||||
void write(E const & e)
|
||||
{
|
||||
char zstr[1024];
|
||||
to_json(j_[to_zstr(zstr, get_type_name<E>())], e);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace serialization
|
||||
|
||||
} } // namespace boost::leaf
|
||||
|
||||
#endif // #ifndef BOOST_LEAF_SERIALIZATION_JSON_WRITER_HPP_INCLUDED
|
||||
37
include/boost/leaf/serialization/nlohmann_writer.hpp
Normal file
37
include/boost/leaf/serialization/nlohmann_writer.hpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef BOOST_LEAF_SERIALIZATION_NLOHMANN_WRITER_HPP_INCLUDED
|
||||
#define BOOST_LEAF_SERIALIZATION_NLOHMANN_WRITER_HPP_INCLUDED
|
||||
|
||||
// Copyright 2018-2026 Emil Dotchevski and Reverge Studios, Inc.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
template <class Json>
|
||||
struct nlohmann_writer
|
||||
{
|
||||
Json & j_;
|
||||
|
||||
template <class T>
|
||||
friend auto write(nlohmann_writer & w, T const & x) -> decltype(to_json(std::declval<Json &>(), x))
|
||||
{
|
||||
to_json(w.j_, x);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
friend void write_nested(nlohmann_writer & w, T const & x, char const * name)
|
||||
{
|
||||
nlohmann_writer nested{w.j_[name]};
|
||||
write(nested, x);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
#endif // #ifndef BOOST_LEAF_SERIALIZATION_NLOHMANN_WRITER_HPP_INCLUDED
|
||||
@@ -1,102 +0,0 @@
|
||||
#ifndef BOOST_LEAF_SERIALIZATION_TYPE_NAME_HPP_INCLUDED
|
||||
#define BOOST_LEAF_SERIALIZATION_TYPE_NAME_HPP_INCLUDED
|
||||
|
||||
// Copyright 2018-2026 Emil Dotchevski and Reverge Studios, Inc.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/leaf/detail/demangle.hpp>
|
||||
|
||||
#include <functional>
|
||||
|
||||
#if BOOST_LEAF_CFG_STD_STRING
|
||||
# include <string>
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
# include <string_view>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
|
||||
struct type_name
|
||||
{
|
||||
char const * name_not_zero_terminated_at_length;
|
||||
std::size_t length;
|
||||
std::size_t hash;
|
||||
|
||||
friend bool operator==(type_name const & a, type_name const & b) noexcept
|
||||
{
|
||||
BOOST_LEAF_ASSERT((a.hash == b.hash) == (a.length == b.length && std::memcmp(a.name_not_zero_terminated_at_length, b.name_not_zero_terminated_at_length, a.length) == 0));
|
||||
return a.hash == b.hash;
|
||||
}
|
||||
|
||||
friend bool operator!=(type_name const & a, type_name const & b) noexcept
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
friend bool operator<(type_name const & a, type_name const & b) noexcept
|
||||
{
|
||||
if( int cmp = std::memcmp(a.name_not_zero_terminated_at_length, b.name_not_zero_terminated_at_length, a.length < b.length ? a.length : b.length) )
|
||||
return cmp < 0;
|
||||
return a.length < b.length;
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
friend std::ostream & operator<<(std::basic_ostream<CharT, Traits> & os, type_name const & x)
|
||||
{
|
||||
return os.write(x.name_not_zero_terminated_at_length, x.length);
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
friend std::string_view to_string_view(type_name const & x) noexcept
|
||||
{
|
||||
return std::string_view(x.name_not_zero_terminated_at_length, x.length);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BOOST_LEAF_CFG_STD_STRING
|
||||
friend std::string to_string(type_name const & x)
|
||||
{
|
||||
return std::string(x.name_not_zero_terminated_at_length, x.length);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <std::size_t S>
|
||||
friend char * to_zstr(char (&zstr)[S], type_name const & x) noexcept
|
||||
{
|
||||
std::size_t n = x.length < S - 1 ? x.length : S - 1;
|
||||
std::memcpy(zstr, x.name_not_zero_terminated_at_length, n);
|
||||
zstr[n] = 0;
|
||||
return zstr;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
type_name get_type_name()
|
||||
{
|
||||
n::r parsed = n::p<T>();
|
||||
return { parsed.name_not_zero_terminated_at_length, parsed.length, parsed.hash };
|
||||
}
|
||||
|
||||
} // namespace serialization
|
||||
|
||||
} } // namespace boost::leaf
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<boost::leaf::serialization::type_name>
|
||||
{
|
||||
std::size_t operator()(boost::leaf::serialization::type_name const & x) const noexcept
|
||||
{
|
||||
return x.hash;
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
#endif // #ifndef BOOST_LEAF_SERIALIZATION_TYPE_NAME_HPP_INCLUDED
|
||||
@@ -1,61 +0,0 @@
|
||||
#ifndef BOOST_LEAF_SERIALIZATION_WRITER_HPP_INCLUDED
|
||||
#define BOOST_LEAF_SERIALIZATION_WRITER_HPP_INCLUDED
|
||||
|
||||
// Copyright 2018-2026 Emil Dotchevski and Reverge Studios, Inc.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/leaf/config.hpp>
|
||||
#include <boost/leaf/serialization/type_name.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
class writer
|
||||
{
|
||||
type_name const type_;
|
||||
|
||||
protected:
|
||||
|
||||
template <class Derived>
|
||||
explicit writer(Derived * d) noexcept:
|
||||
type_(get_type_name<Derived>())
|
||||
{
|
||||
BOOST_LEAF_ASSERT(d == this), (void) d;
|
||||
}
|
||||
|
||||
~writer() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
template <class Derived>
|
||||
Derived * get() noexcept
|
||||
{
|
||||
return type_ == get_type_name<typename std::decay<Derived>::type>() ? static_cast<Derived *>(this) : nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <class W, class E>
|
||||
typename std::enable_if<std::is_base_of<writer, W>::value>::type
|
||||
serialize(W &, E const &)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class>
|
||||
struct dependent_writer
|
||||
{
|
||||
using type = serialization::writer;
|
||||
};
|
||||
}
|
||||
|
||||
} } // namespace boost::leaf
|
||||
|
||||
#endif // #ifndef BOOST_LEAF_SERIALIZATION_WRITER_HPP_INCLUDED
|
||||
@@ -224,10 +224,7 @@ if option_enable_unit_tests
|
||||
'_hpp_on_error_test',
|
||||
'_hpp_pred_test',
|
||||
'_hpp_result_test',
|
||||
'_hpp_serialization_diagnostics_writer_test',
|
||||
'_hpp_serialization_json_writer_test',
|
||||
'_hpp_serialization_writer_test',
|
||||
'_hpp_serialization_type_name_test',
|
||||
'_hpp_serialization_nlohmann_writer_test',
|
||||
'_hpp_to_variant_test',
|
||||
]
|
||||
foreach t : header_tests
|
||||
|
||||
@@ -44,10 +44,7 @@ compile _hpp_leaf_test.cpp ;
|
||||
compile _hpp_on_error_test.cpp ;
|
||||
compile _hpp_pred_test.cpp ;
|
||||
compile _hpp_result_test.cpp ;
|
||||
compile _hpp_serialization_diagnostics_writer_test.cpp ;
|
||||
compile _hpp_serialization_json_writer_test.cpp ;
|
||||
compile _hpp_serialization_writer_test.cpp ;
|
||||
compile _hpp_serialization_type_name_test.cpp ;
|
||||
compile _hpp_serialization_nlohmann_writer_test.cpp ;
|
||||
compile _hpp_to_variant_test.cpp ;
|
||||
|
||||
run boost_exception_test.cpp ;
|
||||
@@ -146,8 +143,8 @@ lib so_dll_static_lib1 : so_dll_lib1.cpp : <link>static <define>BOOST_LEAF_SO_DL
|
||||
lib so_dll_static_lib2 : so_dll_lib2.cpp : <link>static <define>BOOST_LEAF_SO_DLL_TEST_STATIC <target-os>windows:<define>BOOST_LEAF_CFG_WIN32=2 ;
|
||||
run so_dll_test.cpp so_dll_static_lib1 so_dll_static_lib2 : : : <define>BOOST_LEAF_SO_DLL_TEST_STATIC <target-os>windows:<define>BOOST_LEAF_CFG_WIN32=2 : so_dll_static_test ;
|
||||
|
||||
compile-fail _compile-fail-arg_boost_error_info_1.cpp ;
|
||||
compile-fail _compile-fail-arg_boost_error_info_2.cpp ;
|
||||
compile-fail _compile-fail-arg_boost_error_info_1.cpp : <exception-handling>off:<build>no ;
|
||||
compile-fail _compile-fail-arg_boost_error_info_2.cpp : <exception-handling>off:<build>no ;
|
||||
compile-fail _compile-fail-arg_catch_1.cpp ;
|
||||
compile-fail _compile-fail-arg_catch_2.cpp ;
|
||||
compile-fail _compile-fail-arg_match_1.cpp ;
|
||||
@@ -162,11 +159,11 @@ compile-fail _compile-fail-error_obj_ptr.cpp ;
|
||||
compile-fail _compile-fail-exception_1.cpp ;
|
||||
compile-fail _compile-fail-exception_2.cpp ;
|
||||
compile-fail _compile-fail-new_error.cpp ;
|
||||
compile-fail _compile-fail-nlohmann.cpp ;
|
||||
compile-fail _compile-fail-result_1.cpp ;
|
||||
compile-fail _compile-fail-result_2.cpp ;
|
||||
compile-fail _compile-fail-result_3.cpp ;
|
||||
compile-fail _compile-fail-result_4.cpp ;
|
||||
compile-fail _compile-fail-to_json.cpp ;
|
||||
|
||||
exe try_capture_all_exceptions : ../example/try_capture_all_exceptions.cpp : <threading>single:<build>no <exception-handling>off:<build>no <variant>leaf_debug_capture0:<build>no <variant>leaf_release_capture0:<build>no ;
|
||||
exe try_capture_all_result : ../example/try_capture_all_result.cpp : <threading>single:<build>no <variant>leaf_debug_capture0:<build>no <variant>leaf_release_capture0:<build>no <variant>leaf_debug_embedded:<build>no <variant>leaf_release_embedded:<build>no ;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/leaf/serialization/json_writer.hpp>
|
||||
#include <boost/leaf/serialization/nlohmann_writer.hpp>
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
struct no_to_json {};
|
||||
@@ -13,5 +13,6 @@ struct e_no_to_json
|
||||
};
|
||||
|
||||
nlohmann::json j;
|
||||
boost::leaf::serialization::nlohmann_writer<nlohmann::json> w{j};
|
||||
e_no_to_json e;
|
||||
auto x = (boost::leaf::serialization::to_json(j, e), 0);
|
||||
auto x = (write(w, e), 0);
|
||||
@@ -1,7 +0,0 @@
|
||||
// Copyright 2018-2025 Emil Dotchevski and Reverge Studios, Inc.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/leaf/serialization/diagnostics_writer.hpp>
|
||||
#include <boost/leaf/serialization/diagnostics_writer.hpp>
|
||||
int main() { return 0; }
|
||||
@@ -2,6 +2,6 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/leaf/serialization/json_writer.hpp>
|
||||
#include <boost/leaf/serialization/json_writer.hpp>
|
||||
#include <boost/leaf/serialization/nlohmann_writer.hpp>
|
||||
#include <boost/leaf/serialization/nlohmann_writer.hpp>
|
||||
int main() { return 0; }
|
||||
@@ -1,7 +0,0 @@
|
||||
// Copyright 2018-2026 Emil Dotchevski and Reverge Studios, Inc.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/leaf/serialization/type_name.hpp>
|
||||
#include <boost/leaf/serialization/type_name.hpp>
|
||||
int main() { return 0; }
|
||||
@@ -1,7 +0,0 @@
|
||||
// Copyright 2018-2025 Emil Dotchevski and Reverge Studios, Inc.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/leaf/serialization/writer.hpp>
|
||||
#include <boost/leaf/serialization/writer.hpp>
|
||||
int main() { return 0; }
|
||||
@@ -10,7 +10,7 @@
|
||||
# include <boost/leaf/diagnostics.hpp>
|
||||
# include <boost/leaf/common.hpp>
|
||||
# include <boost/leaf/on_error.hpp>
|
||||
# include <boost/leaf/serialization/json_writer.hpp>
|
||||
# include <boost/leaf/serialization/nlohmann_writer.hpp>
|
||||
#endif
|
||||
|
||||
#include "nlohmann/json.hpp"
|
||||
@@ -23,19 +23,23 @@
|
||||
|
||||
#include "lightweight_test.hpp"
|
||||
|
||||
#if BOOST_LEAF_CFG_STD_STRING
|
||||
|
||||
namespace leaf = boost::leaf;
|
||||
|
||||
using nlohmann_writer = leaf::serialization::json_writer<nlohmann::ordered_json>;
|
||||
using output_writer = leaf::serialization::nlohmann_writer<nlohmann::ordered_json>;
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
namespace serialization {
|
||||
|
||||
template <class E>
|
||||
void serialize(writer & w, E const & e)
|
||||
template <class Handle, class E>
|
||||
void serialize(Handle & h, E const & e, char const * name)
|
||||
{
|
||||
if( nlohmann_writer * nw = w.get<nlohmann_writer>() )
|
||||
nw->write(e);
|
||||
h.dispatch(
|
||||
[&](nlohmann_writer<nlohmann::json> & w) { write_nested(w, e, name); },
|
||||
[&](nlohmann_writer<nlohmann::ordered_json> & w) { write_nested(w, e, name); }
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -49,6 +53,11 @@ struct my_exception_ptr
|
||||
std::exception_ptr value;
|
||||
};
|
||||
|
||||
struct my_error_code
|
||||
{
|
||||
std::error_code value;
|
||||
};
|
||||
|
||||
template <int N>
|
||||
struct my_error
|
||||
{
|
||||
@@ -74,6 +83,7 @@ leaf::result<void> fail()
|
||||
#if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
|
||||
std::make_error_code(std::errc::invalid_argument),
|
||||
std::make_error_condition(std::errc::io_error),
|
||||
my_error_code{std::make_error_code(std::errc::invalid_argument)},
|
||||
#endif
|
||||
42,
|
||||
my_error<1>{1, "error one"},
|
||||
@@ -89,6 +99,7 @@ void leaf_throw()
|
||||
#if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
|
||||
std::make_error_code(std::errc::invalid_argument),
|
||||
std::make_error_condition(std::errc::io_error),
|
||||
my_error_code{std::make_error_code(std::errc::invalid_argument)},
|
||||
#endif
|
||||
42,
|
||||
my_error<1>{1, "error one"},
|
||||
@@ -103,6 +114,7 @@ void throw_()
|
||||
#if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
|
||||
std::make_error_code(std::errc::invalid_argument),
|
||||
std::make_error_condition(std::errc::io_error),
|
||||
my_error_code{std::make_error_code(std::errc::invalid_argument)},
|
||||
#endif
|
||||
42,
|
||||
my_error<1>{1, "error one"},
|
||||
@@ -157,10 +169,10 @@ void check_diagnostic_details(nlohmann::ordered_json const & j, bool has_source_
|
||||
BOOST_TEST_EQ(e2j["message"].get<std::string>(), "error two");
|
||||
|
||||
auto const & ej = j["boost::leaf::e_errno"];
|
||||
BOOST_TEST_EQ(ej["value"].get<int>(), ENOENT);
|
||||
BOOST_TEST(!ej["message"].get<std::string>().empty());
|
||||
BOOST_TEST_EQ(ej["errno"].get<int>(), ENOENT);
|
||||
BOOST_TEST(!ej["strerror"].get<std::string>().empty());
|
||||
|
||||
BOOST_TEST_EQ(j["boost::leaf::e_api_function"]["value"].get<std::string>(), "my_api_function");
|
||||
BOOST_TEST_EQ(j["boost::leaf::e_api_function"].get<std::string>(), "my_api_function");
|
||||
|
||||
if( BOOST_LEAF_CFG_STD_SYSTEM_ERROR )
|
||||
{
|
||||
@@ -173,6 +185,11 @@ void check_diagnostic_details(nlohmann::ordered_json const & j, bool has_source_
|
||||
BOOST_TEST_EQ(econdj["value"].get<int>(), static_cast<int>(std::errc::io_error));
|
||||
BOOST_TEST(!econdj["category"].get<std::string>().empty());
|
||||
BOOST_TEST(!econdj["message"].get<std::string>().empty());
|
||||
|
||||
auto const & mecj = j["my_error_code"];
|
||||
BOOST_TEST_EQ(mecj["value"].get<int>(), static_cast<int>(std::errc::invalid_argument));
|
||||
BOOST_TEST(!mecj["category"].get<std::string>().empty());
|
||||
BOOST_TEST(!mecj["message"].get<std::string>().empty());
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -190,7 +207,7 @@ void check_diagnostic_details(nlohmann::ordered_json const & j, bool has_source_
|
||||
void check_exception(nlohmann::ordered_json const & j)
|
||||
{
|
||||
auto const & exj = j["std::exception"];
|
||||
BOOST_TEST(!exj["type"].get<std::string>().empty());
|
||||
BOOST_TEST(!exj["dynamic_type"].get<std::string>().empty());
|
||||
BOOST_TEST(!exj["what"].get<std::string>().empty());
|
||||
}
|
||||
#endif
|
||||
@@ -207,7 +224,7 @@ int main()
|
||||
[&j](leaf::diagnostic_info const & di, my_error<1> const * e1)
|
||||
{
|
||||
BOOST_TEST(e1 != nullptr);
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
di.write_to(w);
|
||||
}
|
||||
);
|
||||
@@ -225,7 +242,7 @@ int main()
|
||||
[&j](leaf::diagnostic_details const & dd, my_error<1> const * e1)
|
||||
{
|
||||
BOOST_TEST(e1 != nullptr);
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
dd.write_to(w);
|
||||
}
|
||||
);
|
||||
@@ -244,7 +261,7 @@ int main()
|
||||
[&j](leaf::diagnostic_info const & di, my_error<1> const * e1)
|
||||
{
|
||||
BOOST_TEST(e1 != nullptr);
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
di.write_to(w);
|
||||
}
|
||||
);
|
||||
@@ -263,7 +280,7 @@ int main()
|
||||
[&j](leaf::diagnostic_details const & dd, my_error<1> const * e1)
|
||||
{
|
||||
BOOST_TEST(e1 != nullptr);
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
dd.write_to(w);
|
||||
}
|
||||
);
|
||||
@@ -282,7 +299,7 @@ int main()
|
||||
[&j](leaf::diagnostic_info const & di, my_error<1> const * e1)
|
||||
{
|
||||
BOOST_TEST(e1 != nullptr);
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
di.write_to(w);
|
||||
}
|
||||
);
|
||||
@@ -300,7 +317,7 @@ int main()
|
||||
[&j](leaf::diagnostic_details const & dd, my_error<1> const * e1)
|
||||
{
|
||||
BOOST_TEST(e1 != nullptr);
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
dd.write_to(w);
|
||||
}
|
||||
);
|
||||
@@ -317,14 +334,14 @@ int main()
|
||||
},
|
||||
[&j](leaf::diagnostic_details const & dd, my_exception_ptr *)
|
||||
{
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
dd.write_to(w);
|
||||
}
|
||||
);
|
||||
std::cout << __LINE__ << " std::exception_ptr JSON output:\n" << std::setw(2) << j << std::endl;
|
||||
|
||||
auto const & ep = j["my_exception_ptr"]["value"];
|
||||
std::string type = ep["type"].get<std::string>();
|
||||
auto const & ep = j["my_exception_ptr"];
|
||||
std::string type = ep["dynamic_type"].get<std::string>();
|
||||
std::string what = ep["what"].get<std::string>();
|
||||
BOOST_TEST(type.find("std::runtime_error") != std::string::npos);
|
||||
BOOST_TEST_EQ(what, "test exception");
|
||||
@@ -339,14 +356,14 @@ int main()
|
||||
},
|
||||
[&j](leaf::diagnostic_details const & dd, my_exception_ptr *)
|
||||
{
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
dd.write_to(w);
|
||||
}
|
||||
);
|
||||
std::cout << __LINE__ << " non-std::exception_ptr JSON output:\n" << std::setw(2) << j << std::endl;
|
||||
|
||||
auto const & ep = j["my_exception_ptr"]["value"];
|
||||
std::string type = ep["type"].get<std::string>();
|
||||
auto const & ep = j["my_exception_ptr"];
|
||||
std::string type = ep["dynamic_type"].get<std::string>();
|
||||
std::string what = ep["what"].get<std::string>();
|
||||
BOOST_TEST_EQ(type, "<<unknown>>");
|
||||
BOOST_TEST_EQ(what, "N/A");
|
||||
@@ -357,7 +374,7 @@ int main()
|
||||
nlohmann::ordered_json j;
|
||||
leaf::result<int> r = 42;
|
||||
BOOST_TEST(r);
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
r.write_to(w);
|
||||
std::cout << __LINE__ << " result<int> success JSON output:\n" << std::setw(2) << j << std::endl;
|
||||
BOOST_TEST_EQ(j["int"].get<int>(), 42);
|
||||
@@ -367,7 +384,7 @@ int main()
|
||||
nlohmann::ordered_json j;
|
||||
leaf::result<int> r = leaf::new_error();
|
||||
BOOST_TEST(!r);
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
r.write_to(w);
|
||||
std::cout << __LINE__ << " result<int> error JSON output:\n" << std::setw(2) << j << std::endl;
|
||||
BOOST_TEST(j["boost::leaf::error_id"].get<int>() > 0);
|
||||
@@ -382,7 +399,7 @@ int main()
|
||||
return leaf::new_error(my_error<1>{1, "error one"}, my_error<2>{2, "error two"});
|
||||
} );
|
||||
BOOST_TEST(!r);
|
||||
nlohmann_writer w(j);
|
||||
output_writer w{j};
|
||||
r.write_to(w);
|
||||
std::cout << __LINE__ << " result<int> captured error JSON output:\n" << std::setw(2) << j << std::endl;
|
||||
BOOST_TEST(j["boost::leaf::error_id"].get<int>() > 0);
|
||||
@@ -397,3 +414,12 @@ int main()
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,7 +19,7 @@ int main()
|
||||
#ifdef BOOST_LEAF_TEST_SINGLE_HEADER
|
||||
# include "leaf.hpp"
|
||||
#else
|
||||
# include <boost/leaf/serialization/diagnostics_writer.hpp>
|
||||
# include <boost/leaf/detail/diagnostics_writer.hpp>
|
||||
#endif
|
||||
|
||||
#include <sstream>
|
||||
@@ -72,7 +72,7 @@ template <int Line, class T>
|
||||
std::string print(T const & x, char const * prefix, char const * delimiter)
|
||||
{
|
||||
std::ostringstream s;
|
||||
leaf::serialization::diagnostics_writer w(s);
|
||||
leaf::detail::diagnostics_writer w(s);
|
||||
w.set_prefix(prefix);
|
||||
w.set_delimiter(delimiter);
|
||||
w.write(x);
|
||||
|
||||
@@ -5,19 +5,14 @@
|
||||
#ifdef BOOST_LEAF_TEST_SINGLE_HEADER
|
||||
# include "leaf.hpp"
|
||||
#else
|
||||
# include <boost/leaf/serialization/type_name.hpp>
|
||||
# include <boost/leaf/detail/type_name.hpp>
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
#include <unordered_set>
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
# include <string_view>
|
||||
#endif
|
||||
|
||||
namespace leaf = boost::leaf;
|
||||
namespace serialization = boost::leaf::serialization;
|
||||
namespace detail = boost::leaf::detail;
|
||||
|
||||
#include "lightweight_test.hpp"
|
||||
|
||||
@@ -44,7 +39,7 @@ template <int> struct struct_template1 { };
|
||||
template <class> class class_template2 { };
|
||||
template <class> struct struct_template2 { };
|
||||
|
||||
bool test(serialization::type_name const & tn, char const * correct)
|
||||
bool test(detail::type_name const & tn, char const * correct)
|
||||
{
|
||||
return
|
||||
std::strlen(correct) == tn.length &&
|
||||
@@ -53,7 +48,7 @@ bool test(serialization::type_name const & tn, char const * correct)
|
||||
|
||||
int main()
|
||||
{
|
||||
using serialization::get_type_name;
|
||||
using leaf::detail::get_type_name;
|
||||
|
||||
BOOST_TEST(test(get_type_name<leaf::in_namespace_boost_leaf>(), "boost::leaf::in_namespace_boost_leaf"));
|
||||
|
||||
@@ -84,38 +79,5 @@ int main()
|
||||
BOOST_TEST(get_type_name<int>() != get_type_name<float>());
|
||||
BOOST_TEST(get_type_name<class_>() != get_type_name<struct_>());
|
||||
|
||||
BOOST_TEST(get_type_name<class_>() < get_type_name<struct_>()); // "class_" < "struct_"
|
||||
BOOST_TEST(!(get_type_name<struct_>() < get_type_name<class_>()));
|
||||
BOOST_TEST(!(get_type_name<int>() < get_type_name<int>())); // not less than itself
|
||||
BOOST_TEST(get_type_name<int>() < get_type_name<long>()); // "int" < "long"
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
{
|
||||
auto sv = to_string_view(get_type_name<int>());
|
||||
BOOST_TEST(sv == "int");
|
||||
}
|
||||
{
|
||||
auto sv = to_string_view(get_type_name<class_>());
|
||||
BOOST_TEST(sv == "class_");
|
||||
}
|
||||
{
|
||||
auto sv = to_string_view(get_type_name<leaf_test::struct_>());
|
||||
BOOST_TEST(sv == "leaf_test::struct_");
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOST_TEST(std::hash<serialization::type_name>()(get_type_name<int>()) == get_type_name<int>().hash);
|
||||
BOOST_TEST(std::hash<serialization::type_name>()(get_type_name<int>()) == std::hash<serialization::type_name>()(get_type_name<int>()));
|
||||
{
|
||||
std::unordered_set<serialization::type_name> s;
|
||||
s.insert(get_type_name<int>());
|
||||
s.insert(get_type_name<float>());
|
||||
s.insert(get_type_name<int>()); // duplicate
|
||||
BOOST_TEST(s.size() == 2);
|
||||
BOOST_TEST(s.count(get_type_name<int>()) == 1);
|
||||
BOOST_TEST(s.count(get_type_name<float>()) == 1);
|
||||
BOOST_TEST(s.count(get_type_name<double>()) == 0);
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user