00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef GNASH_PROPERTY_H
00021 #define GNASH_PROPERTY_H
00022
00023 #include <boost/variant.hpp>
00024 #include <cassert>
00025 #include <boost/bind.hpp>
00026 #include <typeinfo>
00027
00028 #include "PropFlags.h"
00029 #include "as_value.h"
00030 #include "ObjectURI.h"
00031
00032 namespace gnash {
00033 typedef as_value (*as_c_function_ptr)(const fn_call& fn);
00034 class as_function;
00035 }
00036
00037 namespace gnash {
00038
00040
00043 class GetterSetter
00044 {
00045 class NativeGetterSetter;
00046
00047
00048
00049
00050
00052
00056 template<typename Arg, typename S>
00057 struct GetSetVisitor : boost::static_visitor<typename S::result_type>
00058 {
00059 GetSetVisitor(const Arg& arg) : _arg(arg) {}
00060 template<typename T> typename S::result_type operator()(T& t) const {
00061 return S()(t, _arg);
00062 }
00063 private:
00064 const Arg& _arg;
00065 };
00066
00068 struct Set
00069 {
00070 typedef void result_type;
00071 template<typename T, typename Arg>
00072 result_type operator()(T& t, Arg& a) const {
00073 t.set(a);
00074 }
00075 };
00076
00078 struct Get
00079 {
00080 typedef as_value result_type;
00081 template<typename T, typename Arg>
00082 result_type operator()(T& t, Arg& a) const {
00083 return t.get(a);
00084 }
00085 };
00086
00088
00090 struct SetUnderlying : boost::static_visitor<>
00091 {
00092 template<typename T>
00093 result_type operator()(T& gs, const as_value& val) const {
00094 gs.setUnderlying(val);
00095 }
00096 result_type operator()(NativeGetterSetter&, const as_value&) const {}
00097 };
00098
00100
00102 struct GetUnderlying : boost::static_visitor<as_value>
00103 {
00104 template<typename T>
00105 result_type operator()(const T& gs) const {
00106 return gs.getUnderlying();
00107 }
00108 result_type operator()(const NativeGetterSetter&) const {
00109 return result_type();
00110 }
00111 };
00112
00114 struct MarkReachable : boost::static_visitor<>
00115 {
00116 template<typename T>
00117 result_type operator()(const T& gs) const {
00118 gs.markReachableResources();
00119 }
00120 };
00121
00122 public:
00123
00125 GetterSetter(as_function* getter, as_function* setter)
00126 :
00127 _getset(UserDefinedGetterSetter(getter, setter))
00128 {}
00129
00131 GetterSetter(as_c_function_ptr getter, as_c_function_ptr setter)
00132 :
00133 _getset(NativeGetterSetter(getter, setter))
00134 {}
00135
00137 as_value get(fn_call& fn) const {
00138 GetSetVisitor<const fn_call, Get> s(fn);
00139 return boost::apply_visitor(s, _getset);
00140 }
00141
00143 void set(const fn_call& fn) {
00144 GetSetVisitor<fn_call, Set> s(fn);
00145 boost::apply_visitor(s, _getset);
00146 }
00147
00149 void setCache(const as_value& v) {
00150 boost::apply_visitor(boost::bind(SetUnderlying(), _1, v), _getset);
00151 }
00152
00154 as_value getCache() const {
00155 return boost::apply_visitor(GetUnderlying(), _getset);
00156 }
00157
00158 void markReachableResources() const {
00159 boost::apply_visitor(MarkReachable(), _getset);
00160 }
00161
00162 private:
00163
00165 class UserDefinedGetterSetter
00166 {
00167 public:
00168
00169 UserDefinedGetterSetter(as_function* get, as_function* set)
00170 :
00171 _getter(get),
00172 _setter(set),
00173 _underlyingValue(),
00174 _beingAccessed(false)
00175 {}
00176
00178 as_value get(const fn_call& fn) const;
00179
00181 void set(const fn_call& fn);
00182
00184 const as_value& getUnderlying() const { return _underlyingValue; }
00185
00187 void setUnderlying(const as_value& v) { _underlyingValue = v; }
00188
00189 void markReachableResources() const;
00190
00191 private:
00192
00196
00199 class ScopedLock : boost::noncopyable
00200 {
00201 public:
00202
00203 explicit ScopedLock(const UserDefinedGetterSetter& na)
00204 :
00205 _a(na),
00206 _obtainedLock(_a._beingAccessed ? false : true)
00207 {
00208
00209
00210 if (_obtainedLock) _a._beingAccessed = true;
00211 }
00212
00213 ~ScopedLock() { if ( _obtainedLock) _a._beingAccessed = false; }
00214
00216
00221 bool obtainedLock() const { return _obtainedLock; }
00222
00223 private:
00224
00225 const UserDefinedGetterSetter& _a;
00226 bool _obtainedLock;
00227
00228 };
00229
00230 as_function* _getter;
00231 as_function* _setter;
00232 as_value _underlyingValue;
00233 mutable bool _beingAccessed;
00234 };
00235
00237 class NativeGetterSetter
00238 {
00239 public:
00240
00241 NativeGetterSetter(as_c_function_ptr get, as_c_function_ptr set)
00242 :
00243 _getter(get), _setter(set) {}
00244
00246 as_value get(const fn_call& fn) const {
00247 return _getter(fn);
00248 }
00249
00251 void set(const fn_call& fn) {
00252 _setter(fn);
00253 }
00254
00256 void markReachableResources() const {}
00257
00258 private:
00259 as_c_function_ptr _getter;
00260 as_c_function_ptr _setter;
00261 };
00262
00263 boost::variant<UserDefinedGetterSetter, NativeGetterSetter> _getset;
00264
00265 };
00266
00268
00270
00274 class Property
00275 {
00276
00278 struct SetReachable : boost::static_visitor<>
00279 {
00280 result_type operator()(const as_value& val) const {
00281 val.setReachable();
00282 }
00283 result_type operator()(const GetterSetter& gs) const {
00284 return gs.markReachableResources();
00285 }
00286 };
00287
00288 public:
00289
00290 Property(const ObjectURI& uri, const as_value& value,
00291 const PropFlags& flags)
00292 :
00293 _bound(value),
00294 _uri(uri),
00295 _flags(flags),
00296 _destructive(false)
00297 {}
00298
00299 Property(const ObjectURI& uri,
00300 as_function* getter, as_function* setter,
00301 const PropFlags& flags, bool destroy = false)
00302 :
00303 _bound(GetterSetter(getter, setter)),
00304 _uri(uri),
00305 _flags(flags),
00306 _destructive(destroy)
00307 {}
00308
00309 Property(const ObjectURI& uri, as_c_function_ptr getter,
00310 as_c_function_ptr setter, const PropFlags& flags,
00311 bool destroy = false)
00312 :
00313 _bound(GetterSetter(getter, setter)),
00314 _uri(uri),
00315 _flags(flags),
00316 _destructive(destroy)
00317 {}
00318
00320 Property(const Property& p)
00321 :
00322 _bound(p._bound),
00323 _uri(p._uri),
00324 _flags(p._flags),
00325 _destructive(p._destructive)
00326 {}
00327
00329 const PropFlags& getFlags() const { return _flags; }
00330
00332 void setFlags(const PropFlags& flags) const {
00333 _flags = flags;
00334 }
00335
00337
00345 as_value getValue(const as_object& this_ptr) const;
00346
00348
00354 as_value getCache() const;
00355
00357
00363 void setCache(const as_value& v);
00364
00366
00381 bool setValue(as_object& this_ptr, const as_value &value) const;
00382
00384 bool isGetterSetter() const {
00385 return _bound.type() == typeid(GetterSetter);
00386 }
00387
00389 void clearVisible(int swfVersion) { _flags.clear_visible(swfVersion); }
00390
00392 const ObjectURI& uri() const {
00393 return _uri;
00394 }
00395
00397 void setReachable() const {
00398 return boost::apply_visitor(SetReachable(), _bound);
00399 }
00400
00401 private:
00402
00403
00404 typedef boost::variant<as_value, GetterSetter> BoundType;
00405
00407 mutable BoundType _bound;
00408
00410 ObjectURI _uri;
00411
00413 mutable PropFlags _flags;
00414
00415
00416
00417
00418 mutable bool _destructive;
00419
00420 };
00421
00423 inline bool
00424 readOnly(const Property& prop) {
00425 return prop.getFlags().test<PropFlags::readOnly>();
00426 }
00427
00429 inline bool
00430 visible(const Property& prop, int version) {
00431 return prop.getFlags().get_visible(version);
00432 }
00433
00434 }
00435
00436 #endif // GNASH_PROPERTY_H