• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • Examples
  • File List
  • File Members

Property.h

Go to the documentation of this file.
00001 // 
00002 //   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
00003 //   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 "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: // user-defined
00064                                 return boost::get<UserDefinedGetterSetter>(_getset).get(fn);
00065                                 break;
00066                         case 1: // native 
00067                                 return boost::get<NativeGetterSetter>(_getset).get(fn);
00068                                 break;
00069                 }
00070                 return as_value(); // not reached (TODO: log error ? assert ?)
00071         }
00072 
00074         void set(fn_call& fn)
00075         {
00076                 switch ( _getset.which() )
00077                 {
00078                         case 0: // user-defined
00079                                 boost::get<UserDefinedGetterSetter>(_getset).set(fn);
00080                                 break;
00081                         case 1: // native 
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: // user-defined
00093                                 boost::get<UserDefinedGetterSetter>(_getset).setUnderlying(v);
00094                                 break;
00095                         case 1: // native 
00096                                 // nothing to do for native
00097                                 break;
00098                 }
00099         }
00100 
00102         const as_value& getCache() const
00103         {
00104                 switch (_getset.which())
00105                 {
00106                         case 0: // user-defined
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                 // If we didn't obtain the lock it would be true anyway,
00176                 // but it's probably polite to avoid touching it.
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         // Store the various types of things that can be held.
00385         typedef boost::variant<boost::blank, as_value, GetterSetter> BoundType;
00386 
00388         mutable BoundType _bound;
00389 
00390         // If true, as soon as getValue has been invoked once, the
00391         // returned value becomes a fixed return (though it can be
00392         // overwritten if not readOnly)
00393         mutable bool _destructive;
00394         
00395     // TODO: this should be const, but the assignment operator is still needed 
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 } // namespace gnash
00413 
00414 #endif // GNASH_PROPERTY_H

Generated on Fri Mar 16 2012 15:46:11 for Gnash by  doxygen 1.7.1