The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
variant.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2016 by David White <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "global.hpp"
16 
17 #include <cmath>
18 #include <iostream>
19 #include <string.h>
20 
21 #include <boost/lexical_cast.hpp>
22 
23 #include "formatter.hpp"
24 #include "formula/callable.hpp"
25 #include "formula/function.hpp"
26 #include "util.hpp"
27 
28 namespace {
29 std::string variant_type_to_string(variant::TYPE type) {
30  switch(type) {
31  case variant::TYPE_NULL:
32  return "null";
33  case variant::TYPE_INT:
34  return "integer";
36  return "decimal";
38  return "object";
39  case variant::TYPE_LIST:
40  return "list";
42  return "string";
43  case variant::TYPE_MAP:
44  return "map";
45  default:
46  assert(false);
47  return "invalid";
48  }
49 }
50 
51 std::vector<const char*> call_stack;
52 }
53 
54 void push_call_stack(const char* str)
55 {
56  call_stack.push_back(str);
57 }
58 
60 {
61  call_stack.pop_back();
62 }
63 
65 {
67  for(std::vector<const char*>::const_iterator i = call_stack.begin();
68  i != call_stack.end(); ++i) {
69  if(!*i) {
70  continue;
71  }
72  res += " ";
73  res += *i;
74  res += "\n";
75  }
76  return res;
77 }
78 
80  std::cerr << "ERROR: " << message << "\n" << get_call_stack();
81 }
82 
84  : type_(TYPE_NULL)
85  , list_iterator_()
86  , map_iterator_()
87 {
88 }
89 
91  : type_(iter.type_)
92  , list_iterator_()
93  , map_iterator_()
94 {
95  switch(type_) {
96  case TYPE_LIST :
98  break;
99 
100  case TYPE_MAP:
102  break;
103 
104  case TYPE_NULL:
105  /* DO NOTHING */
106  break;
107  }
108 }
109 
111  const std::vector<variant>::iterator& iter)
112  : type_(TYPE_LIST)
113  , list_iterator_(iter)
114  , map_iterator_()
115 {
116 }
117 
120  : type_(TYPE_MAP)
121  , list_iterator_()
122  , map_iterator_(iter)
123 {
124 }
125 
127 {
128  if (type_ == TYPE_LIST)
129  {
130  return variant( *list_iterator_);
131  } else if (type_ == TYPE_MAP)
132  {
134  variant res( p );
135  return res;
136  } else
137  return variant();
138 }
139 
141 {
142  if (type_ == TYPE_LIST)
143  {
144  ++list_iterator_;
145  } else if (type_ == TYPE_MAP)
146  {
147  ++map_iterator_;
148  }
149 
150  return *this;
151 }
152 
154 {
155  variant_iterator iter(*this);
156  if (type_ == TYPE_LIST)
157  {
158  ++list_iterator_;
159  } else if (type_ == TYPE_MAP)
160  {
161  ++map_iterator_;
162  }
163 
164  return iter;
165 }
166 
168 {
169  if (type_ == TYPE_LIST)
170  {
171  --list_iterator_;
172  } else if (type_ == TYPE_MAP)
173  {
174  --map_iterator_;
175  }
176 
177  return *this;
178 }
179 
181 {
182  variant_iterator iter(*this);
183  if (type_ == TYPE_LIST)
184  {
185  --list_iterator_;
186  } else if (type_ == TYPE_MAP)
187  {
188  --map_iterator_;
189  }
190 
191  return iter;
192 }
193 
195 {
196  if (this == &that)
197  return *this;
198  type_ = that.type_;
199  switch(type_) {
200  case TYPE_LIST :
202  break;
203 
204  case TYPE_MAP:
206  break;
207 
208  case TYPE_NULL:
209  /* DO NOTHING */
210  break;
211  }
212 
213  return *this;
214 }
215 
217 {
218  if (type_ == TYPE_LIST)
219  {
220  if (that.type_ != TYPE_LIST)
221  return false;
222  return list_iterator_ == that.list_iterator_;
223  } else if (type_ == TYPE_MAP)
224  {
225  if (that.type_ != TYPE_MAP)
226  return false;
227  return map_iterator_ == that.map_iterator_;
228  } else if (type_ == TYPE_NULL && that.type_ == TYPE_NULL )
229  return true;
230  else
231  return false;
232 }
233 
235 {
236  if (type_ == TYPE_LIST)
237  {
238  if (that.type_ != TYPE_LIST)
239  return true;
240  return list_iterator_ != that.list_iterator_;
241  } else if (type_ == TYPE_MAP)
242  {
243  if (that.type_ != TYPE_MAP)
244  return true;
245  return map_iterator_ != that.map_iterator_;
246  } else if (type_ == TYPE_NULL && that.type_ == TYPE_NULL )
247  return false;
248  else
249  return true;
250 }
251 
252 struct variant_list {
254  : elements()
255  , refcount(0)
256  {
257  }
258 
259  std::vector<variant> elements;
260  int refcount;
261 };
262 
265  : str()
266  , refcount(0)
267  {
268  }
269 
271  int refcount;
272 };
273 
274 struct variant_map {
276  : elements()
277  , refcount(0)
278  {
279  }
280 
281  std::map<variant,variant> elements;
282  int refcount;
283 };
284 
286 {
287  switch(type_) {
288  case TYPE_LIST:
289  ++list_->refcount;
290  break;
291  case TYPE_STRING:
292  ++string_->refcount;
293  break;
294  case TYPE_MAP:
295  ++map_->refcount;
296  break;
297  case TYPE_CALLABLE:
299  break;
300 
301  // These are not used here, add them to silence a compiler warning.
302  case TYPE_NULL:
303  case TYPE_DECIMAL:
304  case TYPE_INT :
305  break;
306  }
307 }
308 
310 {
311  switch(type_) {
312  case TYPE_LIST:
313  if(--list_->refcount == 0) {
314  delete list_;
315  }
316  break;
317  case TYPE_STRING:
318  if(--string_->refcount == 0) {
319  delete string_;
320  }
321  break;
322  case TYPE_MAP:
323  if(--map_->refcount == 0) {
324  delete map_;
325  }
326  break;
327  case TYPE_CALLABLE:
329  break;
330 
331  // These are not used here, add them to silence a compiler warning.
332  case TYPE_NULL:
333  case TYPE_DECIMAL:
334  case TYPE_INT :
335  break;
336  }
337 }
338 
340  return variant_type_to_string(type_);
341 }
342 
343 variant::variant() : type_(TYPE_NULL), int_value_(0)
344 {}
345 
346 variant::variant(int n) : type_(TYPE_INT), int_value_(n)
347 {}
348 
349 variant::variant(int n, variant::DECIMAL_VARIANT_TYPE /*type*/) : type_(TYPE_DECIMAL), decimal_value_(n)
350 {}
351 
352 variant::variant(double n, variant::DECIMAL_VARIANT_TYPE /*type*/) : type_(TYPE_DECIMAL) {
353  n *= 1000;
354  decimal_value_ = static_cast<int>(n);
355 
356  n -= decimal_value_;
357 
358  if(n > 0.5)
359  decimal_value_++;
360  else if(n < -0.5)
361  decimal_value_--;
362 }
363 
365  : type_(TYPE_CALLABLE), callable_(callable)
366 {
367  assert(callable_);
369 }
370 
371 variant::variant(std::vector<variant>* array)
372  : type_(TYPE_LIST)
373 {
374  assert(array);
375  list_ = new variant_list;
376  list_->elements.swap(*array);
378 }
379 
381  : type_(TYPE_STRING)
382 {
383  string_ = new variant_string;
384  string_->str = str;
386 }
387 
388 variant::variant(std::map<variant,variant>* map)
389  : type_(TYPE_MAP)
390 {
391  assert(map);
392  map_ = new variant_map;
393  map_->elements.swap(*map);
395 }
396 
398  : type_(v.type_)
399 {
400  memcpy(this, &v, sizeof(v));
402 }
403 
405 {
406  release();
407 }
408 
410 {
411  if(&v != this) {
412  release();
413  memcpy(this, &v, sizeof(v));
415  }
416  return *this;
417 }
418 
420 {
421  if(type_ == TYPE_CALLABLE) {
422  return *this;
423  }
424 
426  assert(list_);
427  if(n >= list_->elements.size()) {
428  throw type_error("invalid index");
429  }
430 
431  return list_->elements[n];
432 }
433 
435 {
436  if(type_ == TYPE_CALLABLE) {
437  return *this;
438  }
439 
440  if(type_ == TYPE_MAP) {
441  assert(map_);
442  std::map<variant,variant>::const_iterator i = map_->elements.find(v);
443  if (i == map_->elements.end())
444  {
445  static variant null_variant;
446  return null_variant;
447  }
448  return i->second;
449  } else if(type_ == TYPE_LIST) {
450  if(v.is_list()) {
451  std::vector<variant> slice;
452 
453  for(size_t i = 0; i < v.num_elements(); ++i) {
454  slice.push_back( (*this)[v[i]] );
455  }
456  return variant(&slice);
457  } else if(v.as_int() < 0) {
458  return operator[](num_elements() + v.as_int());
459  }
460  return operator[](v.as_int());
461  } else {
462  throw type_error((formatter() << "type error: "
463  << " expected a list or a map but found " << type_string()
464  << " (" << to_debug_string() << ")").str());
465  }
466 }
467 
469 {
470  must_be(TYPE_MAP);
471  assert(map_);
472  std::vector<variant> tmp;
473  for(std::map<variant,variant>::const_iterator i=map_->elements.begin(); i != map_->elements.end(); ++i) {
474  tmp.push_back(i->first);
475  }
476  return variant(&tmp);
477 }
478 
480 {
481  must_be(TYPE_MAP);
482  assert(map_);
483  std::vector<variant> tmp;
484  for(std::map<variant,variant>::const_iterator i=map_->elements.begin(); i != map_->elements.end(); ++i) {
485  tmp.push_back(i->second);
486  }
487  return variant(&tmp);
488 }
489 
491 {
492  if(type_ == TYPE_LIST)
493  return variant_iterator( list_->elements.begin() );
494 
495  if(type_ == TYPE_MAP)
496  return variant_iterator( map_->elements.begin() );
497 
498  return variant_iterator();
499 }
501 {
502  if(type_ == TYPE_LIST)
503  return variant_iterator( list_->elements.end() );
504 
505  if(type_ == TYPE_MAP)
506  return variant_iterator( map_->elements.end() );
507 
508  return variant_iterator();
509 }
510 
511 bool variant::is_empty() const
512 {
513  if(type_ == TYPE_NULL) {
514  return true;
515  } else if (type_ == TYPE_LIST) {
516  assert(list_);
517  return list_->elements.empty();
518  } else if (type_ == TYPE_MAP) {
519  assert(map_);
520  return map_->elements.empty();
521  }
522 
523  return false;
524 }
525 
526 size_t variant::num_elements() const
527 {
528  if(type_ == TYPE_CALLABLE) {
529  return 1;
530  }
531 
532  if (type_ == TYPE_LIST) {
533  assert(list_);
534  return list_->elements.size();
535  } else if (type_ == TYPE_MAP) {
536  assert(map_);
537  return map_->elements.size();
538  } else {
539  throw type_error((formatter() << "type error: "
540  << " expected a list or a map but found " << type_string()
541  << " (" << to_debug_string() << ")").str());
542  }
543 }
544 
546 {
547  if(is_callable()) {
548  return callable_->query_value(str);
549  }
550 
551  if(str == "self") {
552  return *this;
553  } else {
554  return variant();
555  }
556 }
557 
558 int variant::as_int() const {
559  if(type_ == TYPE_NULL) { return 0; }
560  if(type_ == TYPE_DECIMAL) { return as_decimal() / 1000; }
561  must_be(TYPE_INT);
562  return int_value_;
563 }
564 
566 {
567  if( type_ == TYPE_DECIMAL) {
568  return decimal_value_;
569  } else if( type_ == TYPE_INT ) {
570  return int_value_*1000;
571  } else if( type_ == TYPE_NULL) {
572  return 0;
573  } else {
574  throw type_error((formatter() << "type error: "
575  << " expected integer or decimal but found " << type_string()
576  << " (" << to_debug_string() << ")").str());
577  }
578 }
579 
580 bool variant::as_bool() const
581 {
582  switch(type_) {
583  case TYPE_NULL:
584  return false;
585  case TYPE_INT:
586  return int_value_ != 0;
587  case TYPE_DECIMAL:
588  return decimal_value_ != 0;
589  case TYPE_CALLABLE:
590  return callable_ != nullptr;
591  case TYPE_LIST:
592  return !list_->elements.empty();
593  case TYPE_MAP:
594  return !map_->elements.empty();
595  case TYPE_STRING:
596  return !string_->str.empty();
597  default:
598  assert(false);
599  return false;
600  }
601 }
602 
604 {
606  assert(string_);
607  return string_->str;
608 }
609 
610 const std::vector<variant>& variant::as_list() const
611 {
613  assert(list_);
614  return list_->elements;
615 }
616 
617 const std::map<variant,variant>& variant::as_map() const
618 {
619  must_be(TYPE_MAP);
620  assert(map_);
621  return map_->elements;
622 }
623 
625 {
626  if(type_ == TYPE_LIST) {
627  if(v.type_ == TYPE_LIST) {
628  std::vector<variant> res;
629  res.reserve(list_->elements.size() + v.list_->elements.size());
630  for(size_t i = 0; i<list_->elements.size(); ++i) {
631  const variant& var = list_->elements[i];
632  res.push_back(var);
633  }
634 
635  for(size_t j = 0; j<v.list_->elements.size(); ++j) {
636  const variant& var = v.list_->elements[j];
637  res.push_back(var);
638  }
639 
640  return variant(&res);
641  }
642  }
643  if(type_ == TYPE_MAP) {
644  if(v.type_ == TYPE_MAP) {
645  std::map<variant,variant> res(map_->elements);
646 
647  for(std::map<variant,variant>::const_iterator i = v.map_->elements.begin(); i != v.map_->elements.end(); ++i) {
648  res[i->first] = i->second;
649  }
650 
651  return variant(&res);
652  }
653  }
654  if(type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL) {
655  return variant( as_decimal() + v.as_decimal() , DECIMAL_VARIANT);
656  }
657 
658  return variant(as_int() + v.as_int());
659 }
660 
662 {
663  if(type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL) {
664  return variant( as_decimal() - v.as_decimal() , DECIMAL_VARIANT);
665  }
666 
667  return variant(as_int() - v.as_int());
668 }
669 
671 {
672  if(type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL) {
673 
674  long long long_int = as_decimal();
675 
676  long_int *= v.as_decimal();
677 
678  long_int /= 100;
679 
680  if( long_int%10 >= 5) {
681  long_int /= 10;
682  ++long_int;
683  } else
684  long_int/=10;
685 
686  return variant( static_cast<int>(long_int) , variant::DECIMAL_VARIANT );
687  }
688 
689  return variant(as_int() * v.as_int());
690 }
691 
693 {
694  if(type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL) {
695  int denominator = v.as_decimal();
696 
697  if(denominator == 0) {
698  throw type_error((formatter() << "divide by zero error").str());
699  }
700 
701  long long long_int = as_decimal();
702 
703  long_int *= 10000;
704 
705  long_int /= denominator;
706 
707  if( long_int%10 >= 5) {
708  long_int /= 10;
709  ++long_int;
710  } else
711  long_int/=10;
712 
713  return variant( static_cast<int>(long_int) , variant::DECIMAL_VARIANT);
714  }
715 
716 
717  const int numerator = as_int();
718  const int denominator = v.as_int();
719  if(denominator == 0) {
720  throw type_error((formatter() << "divide by zero error").str());;
721  }
722 
723  return variant(numerator/denominator);
724 }
725 
727 {
728  if(type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL) {
729  const int numerator = as_decimal();
730  const int denominator = v.as_decimal();
731  if(denominator == 0) {
732  throw type_error((formatter() << "divide by zero error").str());
733  }
734 
735  return variant(numerator%denominator, DECIMAL_VARIANT);
736  } else {
737  const int numerator = as_int();
738  const int denominator = v.as_int();
739  if(denominator == 0) {
740  throw type_error((formatter() << "divide by zero error").str());
741  }
742 
743  return variant(numerator%denominator);
744  }
745 }
746 
747 
749 {
750  if( type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL ) {
751 
752  double res = pow( as_decimal()/1000.0 , v.as_decimal()/1000.0 );
753 
754  if(res != res) return variant();
755 
756  return variant(res, DECIMAL_VARIANT);
757  }
758 
759  return variant(static_cast<int>(
760  round_portable(pow(static_cast<double>(as_int()), v.as_int()))));
761 }
762 
764 {
765  if( type_ == TYPE_DECIMAL)
767 
768  return variant(-as_int());
769 }
770 
771 bool variant::operator==(const variant& v) const
772 {
773  if(type_ != v.type_) {
774  if( type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL ) {
775  return as_decimal() == v.as_decimal();
776  }
777 
778  return false;
779  }
780 
781  switch(type_) {
782  case TYPE_NULL: {
783  return v.is_null();
784  }
785 
786  case TYPE_STRING: {
787  return string_->str == v.string_->str;
788  }
789 
790  case TYPE_INT: {
791  return int_value_ == v.int_value_;
792  }
793 
794  case TYPE_DECIMAL: {
795  return decimal_value_ == v.decimal_value_;
796  }
797 
798  case TYPE_LIST: {
799  if(num_elements() != v.num_elements()) {
800  return false;
801  }
802 
803  for(size_t n = 0; n != num_elements(); ++n) {
804  if((*this)[n] != v[n]) {
805  return false;
806  }
807  }
808 
809  return true;
810  }
811 
812  case TYPE_MAP: {
813  return map_->elements == v.map_->elements;
814  }
815 
816  case TYPE_CALLABLE: {
817  return callable_->equals(v.callable_);
818  }
819  }
820 
821  return false;
822 }
823 
824 bool variant::operator!=(const variant& v) const
825 {
826  return !operator==(v);
827 }
828 
829 bool variant::operator<=(const variant& v) const
830 {
831  if(type_ != v.type_) {
832  if(type_ == TYPE_DECIMAL && v.type_ == TYPE_INT) {
833  return as_decimal() <= v.as_decimal();
834  }
835  if(v.type_ == TYPE_DECIMAL && type_ == TYPE_INT) {
836  return as_decimal() <= v.as_decimal();
837  }
838 
839  return type_ < v.type_;
840  }
841 
842  switch(type_) {
843  case TYPE_NULL: {
844  return true;
845  }
846 
847  case TYPE_STRING: {
848  return string_->str <= v.string_->str;
849  }
850 
851  case TYPE_INT: {
852  return int_value_ <= v.int_value_;
853  }
854 
855  case TYPE_DECIMAL: {
856  return decimal_value_ <= v.decimal_value_;
857  }
858 
859  case TYPE_LIST: {
860  for(size_t n = 0; n != num_elements() && n != v.num_elements(); ++n) {
861  if((*this)[n] < v[n]) {
862  return true;
863  } else if((*this)[n] > v[n]) {
864  return false;
865  }
866  }
867 
868  return num_elements() <= v.num_elements();
869  }
870 
871  case TYPE_MAP: {
872  return map_->elements <= v.map_->elements;
873  }
874 
875  case TYPE_CALLABLE: {
876  return !v.callable_->less(callable_);
877  }
878  }
879 
880  assert(false);
881  return false;
882 }
883 
884 bool variant::operator>=(const variant& v) const
885 {
886  return v <= *this;
887 }
888 
889 bool variant::operator<(const variant& v) const
890 {
891  return !(*this >= v);
892 }
893 
894 bool variant::operator>(const variant& v) const
895 {
896  return !(*this <= v);
897 }
898 
900 {
902  v.must_be(TYPE_LIST);
903 
904  if( num_elements() != v.num_elements() )
905  throw type_error("Operator '.+' requires two lists of the same length");
906 
907  std::vector< variant > res;
908  res.reserve(num_elements());
909 
910  for(size_t i = 0; i < num_elements(); ++i) {
911  res.push_back( (*this)[i] + v[i] );
912  }
913 
914  return variant( &res );
915 }
916 
918 {
920  v.must_be(TYPE_LIST);
921 
922  if( num_elements() != v.num_elements() )
923  throw type_error("Operator '.-' requires two lists of the same length");
924 
925  std::vector< variant > res;
926  res.reserve(num_elements());
927 
928  for(size_t i = 0; i < num_elements(); ++i) {
929  res.push_back( (*this)[i] - v[i] );
930  }
931 
932  return variant( &res );
933 }
934 
936 {
938  v.must_be(TYPE_LIST);
939 
940  if( num_elements() != v.num_elements() )
941  throw type_error("Operator '.*' requires two lists of the same length");
942 
943  std::vector< variant > res;
944  res.reserve(num_elements());
945 
946  for(size_t i = 0; i < num_elements(); ++i) {
947  res.push_back( (*this)[i] * v[i] );
948  }
949 
950  return variant( &res );
951 }
952 
954 {
956  v.must_be(TYPE_LIST);
957 
958  if( num_elements() != v.num_elements() )
959  throw type_error("Operator './' requires two lists of the same length");
960 
961  std::vector< variant > res;
962  res.reserve(num_elements());
963 
964  for(size_t i = 0; i < num_elements(); ++i) {
965  res.push_back( (*this)[i] / v[i] );
966  }
967 
968  return variant( &res );
969 }
970 
972 {
973  if(type_ == TYPE_LIST) {
974  v.must_be(TYPE_LIST);
975 
976  std::vector< variant > res;
977  res.reserve(num_elements() + v.num_elements());
978 
979  for(size_t i = 0; i < num_elements(); ++i) {
980  res.push_back( (*this)[i] );
981  }
982 
983  for(size_t i = 0; i < v.num_elements(); ++i) {
984  res.push_back( v[i] );
985  }
986 
987  return variant( &res );
988  } else if(type_ == TYPE_STRING) {
989  v.must_be(TYPE_STRING);
991  return variant( res );
992  } else {
993  throw type_error((formatter() << "type error: expected two "
994  << " lists or two maps but found " << type_string()
995  << " (" << to_debug_string() << ")"
996  << " and " << v.type_string()
997  << " (" << v.to_debug_string() << ")").str());
998  }
999 }
1000 
1002  must_be(TYPE_INT);
1003  v.must_be(TYPE_INT);
1004 
1005  int lhs = as_int(), rhs = v.as_int();
1006  int len = abs(rhs - lhs) + 1;
1007 
1008  std::vector< variant > res;
1009  res.reserve(len);
1010 
1011  for(size_t i = lhs; res.size() != res.capacity(); lhs < rhs ? ++i : --i) {
1012  res.push_back( variant(i) );
1013  }
1014 
1015  return variant( &res );
1016 }
1017 
1018 bool variant::contains(const variant& v) const {
1019  if(type_ != TYPE_LIST && type_ != TYPE_MAP) {
1020  throw type_error((formatter() << "type error: expected "
1021  << variant_type_to_string(TYPE_LIST) << " or "
1022  << variant_type_to_string(TYPE_MAP) << " but found "
1023  << variant_type_to_string(type_)
1024  << " (" << to_debug_string() << ")").str());
1025  }
1026 
1027  if(type_ == TYPE_LIST) {
1028  variant_iterator iter = std::find(begin(), end(), v);
1029  return iter != end();
1030  } else {
1031  std::map<variant,variant>::const_iterator iter = map_->elements.find(v);
1032  return iter != map_->elements.end();
1033  }
1034 }
1035 
1037 {
1038  if(type_ != t) {
1039  throw type_error((formatter() << "type error: " << " expected "
1040  << variant_type_to_string(t) << " but found " << type_string()
1041  << " (" << to_debug_string() << ")").str());
1042  }
1043 }
1044 
1046 {
1047  switch(type_) {
1048  case TYPE_NULL:
1049  str += "null()";
1050  break;
1051  case TYPE_INT:
1052  str += std::to_string(int_value_);
1053  break;
1054  case TYPE_DECIMAL: {
1055  std::ostringstream s;
1056 
1057  int fractional = decimal_value_ % 1000;
1058  int integer = (decimal_value_ - fractional) / 1000;
1059 
1060  s << integer << ".";
1061 
1062  fractional = abs(fractional);
1063 
1064  if( fractional < 100) {
1065  if( fractional < 10)
1066  s << "00";
1067  else
1068  s << 0;
1069  }
1070 
1071  s << fractional;
1072 
1073  str += s.str();
1074  break;
1075  }
1076  case TYPE_CALLABLE:
1077  callable_->serialize(str);
1078  break;
1079  case TYPE_LIST: {
1080  str += "[";
1081  bool first_time = true;
1082  for(size_t i=0; i<list_->elements.size(); ++i) {
1083  const variant& var = list_->elements[i];
1084  if(!first_time) {
1085  str += ",";
1086  }
1087  first_time = false;
1088  var.serialize_to_string(str);
1089  }
1090  str += "]";
1091  break;
1092  }
1093  case TYPE_MAP: {
1094  str += "[";
1095  bool first_time = true;
1096  for(std::map<variant,variant>::const_iterator i=map_->elements.begin(); i != map_->elements.end(); ++i) {
1097  if(!first_time) {
1098  str += ",";
1099  }
1100  first_time = false;
1101  i->first.serialize_to_string(str);
1102  str += "->";
1103  i->second.serialize_to_string(str);
1104  }
1105  if(map_->elements.empty()) {
1106  str += "->";
1107  }
1108  str += "]";
1109  break;
1110  }
1111  case TYPE_STRING:
1112  str += "'";
1113  for(std::string::iterator it = string_->str.begin(); it < string_->str.end(); ++it) {
1114  switch(*it) {
1115  case '\'':
1116  str += "[']";
1117  break;
1118  case '[':
1119  str += "[(]";
1120  break;
1121  case ']':
1122  str += "[)]";
1123  break;
1124  default:
1125  str += *it;
1126  break;
1127  }
1128  }
1129  str += "'";
1130  break;
1131  default:
1132  assert(false);
1133  }
1134 }
1135 
1137 {
1138  try {
1139  *this = game_logic::formula(str).evaluate();
1140  } catch(...) {
1141  *this = variant(str);
1142  }
1143 }
1144 
1146 {
1147  switch(type_) {
1148  case TYPE_LIST:
1149  return list_->refcount;
1150  break;
1151  case TYPE_STRING:
1152  return string_->refcount;
1153  break;
1154  case TYPE_MAP:
1155  return map_->refcount;
1156  break;
1157  case TYPE_CALLABLE:
1158  return callable_->refcount();
1159  break;
1160  default:
1161  return -1;
1162  }
1163 }
1164 
1166 {
1167  switch(type_) {
1168  case TYPE_NULL:
1169  return "0";
1170  case TYPE_INT:
1171  return std::to_string(int_value_);
1172  case TYPE_DECIMAL: {
1173  std::ostringstream s;
1174 
1175  int fractional = decimal_value_ % 1000;
1176  int integer = (decimal_value_ - fractional) / 1000;
1177 
1178  s << integer << ".";
1179 
1180  fractional = abs(fractional);
1181 
1182  if( fractional < 100) {
1183  if( fractional < 10)
1184  s << "00";
1185  else
1186  s << 0;
1187  }
1188 
1189  s << fractional;
1190 
1191  return s.str();
1192  }
1193  case TYPE_CALLABLE:
1194  return "(object)";
1195  case TYPE_LIST: {
1196  std::string res = "";
1197  for(size_t i=0; i<list_->elements.size(); ++i) {
1198  const variant& var = list_->elements[i];
1199  if(!res.empty()) {
1200  res += ", ";
1201  }
1202 
1203  res += var.string_cast();
1204  }
1205 
1206  return res;
1207  }
1208  case TYPE_MAP: {
1209  std::string res = "";
1210  for(std::map<variant,variant>::const_iterator i=map_->elements.begin(); i != map_->elements.end(); ++i) {
1211  if(!res.empty()) {
1212  res += ",";
1213  }
1214  res += i->first.string_cast();
1215  res += "->";
1216  res += i->second.string_cast();
1217  }
1218  return res;
1219  }
1220 
1221  case TYPE_STRING:
1222  return string_->str;
1223  default:
1224  assert(false);
1225  return "invalid";
1226  }
1227 }
1228 
1229 std::string variant::to_debug_string(std::vector<const game_logic::formula_callable*>* seen, bool verbose) const
1230 {
1231  std::vector<const game_logic::formula_callable*> seen_stack;
1232  if(!seen) {
1233  seen = &seen_stack;
1234  }
1235 
1236  std::ostringstream s;
1237  switch(type_) {
1238  case TYPE_NULL:
1239  s << "(null)";
1240  break;
1241  case TYPE_INT:
1242  s << int_value_;
1243  break;
1244  case TYPE_DECIMAL: {
1245  int fractional = decimal_value_ % 1000;
1246  int integer = (decimal_value_ - fractional) / 1000;
1247 
1248  // Make sure we get the sign on small negative values.
1249  if ( integer == 0 && decimal_value_ < 0 )
1250  s << '-';
1251  s << integer << ".";
1252 
1253  fractional = abs(fractional);
1254 
1255  if( fractional < 100) {
1256  if( fractional < 10)
1257  s << "00";
1258  else
1259  s << 0;
1260  }
1261 
1262  s << fractional;
1263 
1264  break;
1265  }
1266  case TYPE_LIST: {
1267  s << "[";
1268  for(size_t n = 0; n != num_elements(); ++n) {
1269  if(n != 0) {
1270  s << ", ";
1271  }
1272 
1273  s << operator[](n).to_debug_string(seen, verbose);
1274  }
1275  s << "]";
1276  break;
1277  }
1278  case TYPE_CALLABLE: {
1279  s << "{";
1280  if(std::find(seen->begin(), seen->end(), callable_) == seen->end()) {
1281  if(!verbose)
1282  seen->push_back(callable_);
1283  std::vector<game_logic::formula_input> v = callable_->inputs();
1284  bool first = true;
1285  for(size_t i=0; i<v.size(); ++i) {
1286  const game_logic::formula_input& input = v[i];
1287  if(!first) {
1288  s << ", ";
1289  }
1290  first = false;
1291  s << input.name << " ";
1292  if(input.access == game_logic::FORMULA_READ_WRITE) {
1293  s << "(read-write) ";
1294  } else if(input.access == game_logic::FORMULA_WRITE_ONLY) {
1295  s << "(writeonly) ";
1296  }
1297 
1298  s << "-> " << callable_->query_value(input.name).to_debug_string(seen, verbose);
1299  }
1300  } else {
1301  s << "...";
1302  }
1303  s << "}";
1304  break;
1305  }
1306  case TYPE_MAP: {
1307  s << "[";
1308  bool first_time = true;
1309  for(std::map<variant,variant>::const_iterator i=map_->elements.begin(); i != map_->elements.end(); ++i) {
1310  if(!first_time) {
1311  s << ",";
1312  }
1313  first_time = false;
1314  s << i->first.to_debug_string(seen, verbose);
1315  s << "->";
1316  s << i->second.to_debug_string(seen, verbose);
1317  }
1318  s << "]";
1319  break;
1320  }
1321  case TYPE_STRING: {
1322  s << "'" << string_->str << "'";
1323  break;
1324  }
1325  }
1326 
1327  return s.str();
1328 }
bool operator<(const variant &) const
Definition: variant.cpp:889
size_t num_elements() const
Definition: variant.cpp:526
variant operator^(const variant &) const
Definition: variant.cpp:748
void pop_call_stack()
Definition: variant.cpp:59
variant operator*(const variant &) const
Definition: variant.cpp:670
variant build_range(const variant &v) const
Definition: variant.cpp:1001
variant operator/(const variant &) const
Definition: variant.cpp:692
bool is_callable() const
Definition: variant.hpp:100
FORMULA_ACCESS_TYPE access
Definition: callable.hpp:27
std::vector< variant >::iterator list_iterator_
Definition: variant.hpp:233
GLuint GLuint GLsizei GLenum type
Definition: glew.h:1221
static l_noret error(LoadState *S, const char *why)
Definition: lundump.cpp:29
GLenum GLenum GLenum input
Definition: glew.h:10668
int decimal_value_
Definition: variant.hpp:168
variant_string * string_
Definition: variant.hpp:172
std::vector< variant > elements
Definition: variant.cpp:259
void must_be(TYPE t) const
Definition: variant.cpp:1036
variant_iterator end() const
Definition: variant.cpp:500
const std::map< variant, variant > & as_map() const
Definition: variant.cpp:617
bool contains(const variant &other) const
Definition: variant.cpp:1018
variant list_elements_sub(const variant &v) const
Definition: variant.cpp:917
bool as_bool() const
Definition: variant.cpp:580
variant list_elements_mul(const variant &v) const
Definition: variant.cpp:935
const game_logic::formula_callable * callable_
Definition: variant.hpp:169
GLdouble GLdouble t
Definition: glew.h:1366
std::string get_call_stack()
Definition: variant.cpp:64
type_error(const std::string &str)
Definition: variant.cpp:79
bool is_null() const
Definition: variant.hpp:80
variant query_value(const std::string &key) const
Definition: callable.hpp:39
bool operator<=(const variant &) const
Definition: variant.cpp:829
variant list_elements_add(const variant &v) const
Definition: variant.cpp:899
std::map< variant, variant > elements
Definition: variant.cpp:281
INT32 * numerator
Definition: wglew.h:1100
GLenum array
Definition: glew.h:6910
TYPE type_
Definition: variant.hpp:165
void serialize(std::string &str) const
Definition: callable.hpp:67
std::ostringstream wrapper.
Definition: formatter.hpp:32
bool is_list() const
Definition: variant.hpp:92
INT32 INT32 * denominator
Definition: wglew.h:1100
int as_int() const
Definition: variant.cpp:558
const GLdouble * v
Definition: glew.h:1359
GLenum GLsizei len
Definition: glew.h:5662
variant list_elements_div(const variant &v) const
Definition: variant.cpp:953
bool operator>(const variant &) const
Definition: variant.cpp:894
std::map< variant, variant >::iterator map_iterator_
Definition: variant.hpp:234
std::string string_cast() const
Definition: variant.cpp:1165
Iterator class for the variant.
Definition: variant.hpp:188
variant get_keys() const
Definition: variant.cpp:468
void push_call_stack(const char *str)
Definition: variant.cpp:54
void serialize_to_string(std::string &str) const
Definition: variant.cpp:1045
variant operator*() const
Definition: variant.cpp:126
GLfloat GLfloat p
Definition: glew.h:12766
Templates and utility-routines for strings and numbers.
variant concatenate(const variant &v) const
Definition: variant.cpp:971
bool less(const formula_callable *other) const
Definition: callable.hpp:60
std::string str
Definition: variant.cpp:270
bool equals(const formula_callable *other) const
Definition: callable.hpp:56
std::vector< formula_input > inputs() const
Definition: callable.hpp:50
int int_value_
Definition: variant.hpp:167
double round_portable(double d)
Definition: util.hpp:76
bool is_empty() const
Definition: variant.cpp:511
GLuint res
Definition: glew.h:9258
static variant evaluate(const const_formula_ptr &f, const formula_callable &variables, formula_debugger *fdb=nullptr, variant default_res=variant(0))
Definition: formula.hpp:31
variant_iterator begin() const
Definition: variant.cpp:490
void intrusive_ptr_add_ref(const reference_counted_object *obj)
int as_decimal() const
Definition: variant.cpp:565
variant_map * map_
Definition: variant.hpp:173
variant & operator=(const variant &v)
Definition: variant.cpp:409
const std::string & as_string() const
Definition: variant.cpp:603
bool operator==(const variant &) const
Definition: variant.cpp:771
variant_iterator & operator--()
Definition: variant.cpp:167
variant_list * list_
Definition: variant.hpp:171
variant operator%(const variant &) const
Definition: variant.cpp:726
size_t i
Definition: function.cpp:1057
variant operator+(const variant &) const
Definition: variant.cpp:624
bool operator!=(const variant_iterator &that) const
Definition: variant.cpp:234
void release()
Definition: variant.cpp:309
void increment_refcount()
Definition: variant.cpp:285
variant()
Definition: variant.cpp:343
variant_iterator()
Constructor for a TYPE_NULL variant.
Definition: variant.cpp:83
DECIMAL_VARIANT_TYPE
Definition: variant.hpp:57
std::string to_debug_string(std::vector< const game_logic::formula_callable * > *seen=nullptr, bool verbose=false) const
Definition: variant.cpp:1229
void intrusive_ptr_release(const reference_counted_object *obj)
GLclampd n
Definition: glew.h:5903
bool find(E event, F functor)
Tests whether an event handler is available.
variant get_values() const
Definition: variant.cpp:479
const std::vector< variant > & as_list() const
Definition: variant.cpp:610
variant get_member(const std::string &str) const
Definition: variant.cpp:545
GLint * first
Definition: glew.h:1496
GLsizei GLenum GLuint GLuint GLsizei char * message
Definition: glew.h:2499
int refcount
Definition: variant.cpp:282
void serialize_from_string(const std::string &str)
Definition: variant.cpp:1136
variant operator-() const
Definition: variant.cpp:763
variant_iterator & operator=(const variant_iterator &that)
Definition: variant.cpp:194
std::string::const_iterator iterator
Definition: tokenizer.hpp:21
GLdouble s
Definition: glew.h:1358
variant_iterator & operator++()
Definition: variant.cpp:140
GLsizei const GLcharARB ** string
Definition: glew.h:4503
variant operator[](size_t n) const
Definition: variant.cpp:419
std::string type_string() const
Definition: variant.cpp:339
~variant()
Definition: variant.cpp:404
bool operator>=(const variant &) const
Definition: variant.cpp:884
int refcount() const
Definition: variant.cpp:1145
bool operator!=(const variant &) const
Definition: variant.cpp:824
bool operator==(const variant_iterator &that) const
Definition: variant.cpp:216