cgv
Loading...
Searching...
No Matches
ppp_variant.cxx
1#include "variant.h"
2#include "variables.h"
3#include <cgv/utils/convert.h>
4#include <cgv/utils/tokenizer.h>
5#include <cgv/utils/file.h>
6#include <cgv/utils/dir.h>
7#include <cgv/utils/scan.h>
8#include <stdlib.h>
9#include <iostream>
10
11using namespace cgv::utils;
12
13namespace cgv {
14 namespace ppp {
15
16
17 func_type::func_type(unsigned _i, unsigned _j, ph_processor* _ph_proc, namespace_info* _ns)
18 : block_begin(_i), block_end(_j), ph_proc(_ph_proc), ns(_ns)
19 {
20 }
21
22
23 variant::variant() : vt(UNDEF_VALUE), reference_value(0) {}
24
27 {
28 vt = v.vt;
29 switch (vt) {
30 case BOOL_VALUE: bool_value = v.bool_value; break;
31 case INT_VALUE: int_value = v.int_value; break;
32 case DOUBLE_VALUE: dbl_value = v.dbl_value; break;
33 case STRING_VALUE: string_value = new std::string(*v.string_value); break;
34 case REFERENCE_VALUE: reference_value = v.reference_value; break;
35 case NAME_VALUE: name_value = new std::string(*v.name_value); break;
36 case LIST_VALUE: list_value = new list_type(*v.list_value); break;
37 case MAP_VALUE: map_value = new map_type(*v.map_value); break;
38 case FUNC_VALUE: func_value = new func_type(*v.func_value); break;
39 default: break;
40 }
41 }
42
43 variant::variant(bool v) : vt(BOOL_VALUE), bool_value(v) {}
44 variant::variant(int v) : vt(INT_VALUE), int_value(v) {}
45 variant::variant(double v) : vt(DOUBLE_VALUE), dbl_value(v) {}
46 variant::variant(const std::string& v) : vt(STRING_VALUE), string_value(new std::string(v)) {}
47 variant::variant(variant* v) : vt(REFERENCE_VALUE), reference_value(v) {}
49 variant::variant(ValueType, const std::string& v)
50 {
51 vt = NAME_VALUE;
52 name_value = new std::string(v);
53 }
55 variant::variant(const list_type& v) : vt(LIST_VALUE), list_value(new list_type(v)) {}
57 variant::variant(const map_type& v) : vt(MAP_VALUE), map_value(new map_type(v)) {}
59 variant::variant(const func_type& v) : vt(FUNC_VALUE), func_value(new func_type(v)) {}
60
62 {
63 clear();
64 }
65
67 {
68 switch (vt) {
69 case STRING_VALUE: delete string_value; string_value = 0; break;
70 case REFERENCE_VALUE: reference_value = 0; break;
71 case NAME_VALUE: delete name_value; name_value = 0; break;
72 case LIST_VALUE: delete list_value; list_value = 0; break;
73 case MAP_VALUE: delete map_value; map_value = 0; break;
74 case FUNC_VALUE: delete func_value; func_value = 0; break;
75 default:break;
76 }
77 vt = UNDEF_VALUE;
78 }
79
80
82 {
83 if (&v == this)
84 return *this;
85 clear();
86 vt = v.vt;
87 switch (vt) {
88 case BOOL_VALUE: bool_value = v.bool_value; break;
89 case INT_VALUE: int_value = v.int_value; break;
90 case DOUBLE_VALUE: dbl_value = v.dbl_value; break;
91 case STRING_VALUE: string_value = new std::string(*v.string_value); break;
92 case REFERENCE_VALUE: reference_value = v.reference_value; break;
93 case NAME_VALUE: name_value = new std::string(*v.name_value); break;
94 case LIST_VALUE: list_value = new list_type(*v.list_value); break;
95 case MAP_VALUE: map_value = new map_type(*v.map_value); break;
96 case FUNC_VALUE: func_value = new func_type(*v.func_value); break;
97 default: break;
98 }
99 return *this;
100 }
101
102 bool variant::is_unary_applicable(OperatorType ot)
103 {
104 switch (ot) {
105 case OT_INC:
106 case OT_DEC:
107 return is_reference() || is_str();
108 case OT_NEGATE:
109 case OT_COMPL:
110 return is_int() || is_double() || is_bool();
111 case OT_MAP_UP:
112 case OT_UNARY_MAP:
113 return is_str() || is_name();
114 case OT_MAP_DOWN:
115 return has_child_namespace() && (is_str() || is_name());
116 case OT_EXISTS:
117 return !is_list() && !is_map();
118 default:break;
119 }
120 return true;
121 }
122
123 bool variant::unary_check_defined(OperatorType ot)
124 {
125 switch (ot) {
126 case OT_UNARY_MAP:
127 case OT_MAP_UP:
128 case OT_MAP_DOWN:
129 case OT_INC:
130 case OT_DEC:
131 return true;
132 default:
133 return !is_undefined();
134 }
135 }
136
137 void variant::apply_unary(OperatorType ot)
138 {
139 switch (ot) {
140 case OT_NOT:
141 if (is_list() || is_map())
142 set_int(get_size());
143 else if (is_str())
144 set_int((int)get_str().size());
145 else
146 set_bool(!get_bool());
147 break;
148 case OT_COMPL:
149 set_int(~get_int());
150 break;
151 case OT_EXISTS:
152 set_bool(cgv::utils::file::exists(get_str()) || cgv::utils::dir::exists(get_str()));
153 break;
154 case OT_INC:
155 if (is_int())
156 ++ref_value().int_value;
157 else if (is_double())
158 ref_value().dbl_value += 1;
159 else if (is_str())
160 set_str(to_upper(*ref_value().string_value));
161 break;
162 case OT_DEC:
163 if (is_int())
164 --ref_value().int_value;
165 else if (is_double())
166 ref_value().dbl_value -= 1;
167 else if (is_str())
168 set_str(to_lower(*ref_value().string_value));
169 break;
170 case OT_NEGATE:
171 if (is_double())
172 set_double(-get_double());
173 else
174 set_int(-get_int());
175 break;
176 case OT_UNARY_MAP:
177 {
178 namespace_info* cns = get_current_namespace();
179 namespace_info* ns = cns;
180 while (ns->environment_ns)
181 ns = ns->environment_ns;
182 set_current_namespace(ns);
183 if (is_name())
184 *this = variant(&ref_variable(get_name()));
185 else
186 *this = variant(&ref_variable(get_str()));
187 set_current_namespace(cns);
188 }
189 break;
190 case OT_MAP_UP:
191 if (is_name())
192 *this = variant(&ref_variable(get_name(), true));
193 else
194 *this = variant(&ref_variable(get_str(), true));
195 break;
196 case OT_MAP_DOWN:
197 if (has_child_namespace()) {
198 goto_child_namespace();
199 if (is_name())
200 *this = variant(&ref_variable(get_name()));
201 else
202 *this = variant(&ref_variable(get_str()));
203 goto_parent_namespace();
204 }
205 break;
206 default: break;
207 }
208 }
209
210 bool variant::is_binary_applicable(OperatorType ot, const variant& v2)
211 {
212 switch (ot) {
213 case OT_ASSIGN:
214 case OT_ASSIGN_REF:
215 case OT_ASSIGN_ADD:
216 case OT_ASSIGN_SUB:
217 case OT_ASSIGN_MUL:
218 case OT_ASSIGN_DIV:
219 case OT_ASSIGN_AND:
220 case OT_ASSIGN_OR:
221 case OT_ASSIGN_XOR:
222 case OT_ASSIGN_LSH:
223 case OT_ASSIGN_RSH:
224 return is_reference();
225 case OT_LOG_OR:
226 case OT_LOG_AND:
227 case OT_AND:
228 case OT_OR:
229 case OT_XOR:
230 case OT_DIV:
231 case OT_MOD:
232 case OT_LSH:
233 case OT_RSH:
234 return !is_str() && !is_list() && !is_map() && !v2.is_str() && !v2.is_list() && !v2.is_map();
235 case OT_MUL:
236 return !is_list() && !is_map() && !v2.is_list() && !v2.is_map();
237 case OT_LESS:
238 return !is_list() && !is_map() && !v2.is_map();
239 case OT_EQUAL_TYPE:
240 case OT_UNEQUAL_TYPE:
241 return true;
242 case OT_GREATER:
243 case OT_LESS_OR_EQUAL:
244 case OT_GREATER_OR_EQUAL:
245 case OT_EQUAL:
246 case OT_UNEQUAL:
247 return !is_list() && !is_map() && !v2.is_list() && !v2.is_map();
248 case OT_ADD:
249 case OT_SUB:
250 return !is_map() && !v2.is_list() && !v2.is_map() && (!v2.is_str() || is_str());
251 case OT_DOT:
252 return
253 (is_str() && (v2.is_bool() || v2.is_int() || v2.is_double() || v2.is_str())) ||
254 ((is_bool() || is_int() || is_double()) && v2.is_str()) ||
255 is_list() ||
256 v2.is_list() ||
257 (is_map() && v2.is_list());
258 case OT_BINARY_MAP:
259 return is_map() && (v2.is_name() || v2.is_str());
260 default: break;
261 }
262 return true;
263 }
264
265 bool variant::binary_check_defined(OperatorType ot, const variant& v2)
266 {
267 /*
268 if (ot == OT_BINARY_MAP) {
269 static int x = ot;
270 }
271 */
272 if (ot == OT_EQUAL_TYPE || ot == OT_UNEQUAL_TYPE)
273 return true;
274 if (ot == OT_BINARY_MAP)
275 return !is_undefined();
276 if (v2.is_undefined())
277 return false;
278 if (ot >= OT_ASSIGN && ot <= OT_ASSIGN_RSH)
279 return true;
280 return !is_undefined();
281 }
282
283 void variant::apply_binary(OperatorType ot, const variant& v2)
284 {
285 switch (ot) {
286 case OT_ASSIGN:
287 ref_value() = v2.get_value();
288 break;
289 case OT_ASSIGN_REF:
290 if (v2.is_name())
291 ref_value() = variant(&ref_variable(v2.get_name()));
292 else
293 ref_value() = v2;
294 break;
295 case OT_ASSIGN_ADD:
296 if (match_number_type(v2))
297 ref_value().ref_int() += v2.get_int();
298 else
299 ref_value().ref_double() += v2.get_double();
300 break;
301 case OT_ASSIGN_SUB:
302 if (match_number_type(v2))
303 ref_value().ref_int() -= v2.get_int();
304 else
305 ref_value().ref_double() -= v2.get_double();
306 break;
307 case OT_ASSIGN_MUL:
308 if (match_number_type(v2))
309 ref_value().ref_int() *= v2.get_int();
310 else
311 ref_value().ref_double() *= v2.get_double();
312 break;
313 case OT_ASSIGN_DIV:
314 if (match_number_type(v2))
315 ref_value().ref_int() /= v2.get_int();
316 else
317 ref_value().ref_double() /= v2.get_double();
318 break;
319 case OT_ASSIGN_AND:
321 ref_value().ref_int() &= v2.get_int();
322 break;
323 case OT_ASSIGN_OR:
325 ref_value().ref_int() |= v2.get_int();
326 break;
327 case OT_ASSIGN_XOR:
329 ref_value().ref_int() ^= v2.get_int();
330 break;
331 case OT_ASSIGN_LSH:
333 ref_value().ref_int() <<= v2.get_int();
334 break;
335 case OT_ASSIGN_RSH:
337 ref_value().ref_int() >>= v2.get_int();
338 break;
339 case OT_LOG_OR:
340 set_bool(get_bool() || v2.get_bool());
341 break;
342 case OT_LOG_AND:
343 set_bool(get_bool() && v2.get_bool());
344 break;
345 case OT_OR:
346 if (is_int() && v2.is_int())
347 set_int(get_int() | v2.get_int());
348 else
349 set_bool(get_bool() || v2.get_bool());
350 break;
351 case OT_AND:
352 if (is_int() && v2.is_int())
353 set_int(get_int() & v2.get_int());
354 else
355 set_bool(get_bool() && v2.get_bool());
356 break;
357 case OT_XOR:
358 if (is_int() && v2.is_int())
359 set_int(get_int() ^ v2.get_int());
360 else
361 set_bool(get_bool() ^ v2.get_bool());
362 break;
363 case OT_LSH:
364 set_int(get_int() << v2.get_int());
365 break;
366 case OT_RSH:
367 set_int(get_int() >> v2.get_int());
368 break;
369 case OT_LESS:
370 if (v2.is_list()) {
371 bool found = false;
372 for (unsigned int i = 0; i < v2.get_size(); ++i) {
373 variant tmp(*this);
374 if (tmp.is_binary_applicable(OT_EQUAL, v2.get_element(i))) {
375 tmp.apply_binary(OT_EQUAL, v2.get_element(i));
376 if (tmp.get_bool()) {
377 found = true;
378 break;
379 }
380 }
381 }
382 set_bool(found);
383 }
384 else {
385 switch (get_value_type()) {
386 case BOOL_VALUE:
387 case INT_VALUE:
388 case DOUBLE_VALUE: set_bool(get_double() < v2.get_double()); break;
389 case STRING_VALUE: set_bool(get_str() < v2.get_str()); break;
390 default: break;
391 }
392 }
393 break;
394 case OT_GREATER:
395 switch (get_value_type()) {
396 case BOOL_VALUE:
397 case INT_VALUE:
398 case DOUBLE_VALUE: set_bool(get_double() > v2.get_double()); break;
399 case STRING_VALUE: set_bool(get_str() > v2.get_str()); break;
400 default: break;
401 }
402 break;
403 case OT_LESS_OR_EQUAL:
404 switch (get_value_type()) {
405 case BOOL_VALUE:
406 case INT_VALUE:
407 case DOUBLE_VALUE: set_bool(get_double() <= v2.get_double()); break;
408 case STRING_VALUE: set_bool(get_str() <= v2.get_str()); break;
409 default: break;
410 }
411 break;
412 case OT_GREATER_OR_EQUAL:
413 switch (get_value_type()) {
414 case BOOL_VALUE:
415 case INT_VALUE:
416 case DOUBLE_VALUE: set_bool(get_double() >= v2.get_double()); break;
417 case STRING_VALUE: set_bool(get_str() >= v2.get_str()); break;
418 default: break;
419 }
420 break;
421 case OT_EQUAL:
422 switch (get_value_type()) {
423 case BOOL_VALUE:
424 case INT_VALUE:
425 case DOUBLE_VALUE: set_bool(get_double() == v2.get_double()); break;
426 case STRING_VALUE: set_bool(get_str() == v2.get_str()); break;
427 default: break;
428 }
429 break;
430 case OT_UNEQUAL:
431 switch (get_value_type()) {
432 case BOOL_VALUE:
433 case INT_VALUE:
434 case DOUBLE_VALUE: set_bool(get_double() != v2.get_double()); break;
435 case STRING_VALUE: set_bool(get_str() != v2.get_str()); break;
436 default: break;
437 }
438 break;
439 case OT_EQUAL_TYPE:
440 set_bool(get_value_type() == v2.get_value_type());
441 break;
442 case OT_UNEQUAL_TYPE:
443 set_bool(get_value_type() != v2.get_value_type());
444 break;
445 case OT_ADD:
446 if (is_str()) {
447 if (v2.is_str()) {
448 std::size_t p = get_str().find_first_of(v2.get_str());
449 if (p != std::string::npos)
450 set_str(get_str().substr(p));
451 }
452 else {
453 int idx = v2.get_int();
454 if (idx >= (int)get_str().size())
455 set_str("");
456 else
457 set_str(get_str().substr(v2.get_int()));
458 }
459 }
460 else if (is_list()) {
461 int idx = v2.get_int();
462 if (idx >= (int)get_size())
463 set_list();
464 else {
465 std::vector<variant> l = get_list();
466 l.erase(l.begin(), l.begin() + idx);
467 set_list(l);
468 }
469 }
470 else {
471 if (is_double() || v2.is_double())
472 set_double(get_double() + v2.get_double());
473 else
474 set_int(get_int() + v2.get_int());
475 }
476 break;
477 case OT_SUB:
478 if (is_str()) {
479 if (v2.is_str()) {
480 std::size_t p = get_str().find_last_of(v2.get_str());
481 if (p != std::string::npos)
482 set_str(get_str().substr(0, p));
483 }
484 else {
485 int idx = v2.get_int();
486 if (idx >= (int)get_str().size())
487 set_str("");
488 else
489 set_str(get_str().substr(0, get_str().size() - idx));
490 }
491 }
492 else if (is_list()) {
493 int idx = v2.get_int();
494 if (idx >= (int)get_size())
495 set_list();
496 else {
497 std::vector<variant> l = get_list();
498 for (int i = 0; i < idx; ++i)
499 l.pop_back();
500 set_list(l);
501 }
502 }
503 else {
504 if (is_double() || v2.is_double())
505 set_double(get_double() - v2.get_double());
506 else
507 set_int(get_int() - v2.get_int());
508 }
509 break;
510 case OT_MUL:
511 if (is_str()) {
512 std::string arg = v2.get_str();
513 if (arg.size() > 3) {
514 std::vector<token> toks;
515 tokenizer(arg).set_ws(arg.substr(0, 1)).bite_all(toks);
516 if (toks.size() > 0) {
517 std::string s1 = to_string(toks[0]);
518 std::string s2;
519 if (toks.size() > 1)
520 s2 = to_string(toks[1]);
521 std::string s = get_str();
522 replace(s, s1, s2);
523 /*
524 std::cout << "replace('" << get_str().c_str()
525 << "', '" << s1.c_str() << "', "
526 << s2.c_str() << "') ==> " << s.c_str() << std::endl;*/
527 set_str(s);
528 }
529 }
530 }
531 else {
532 if (is_double() || v2.is_double())
533 set_double(get_double() * v2.get_double());
534 else
535 set_int(get_int() * v2.get_int());
536 }
537 break;
538 case OT_DIV:
539 if (is_double() || v2.is_double())
540 set_double(get_double() / v2.get_double());
541 else
542 set_int(get_int() / v2.get_int());
543 break;
544 case OT_MOD:
545 set_int(get_int() % v2.get_int());
546 break;
547 case OT_DOT:
548 if (is_map()) {
549 if (v2.is_list()) {
550 map_type m = get_map();
551 list_type l = v2.get_list();
552 if (l.size() > 0) {
553 if (!l[0].is_list()) {
554 if (l.size() == 2) {
555 m[l[0].get_str()] = l[1].get_value();
556 }
557 }
558 else {
559 for (unsigned int i = 0; i < l.size(); ++i) {
560 if (l[i].is_list()) {
561 if (l[i].get_size() == 2) {
562 m[l[i].ref_element((unsigned int)0).get_str()] = l[i].get_element((unsigned int)1).get_value();
563 }
564 }
565 }
566 }
567 }
568 set_map(m);
569 }
570 }
571 else if (!is_list())
572 if (!v2.is_list())
573 set_str(get_str() + v2.get_str());
574 else {
575 // prepend
576 list_type l = v2.get_list();
577 l.insert(l.begin(), get_value());
578 set_list(l);
579 }
580 else
581 if (v2.is_list()) {
582 // concat lists
583 std::vector<variant> l = get_list();
584 unsigned int n = v2.get_size();
585 for (unsigned int i = 0; i < n; ++i)
586 l.push_back(v2.get_element(i).get_value());
587 set_list(l);
588 }
589 else {
590 // append to list
591 std::vector<variant> l = get_list();
592 l.push_back(v2.get_value());
593 set_list(l);
594 }
595 break;
596 case OT_BINARY_MAP:
597 if (is_reference()) {
598 if (v2.is_name())
599 *this = variant(&ref_element(v2.get_name()));
600 else
601 *this = variant(&ref_element(v2.get_str()));
602 }
603 else {
604 variant tmp;
605 if (v2.is_name())
606 tmp = get_element(v2.get_name());
607 else
608 tmp = get_element(v2.get_str());
609 *this = tmp;
610 }
611 break;
612 default: break;
613 }
614 }
615
616
617 ValueType variant::get_type() const
618 {
619 return vt;
620 }
621
622 ValueType variant::get_value_type() const
623 {
624 if (get_type() == REFERENCE_VALUE)
625 return reference_value->get_value_type();
626 if (get_type() == NAME_VALUE) {
627 variant* v = find_variable(get_name());
628 if (v)
629 return v->get_value_type();
630 else
631 return UNDEF_VALUE;
632 }
633 return get_type();
634 }
635
637 {
638 return get_value_type() == UNDEF_VALUE;
639 }
640
641 bool variant::is_bool() const
642 {
643 return get_value_type() == BOOL_VALUE;
644 }
645
646 bool variant::is_int() const
647 {
648 return get_value_type() == INT_VALUE;
649 }
650
652 {
653 return get_value_type() == DOUBLE_VALUE;
654 }
655
656 bool variant::is_str() const
657 {
658 return get_value_type() == STRING_VALUE;
659 }
660
661 bool variant::is_list() const
662 {
663 return get_value_type() == LIST_VALUE;
664 }
665
666 bool variant::is_map() const
667 {
668 return get_value_type() == MAP_VALUE;
669 }
670
672 bool variant::is_func() const
673 {
674 return get_value_type() == FUNC_VALUE;
675 }
676
677
679 {
680 return get_type() == REFERENCE_VALUE || get_type() == NAME_VALUE;
681 }
682
683 bool variant::is_name() const
684 {
685 return get_type() == NAME_VALUE;
686 }
687
688
689 bool variant::get_bool() const
690 {
691 switch (get_value_type()) {
692 case UNDEF_VALUE:
693 return false;
694 case BOOL_VALUE:
695 return get_value().bool_value;
696 case INT_VALUE:
697 return get_value().int_value != 0;
698 case DOUBLE_VALUE:
699 return get_value().dbl_value != 0;
700 case STRING_VALUE:
701 return get_str().size() != 0;
702 case LIST_VALUE:
703 case MAP_VALUE:
704 return get_value().get_size() > 0;
705 default: break;
706 }
707 return false;
708 }
709
711 {
712 switch (get_value_type()) {
713 case UNDEF_VALUE:
714 return -1;
715 case BOOL_VALUE:
716 return get_value().bool_value ? 1 : 0;
717 case INT_VALUE:
718 return get_value().int_value;
719 case DOUBLE_VALUE:
720 return (int)get_value().dbl_value;
721 case STRING_VALUE:
722 return atoi(get_str().c_str());
723 case LIST_VALUE:
724 case MAP_VALUE:
725 return get_value().get_size();
726 default: break;
727 }
728 return 0;
729 }
730
731 double variant::get_double() const
732 {
733 switch (get_value_type()) {
734 case UNDEF_VALUE:
735 return -1;
736 case BOOL_VALUE:
737 return get_value().bool_value ? 1.0 : 0.0;
738 case INT_VALUE:
739 return get_value().int_value;
740 case DOUBLE_VALUE:
741 return get_value().dbl_value;
742 case STRING_VALUE:
743 return atof(get_str().c_str());
744 case LIST_VALUE:
745 case MAP_VALUE:
746 return get_value().get_size();
747 default: break;
748 }
749 return 0;
750 }
751
752 std::string variant::get_str() const
753 {
754 switch (get_value_type()) {
755 case UNDEF_VALUE:
756 return "UNDEFINED";
757 case BOOL_VALUE:
758 return to_string(get_value().bool_value);
759 case INT_VALUE:
760 return to_string(get_value().int_value);
761 case DOUBLE_VALUE:
762 return to_string(get_value().dbl_value);
763 case STRING_VALUE:
764 return *get_value().string_value;
765 case LIST_VALUE:
766 case MAP_VALUE:
767 {
768 const variant& v = get_value();
769 std::string s("[");
770 for (unsigned int i = 0; i < v.get_size(); ++i) {
771 if (i > 0)
772 s = s + ",";
773 if (v.get_type() == MAP_VALUE)
774 s = s + v.get_element_name(i) + "::";
775 s = s + v.get_element(i).get_str();
776 }
777 s = s + "]";
778 return s;
779 }
780 }
781 return "";
782 }
783
784 const std::string& variant::get_name() const
785 {
786 if (get_type() == NAME_VALUE)
787 return *name_value;
788 std::cerr << "attemt to access name of non name variant value" << std::endl;
789 static std::string dummy;
790 return dummy;
791 }
792
793 void variant::set_bool(bool v)
794 {
795 *this = variant(v);
796 }
797
798 void variant::set_int(int v)
799 {
800 *this = variant(v);
801 }
802
803 void variant::set_double(double v)
804 {
805 *this = variant(v);
806 }
807
808 void variant::set_str(const std::string& v)
809 {
810 *this = variant(v);
811 }
812
813 void variant::set_name(const std::string& v)
814 {
815 *this = variant(NAME_VALUE, v);
816 }
817
818 void variant::set_list()
819 {
820 *this = variant(list_type());
821 }
822
823 void variant::set_list(const list_type& l)
824 {
825 *this = variant(l);
826 }
827
828 void variant::set_map()
829 {
830 *this = variant(map_type());
831 }
832
833 void variant::set_map(const map_type& m)
834 {
835 *this = variant(m);
836 }
837
838
840 {
841 return reference_value;
842 }
843
844
845 const variant::list_type& variant::get_list() const
846 {
847 return *get_value().list_value;
848 }
849
850
851 bool& variant::ref_bool()
852 {
853 return ref_value().bool_value;
854 }
855
856 int& variant::ref_int()
857 {
858 return ref_value().int_value;
859 }
860
861 double& variant::ref_double()
862 {
863 return ref_value().dbl_value;
864 }
865
866 std::string& variant::ref_str()
867 {
868 return *ref_value().string_value;
869 }
870
871 variant::list_type& variant::ref_list()
872 {
873 return *ref_value().list_value;
874 }
875
876 const variant::map_type& variant::get_map() const
877 {
878 return *get_value().map_value;
879 }
880
883 {
884 ref_value().set_int(get_int());
885 }
886
889 {
890 ValueType vt = get_type();
891 if (vt == DOUBLE_VALUE || v2.get_type() == DOUBLE_VALUE) {
892 if (vt != DOUBLE_VALUE)
893 ref_value().set_double(get_double());
894 return false;
895 }
896 if (vt != INT_VALUE)
898 return true;
899 }
900
901 variant::map_type& variant::ref_map()
902 {
903 return *ref_value().map_value;
904 }
905
908 {
909 return *ref_value().func_value;
910 }
911
912
914 {
915 if (get_type() == REFERENCE_VALUE)
916 return reference_value->get_value();
917 if (get_type() == NAME_VALUE)
918 return ref_variable(get_name()).get_value();
919 return *this;
920 }
921
923 {
924 if (get_type() == REFERENCE_VALUE)
925 return reference_value->ref_value();
926 if (get_type() == NAME_VALUE)
927 return ref_variable(get_name()).ref_value();
928 return *this;
929 }
930
931 unsigned int variant::get_size() const
932 {
933 switch (get_value_type()) {
934 case STRING_VALUE: return (unsigned int)get_value().string_value->size();
935 case LIST_VALUE: return (unsigned int)get_list().size();
936 case MAP_VALUE: return (unsigned int)get_map().size();
937 default: break;
938 }
939 return 1;
940 }
941
944 {
945 switch (get_value_type()) {
946 case LIST_VALUE:
947 {
948 const list_type& L = get_list();
949 unsigned N = 0, n = (unsigned)L.size();
950 for (unsigned i = 0; i < n; ++i)
951 N += L[i].get_total_nr_elements();
952 return N;
953 }
954 case MAP_VALUE:
955 {
956 const map_type& M = get_map();
957 unsigned N = 0;
958 for (map_type::const_iterator i = M.begin(); i != M.end(); ++i)
959 N += i->second.get_total_nr_elements();
960 return N;
961 }
962 default: break;
963 }
964 return 1;
965 }
966
967
969 {
970 if (get_value_type() == MAP_VALUE) {
971 map_type::iterator mi = ref_map().begin();
972 for (unsigned int j = 0; j < i; ++j)
973 ++mi;
974 return mi->second;
975 }
976 return ref_list()[i];
977 }
978
979 const variant& variant::get_element(unsigned int i) const
980 {
981 if (get_value_type() == MAP_VALUE) {
982 map_type::const_iterator mi = get_map().begin();
983 for (unsigned int j = 0; j < i; ++j)
984 ++mi;
985 return mi->second;
986 }
987 return get_list()[i];
988 }
989
990 void variant::append_to_list(const variant& v)
991 {
992 ref_list().push_back(v);
993 }
994
995 void variant::prepend_to_list(const variant& v)
996 {
997 ref_list().insert(ref_list().begin(), v);
998 }
999
1000 void variant::pop_back_from_list()
1001 {
1002 ref_list().pop_back();
1003 }
1004
1005 void variant::pop_front_from_list()
1006 {
1007 ref_list().erase(ref_list().begin());
1008 }
1009
1010 const variant& variant::get_element(const std::string& name)
1011 {
1012 if (get_value_type() == MAP_VALUE)
1013 return ref_map()[name];
1014 std::cerr << "attemt to get_element of non map variant by name" << std::endl;
1015 static variant dummy;
1016 return dummy;
1017 }
1018
1019 variant& variant::ref_element(const std::string& name)
1020 {
1021 if (get_value_type() == MAP_VALUE) {
1022 map_type& M = ref_map();
1023 return M[name];
1024 }
1025 std::cerr << "attemt to ref_element of non map variant by name" << std::endl;
1026 static variant dummy;
1027 return dummy;
1028 }
1029
1030
1031 const std::string& variant::get_element_name(unsigned int i) const
1032 {
1033 map_type::const_iterator mi = get_map().begin();
1034 for (unsigned int j = 0; j < i; ++j)
1035 ++mi;
1036 return mi->first;
1037 }
1038
1039 void variant::insert(const std::string& name, const variant& v)
1040 {
1041 ref_map()[name] = v;
1042 }
1043
1044
1045 std::ostream& operator << (std::ostream& os, const variant& v)
1046 {
1047 static unsigned tab = 0;
1048 switch (v.get_type()) {
1049 case UNDEF_VALUE:
1050 return os << ">UNDEF<";
1051 case REFERENCE_VALUE:
1052 return os << "*" << *v.get_reference();
1053 case NAME_VALUE:
1054 return os << "<" << v.get_name() << ">";
1055 case LIST_VALUE:
1056 case MAP_VALUE:
1057 {
1058 unsigned int n = v.get_size();
1059 unsigned N = v.get_total_nr_elements();
1060 os << '[';
1061 if (N > 5)
1062 tab += 2;
1063 for (unsigned int i = 0; i < n; ++i) {
1064 if (i > 0)
1065 os << ", ";
1066 if (N > 5)
1067 os << "\n" << std::string(tab, ' ');
1068 if (v.get_type() == MAP_VALUE)
1069 os << v.get_element_name(i) << "=";
1070 os << v.get_element(i);
1071 }
1072 if (N > 5) {
1073 tab -= 2;
1074 os << "\n" << std::string(tab, ' ');
1075 }
1076 return os << ']';
1077 }
1078 default:
1079 return os << v.get_str().c_str();
1080 }
1081 }
1082
1083 }
1084}
std::string get_str() const
lookup names and follow references and convert to string
ValueType get_value_type() const
lookup names and follow references and return value type
unsigned get_total_nr_elements() const
return total number of elements in a list or map summing over all elements recursively
const map_type & get_map() const
constant access to map value
const variant & get_value() const
lookup names and follow references and return the reached variant
double get_double() const
lookup names and follow references and convert to double: undef ... -1, bool ... 0 or 1,...
variant()
construct undefined value
const std::string & get_element_name(unsigned int i) const
return the name of the i-th element in a map
bool is_int() const
lookup names and follow references and return whether variant is int
const list_type & get_list() const
constant access to list value
int get_int() const
lookup names and follow references and convert to int: undef ... -1, bool ... 0 or 1,...
ValueType get_type() const
return the variant type
const std::string & get_name() const
return the name of a name value
ValueType vt
store type of value
Definition variant.h:36
~variant()
destructor
func_type & ref_func()
access to func value
variant & operator=(const variant &v)
assignment operator
bool is_reference() const
name and reference type return true
unsigned int get_size() const
return number of elements in a list or map
variant & ref_element(unsigned int i)
return a reference to the i-th element in a list or map
bool is_name() const
only a name returns true
bool is_func() const
lookup names and follow references and return whether variant is func
variant * get_reference() const
return the pointer of a reference
bool get_bool() const
lookup names and follow references and convert to bool: undef ... false, int ... compares unequal zer...
bool is_bool() const
lookup names and follow references and return whether variant is bool
void ensure_int_type()
convert to int type
bool is_undefined() const
lookup names and follow references and return whether variant is undefined
variant & ref_value()
lookup names and follow references and return reference to the reached variant
void insert(const std::string &name, const variant &v)
insert a new entry to the map
bool match_number_type(const variant &v2)
convert to int or double such that result of binary operators can be stored in this variant without l...
const variant & get_element(unsigned int i) const
return a const reference to the i-th element in a list or map
bool is_list() const
lookup names and follow references and return whether variant is list
bool is_str() const
lookup names and follow references and return whether variant is string
bool is_double() const
lookup names and follow references and return whether variant is double
bool is_map() const
lookup names and follow references and return whether variant is map
void clear()
remove all elements from a list or map and set to undefined type
the tokenizer allows to split text into tokens in a convenient way.
Definition tokenizer.h:68
tokenizer & set_ws(const std::string &ws)
set the list of white spaces, that separate tokens and are skipped
Definition tokenizer.cxx:38
namespace that holds tools that dont fit any other namespace
unsigned int replace(std::string &s, char c1, char c2)
replace char c1 with c2 in the given string _s and return number of replacements
Definition scan.cxx:159
std::string to_string(const std::string &v, unsigned int w, unsigned int p, bool)
specialization of conversion from string to strings
char to_upper(char c)
convert char to upper case
Definition scan.cxx:106
the cgv namespace
Definition print.h:11
Helper functions to process strings.