variant.hpp

Go to the documentation of this file.
00001 /* $Id: variant.hpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2008 - 2012 by David White <dave@whitevine.net>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
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 /*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     //this function returns variant's internal representation of decimal number:
00087     //for example number 1.234 is represented as 1234
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  * Iterator class for the variant.
00175  *
00176  * Depending on the @p type_ the @p list_iterator_ and the @p map_iterator_ are
00177  * a valid iterator or singular. Since most actions on singular iterators
00178  * result in Undefined Behaviour care should be taken when copying the
00179  * @p list_iterator_ and @p map_iterator_.
00180  */
00181 class variant_iterator {
00182 public:
00183     /**
00184      * Constructor for a TYPE_NULL variant.
00185      */
00186     variant_iterator();
00187 
00188     /**
00189      * Constructor for a TYPE_LIST variant.
00190      *
00191      * @pre @p iter is not singular.
00192      *
00193      * @param iter                Iterator to initialize @p list_iterator_ with.
00194      */
00195     explicit variant_iterator(const std::vector<variant>::iterator& iter);
00196 
00197     /**
00198      * Constructor for a TYPE_MAP variant.
00199      *
00200      * @pre @p iter is not singular.
00201      *
00202      * @param iter                Iterator to initialize @p map_iterator_ with.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:14 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs