00001
00002
00003 #include "cppscript"
00004 #include "dynamic/extensions.hpp"
00005 #include "wrap_cpp_container.hpp"
00006
00007 #include <list>
00008 #include <cstring>
00009
00010
00011 static_call( register_pickle_type(cmp_object,object()) );
00012
00013 using internal::nonroot_var;
00014
00015
00016 namespace
00017 {
00018 struct member_cmp
00019 {
00020 bool operator()(const char * s1, const char * s2) const
00021 {
00022 return strcmp(s1, s2)<0;
00023 }
00024 };
00025
00026
00027 struct object_traits
00028 {
00029 typedef std::pair<const char * const, nonroot_var> value_type;
00030
00031 typedef std::map<const char*, nonroot_var, member_cmp, dynamic::allocator<value_type> > container;
00032
00033 static var key(value_type & i)
00034 {
00035 return i.first;
00036 }
00037
00038 static var deref(value_type & i)
00039 {
00040 return i.first;
00041 }
00042
00043 static const char * key(const var & k)
00044 {
00045 return 0;
00046 }
00047
00048 static var value(value_type & i)
00049 {
00050 return i.second.get();
00051 }
00052
00053 static void mark_reachable(value_type & i, gc::garbage_collector & gc)
00054 {
00055 i.second.ref().impl().mark_reachable(gc);
00056 }
00057
00058 static const var_cmp_index comparison_index = cmp_object;
00059
00060 static const char * class_name()
00061 {
00062 return "object";
00063 }
00064
00065 static const char * iterator_class_name()
00066 {
00067 return "object::iterator";
00068 }
00069 };
00070 }
00071
00072 namespace dynamic
00073 {
00074 namespace types
00075 {
00077
00078 class object_impl : public dynamic::internal::wrap_assoc_container<object_traits>
00079 {
00080 private:
00081 typedef internal::wrap_assoc_container<object_traits> super_type;
00082
00083 const char * m_class_name;
00084
00085 std::list<std::string> m_object_names;
00086
00087 public:
00088 object_impl(const char * class_name) : m_class_name(class_name)
00089 {
00090 }
00091
00092 std::string class_name()
00093 {
00094 return m_class_name;
00095 }
00096
00097 var get_member(const char * k)
00098 {
00099 iterator i=this->m_data.find(k);
00100 if( i == this->m_data.end() )
00101 throw not_found(k);
00102 return object_traits::value(*i);
00103 }
00104
00105 void set_member(const var & k, const var & v)
00106 {
00107 throw not_supported(this, "set_member(var,var)");
00108 }
00109
00110 var call(const var&k, const var & v)
00111 {
00112 throw not_supported(this, "call with 2 arguments");
00113 }
00114
00115 int max_args()
00116 {
00117 return -1;
00118 }
00119
00120 var get_member(const var & v)
00121 {
00122 return get_member( v.as_string().c_str() );
00123 }
00124
00125 bool contains(const var & v)
00126 {
00127 return this->m_data.find(v.as_string().c_str()) != this->m_data.end();
00128 }
00129
00130 void erase(const var & v)
00131 {
00132 this->m_data.erase(v.as_string().c_str());
00133 }
00134
00135 void set_member(const char * k, const var & v)
00136 {
00137 this->m_data[k] = v;
00138 this->invalidate_iterators();
00139 }
00140
00141 void pickle(pickler & p)
00142 {
00143 p.write_object_type(comparison_index());
00144
00145 p.write_string(m_class_name);
00146 p.write_int(int(this->m_data.size()));
00147 for(iterator i=this->m_data.begin(); i!=this->m_data.end(); ++i)
00148 {
00149 p.write_string(i->first);
00150 p.write_object(i->second.ref());
00151 }
00152 }
00153
00154 void unpickle(unpickler & p)
00155 {
00156 m_object_names.push_back( p.read_string() );
00157 m_class_name = m_object_names.back().c_str();
00158 int size = p.read_int();
00159 for(int i=0; i<size; ++i)
00160 {
00161 m_object_names.push_back( p.read_string() );
00162 var v = p.read_object();
00163 this->m_data.insert( std::make_pair( m_object_names.back().c_str(), v) );
00164 }
00165 }
00166
00167 var member_inc(const char * k)
00168 {
00169 iterator i=this->m_data.find(k);
00170 if( i == this->m_data.end() )
00171 throw not_found(k);
00172 ++i->second.ref();
00173 return i->second.get();
00174 }
00175
00176 var member_dec(const char * k)
00177 {
00178 iterator i=this->m_data.find(k);
00179 if( i == this->m_data.end() )
00180 throw not_found(k);
00181 --i->second.ref();
00182 return i->second.get();
00183 }
00184
00185 var member_add(const char * k, const var & v)
00186 {
00187 iterator i=this->m_data.find(k);
00188 if( i == this->m_data.end() )
00189 throw not_found(k);
00190 i->second.ref() += v;
00191 return i->second.get();
00192 }
00193
00194 var member_sub(const char * k, const var & v)
00195 {
00196 iterator i=this->m_data.find(k);
00197 if( i == this->m_data.end() )
00198 throw not_found(k);
00199 i->second.ref() -= v;
00200 return i->second.get();
00201 }
00202
00203 var member_inc(const char * k, int)
00204 {
00205 iterator i=this->m_data.find(k);
00206 if( i == this->m_data.end() )
00207 throw not_found(k);
00208 var tmp = i->second.get();
00209 ++i->second.ref();
00210 return tmp;
00211 }
00212
00213 var member_dec(const char * k, int)
00214 {
00215 iterator i=this->m_data.find(k);
00216 if( i == this->m_data.end() )
00217 throw not_found(k);
00218 var tmp = i->second.get();
00219 --i->second.ref();
00220 return tmp;
00221 }
00222
00223 void output(ostream & ss)
00224 {
00225 ss << m_class_name;
00226 }
00227
00228 void output(wostream & ss)
00229 {
00230 ss << m_class_name;
00231 }
00232
00233 var clone()
00234 {
00235 return new object_impl(*this);
00236 }
00237
00238 void mixin(const var & other)
00239 {
00240 object_impl * other_impl = dynamic_cast<object_impl*>(other.impl().shared_var());
00241
00242 if(!other_impl) throw not_supported(other, "mixin from");
00243
00244 for(object_traits::container::iterator i=other_impl->m_data.begin(); i!=other_impl->m_data.end(); ++i)
00245 {
00246 this->invalidate_iterators();
00247 this->m_data.insert(*i);
00248 }
00249 }
00250 };
00251 }
00252 }
00253
00254
00255 var dynamic::object()
00256 {
00257 return new types::object_impl("");
00258 }
00259
00260
00261 var dynamic::create_closure(const var & object, const char * method, const var & fn)
00262 {
00263 return bind(fn, object);
00264 }
00265
00266
00267 var dynamic::object(const char * name)
00268 {
00269 return new types::object_impl(name);
00270 }