9 #include <unordered_map> 18 namespace annotatable {
35 std::function<void(void *data)> destructor;
45 Anything(
void *data, std::function<
void(
void *data)> destructor, std::type_index type);
58 static Anything make(
const T &ob) {
62 delete static_cast<T*
>(data);
64 std::type_index(
typeid(T))
72 static Anything make(T &&ob) {
76 delete static_cast<T*
>(data);
78 std::type_index(
typeid(T))
89 Anything(
const Anything&) =
delete;
90 Anything& operator=(
const Anything&) =
delete;
95 Anything(Anything &&src);
100 Anything& operator=(Anything &&src);
107 template <
typename T>
109 if (std::type_index(
typeid(T)) != type) {
110 throw std::bad_cast();
112 return static_cast<T*
>(data);
120 template <
typename T>
121 const T *get_const()
const {
122 if (std::type_index(
typeid(T)) != type) {
123 throw std::bad_cast();
125 return static_cast<T*
>(data);
138 const void *
get()
const {
145 std::type_index get_type_index()
const;
155 virtual ~Serializable() =
default;
156 virtual void serialize(cbor::MapWriter&)
const = 0;
163 class SerDesRegistry {
171 std::function<
void(
const std::shared_ptr<Anything>&, cbor::MapWriter&)>
180 std::function<
std::shared_ptr<Anything>(const cbor::MapReader&)>
204 template <typename T>
206 std::function<
void(const T&, cbor::MapWriter&)> serialize,
207 std::function<T(const cbor::MapReader&)> deserialize,
208 const
std::
string &name = ""
210 const std::string full_name = std::string(
211 "{" + (name.empty() ? std::string(
typeid(T).name()) : name) +
"}");
212 serializers.insert(std::make_pair(
213 std::type_index(
typeid(T)),
214 [serialize, full_name](
const std::shared_ptr<Anything> &anything, cbor::MapWriter &map) {
215 auto submap = map.append_map(full_name);
216 serialize(*(anything->get_const<T>()), submap);
219 deserializers.insert(std::make_pair(
221 [deserialize](
const cbor::MapReader &map) -> std::shared_ptr<Anything> {
222 return std::make_shared<Anything>(Anything::make(deserialize(map)));
248 template <
typename T>
249 void add(
const std::string &name =
"") {
250 const std::string full_name = std::string(
251 "{" + (name.empty() ? std::string(
typeid(T).name()) : name) +
"}");
252 serializers.insert(std::make_pair(
253 std::type_index(
typeid(T)),
254 [full_name](
const std::shared_ptr<Anything> &anything, cbor::MapWriter &map) {
255 auto submap = map.append_map(full_name);
256 anything->get_const<T>()->serialize(submap);
259 deserializers.insert(std::make_pair(
261 [](
const cbor::MapReader &map) -> std::shared_ptr<Anything> {
262 return std::make_shared<Anything>(Anything::make(T(map)));
272 void serialize(std::shared_ptr<Anything> obj, cbor::MapWriter &map)
const;
279 std::shared_ptr<Anything> deserialize(
const std::string &key,
const cbor::Reader &value)
const;
288 #ifdef BUILDING_TREE_LIB 289 __declspec(dllexport)
291 __declspec(dllimport)
294 extern SerDesRegistry serdes_registry;
305 using AnnotationMap = TREE_MAP(std::type_index, std::shared_ptr<Anything>);
306 AnnotationMap annotations = {};
311 mutable const std::type_index *cached_annot_type =
nullptr;
316 mutable void *cached_annot_ptr =
nullptr;
322 template <
typename T>
323 const std::type_index &get_static_type_index()
const {
324 static const auto TI = std::type_index(
typeid(T));
334 template <
typename T>
335 void *find_annotation_cached()
const {
336 const auto &ti = get_static_type_index<T>();
337 if (cached_annot_type == &ti) {
338 return cached_annot_ptr;
340 auto it = annotations.find(ti);
341 if (it != annotations.end()) {
342 cached_annot_type = &ti;
343 cached_annot_ptr = it->second->get();
344 return cached_annot_ptr;
356 virtual ~Annotatable();
369 template <
typename T>
370 void set_annotation(
const T &ob) {
371 TREE_MAP_SET(annotations, get_static_type_index<T>(), std::make_shared<Anything>(Anything::make<T>(ob)));
372 cached_annot_type =
nullptr;
384 template <
typename T>
385 void set_annotation(T &&ob) {
386 TREE_MAP_SET(annotations, get_static_type_index<T>(), std::make_shared<Anything>(Anything::make<T>(std::move(ob))));
387 cached_annot_type =
nullptr;
394 template <
typename T>
395 bool has_annotation()
const {
396 return find_annotation_cached<T>() !=
nullptr;
403 template <
typename T>
404 T *get_annotation_ptr() {
405 return static_cast<T*
>(find_annotation_cached<T>());
412 template <
typename T>
413 const T *get_annotation_ptr()
const {
414 return static_cast<const T*
>(find_annotation_cached<T>());
421 template <
typename T>
422 T &get_annotation() {
423 if (
auto annotation = get_annotation_ptr<T>()) {
426 throw TREE_RUNTIME_ERROR(
"object does not have an annotation of this type");
434 template <
typename T>
435 const T &get_annotation()
const {
436 if (
auto annotation = get_annotation_ptr<T>()) {
439 throw TREE_RUNTIME_ERROR(
"object does not have an annotation of this type");
446 template <
typename T>
447 void erase_annotation() {
448 annotations.erase(get_static_type_index<T>());
449 cached_annot_type =
nullptr;
457 template <
typename T>
458 void copy_annotation(
const Annotatable &src) {
459 if (
auto annotation = src.get_annotation_ptr<T>()) {
460 set_annotation(*annotation);
462 erase_annotation<T>();
471 void copy_annotations(
const Annotatable &src);
481 void serialize_annotations(cbor::MapWriter &map)
const;
492 void deserialize_annotations(
const cbor::MapReader &map);