1 #include "asserts.hpp"
2 #include "foreach.hpp"
3 #include "string_utils.hpp"
4 #include "variant_utils.hpp"
5
map_into_callable(variant v)6 game_logic::formula_callable_ptr map_into_callable(variant v)
7 {
8 if(v.is_callable()) {
9 return game_logic::formula_callable_ptr(v.mutable_callable());
10 } else if(v.is_map()) {
11 game_logic::map_formula_callable* res = new game_logic::map_formula_callable;
12 foreach(const variant_pair& p, v.as_map()) {
13 res->add(p.first.as_string(), p.second);
14 }
15
16 return game_logic::formula_callable_ptr(res);
17 } else {
18 return game_logic::formula_callable_ptr();
19 }
20 }
21
append_variants(variant a,variant b)22 variant append_variants(variant a, variant b)
23 {
24 if(a.is_null()) {
25 return b;
26 } else if(b.is_null()) {
27 return a;
28 } else if(a.is_list()) {
29 if(b.is_list()) {
30 if(b.num_elements() > 0 && (b[0].is_numeric() || b[0].is_string()) ||
31 a.num_elements() > 0 && (a[0].is_numeric() || a[0].is_string())) {
32 //lists of numbers or strings are treated like scalars and we
33 //set the value of b.
34 return b;
35 }
36
37 return a + b;
38 } else {
39 std::vector<variant> v(1, b);
40 return a + variant(&v);
41 }
42 } else if(b.is_list()) {
43 std::vector<variant> v(1, a);
44 return variant(&v) + b;
45 } else if(a.is_map() && b.is_map()) {
46 std::vector<variant> v;
47 v.push_back(a);
48 v.push_back(b);
49 return variant(&v);
50 } else {
51 return b;
52 }
53 }
54
parse_variant_list_or_csv_string(variant v)55 std::vector<std::string> parse_variant_list_or_csv_string(variant v)
56 {
57 if(v.is_string()) {
58 return util::split(v.as_string());
59 } else if(v.is_list()) {
60 return v.as_list_string();
61 } else {
62 ASSERT_LOG(v.is_null(), "Unexpected value when expecting a string list: " << v.write_json());
63 return std::vector<std::string>();
64 }
65 }
66
merge_variant_over(variant * aptr,variant b)67 void merge_variant_over(variant* aptr, variant b)
68 {
69 variant& a = *aptr;
70
71 foreach(variant key, b.get_keys().as_list()) {
72 a = a.add_attr(key, append_variants(a[key], b[key]));
73 }
74
75 if(!a.get_debug_info() && b.get_debug_info()) {
76 a.set_debug_info(*b.get_debug_info());
77 }
78 }
79
visit_variants(variant v,boost::function<void (variant)> fn)80 void visit_variants(variant v, boost::function<void (variant)> fn)
81 {
82 fn(v);
83
84 if(v.is_list()) {
85 foreach(const variant& item, v.as_list()) {
86 visit_variants(item, fn);
87 }
88 } else if(v.is_map()) {
89 foreach(const variant_pair& item, v.as_map()) {
90 visit_variants(item.second, fn);
91 }
92 }
93 }
94
deep_copy_variant(variant v)95 variant deep_copy_variant(variant v)
96 {
97 if(v.is_map()) {
98 std::map<variant,variant> m;
99 foreach(variant key, v.get_keys().as_list()) {
100 m[key] = deep_copy_variant(v[key]);
101 }
102
103 return variant(&m);
104 } else if(v.is_list()) {
105 std::vector<variant> items;
106 foreach(variant item, v.as_list()) {
107 items.push_back(deep_copy_variant(item));
108 }
109
110 return variant(&items);
111 } else {
112 return v;
113 }
114 }
115
add_value(const std::string & name,const variant & val)116 variant_builder& variant_builder::add_value(const std::string& name, const variant& val)
117 {
118 attr_[variant(name)].push_back(val);
119 return *this;
120 }
121
set_value(const std::string & name,const variant & val)122 variant_builder& variant_builder::set_value(const std::string& name, const variant& val)
123 {
124 variant key(name);
125 attr_.erase(key);
126 attr_[key].push_back(val);
127 return *this;
128 }
129
merge_object(variant obj)130 void variant_builder::merge_object(variant obj)
131 {
132 foreach(variant key, obj.get_keys().as_list()) {
133 set_value(key.as_string(), obj[key]);
134 }
135 }
136
build()137 variant variant_builder::build()
138 {
139 std::map<variant, variant> res;
140 for(std::map<variant, std::vector<variant> >::iterator i = attr_.begin(); i != attr_.end(); ++i) {
141 if(i->second.size() == 1) {
142 res[i->first] = i->second[0];
143 } else {
144 res[i->first] = variant(&i->second);
145 }
146 }
147 return variant(&res);
148 }
149
150