1#include "find_reflection_handler.h"
3#include <cgv/utils/tokenizer.h>
9bool find_reflection_handler::at_end()
const
11 return token_idx == tokens.size();
14bool find_reflection_handler::step_if_matches(
const std::string& name)
19 if (tokens[token_idx] == name) {
40find_reflection_handler::~find_reflection_handler()
55 return found && valid;
82 for (
unsigned i = 0; i < target_tokens.size(); ++i)
83 this->member_name += target_tokens[i];
84 this->member_name += member_name;
87 this->member_name = member_name;
89 this->rt = rt->
clone();
90 this->member_ptr = member_ptr;
91 this->group_kind = group_kind;
92 this->grp_size = grp_size;
102 if (traversed_groups.empty()) {
103 std::cerr <<
"find reflection handler encountered case where group begin was not matched with group end" << std::endl;
105 if (traversed_groups.back().group_kind != GK_BASE_CLASS)
106 target_tokens.pop_back();
108 if (traverse_matched_groups && !found && (traversed_groups.back().group_ptr == target_ptr))
109 process_member_void(traversed_groups.back().group_name, traversed_groups.back().group_ptr, traversed_groups.back().rt, traversed_groups.back().group_kind, traversed_groups.back().group_size);
110 delete traversed_groups.back().rt;
111 traversed_groups.back().rt = 0;
112 traversed_groups.pop_back();
114 check_for_index_increment();
117void find_reflection_handler::push_group(
const std::string& _group_name,
void* _group_ptr,
abst_reflection_traits* _rt, GroupKind _group_kind,
unsigned _group_size)
119 traversed_groups.resize(traversed_groups.size() + 1);
120 traversed_groups.back().group_name = _group_name;
121 traversed_groups.back().group_ptr = _group_ptr;
122 traversed_groups.back().group_kind = _group_kind;
123 traversed_groups.back().rt = _rt->
clone();
124 traversed_groups.back().group_size = _group_size;
131 switch (group_kind) {
134 if (!traverse_matched_groups) {
135 if (target_ptr == group_ptr) {
140 push_group(
"base_class", group_ptr, rt, group_kind, grp_size);
145 std::cerr <<
"did not expect base " << rt->
get_type_name() << std::endl;
149 if (token_idx == tokens.size() - 1) {
155 if (tokens[token_idx] ==
".") {
160 std::cerr <<
"only .-operator allowed on base class " << group_name <<
"!" << std::endl;
170 if (!traverse_matched_groups) {
171 if (target_ptr == group_ptr) {
176 push_group(group_name, group_ptr, rt, group_kind, grp_size);
177 target_tokens.push_back(group_name +
".");
181 if (step_if_matches(group_name)) {
187 if (group_name ==
"" && tokens[token_idx] !=
".")
189 if (tokens[token_idx] ==
".") {
191 if (token_idx == tokens.size()) {
192 std::cerr <<
".-operator applied on " << group_name <<
":" << rt->
get_type_name() <<
" must be followed by element name" << std::endl;
198 std::cerr <<
"only .-operator allowed on structure " << group_name <<
":" << rt->
get_type_name() <<
"!" << std::endl;
208 if (!traverse_matched_groups) {
209 if (target_ptr == group_ptr) {
214 push_group(group_name, group_ptr, rt, group_kind, grp_size);
215 target_tokens.push_back(
"[0].");
219 if (step_if_matches(group_name)) {
225 if (tokens[token_idx] ==
"[") {
227 if (token_idx == tokens.size()) {
228 std::cerr <<
"[-operator applied on array " << group_name <<
" must be followed by index" << std::endl;
233 std::cerr <<
"index to access array " << group_name <<
" can only be of integer type, but found token " << tokens[token_idx] << std::endl;
236 if (idx < 0 || idx >= (
int)grp_size) {
237 std::cerr <<
"index " << idx <<
" to access array " << group_name <<
" is out of range [0," << grp_size <<
"[! " << std::endl;
241 if (token_idx == tokens.size()) {
242 std::cerr <<
"[" << idx <<
"-operator applied to array " << group_name <<
" must be followed by ]" << std::endl;
249 std::cerr <<
"only []-operator allowed on array " << group_name <<
"!" << std::endl;
259 if (!traverse_matched_groups) {
260 if (target_ptr == group_ptr) {
265 push_group(group_name, group_ptr, rt, group_kind, grp_size);
266 target_tokens.push_back(
"[0].");
270 if (step_if_matches(group_name)) {
276 if (tokens[token_idx] ==
"[") {
278 if (token_idx == tokens.size()) {
279 std::cerr <<
"[-operator applied on vector " << group_name <<
" must be followed by index" << std::endl;
284 std::cerr <<
"index to access vector " << group_name <<
" can only be of integer type, but found token " << tokens[token_idx] << std::endl;
287 if (idx < 0 || idx >= (
int)grp_size) {
288 std::cerr <<
"index " << idx <<
" to access vector " << group_name <<
" is out of range [0," << grp_size <<
"[! " << std::endl;
292 if (token_idx == tokens.size()) {
293 std::cerr <<
"[" << idx <<
"-operator applied to vector " << group_name <<
" must be followed by ]" << std::endl;
299 else if (tokens[token_idx] ==
".") {
301 if (token_idx == tokens.size()) {
302 std::cerr <<
".-operator applied on vector " << group_name <<
":" << rt->
get_type_name() <<
" must be followed by element name" << std::endl;
308 std::cerr <<
"only . or [-operator allowed on vector " << group_name <<
":" << rt->
get_type_name() <<
"!" << std::endl;
321void find_reflection_handler::check_for_index_increment()
323 if (traversed_groups.empty() || target_tokens.empty())
326 if (traversed_groups.back().group_kind == GK_ARRAY || traversed_groups.back().group_kind == GK_VECTOR) {
327 std::string& tok = target_tokens.back();
328 if (tok.back() !=
']' || tok.front() !=
'[') {
329 std::cerr <<
"found none array target token for array group :(" << std::endl;
332 tok = std::string(
"[") +
cgv::utils::to_string(atoi(tok.substr(1, tok.size() - 2).c_str()) + 1) +
"]";
339 if (member_ptr == target_ptr) {
343 check_for_index_increment();
347 if (step_if_matches(member_name)) {
353 std::cerr <<
"non group member " << member_name <<
":" << rt->
get_type_name() <<
" may not follow operators!" << std::endl;
bool found_target() const
return whether target has been found
void reflect_group_end(GroupKind group_kind)
ensure that matched group pointers are found also in case that groups are traversed further and no gr...
find_reflection_handler(const std::string &_target)
construct from textual target description
bool found_valid_target() const
return whether a valid target has been found. The semantic of being valid is defined in derived class...
bool reflect_method_void(const std::string &method_name, method_interface *mi_ptr, abst_reflection_traits *return_traits, const std::vector< abst_reflection_traits * > ¶m_value_traits)
ignore methods
void * get_member_ptr() const
in case a valid target has been found, return a pointer to the member
const std::string & get_member_name() const
in case a valid target has been found, return the name of the member
int reflect_group_begin(GroupKind group_kind, const std::string &group_name, void *group_ptr, abst_reflection_traits *rt, unsigned grp_size)
overload to navigate grouped reflection information
bool reflect_member_void(const std::string &member_name, void *member_ptr, abst_reflection_traits *rt)
check for target during member reflection
virtual void process_member_void(const std::string &member_name, void *member_ptr, abst_reflection_traits *rt, GroupKind group_kind=GK_NO_GROUP, unsigned grp_size=-1)
virtual method that is overloaded by derived classes to handle the target member
abst_reflection_traits * get_reflection_traits() const
in case a valid target has been found, return a point to the reflection traits describing the type of...
GroupKind
different support group types
the tokenizer allows to split text into tokens in a convenient way.
tokenizer & set_sep(const std::string &sep, bool merge)
set the list of separators and specify whether succeeding separators are merged into single tokens
tokenizer & set_ws(const std::string &ws)
set the list of white spaces, that separate tokens and are skipped
tokenizer & set_skip(const std::string &open, const std::string &close)
set several character pairs that enclose tokens that are not split
std::string to_string(const std::string &v, unsigned int w, unsigned int p, bool)
specialization of conversion from string to strings
bool is_integer(const char *begin, const char *end, int &value)
check if the text range (begin,end( defines an integer value. If yes, store the value in the passed r...
Helper functions to process strings.
abstract interface for type reflection with basic type management and optional string conversion
virtual abst_reflection_traits * clone()=0
clone function
virtual const char * get_type_name() const =0
return the type name
abstract interface to call a method of a given instance.