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