formula_callable.hpp

Go to the documentation of this file.
00001 /* $Id: formula_callable.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 FORMULA_CALLABLE_HPP_INCLUDED
00017 #define FORMULA_CALLABLE_HPP_INCLUDED
00018 
00019 #include "reference_counted_object.hpp"
00020 #include "variant.hpp"
00021 
00022 namespace game_logic
00023 {
00024 
00025 enum FORMULA_ACCESS_TYPE { FORMULA_READ_ONLY, FORMULA_WRITE_ONLY, FORMULA_READ_WRITE };
00026 struct formula_input {
00027     std::string name;
00028     FORMULA_ACCESS_TYPE access;
00029     explicit formula_input(const std::string& name, FORMULA_ACCESS_TYPE access=FORMULA_READ_WRITE)
00030             : name(name), access(access)
00031     {}
00032 };
00033 
00034 //interface for objects that can have formulae run on them
00035 class formula_callable : public reference_counted_object {
00036 public:
00037     explicit formula_callable(bool has_self=true) : type_(FORMULA_C), has_self_(has_self)
00038     {}
00039 
00040     variant query_value(const std::string& key) const {
00041         if(has_self_ && key == "self") {
00042             return variant(this);
00043         }
00044         return get_value(key);
00045     }
00046 
00047     void mutate_value(const std::string& key, const variant& value) {
00048         set_value(key, value);
00049     }
00050 
00051     std::vector<formula_input> inputs() const {
00052         std::vector<formula_input> res;
00053         get_inputs(&res);
00054         return res;
00055     }
00056 
00057     bool equals(const formula_callable* other) const {
00058         return do_compare(other) == 0;
00059     }
00060 
00061     bool less(const formula_callable* other) const {
00062         return do_compare(other) < 0;
00063     }
00064 
00065     virtual void get_inputs(std::vector<formula_input>* /*inputs*/) const {};
00066 
00067         //note: this function should NOT overwrite str, but append text to it!
00068     void serialize(std::string& str) const {
00069         serialize_to_string(str);
00070     }
00071 
00072     bool has_key(const std::string& key) const
00073         { return !query_value(key).is_null(); }
00074 
00075 protected:
00076     virtual ~formula_callable() {}
00077 
00078     virtual void set_value(const std::string& key, const variant& value);
00079     virtual int do_compare(const formula_callable* callable) const {
00080         if( type_ < callable->type_ )
00081             return -1;
00082 
00083         if( type_ > callable->type_ )
00084             return 1;
00085 
00086         return this < callable ? -1 : (this == callable ? 0 : 1);
00087     }
00088 
00089         //note: this function should NOT overwrite str, but append text to it!
00090     virtual void serialize_to_string(std::string& /*str*/) const {
00091         throw type_error("Tried to serialize type which cannot be serialized");
00092     }
00093 
00094     //priority for objects that are derived from this class, used in do_compare
00095     //when comparing objects of different types
00096     //for example: formula_callable < terrain_callable < unit_type_callable ...
00097         enum TYPE { FORMULA_C, TERRAIN_C, LOCATION_C, UNIT_TYPE_C, UNIT_C,
00098                         ATTACK_TYPE_C, MOVE_PARTIAL_C, MOVE_C, ATTACK_C, MOVE_MAP_C };
00099 
00100         TYPE type_;
00101 private:
00102     virtual variant get_value(const std::string& key) const = 0;
00103     bool has_self_;
00104 };
00105 
00106 class formula_callable_no_ref_count : public formula_callable {
00107 public:
00108     formula_callable_no_ref_count() {
00109         turn_reference_counting_off();
00110     }
00111     virtual ~formula_callable_no_ref_count() {}
00112 };
00113 
00114 class formula_callable_with_backup : public formula_callable {
00115     const formula_callable& main_;
00116     const formula_callable& backup_;
00117     variant get_value(const std::string& key) const {
00118         variant var = main_.query_value(key);
00119         if(var.is_null()) {
00120             return backup_.query_value(key);
00121         }
00122 
00123         return var;
00124     }
00125 
00126     void get_inputs(std::vector<formula_input>* inputs) const {
00127         main_.get_inputs(inputs);
00128         backup_.get_inputs(inputs);
00129     }
00130 public:
00131     formula_callable_with_backup(const formula_callable& main, const formula_callable& backup) : formula_callable(false), main_(main), backup_(backup)
00132     {}
00133 };
00134 
00135 class formula_variant_callable_with_backup : public formula_callable {
00136     variant var_;
00137     const formula_callable& backup_;
00138     variant get_value(const std::string& key) const {
00139         variant var = var_.get_member(key);
00140         if(var.is_null()) {
00141             return backup_.query_value(key);
00142         }
00143 
00144         return var;
00145     }
00146 
00147     void get_inputs(std::vector<formula_input>* inputs) const {
00148         backup_.get_inputs(inputs);
00149     }
00150 
00151 public:
00152     formula_variant_callable_with_backup(const variant& var, const formula_callable& backup) : formula_callable(false), var_(var), backup_(backup)
00153     {}
00154 };
00155 
00156 class map_formula_callable : public formula_callable {
00157 public:
00158     explicit map_formula_callable(const formula_callable* fallback=NULL);
00159     map_formula_callable& add(const std::string& key, const variant& value);
00160     void set_fallback(const formula_callable* fallback) { fallback_ = fallback; }
00161     bool empty() const { return values_.empty(); }
00162     void clear() { values_.clear(); }
00163 
00164     typedef std::map<std::string,variant>::const_iterator const_iterator;
00165 
00166     const_iterator begin() const { return values_.begin(); }
00167     const_iterator end() const { return values_.end(); }
00168 
00169 private:
00170     variant get_value(const std::string& key) const;
00171     void get_inputs(std::vector<formula_input>* inputs) const;
00172     void set_value(const std::string& key, const variant& value);
00173     std::map<std::string,variant> values_;
00174     const formula_callable* fallback_;
00175 };
00176 
00177 typedef boost::intrusive_ptr<map_formula_callable> map_formula_callable_ptr;
00178 typedef boost::intrusive_ptr<const map_formula_callable> const_map_formula_callable_ptr;
00179 
00180 }
00181 
00182 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Thu May 24 2012 01:02:36 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs