Gnash
0.8.10
|
00001 // 00002 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 00003 // Free Software Foundation, Inc 00004 // 00005 // This program is free software; you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation; either version 3 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // This program is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with this program; if not, write to the Free Software 00017 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 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 // The following helper structs define common operations on the 00048 // Two types of GetterSetter. Some operations are applicable only to 00049 // one type. 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 // If we didn't obtain the lock it would be true anyway, 00209 // but it's probably polite to avoid touching it. 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 // Store the various types of things that can be held. 00404 typedef boost::variant<as_value, GetterSetter> BoundType; 00405 00407 mutable BoundType _bound; 00408 00410 ObjectURI _uri; 00411 00413 mutable PropFlags _flags; 00414 00415 // If true, as soon as getValue has been invoked once, the 00416 // returned value becomes a fixed return (though it can be 00417 // overwritten if not readOnly) 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 } // namespace gnash 00435 00436 #endif // GNASH_PROPERTY_H