cgv
Loading...
Searching...
No Matches
find_reflection_handler.cxx
1#include "find_reflection_handler.h"
2
3#include <cgv/utils/tokenizer.h>
4#include <cgv/utils/scan.h>
5
6namespace cgv {
7 namespace reflect {
8
9bool find_reflection_handler::at_end() const
10{
11 return token_idx == tokens.size();
12}
13
14bool find_reflection_handler::step_if_matches(const std::string& name)
15{
16 if (name == "")
17 return true;
18 if (!at_end()) {
19 if (tokens[token_idx] == name) {
20 ++token_idx;
21 return true;
22 }
23 }
24 return false;
25}
26
27find_reflection_handler::find_reflection_handler(const std::string& _target) : target(&_target), target_ptr(0), found(false), valid(true)
28{
29 cgv::utils::tokenizer(*target).set_sep(".[]").set_skip("'\"", "'\"", "\\\\").set_ws("").bite_all(tokens);
30 token_idx = 0;
31 rt = 0;
32}
33
34find_reflection_handler::find_reflection_handler(const void* _target_ptr, bool _traverse_matched_groups) : target(0), target_ptr(_target_ptr), traverse_matched_groups(_traverse_matched_groups), found(false), valid(true)
35{
36 rt = 0;
37}
38
40find_reflection_handler::~find_reflection_handler()
41{
42 if (rt)
43 delete rt;
44}
45
48{
49 return found;
50}
51
54{
55 return found && valid;
56}
57
60{
61 return member_ptr;
62}
63
64
67{
68 return member_name;
69}
70
76
78void find_reflection_handler::process_member_void(const std::string& member_name, void* member_ptr,
79 abst_reflection_traits* rt, GroupKind group_kind, unsigned grp_size)
80{
81 if (target_ptr) {
82 for (unsigned i = 0; i < target_tokens.size(); ++i)
83 this->member_name += target_tokens[i];
84 this->member_name += member_name;
85 }
86 else {
87 this->member_name = member_name;
88 }
89 this->rt = rt->clone();
90 this->member_ptr = member_ptr;
91 this->group_kind = group_kind;
92 this->grp_size = grp_size;
93 found = true;
94}
95
98{
99 if (target_ptr == 0)
100 return;
101
102 if (traversed_groups.empty()) {
103 std::cerr << "find reflection handler encountered case where group begin was not matched with group end" << std::endl;
104 }
105 if (traversed_groups.back().group_kind != GK_BASE_CLASS)
106 target_tokens.pop_back();
107
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();
113
114 check_for_index_increment();
115}
116
117void find_reflection_handler::push_group(const std::string& _group_name, void* _group_ptr, abst_reflection_traits* _rt, GroupKind _group_kind, unsigned _group_size)
118{
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;
125}
126
128int find_reflection_handler::reflect_group_begin(GroupKind group_kind, const std::string& group_name, void* group_ptr,
129 abst_reflection_traits* rt, unsigned grp_size)
130{
131 switch (group_kind) {
132 case GK_BASE_CLASS :
133 if (target_ptr) {
134 if (!traverse_matched_groups) {
135 if (target_ptr == group_ptr) {
136 process_member_void("base_class", group_ptr, rt, group_kind, grp_size);
137 return GT_TERMINATE;
138 }
139 }
140 push_group("base_class", group_ptr, rt, group_kind, grp_size);
141 return GT_COMPLETE;
142 }
143 else {
144 if (at_end()) {
145 std::cerr << "did not expect base " << rt->get_type_name() << std::endl;
146 return GT_TERMINATE;
147 }
148 else if (tokens[token_idx] == rt->get_type_name()) {
149 if (token_idx == tokens.size() - 1) {
150 process_member_void("base_class", group_ptr, rt, group_kind, grp_size);
151 return GT_TERMINATE;
152 }
153 else {
154 ++token_idx;
155 if (tokens[token_idx] == ".") {
156 ++token_idx;
157 return GT_COMPLETE;
158 }
159 else {
160 std::cerr << "only .-operator allowed on base class " << group_name << "!" << std::endl;
161 return GT_TERMINATE;
162 }
163 }
164 }
165 else
166 return GT_COMPLETE;
167 }
168 case GK_STRUCTURE:
169 if (target_ptr) {
170 if (!traverse_matched_groups) {
171 if (target_ptr == group_ptr) {
172 process_member_void(group_name, group_ptr, rt, group_kind);
173 return GT_TERMINATE;
174 }
175 }
176 push_group(group_name, group_ptr, rt, group_kind, grp_size);
177 target_tokens.push_back(group_name + ".");
178 return GT_COMPLETE;
179 }
180 else {
181 if (step_if_matches(group_name)) {
182 if (at_end()) {
183 process_member_void(group_name, group_ptr, rt, group_kind);
184 return GT_TERMINATE;
185 }
186 else {
187 if (group_name == "" && tokens[token_idx] != ".")
188 return GT_COMPLETE;
189 if (tokens[token_idx] == ".") {
190 ++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;
193 return GT_TERMINATE;
194 }
195 return GT_COMPLETE;
196 }
197 else {
198 std::cerr << "only .-operator allowed on structure " << group_name << ":" << rt->get_type_name() << "!" << std::endl;
199 return GT_TERMINATE;
200 }
201 }
202 }
203 else
204 return GT_SKIP;
205 }
206 case GK_ARRAY :
207 if (target_ptr) {
208 if (!traverse_matched_groups) {
209 if (target_ptr == group_ptr) {
210 process_member_void(group_name, group_ptr, rt, group_kind);
211 return GT_TERMINATE;
212 }
213 }
214 push_group(group_name, group_ptr, rt, group_kind, grp_size);
215 target_tokens.push_back("[0].");
216 return GT_COMPLETE;
217 }
218 else {
219 if (step_if_matches(group_name)) {
220 if (at_end()) {
221 process_member_void(group_name, group_ptr, rt, group_kind);
222 return GT_TERMINATE;
223 }
224 else {
225 if (tokens[token_idx] == "[") {
226 ++token_idx;
227 if (token_idx == tokens.size()) {
228 std::cerr << "[-operator applied on array " << group_name << " must be followed by index" << std::endl;
229 return GT_TERMINATE;
230 }
231 int idx;
232 if (!cgv::utils::is_integer(tokens[token_idx].begin, tokens[token_idx].end, idx)) {
233 std::cerr << "index to access array " << group_name << " can only be of integer type, but found token " << tokens[token_idx] << std::endl;
234 return GT_TERMINATE;
235 }
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;
238 return GT_TERMINATE;
239 }
240 ++token_idx;
241 if (token_idx == tokens.size()) {
242 std::cerr << "[" << idx << "-operator applied to array " << group_name << " must be followed by ]" << std::endl;
243 return GT_TERMINATE;
244 }
245 ++token_idx;
246 return idx;
247 }
248 else {
249 std::cerr << "only []-operator allowed on array " << group_name << "!" << std::endl;
250 return GT_TERMINATE;
251 }
252 }
253 }
254 else
255 return GT_SKIP;
256 }
257 case GK_VECTOR:
258 if (target_ptr) {
259 if (!traverse_matched_groups) {
260 if (target_ptr == group_ptr) {
261 process_member_void(group_name, group_ptr, rt, group_kind);
262 return GT_TERMINATE;
263 }
264 }
265 push_group(group_name, group_ptr, rt, group_kind, grp_size);
266 target_tokens.push_back("[0].");
267 return GT_COMPLETE;
268 }
269 else {
270 if (step_if_matches(group_name)) {
271 if (at_end()) {
272 process_member_void(group_name, group_ptr, rt, group_kind);
273 return GT_TERMINATE;
274 }
275 else {
276 if (tokens[token_idx] == "[") {
277 ++token_idx;
278 if (token_idx == tokens.size()) {
279 std::cerr << "[-operator applied on vector " << group_name << " must be followed by index" << std::endl;
280 return GT_TERMINATE;
281 }
282 int idx;
283 if (!cgv::utils::is_integer(tokens[token_idx].begin, tokens[token_idx].end, idx)) {
284 std::cerr << "index to access vector " << group_name << " can only be of integer type, but found token " << tokens[token_idx] << std::endl;
285 return GT_TERMINATE;
286 }
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;
289 return GT_TERMINATE;
290 }
291 ++token_idx;
292 if (token_idx == tokens.size()) {
293 std::cerr << "[" << idx << "-operator applied to vector " << group_name << " must be followed by ]" << std::endl;
294 return GT_TERMINATE;
295 }
296 ++token_idx;
297 return idx;
298 }
299 else if (tokens[token_idx] == ".") {
300 ++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;
303 return GT_TERMINATE;
304 }
305 return GT_COMPLETE;
306 }
307 else {
308 std::cerr << "only . or [-operator allowed on vector " << group_name << ":" << rt->get_type_name() << "!" << std::endl;
309 return GT_TERMINATE;
310 }
311 }
312 }
313 else
314 return GT_SKIP;
315 }
316 default:
317 return GT_SKIP;
318 }
319}
320
321void find_reflection_handler::check_for_index_increment()
322{
323 if (traversed_groups.empty() || target_tokens.empty())
324 return;
325
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;
330 }
331 // increment count
332 tok = std::string("[") + cgv::utils::to_string(atoi(tok.substr(1, tok.size() - 2).c_str()) + 1) + "]";
333 }
334}
335
336bool find_reflection_handler::reflect_member_void(const std::string& member_name, void* member_ptr, abst_reflection_traits* rt)
337{
338 if (target_ptr) {
339 if (member_ptr == target_ptr) {
340 process_member_void(member_name, member_ptr, rt);
341 return false;
342 }
343 check_for_index_increment();
344 return true;
345 }
346 else {
347 if (step_if_matches(member_name)) {
348 if (at_end()) {
349 process_member_void(member_name, member_ptr, rt);
350 return false;
351 }
352 else {
353 std::cerr << "non group member " << member_name << ":" << rt->get_type_name() << " may not follow operators!" << std::endl;
354 return false;
355 }
356 }
357 return true;
358 }
359}
360
361bool find_reflection_handler::reflect_method_void(const std::string& method_name, method_interface* mi_ptr,
362 abst_reflection_traits* return_traits, const std::vector<abst_reflection_traits*>& param_value_traits)
363{
364 return true;
365}
366
367 }
368}
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 * > &param_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.
Definition tokenizer.h:68
tokenizer & set_sep(const std::string &sep, bool merge)
set the list of separators and specify whether succeeding separators are merged into single tokens
Definition tokenizer.cxx:59
tokenizer & set_ws(const std::string &ws)
set the list of white spaces, that separate tokens and are skipped
Definition tokenizer.cxx:38
tokenizer & set_skip(const std::string &open, const std::string &close)
set several character pairs that enclose tokens that are not split
Definition tokenizer.cxx:44
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...
Definition scan.cxx:367
the cgv namespace
Definition print.h:11
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.