Skip to content

Commit 4ab4d8a

Browse files
committed
Added polymorphy capabilities using RTTI for unique_ptrs.
1 parent 0cf398f commit 4ab4d8a

9 files changed

+385
-21
lines changed

parse/jsd.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "jsd_optional.h"
1414
#include "jsd_fusion_adapted_struct.h"
1515
#include "jsd_object.h"
16-
#include "jsd_renamed.h"
16+
#include "jsd_renamed.h"
17+
#include "jsd_unique_ptr.h"
1718

1819
#endif

parse/jsd_core.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,15 @@ namespace JSON
8282
case (InvalidPathHandlingBehaviour::THROW): \
8383
throw exc; \
8484
}
85-
// MAKRO END
85+
// MAKRO END
86+
87+
inline std::string member_name(std::string const& base_name, std::string const& name)
88+
{
89+
if (base_name.empty())
90+
return "";
91+
else
92+
return base_name + "." + name;
93+
}
8694
}
8795

8896
#endif

parse/jsd_fusion_adapted_struct.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ namespace JSON
6969
template <typename Derived>
7070
struct Parsable
7171
{
72-
void parse(std::string const& name, PropertyTree const& tree, ParsingOptions const& options = DEFAULT_PARSER_OPTIONS)
72+
void parse(std::string const& name, PropertyTree const& tree, ParsingOptions const& options = {})
7373
{
7474
AdaptedParser<Derived> parser;
7575
parser(*static_cast <Derived*> (this), name, tree, options);

parse/jsd_unique_ptr.h

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#pragma once
2+
3+
#include "jsd_core.h"
4+
#include "../utility/polymorphy.h"
5+
6+
#include <type_traits>
7+
#include <memory>
8+
9+
namespace JSON
10+
{
11+
namespace internal
12+
{
13+
template <typename T, bool ClassType, bool Enabler>
14+
struct type_dependent_retriever
15+
{
16+
};
17+
18+
template <typename T>
19+
struct type_dependent_retriever <T, true, true>
20+
{
21+
static void get(T& value, std::string const& name, PropertyTree const& object, ParsingOptions const& options)
22+
{
23+
value.reset(new T{});
24+
value->parse(name, object, options);
25+
}
26+
};
27+
28+
template <typename T>
29+
struct type_dependent_retriever <T, false, true>
30+
{
31+
static void get(T& value, std::string const& name, PropertyTree const& object, ParsingOptions const& options)
32+
{
33+
value.reset(new T{});
34+
GET_VALUE(T, name, *value, {});
35+
}
36+
};
37+
38+
template <typename T>
39+
struct type_dependent_retriever <T, true, false>
40+
{
41+
static void get(T& value, std::string const& name, PropertyTree const& object, ParsingOptions const& options)
42+
{
43+
using polydecl_type = polydecls <typename T::element_type>;
44+
45+
auto type_name = object.tree.get_optional <std::string> (name + ".__cxx_type");
46+
if (!type_name)
47+
throw std::runtime_error ("object is declared polymorphic, but does not come with a type definition __cxx_type");
48+
polydecl_type::smart_pointer_get(value, type_name.get(), name, object, options);
49+
}
50+
};
51+
52+
template <typename T>
53+
struct type_dependent_retriever <T, false, false>
54+
{
55+
static void get(T& value, std::string const& name, PropertyTree const& object, ParsingOptions const& options)
56+
{
57+
// static_assert(false, "Not a class but polymorphic? you did something wrong!");
58+
// poly, but not a class
59+
}
60+
};
61+
}
62+
63+
template <typename T, typename Deleter>
64+
void parse(std::unique_ptr <T, Deleter>& value, std::string const& name,
65+
PropertyTree const& object, ParsingOptions const& options = {})
66+
{
67+
using polydecl_type = polydecls <T>;
68+
69+
internal::type_dependent_retriever <typename std::decay<decltype(value)>::type,
70+
std::is_class <T>::value,
71+
std::is_same <typename polydecl_type::type, no_poly>::value>::get(value,
72+
name,
73+
object,
74+
options);
75+
}
76+
}

stringify/jss_core.h

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,47 @@ namespace JSON
4242
STREAM << "}"
4343

4444
#define WRITE_ARRAY_END(STREAM) \
45-
STREAM << "]"
45+
STREAM << "]"
46+
47+
inline std::ostream& stringify_object_start(std::ostream& stream, std::string const& name, StringificationOptions const& options)
48+
{
49+
WRITE_OBJECT_START(stream);
50+
return stream;
51+
}
52+
inline std::ostream& stringify_object_end(std::ostream& stream)
53+
{
54+
WRITE_OBJECT_END(stream);
55+
return stream;
56+
}
57+
58+
class object_scope
59+
{
60+
public:
61+
object_scope(std::ostream& stream, std::string const& name, StringificationOptions& options)
62+
: stream_(stream)
63+
, options_(options)
64+
{
65+
options_.in_object = true;
66+
stringify_object_start(stream_, name, options);
67+
}
68+
69+
~object_scope()
70+
{
71+
stringify_object_end(stream_);
72+
options_.in_object = false;
73+
}
74+
75+
object_scope& operator=(object_scope const&) = delete;
76+
object_scope& operator=(object_scope&&) = delete;
77+
object_scope(object_scope const&) = delete;
78+
object_scope(object_scope&&) = delete;
79+
80+
private:
81+
std::ostream& stream_;
82+
StringificationOptions& options_;
83+
};
84+
85+
#define JSON_OBJECT_STRINGIFY(stream, options) object_scope(stream, options) _json_os__;
4686
}
4787

4888
#endif // JSS_CORE_H_INCLUDED

stringify/jss_fusion_adapted_struct.h

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44
#include "jss_core.h"
55

66
#ifndef JSS_OBJECT_H_INCLUDED
7-
#include "jss_object.h"
7+
# include "jss_object.h"
88
#endif
99

10-
#include "jss_optional.h"
10+
#include "jss_optional.h"
11+
#include "../utility/polymorphy.h"
12+
13+
#include <iostream>
14+
#include <type_traits>
1115

12-
#include <iostream>
1316
#include <boost/fusion/mpl.hpp>
1417
#include <boost/fusion/adapted.hpp>
1518
#include <boost/fusion/include/at.hpp>
@@ -19,8 +22,41 @@
1922
#include <boost/fusion/include/size.hpp>
2023

2124
namespace JSON
22-
{
23-
template <typename T>
25+
{
26+
namespace internal
27+
{
28+
template <typename Base, typename Derived, bool Enable = !std::is_same <Base, Derived>::value>
29+
struct Polify
30+
{
31+
};
32+
33+
template <typename Base, typename Derived>
34+
struct Polify <Base, Derived, false>
35+
{
36+
template <typename... List>
37+
static void exec(List&...)
38+
{
39+
// not enabled
40+
}
41+
};
42+
43+
template <typename Base, typename Derived>
44+
struct Polify <Base, Derived, true>
45+
{
46+
static void exec(std::ostream& stream, bool& first, Derived const& object)
47+
{
48+
using polydecl_type = polydecls <Base>;
49+
if (std::is_same <typename polydecl_type::type, no_poly>::value == false)
50+
{
51+
// leave polymorphy mark behind
52+
stream << "\"__cxx_type\": \"" << polydecl_type::identify_type(&object) << "\"";
53+
first = false;
54+
}
55+
}
56+
};
57+
}
58+
59+
template <typename T, typename Base = T>
2460
class AdaptedStringifier
2561
{
2662
public:
@@ -36,7 +72,8 @@ namespace JSON
3672

3773
bool first = true;
3874

39-
stream << '{';
75+
stream << '{';
76+
internal::Polify <Base, T>::exec(stream, first, object);
4077
boost::mpl::for_each<range> (std::bind<void>(_helper(boost::fusion::result_of::size<T>::type::value), std::placeholders::_1, std::ref(stream), std::ref(first), std::ref(object), std::ref(options)));
4178
stream << '}';
4279
return stream;
@@ -70,8 +107,16 @@ namespace JSON
70107
{
71108
options.in_object = true;
72109
options.ignore_name = false;
73-
AdaptedStringifier<Derived> stringifier;
110+
AdaptedStringifier <Derived> stringifier;
74111
return stringifier(stream, *static_cast <Derived const*> (this), options);
112+
}
113+
template <typename Base>
114+
std::ostream& stringify(std::ostream& stream, StringificationOptions options) const
115+
{
116+
options.in_object = true;
117+
options.ignore_name = false;
118+
AdaptedStringifier <Derived, Base> stringifier;
119+
return stringifier(stream, *static_cast <Derived const*> (this), options);
75120
}
76121
virtual ~Stringifiable() = default;
77122
};

stringify/jss_optional.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#ifndef JSS_OPTIONAL_H_INCLUDED
22
#define JSS_OPTIONAL_H_INCLUDED
33

4-
#include "tmp_util/fundamental/eval_if.hpp"
5-
#include "tmp_util/fundamental/is_same.hpp"
6-
#include "tmp_util/fundamental/null_type.hpp"
4+
#include "../utility/tmp_util/fundamental/eval_if.hpp"
5+
#include "../utility/tmp_util/fundamental/is_same.hpp"
6+
#include "../utility/tmp_util/fundamental/null_type.hpp"
77

88
// really want to swap with std::optional
99
#include <boost/optional.hpp>

stringify/jss_unique_ptr.h

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,68 @@
11
#ifndef JSS_UNIQUE_PTR_H_INCLUDED
22
#define JSS_UNIQUE_PTR_H_INCLUDED
33

4-
#include "jss_core.h"
4+
#include "jss_core.h"
5+
#include "../utility/polymorphy.h"
6+
57
#include <memory>
68

79
namespace JSON
8-
{
9-
template <typename T,
10-
typename = typename std::enable_if <Internal::can_stringify<T>::value>::type >
11-
std::ostream& stringify(std::ostream& stream, const std::string& name, std::unique_ptr<T> const& value, StringificationOptions const& options = DEFAULT_OPTIONS)
10+
{
11+
namespace internal
12+
{
13+
template <typename T, bool IsClass, bool IsPolymorphic>
14+
struct stringify_call_chooser
15+
{
16+
};
17+
18+
template <typename T>
19+
struct stringify_call_chooser <T, true, false>
20+
{
21+
static void exec(std::ostream& stream, const std::string& name, T const& value, StringificationOptions const& options)
22+
{
23+
value->stringify(stream, options);
24+
}
25+
};
26+
27+
template <typename T>
28+
struct stringify_call_chooser <T, true, true>
29+
{
30+
static void exec(std::ostream& stream, const std::string& name, T const& value, StringificationOptions const& options)
31+
{
32+
//value->stringify(stream, options);
33+
polydecls <typename T::element_type>::smart_pointer_set(value, stream, options);
34+
}
35+
};
36+
37+
template <typename T, bool IsPolymorphic>
38+
struct stringify_call_chooser <T, false, IsPolymorphic>
39+
{
40+
static void exec(std::ostream& stream, const std::string& name, T const& value, StringificationOptions const& options)
41+
{
42+
stringify(stream, name, *value, options);
43+
}
44+
};
45+
}
46+
47+
template <typename T, typename Deleter,
48+
typename = typename std::enable_if <
49+
Internal::can_stringify<T>::value ||
50+
!std::is_same <typename polydecls <T>::type, no_poly>::value
51+
>::type >
52+
std::ostream& stringify(std::ostream& stream, const std::string& name, std::unique_ptr<T, Deleter> const& value, StringificationOptions const& options = {})
1253
{
1354
if (!value)
14-
throw UniquePtrNullptrException{};
15-
return stringify(stream, name, *value, options);
55+
throw UniquePtrNullptrException{};
56+
57+
if (options.in_object && !options.ignore_name)
58+
WRITE_NAME(stream);
59+
60+
internal::stringify_call_chooser <
61+
typename std::decay<decltype(value)>::type,
62+
std::is_class <T>::value,
63+
!std::is_same <typename polydecls <T>::type, no_poly>::value
64+
>::exec(stream, name, value, options);
65+
return stream;
1666
}
1767
}
1868

0 commit comments

Comments
 (0)