00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef FORMULA_CALLABLE_HPP_INCLUDED
00016 #define FORMULA_CALLABLE_HPP_INCLUDED
00017
00018 #include <map>
00019 #include <string>
00020
00021 #include "reference_counted_object.hpp"
00022 #include "variant.hpp"
00023
00024 namespace game_logic
00025 {
00026
00027 enum FORMULA_ACCESS_TYPE { FORMULA_READ_ONLY, FORMULA_WRITE_ONLY, FORMULA_READ_WRITE };
00028 struct formula_input {
00029 std::string name;
00030 FORMULA_ACCESS_TYPE access;
00031 explicit formula_input(const std::string& name, FORMULA_ACCESS_TYPE access=FORMULA_READ_WRITE)
00032 : name(name), access(access)
00033 {}
00034 };
00035
00036
00037 class formula_callable : public reference_counted_object {
00038 public:
00039 explicit formula_callable(bool has_self=true) : has_self_(has_self)
00040 {}
00041
00042 variant query_value(const std::string& key) const {
00043 if(has_self_ && key == "self") {
00044 return variant(this);
00045 }
00046 return get_value(key);
00047 }
00048
00049 void mutate_value(const std::string& key, const variant& value) {
00050 set_value(key, value);
00051 }
00052
00053 std::vector<formula_input> inputs() const {
00054 std::vector<formula_input> res;
00055 get_inputs(&res);
00056 return res;
00057 }
00058
00059 bool equals(const formula_callable* other) const {
00060 return do_compare(other) == 0;
00061 }
00062
00063 bool less(const formula_callable* other) const {
00064 return do_compare(other) < 0;
00065 }
00066
00067 virtual void get_inputs(std::vector<formula_input>* ) const {};
00068
00069 void serialize(std::string& str) const {
00070 serialize_to_string(str);
00071 }
00072
00073 bool has_key(const std::string& key) const
00074 { return !query_value(key).is_null(); }
00075
00076 protected:
00077 virtual ~formula_callable() {}
00078
00079 virtual void set_value(const std::string& key, const variant& value);
00080 virtual int do_compare(const formula_callable* callable) const {
00081 return this < callable ? -1 : (this == callable ? 0 : 1);
00082 }
00083
00084 virtual void serialize_to_string(std::string& ) const {
00085 throw type_error("Tried to serialize type which cannot be serialized");
00086 }
00087 private:
00088 virtual variant get_value(const std::string& key) const = 0;
00089 bool has_self_;
00090 };
00091
00092 class formula_callable_no_ref_count : public formula_callable {
00093 public:
00094 formula_callable_no_ref_count() {
00095 turn_reference_counting_off();
00096 }
00097 virtual ~formula_callable_no_ref_count() {}
00098 };
00099
00100 class formula_callable_with_backup : public formula_callable {
00101 const formula_callable& main_;
00102 const formula_callable& backup_;
00103 variant get_value(const std::string& key) const {
00104 variant var = main_.query_value(key);
00105 if(var.is_null()) {
00106 return backup_.query_value(key);
00107 }
00108
00109 return var;
00110 }
00111
00112 void get_inputs(std::vector<formula_input>* inputs) const {
00113 main_.get_inputs(inputs);
00114 backup_.get_inputs(inputs);
00115 }
00116 public:
00117 formula_callable_with_backup(const formula_callable& main, const formula_callable& backup) : formula_callable(false), main_(main), backup_(backup)
00118 {}
00119 };
00120
00121 class formula_variant_callable_with_backup : public formula_callable {
00122 variant var_;
00123 const formula_callable& backup_;
00124 variant get_value(const std::string& key) const {
00125 variant var = var_.get_member(key);
00126 if(var.is_null()) {
00127 return backup_.query_value(key);
00128 }
00129
00130 return var;
00131 }
00132
00133 void get_inputs(std::vector<formula_input>* inputs) const {
00134 backup_.get_inputs(inputs);
00135 }
00136
00137 public:
00138 formula_variant_callable_with_backup(const variant& var, const formula_callable& backup) : formula_callable(false), var_(var), backup_(backup)
00139 {}
00140 };
00141
00142 class map_formula_callable : public formula_callable {
00143 public:
00144 explicit map_formula_callable(const formula_callable* fallback=NULL);
00145 map_formula_callable& add(const std::string& key, const variant& value);
00146 void set_fallback(const formula_callable* fallback) { fallback_ = fallback; }
00147 bool empty() const { return values_.empty(); }
00148 void clear() { values_.clear(); }
00149
00150 typedef std::map<std::string,variant>::const_iterator const_iterator;
00151
00152 const_iterator begin() const { return values_.begin(); }
00153 const_iterator end() const { return values_.end(); }
00154
00155 private:
00156 variant get_value(const std::string& key) const;
00157 void get_inputs(std::vector<formula_input>* inputs) const;
00158 void set_value(const std::string& key, const variant& value);
00159 std::map<std::string,variant> values_;
00160 const formula_callable* fallback_;
00161 };
00162
00163 typedef boost::intrusive_ptr<map_formula_callable> map_formula_callable_ptr;
00164 typedef boost::intrusive_ptr<const map_formula_callable> const_map_formula_callable_ptr;
00165
00166 }
00167
00168 #endif