cgv
Loading...
Searching...
No Matches
reflection_handler.h
1#pragma once
2
3#include <vector>
4#include <cgv/type/info/type_name.h>
5#include <cgv/utils/convert.h>
6#include <cgv/utils/token.h>
7#include <cgv/type/traits/method_pointer.h>
8#include <cgv/type/info/type_id.h>
9
10#include "self_reflection_tag.h"
11#include "reflection_traits_info.h"
12
13#include "lib_begin.h"
14
16namespace cgv {
18 namespace reflect {
19
24{
25 virtual void call_void(void* instance,
26 const std::vector<abst_reflection_traits*>& param_value_traits,
27 const std::vector<const void*>& param_value_ptrs,
28 const std::vector<std::string>& param_type_names,
29 const abst_reflection_traits* result_traits = 0,
30 void* result_value_ptr = 0,
31 const std::string& result_type = "") = 0;
32};
33
34template <int i, int n, typename M>
36{
37 static void fill_vector(std::vector<abst_reflection_traits*>& param_value_traits)
38 {
39 param_value_traits.push_back(reflection_traits_info<typename cgv::type::traits::method_pointer_argument_list<M,i>::type>::traits_type().clone());
40 if (i+1 < n)
42 }
43};
44
45template <int i, typename M>
47{
48 static void fill_vector(std::vector<abst_reflection_traits*>& param_value_traits)
49 {
50 }
51};
52
54template <typename M>
56
62class CGV_API reflection_handler
63{
64#ifndef REFLECT_TRAITS_WITH_DECLTYPE
65 template <typename B, typename RB>
66 bool reflect_base_impl(B& base_ref, const RB&);
67 template <typename T, unsigned n, typename RT>
68 bool reflect_const_array_impl(const std::string& member_name, T (&member_ref)[n], const RT&);
69 template <typename T, typename RT>
70 bool reflect_vector_impl(const std::string& member_name, std::vector<T>& member_ref, const RT&);
71#endif
72public:
73 template <typename T>
74 friend bool reflect_enum(reflection_handler& rh, const std::string& name, T& instance, const std::string& declarations);
75 template <typename T>
76 friend bool reflect_string(reflection_handler& rh, const std::string& name, T& instance);
77 friend struct detail;
81 enum GroupTraversal { GT_TERMINATE = -3, GT_SKIP = -2, GT_COMPLETE = -1 };
83 static std::string group_traversal_name(GroupTraversal gt);
85 enum GroupKind { GK_NO_GROUP, GK_BASE_CLASS, GK_STRUCTURE, GK_VECTOR, GK_ARRAY, GK_POINTER };
87 static const char* group_kind_name(GroupKind gk);
89 static bool is_array_kind(GroupKind gk);
91protected:
95 GroupTraversal process_structural_group_begin(GroupKind gk, const std::string& member_name, GroupTraversal gt);
97 bool group_end(GroupKind gk);
99 template <typename T, typename RT, typename D>
100 bool self_reflect_member(const std::string& member_name, T& member_ref, const RT&, const D&, bool hard_cast)
101 {
102 RT rt;
103 switch (process_structural_group_begin(GK_STRUCTURE, member_name, GroupTraversal(reflect_group_begin(GK_STRUCTURE, member_name, &member_ref, &rt)))) {
104 case GT_TERMINATE : return false;
105 case GT_COMPLETE :
106 if (hard_cast)
107 return static_cast<D&>(member_ref).D::self_reflect(*this) && group_end(GK_STRUCTURE);
108 else {
109 D& d = static_cast<D&>(member_ref);
110 return d.self_reflect(*this) && group_end(GK_STRUCTURE);
111 }
112 default: return true;
113 }
114 }
116 int reflect_array_begin(GroupKind group_kind, const std::string& group_name, void* group_ptr, abst_reflection_traits* rt, unsigned grp_size);
118
123 {
127 const std::string* name;
129 unsigned idx;
131 nesting_info(GroupKind _group_kind = GK_NO_GROUP, const std::string* _name = 0, unsigned _idx = 0) : group_kind(_group_kind), name(_name), idx(_idx) {};
132 };
134 std::vector<nesting_info> nesting_info_stack;
136
140
151 virtual int reflect_group_begin(GroupKind group_kind, const std::string& group_name, void* group_ptr, abst_reflection_traits* rt, unsigned grp_size = -1);
153
154 virtual void reflect_group_end(GroupKind group_kind);
157 virtual bool reflect_member_void(const std::string& member_name, void* member_ptr, abst_reflection_traits* rt) = 0;
160 virtual bool reflect_method_void(const std::string& method_name, method_interface* mi_ptr,
161 abst_reflection_traits* return_traits, const std::vector<abst_reflection_traits*>& param_value_traits) = 0;
163
164public:
166 virtual ~reflection_handler();
167
171 virtual bool is_creative() const;
179 template <typename T>
180 bool reflect_member(const std::string& member_name, T& member_ref, bool hard_cast = false);
189 template <typename M>
190 bool reflect_method(const std::string& method_name, M m);
192 template <typename B>
193 bool reflect_base(B& base_ref);
195 template <typename T, unsigned n>
196 bool reflect_member(const std::string& member_name, T (&member_ref)[n]);
198 template <typename T>
199 bool reflect_member(const std::string& member_name, std::vector<T>& member_ref);
201
204 template <typename T>
205 bool reflect_member(const std::string& member_name, T*& member_ref);
207 template <typename T, typename S>
208 bool reflect_array(const std::string& member_name, T*& member_ref, S& size);
209};
210
211
212struct detail {
213#ifndef REFLECT_TRAITS_WITH_DECLTYPE
214 template <typename T, ReflectionTraitsKind K>
216 {
217 template <bool has_external, typename RT>
219 static bool reflect(reflection_handler* rh, const std::string& member_name, T& member_ref, const RT&, bool hard_cast) {
220 RT rt;
221 return rh->reflect_member_void(member_name, &member_ref, &rt);
222 }
223 };
224 template <typename RT>
225 struct reflect_impl<true,RT> {
226 static bool reflect(reflection_handler* rh, const std::string& member_name, T& member_ref, const RT&, bool hard_cast) {
227 RT rt;
228 return rh->self_reflect_member(member_name, member_ref, rt, static_cast<typename RT::external_self_reflect_type&>(member_ref), hard_cast);
229 }
230 };
231 template <typename RT>
232 static bool reflect_RT(reflection_handler* rh, const std::string& member_name, T& member_ref, const RT& rt, bool hard_cast) {
233 return reflect_impl<RT::has_external,RT>::reflect(rh, member_name, member_ref, rt, hard_cast);
234 }
235 static bool reflect(reflection_handler* rh, const std::string& member_name, T& member_ref, bool hard_cast) {
236 return reflect_RT(rh, member_name, member_ref, get_reflection_traits(member_ref), hard_cast);
237 }
238 };
239
240 template <typename T> struct reflect_member_impl<T,RTK_STD_TYPE>
241 {
242 static bool reflect(reflection_handler* rh, const std::string& member_name, T& member_ref, bool hard_cast) {
244 return rh->reflect_member_void(member_name, &member_ref, &rt);
245 }
246 };
247#else
248 template <typename T, ReflectionTraitsKind K>
250 {
251 static bool reflect(reflection_handler* rh, const std::string& member_name, T& member_ref, bool hard_cast) {
253 return rh->reflect_member_void(member_name, &member_ref, &rt);
254 }
255 };
256
257 template <typename T> struct reflect_member_impl<T,RTK_EXTERNAL_SELF_REFLECT>
258 {
259 static bool reflect(reflection_handler* rh, const std::string& member_name, T& member_ref, bool hard_cast) {
260 typename reflection_traits_info<T>::traits_type rt;
261 return rh->self_reflect_member(member_name, member_ref, rt, static_cast<typename reflection_traits_info<T>::traits_type::external_self_reflect_type&>(member_ref), hard_cast);
262 }
263 };
264#endif
265 template <typename T> struct reflect_member_impl<T,RTK_SELF_REFLECT>
266 {
267 static bool reflect(reflection_handler* rh, const std::string& member_name, T& member_ref, bool hard_cast) {
269 return rh->self_reflect_member(member_name, member_ref, rt, member_ref, hard_cast);
270 }
271 };
272
273 template <typename M, typename R>
275 static bool reflect(reflection_handler* rh, const std::string& method_name, M m)
276 {
277 static std::vector<abst_reflection_traits*> param_value_traits;
278 static method_interface_impl<M> mi(m);
279 if (param_value_traits.size() != cgv::type::traits::method_pointer<M>::nr_arguments)
282 return rh->reflect_method_void(method_name, &mi, &rt, param_value_traits);
283 }
284 };
285 template <typename M>
286 struct reflect_method_impl<M,void> {
287 static bool reflect(reflection_handler* rh, const std::string& method_name, M m)
288 {
289 static std::vector<abst_reflection_traits*> param_value_traits;
290 static method_interface_impl<M> mi(m);
291 if (param_value_traits.size() != cgv::type::traits::method_pointer<M>::nr_arguments)
293 return rh->reflect_method_void(method_name, &mi, 0, param_value_traits);
294 }
295 };
296
297#ifndef REFLECT_TRAITS_WITH_DECLTYPE
298 template <bool use_get, typename B>
299 struct reflect_base_dispatch { static bool reflect(reflection_handler* rh, B& base_ref) {
300 return rh->reflect_base_impl(base_ref, typename reflection_traits_info<B>::traits_type()); } };
301 template <typename B>
302 struct reflect_base_dispatch<true,B> { static bool reflect(reflection_handler* rh, B& base_ref) {
303 return rh->reflect_base_impl(base_ref, get_reflection_traits(base_ref)); } };
304
305 template <bool use_get, typename T, unsigned n>
306 struct reflect_const_array_dispatch { static bool reflect(reflection_handler* rh, const std::string& member_name, T (&member_ref)[n]) {
307 return rh->reflect_const_array_impl(member_name, member_ref, typename reflection_traits_info<T>::traits_type()); } };
308 template <typename T, unsigned n>
309 struct reflect_const_array_dispatch<true,T,n> { static bool reflect(reflection_handler* rh, const std::string& member_name, T (&member_ref)[n]) {
310 return rh->reflect_const_array_impl(member_name, member_ref, get_reflection_traits(T())); } };
311
312 template <bool use_get, typename T>
313 struct reflect_vector_dispatch { static bool reflect(reflection_handler* rh, const std::string& member_name, std::vector<T>& member_ref) {
314 return rh->reflect_vector_impl(member_name, member_ref, typename reflection_traits_info<T>::traits_type()); } };
315 template <typename T>
316 struct reflect_vector_dispatch<true,T> { static bool reflect(reflection_handler* rh, const std::string& member_name, std::vector<T>& member_ref) {
317 return rh->reflect_vector_impl(member_name, member_ref, get_reflection_traits(T())); } };
318#endif
319};
320
321
322template <typename T>
323bool reflection_handler::reflect_member(const std::string& member_name, T& member_ref, bool hard_cast)
324{
325#ifdef REFLECT_TRAITS_WITH_DECLTYPE
326 return detail::reflect_member_impl<T, reflection_traits_info<T>::kind>::reflect(this, member_name, member_ref, hard_cast);
327#else
328 return detail::reflect_member_impl<T, reflection_traits_info<T>::kind>::reflect(this, member_name, member_ref, hard_cast);
329#endif
330}
331
332template <typename M>
333bool reflection_handler::reflect_method(const std::string& method_name, M m)
334{
336}
337
338#ifdef REFLECT_TRAITS_WITH_DECLTYPE
339template <typename B>
340bool reflection_handler::reflect_base(B& base_ref)
341{
343#else
344template <typename B, typename RB>
345bool reflection_handler::reflect_base_impl(B& base_ref, const RB&)
346{
347 RB rt;
348#endif
349 switch (process_structural_group_begin(GK_BASE_CLASS, "", GroupTraversal(reflect_group_begin(GK_BASE_CLASS, "", &base_ref, &rt)))) {
350 case GT_TERMINATE : return false;
351 case GT_COMPLETE : return reflect_member("", base_ref, true) && group_end(GK_BASE_CLASS);
352 default: return true;
353 }
354}
355#ifndef REFLECT_TRAITS_WITH_DECLTYPE
356template <typename B>
358{
360}
361#endif
362
363
364
365
366
367#ifdef REFLECT_TRAITS_WITH_DECLTYPE
368template <typename T, unsigned n>
369bool reflection_handler::reflect_member(const std::string& member_name, T (&member_ref)[n])
370{
372#else
373template <typename T, unsigned n, typename RT>
374bool reflection_handler::reflect_const_array_impl(const std::string& member_name, T (&member_ref)[n], const RT&)
375{
376 RT rt;
377#endif
378 int grp_tra = reflect_array_begin(GK_ARRAY, member_name, member_ref, &rt, n);
379 if (grp_tra == GT_TERMINATE || grp_tra == GT_SKIP)
380 return grp_tra == GT_SKIP;
381 bool res = true;
382 if (grp_tra == GT_COMPLETE) {
383 for (nesting_info_stack.back().idx=0; res && nesting_info_stack.back().idx<n; ++nesting_info_stack.back().idx)
384 res = reflect_member("", member_ref[nesting_info_stack.back().idx]);
385 group_end(GK_ARRAY);
386 }
387 else {
388 res = reflect_member("", member_ref[grp_tra]);
389 nesting_info_stack.pop_back();
390 }
391 return res;
392}
393#ifndef REFLECT_TRAITS_WITH_DECLTYPE
394template <typename T, unsigned n>
395bool reflection_handler::reflect_member(const std::string& member_name, T (&member_ref)[n])
396{
397 return detail::reflect_const_array_dispatch<reflection_traits_info<T>::use_get,T,n>::reflect(this,member_name,member_ref);
398}
399#endif
400
401#ifdef REFLECT_TRAITS_WITH_DECLTYPE
402template <typename T>
403bool reflection_handler::reflect_member(const std::string& member_name, std::vector<T>& member_ref)
404{
406#else
407template <typename T, typename RT>
408bool reflection_handler::reflect_vector_impl(const std::string& member_name, std::vector<T>& member_ref, const RT&)
409{
410 RT rt;
411#endif
412 int grp_tra = reflect_array_begin(GK_VECTOR, member_name, &member_ref, &rt, (unsigned)member_ref.size());
413 if (grp_tra == GT_TERMINATE || grp_tra == GT_SKIP)
414 return grp_tra == GT_SKIP;
415 bool res = true;
416 if (grp_tra == GT_COMPLETE) {
417 unsigned size = (unsigned)member_ref.size();
418 res = reflect_member("size", size);
419 if (member_ref.size() != size)
420 member_ref.resize(size);
421 for (nesting_info_stack.back().idx=0; res && nesting_info_stack.back().idx<size; ++nesting_info_stack.back().idx)
422 res = reflect_member("", member_ref[nesting_info_stack.back().idx]);
423 group_end(GK_VECTOR);
424 }
425 else {
426 res = reflect_member("", member_ref[grp_tra]);
427 nesting_info_stack.pop_back();
428 }
429 return res;
430}
431#ifndef REFLECT_TRAITS_WITH_DECLTYPE
432template <typename T>
433bool reflection_handler::reflect_member(const std::string& member_name, std::vector<T>& member_ref)
434{
435 return detail::reflect_vector_dispatch<reflection_traits_info<T>::use_get,T>::reflect(this, member_name, member_ref);
436}
437#endif
439
442template <typename T>
443bool reflection_handler::reflect_member(const std::string& member_name, T*& member_ref)
444{
446 GroupTraversal gt = reflect_group_begin(GK_POINTER, member_name, &member_ref, &rt);
447 switch (gt) {
448 case GT_TERMINATE : return false;
449 case GT_SKIP : return true;
450 case GT_COMPLETE : break;
451 default:
452 std::cerr << "group traversal " << group_traversal_name(gt) << " not allowed on pointer group " << member_name << "!" << std::endl;
453 return false;
454 }
455 nesting_info_stack.push_back(nesting_info(GK_POINTER, &member_name));
456 unsigned pointer_type = (member_ref == 0 ? 0 : 1);
457 unsigned pointer_type_tmp = pointer_type;
458 bool res = reflect_member("pointer_type", pointer_type_tmp);
459 if (res) {
460 if (pointer_type_tmp != pointer_type) {
461 if (pointer_type != 0)
462 delete member_ref;
463 if (pointer_type_tmp == 0)
464 member_ref = 0;
465 else
466 member_ref = new T();
467 }
468 if (pointer_type_tmp != 0)
469 res = reflect_member(*member_ref);
470 }
471 group_end(GK_POINTER);
472 return res;
473}
475template <typename T, typename S>
476bool reflection_handler::reflect_array(const std::string& member_name, T*& member_ref, S& size)
477{
479 int grp_tra = reflect_array_begin(GK_ARRAY, member_name, member_ref, &rt, size);
480 if (grp_tra == GT_TERMINATE || grp_tra == GT_SKIP)
481 return grp_tra == GT_SKIP;
482 bool res = true;
483 if (grp_tra == GT_COMPLETE) {
484 unsigned tmp_size = size;
485 res = reflect_member("size", tmp_size);
486 if (size != tmp_size) {
487 T* tmp = member_ref;
488 member_ref = new T[tmp_size];
489 if (tmp) {
490 for (unsigned i=0; i<tmp_size && i < size; ++i)
491 member_ref[i] = tmp[i];
492 delete [] tmp;
493 }
494 size = tmp_size;
495 }
496 for (nesting_info_stack.back().idx=0; res && nesting_info_stack.back().idx<size; ++nesting_info_stack.back().idx)
497 res = reflect_member("", member_ref[nesting_info_stack.back().idx]);
498 group_end(GK_ARRAY);
499 }
500 else {
501 res = reflect_member("", member_ref[grp_tra]);
502 nesting_info_stack.pop_back();
503 }
504 return res;
505}
506
507 }
508}
509
510#include <cgv/config/lib_end.h>
the self reflection handler is passed to the virtual self_reflect() method of cgv::base::base.
int reflect_array_begin(GroupKind group_kind, const std::string &group_name, void *group_ptr, abst_reflection_traits *rt, unsigned grp_size)
type independent functionality of array reflection
virtual bool reflect_method_void(const std::string &method_name, method_interface *mi_ptr, abst_reflection_traits *return_traits, const std::vector< abst_reflection_traits * > &param_value_traits)=0
abstract interface to reflect a method, where return and parameter types are specified as strings.
bool reflect_base(B &base_ref)
reflect a base class with its members
bool reflect_method(const std::string &method_name, M m)
call this to reflect a method by method name and reference to the member.
bool reflect_array(const std::string &member_name, T *&member_ref, S &size)
reflect a dynamic array member of vector type
static std::string group_traversal_name(GroupTraversal gt)
return the group traversals as a string
GroupTraversal process_structural_group_begin(GroupKind gk, const std::string &member_name, GroupTraversal gt)
type independent part of the reflect_group method that starts the group traversal
bool self_reflect_member(const std::string &member_name, T &member_ref, const RT &, const D &, bool hard_cast)
implementation of reflection with internal or external self_reflect function
virtual int reflect_group_begin(GroupKind group_kind, const std::string &group_name, void *group_ptr, abst_reflection_traits *rt, unsigned grp_size=-1)
abstract interface to start reflection of a group of members.
std::vector< nesting_info > nesting_info_stack
stack of nesting_info used during the reflection process
GroupKind
different support group types
virtual bool reflect_member_void(const std::string &member_name, void *member_ptr, abst_reflection_traits *rt)=0
abstract interface to reflect a member variable, where the member type is specified as a string.
GroupTraversal
@ basic types with helper functions
bool reflect_member(const std::string &member_name, T &member_ref, bool hard_cast=false)
call this to reflect a member by member name and reference to the member.
bool group_end(GroupKind gk)
updates the nesting info at the end of group and always returns true
the cgv namespace
Definition print.h:11
abstract interface for type reflection with basic type management and optional string conversion
forward declaration of method_interface_impl which is implemented in <cgv/reflect/method_interface_im...
abstract interface to call a method of a given instance.
for each nesting during traversal a nesting info is pushed back to the end of the nesting info stack
const std::string * name
pointer to type name for base class groups and member name otherwise
unsigned idx
current element index for vector and array groups
GroupKind group_kind
group kind of nesting level
the reflection_traits_info defines compile time information about reflection_traits for a given type ...