Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef VARIANT_HPP_INCLUDED
00017 #define VARIANT_HPP_INCLUDED
00018
00019 #include <boost/shared_ptr.hpp>
00020 #include <map>
00021 #include <vector>
00022
00023 #include "exceptions.hpp"
00024
00025 namespace game_logic {
00026 class formula_callable;
00027 }
00028
00029 void push_call_stack(const char* str);
00030 void pop_call_stack();
00031 std::string get_call_stack();
00032
00033 struct call_stack_manager {
00034 explicit call_stack_manager(const char* str) {
00035 push_call_stack(str);
00036 }
00037
00038 ~call_stack_manager() {
00039 pop_call_stack();
00040 }
00041 };
00042
00043 struct variant_list;
00044 struct variant_string;
00045 struct variant_map;
00046 class variant_iterator;
00047
00048 struct type_error : public game::error {
00049 explicit type_error(const std::string& str);
00050 };
00051
00052
00053 class variant {
00054 public:
00055
00056 enum TYPE { TYPE_NULL, TYPE_INT, TYPE_DECIMAL, TYPE_CALLABLE, TYPE_LIST, TYPE_STRING, TYPE_MAP };
00057
00058 enum DECIMAL_VARIANT_TYPE { DECIMAL_VARIANT };
00059
00060 variant();
00061 explicit variant(int n);
00062 variant(int n, DECIMAL_VARIANT_TYPE );
00063 explicit variant(const game_logic::formula_callable* callable);
00064 explicit variant(std::vector<variant>* array);
00065 explicit variant(const std::string& str);
00066 explicit variant(std::map<variant,variant>* map);
00067 ~variant();
00068
00069 variant(const variant& v);
00070 const variant& operator=(const variant& v);
00071
00072 const variant& operator[](size_t n) const;
00073 const variant& operator[](const variant& v) const;
00074 size_t num_elements() const;
00075 bool is_empty() const;
00076
00077 variant get_member(const std::string& str) const;
00078
00079 bool is_string() const { return type_ == TYPE_STRING; }
00080 bool is_null() const { return type_ == TYPE_NULL; }
00081 bool is_int() const { return type_ == TYPE_INT; }
00082 bool is_decimal() const { return type_ == TYPE_DECIMAL; }
00083 bool is_map() const { return type_ == TYPE_MAP; }
00084 int as_int() const { if(type_ == TYPE_NULL) { return 0; } must_be(TYPE_INT); return int_value_; }
00085
00086
00087
00088 int as_decimal() const;
00089
00090 bool as_bool() const;
00091
00092 bool is_list() const { return type_ == TYPE_LIST; }
00093
00094 const std::string& as_string() const;
00095
00096 bool is_callable() const { return type_ == TYPE_CALLABLE; }
00097 const game_logic::formula_callable* as_callable() const {
00098 must_be(TYPE_CALLABLE); return callable_; }
00099 game_logic::formula_callable* mutable_callable() const {
00100 must_be(TYPE_CALLABLE); return mutable_callable_; }
00101
00102 template<typename T>
00103 T* try_convert() const {
00104 if(!is_callable()) {
00105 return NULL;
00106 }
00107
00108 return dynamic_cast<T*>(mutable_callable());
00109 }
00110
00111 template<typename T>
00112 T* convert_to() const {
00113 T* res = dynamic_cast<T*>(mutable_callable());
00114 if(!res) {
00115 throw type_error("could not convert type");
00116 }
00117
00118 return res;
00119 }
00120
00121 variant operator+(const variant&) const;
00122 variant operator-(const variant&) const;
00123 variant operator*(const variant&) const;
00124 variant operator/(const variant&) const;
00125 variant operator^(const variant&) const;
00126 variant operator%(const variant&) const;
00127 variant operator-() const;
00128
00129 bool operator==(const variant&) const;
00130 bool operator!=(const variant&) const;
00131 bool operator<(const variant&) const;
00132 bool operator>(const variant&) const;
00133 bool operator<=(const variant&) const;
00134 bool operator>=(const variant&) const;
00135
00136 variant list_elements_add(const variant& v) const;
00137 variant list_elements_sub(const variant& v) const;
00138 variant list_elements_mul(const variant& v) const;
00139 variant list_elements_div(const variant& v) const;
00140
00141 variant get_keys() const;
00142 variant get_values() const;
00143
00144 variant_iterator begin() const;
00145 variant_iterator end() const;
00146
00147 void serialize_to_string(std::string& str) const;
00148 void serialize_from_string(const std::string& str);
00149
00150 int refcount() const;
00151
00152 std::string string_cast() const;
00153
00154 std::string to_debug_string(std::vector<const game_logic::formula_callable*>* seen=NULL, bool verbose = false) const;
00155
00156 private:
00157 void must_be(TYPE t) const;
00158 TYPE type_;
00159 union {
00160 int int_value_;
00161 int decimal_value_;
00162 const game_logic::formula_callable* callable_;
00163 game_logic::formula_callable* mutable_callable_;
00164 variant_list* list_;
00165 variant_string* string_;
00166 variant_map* map_;
00167 };
00168
00169 void increment_refcount();
00170 void release();
00171 };
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 class variant_iterator {
00182 public:
00183
00184
00185
00186 variant_iterator();
00187
00188
00189
00190
00191
00192
00193
00194
00195 explicit variant_iterator(const std::vector<variant>::iterator& iter);
00196
00197
00198
00199
00200
00201
00202
00203
00204 explicit variant_iterator(const std::map<variant, variant>::iterator& iter);
00205
00206 variant_iterator(const variant_iterator&);
00207
00208 variant operator*() const;
00209 variant_iterator& operator++();
00210 variant_iterator operator++(int);
00211 variant_iterator& operator=(const variant_iterator& that);
00212 bool operator==(const variant_iterator& that) const;
00213 bool operator!=(const variant_iterator& that) const;
00214
00215 enum TYPE { TYPE_NULL, TYPE_LIST, TYPE_MAP };
00216 private:
00217 TYPE type_;
00218 std::vector<variant>::iterator list_iterator_;
00219 std::map<variant,variant>::iterator map_iterator_;
00220 };
00221
00222 template<typename T>
00223 T* convert_variant(const variant& v) {
00224 T* res = dynamic_cast<T*>(v.mutable_callable());
00225 if(!res) {
00226 throw type_error("could not convert type");
00227 }
00228
00229 return res;
00230 }
00231
00232
00233 template<typename T>
00234 T* try_convert_variant(const variant& v) {
00235 if(!v.is_callable()) {
00236 return NULL;
00237 }
00238
00239 return dynamic_cast<T*>(v.mutable_callable());
00240 }
00241
00242
00243
00244 #endif