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 "PropFlags.h"
00024 #include "as_value.h"
00025 #include "ObjectURI.h"
00026
00027 #include <boost/variant.hpp>
00028 #include <cassert>
00029
00030 namespace gnash {
00031
00032 typedef as_value (*as_c_function_ptr)(const fn_call& fn);
00033
00034 class as_function;
00035 class PropertyList;
00036
00038
00042 class GetterSetter
00043 {
00044 public:
00045
00047 GetterSetter(as_function* getter, as_function* setter)
00048 :
00049 _getset(UserDefinedGetterSetter(getter, setter))
00050 {}
00051
00053 GetterSetter(as_c_function_ptr getter, as_c_function_ptr setter)
00054 :
00055 _getset(NativeGetterSetter(getter, setter))
00056 {}
00057
00059 as_value get(fn_call& fn) const
00060 {
00061 switch ( _getset.which() )
00062 {
00063 case 0:
00064 return boost::get<UserDefinedGetterSetter>(_getset).get(fn);
00065 break;
00066 case 1:
00067 return boost::get<NativeGetterSetter>(_getset).get(fn);
00068 break;
00069 }
00070 return as_value();
00071 }
00072
00074 void set(fn_call& fn)
00075 {
00076 switch ( _getset.which() )
00077 {
00078 case 0:
00079 boost::get<UserDefinedGetterSetter>(_getset).set(fn);
00080 break;
00081 case 1:
00082 boost::get<NativeGetterSetter>(_getset).set(fn);
00083 break;
00084 }
00085 }
00086
00088 void setCache(const as_value& v)
00089 {
00090 switch ( _getset.which() )
00091 {
00092 case 0:
00093 boost::get<UserDefinedGetterSetter>(_getset).setUnderlying(v);
00094 break;
00095 case 1:
00096
00097 break;
00098 }
00099 }
00100
00102 const as_value& getCache() const
00103 {
00104 switch (_getset.which())
00105 {
00106 case 0:
00107 return boost::get<UserDefinedGetterSetter>(
00108 _getset).getUnderlying();
00109 }
00110 static as_value undefVal;
00111 return undefVal;
00112 }
00113
00114 void markReachableResources() const
00115 {
00116 if (_getset.which() == 0) {
00117 boost::get<UserDefinedGetterSetter>(
00118 _getset).markReachableResources();
00119 }
00120 }
00121
00122 private:
00123
00125 class UserDefinedGetterSetter
00126 {
00127 public:
00128
00129 UserDefinedGetterSetter(as_function* get, as_function* set)
00130 :
00131 _getter(get),
00132 _setter(set),
00133 _underlyingValue(),
00134 _beingAccessed(false)
00135 {}
00136
00138 as_value get(fn_call& fn) const;
00139
00141 void set(fn_call& fn);
00142
00144 const as_value& getUnderlying() const { return _underlyingValue; }
00145
00147 void setUnderlying(const as_value& v) { _underlyingValue = v; }
00148
00149 void markReachableResources() const;
00150
00151 private:
00152
00153 as_function* _getter;
00154 as_function* _setter;
00155
00156 as_value _underlyingValue;
00157
00158 mutable bool _beingAccessed;
00159
00163
00166 class ScopedLock : boost::noncopyable
00167 {
00168 public:
00169
00170 ScopedLock(const UserDefinedGetterSetter& na)
00171 :
00172 _a(na),
00173 _obtainedLock(_a._beingAccessed ? false : true)
00174 {
00175
00176
00177 if (_obtainedLock) _a._beingAccessed = true;
00178 }
00179
00180 ~ScopedLock() { if ( _obtainedLock) _a._beingAccessed = false; }
00181
00183
00188 bool obtainedLock() const { return _obtainedLock; }
00189
00190 private:
00191
00192 const UserDefinedGetterSetter& _a;
00193 bool _obtainedLock;
00194
00195 };
00196 };
00197
00199 class NativeGetterSetter {
00200
00201 public:
00202
00203 NativeGetterSetter(as_c_function_ptr get, as_c_function_ptr set)
00204 :
00205 _getter(get), _setter(set) {}
00206
00208 as_value get(fn_call& fn) const
00209 {
00210 return _getter(fn);
00211 }
00212
00214 void set(fn_call& fn)
00215 {
00216 _setter(fn);
00217 }
00218
00219 private:
00220
00221 as_c_function_ptr _getter;
00222 as_c_function_ptr _setter;
00223 };
00224
00225 boost::variant<UserDefinedGetterSetter, NativeGetterSetter> _getset;
00226
00227 };
00228
00230
00232
00236 class Property
00237 {
00238 public:
00240 Property(const ObjectURI& uri)
00241 :
00242 _bound(as_value()),
00243 _destructive(false),
00244 _uri(uri)
00245 {}
00246
00247 Property(const ObjectURI& uri, const as_value& value,
00248 const PropFlags& flags = PropFlags())
00249 :
00250 _flags(flags),
00251 _bound(value),
00252 _destructive(false),
00253 _uri(uri)
00254 {}
00255
00256 Property(const ObjectURI& uri,
00257 as_function *getter, as_function *setter,
00258 const PropFlags& flags, bool destroy = false)
00259 :
00260 _flags(flags),
00261 _bound(GetterSetter(getter, setter)),
00262 _destructive(destroy),
00263 _uri(uri)
00264 {}
00265
00266 Property(const ObjectURI& uri, as_function *getter, as_function *setter,
00267 bool destroy = false)
00268 :
00269 _flags(),
00270 _bound(GetterSetter(getter, setter)),
00271 _destructive(destroy),
00272 _uri(uri)
00273 {}
00274
00275 Property(const ObjectURI& uri, as_c_function_ptr getter,
00276 as_c_function_ptr setter, const PropFlags& flags,
00277 bool destroy = false)
00278 :
00279 _flags(flags),
00280 _bound(GetterSetter(getter, setter)),
00281 _destructive(destroy),
00282 _uri(uri)
00283 {}
00284
00286 Property(const Property& p)
00287 :
00288 _flags(p._flags),
00289 _bound(p._bound),
00290 _destructive(p._destructive),
00291 _uri(p._uri)
00292 {}
00293
00295 const PropFlags& getFlags() const { return _flags; }
00296
00298 void setFlags(const PropFlags& flags) const {
00299 _flags = flags;
00300 }
00301
00303
00311 as_value getValue(const as_object& this_ptr) const;
00312
00314
00320 const as_value& getCache() const;
00321
00323
00329 void setCache(const as_value& v);
00330
00332
00346 void setValue(as_object& this_ptr, const as_value &value) const;
00347
00349 bool isGetterSetter() const {
00350 return _bound.which() == TYPE_GETTER_SETTER;
00351 }
00352
00354 bool isDestructive() const { return _destructive; }
00355
00357 void clearVisible(int swfVersion) { _flags.clear_visible(swfVersion); }
00358
00360 const ObjectURI& uri() const {
00361 return _uri;
00362 }
00363
00365 void setReachable() const;
00366
00367 private:
00368
00370 as_value getDelayedValue(const as_object& this_ptr) const;
00371
00373 void setDelayedValue(as_object& this_ptr, const as_value& value) const;
00374
00375 enum Type {
00376 TYPE_EMPTY,
00377 TYPE_VALUE,
00378 TYPE_GETTER_SETTER
00379 };
00380
00382 mutable PropFlags _flags;
00383
00384
00385 typedef boost::variant<boost::blank, as_value, GetterSetter> BoundType;
00386
00388 mutable BoundType _bound;
00389
00390
00391
00392
00393 mutable bool _destructive;
00394
00395
00396 ObjectURI _uri;
00397
00398 };
00399
00401 inline bool
00402 readOnly(const Property& prop) {
00403 return prop.getFlags().get_read_only();
00404 }
00405
00407 inline bool
00408 visible(const Property& prop, int version) {
00409 return prop.getFlags().get_visible(version);
00410 }
00411
00412 }
00413
00414 #endif // GNASH_PROPERTY_H