1 // 2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 3 // Free Software Foundation, Inc 4 // 5 // This program is free software; you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation; either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with this program; if not, write to the Free Software 17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 19 #ifndef GNASH_PROPERTYLIST_H 20 #define GNASH_PROPERTYLIST_H 21 22 #include <set> 23 #include <string> // for use within map 24 #include <cassert> // for inlines 25 #include <utility> // for std::pair 26 #include <cstdint> 27 #include <boost/multi_index_container.hpp> 28 #include <boost/multi_index/ordered_index.hpp> 29 #include <boost/multi_index/sequenced_index.hpp> 30 #include <boost/multi_index/key_extractors.hpp> 31 #include <boost/noncopyable.hpp> 32 #include <functional> 33 #include <algorithm> 34 35 #include "Property.h" // for templated functions 36 #include "dsodefs.h" // for DSOTEXPORT 37 38 // Forward declaration 39 namespace gnash { 40 class as_object; 41 class as_function; 42 struct ObjectURI; 43 class as_value; 44 } 45 46 namespace gnash { 47 48 /// An abstract property visitor 49 class PropertyVisitor { 50 public: 51 52 /// This function should return false if no further visits are needed. 53 virtual bool accept(const ObjectURI& uri, const as_value& val) = 0; ~PropertyVisitor()54 virtual ~PropertyVisitor() {} 55 }; 56 57 /// An abstract key visitor 58 class KeyVisitor { 59 public: 60 61 /// This function should return false if no further visits are needed. 62 virtual void operator()(const ObjectURI& uri) = 0; ~KeyVisitor()63 virtual ~KeyVisitor() {} 64 }; 65 66 67 /// Set of properties associated with an ActionScript object. 68 // 69 /// The PropertyList container is the sole owner of the Property 70 /// elements in it contained and has full responsibility of their 71 /// construction and destruction. 72 // 73 /// A PropertyList holds a reference to the as_object whose properties it 74 /// contains. This reference will always be valid if the PropertyList 75 /// is a member of as_object. 76 // 77 /// It is theoretically possible for a PropertyList to be used with any 78 /// as_object, not just original as_object it was use with. Currently (as 79 /// there is no use for this scenario) it is not possible to change the 80 /// owner. 81 class PropertyList : boost::noncopyable 82 { 83 public: 84 85 typedef std::set<ObjectURI, ObjectURI::LessThan> PropertyTracker; 86 typedef Property value_type; 87 88 /// Identifier for the sequenced index 89 struct CreationOrder {}; 90 91 /// The sequenced index in creation order. 92 typedef boost::multi_index::sequenced< 93 boost::multi_index::tag<CreationOrder> > SequencedIndex; 94 95 struct KeyExtractor 96 { 97 typedef const ObjectURI& result_type; operatorKeyExtractor98 result_type operator()(const Property& p) const { 99 return p.uri(); 100 } 101 }; 102 103 /// Identifier for the case-sensitive index 104 struct Case {}; 105 106 /// The case-sensitive index 107 typedef boost::multi_index::ordered_unique< 108 boost::multi_index::tag<Case>, 109 KeyExtractor, 110 ObjectURI::LessThan> CaseIndex; 111 112 /// Identifier for the case-insensitive index 113 struct NoCase {}; 114 115 /// The case-insensitive index 116 typedef boost::multi_index::ordered_non_unique< 117 boost::multi_index::tag<NoCase>, 118 KeyExtractor, 119 ObjectURI::CaseLessThan> NoCaseIndex; 120 121 /// The container of the Properties. 122 typedef boost::multi_index_container< 123 value_type, 124 boost::multi_index::indexed_by<SequencedIndex, CaseIndex, NoCaseIndex> 125 > container; 126 127 typedef container::iterator iterator; 128 typedef container::const_iterator const_iterator; 129 130 /// Construct the PropertyList 131 // 132 /// @param obj The as_object to which this PropertyList belongs. 133 DSOTEXPORT PropertyList(as_object& obj); 134 135 /// Visit properties 136 // 137 /// The method will invoke the given visitor method 138 /// passing it two arguments: name of the property and 139 /// value of it. 140 // 141 /// @tparam V The type of the visitor. 142 /// @tparam U An object that may check property values. The object's 143 /// operator() should return false if the property is not 144 /// acceptable. 145 // 146 /// @param visitor The visitor function. It must implement the function: 147 /// bool accept(const ObjectURI&, const as_value&); 148 /// Scan is by enumeration order and stops when accept() 149 /// returns false. 150 template <class U, class V> 151 void visitValues(V& visitor, U cmp = U()) const { 152 153 for (const auto& prop : _props) { 154 155 if (!cmp(prop)) continue; 156 as_value val = prop.getValue(_owner); 157 if (!visitor.accept(prop.uri(), val)) return; 158 } 159 } 160 161 /// Enumerate all non-hidden properties to the given container. 162 // 163 /// Follows enumeration order. Note that this enumeration does not 164 /// access the values. Accessing the values can result in changes to 165 /// the object if the value is a getter-setter, and key enumeration must 166 /// avoid this. 167 /// 168 /// @param donelist Don't enumerate properties in donelist. 169 /// Enumerated properties are added to donelist. 170 void visitKeys(KeyVisitor& v, PropertyTracker& donelist) const; 171 172 /// Set the value of a property, creating a new one if it doesn't exist. 173 // 174 /// If the named property is a getter/setter one it's setter 175 /// will be invoked using the given as_object as 'this' pointer. 176 /// If the property is not found a SimpleProperty will be created. 177 /// 178 /// @param uri 179 /// Name of the property. 180 /// @param value 181 /// a const reference to the as_value to use for setting 182 /// or creating the property. 183 /// @param flagsIfMissing 184 /// Flags to associate to the property if a new one is created. 185 /// @return true if the value was successfully set, false 186 /// otherwise (found a read-only property, most likely). 187 DSOTEXPORT bool setValue(const ObjectURI& uri, const as_value& value, 188 const PropFlags& flagsIfMissing = 0); 189 190 /// Get a property if it exists. 191 // 192 /// @param uri Name of the property. 193 /// @return A Property or 0, if no such property exists. 194 /// All Property objects are owned by this PropertyList. Do 195 /// not delete them. 196 DSOTEXPORT Property* getProperty(const ObjectURI& uri) const; 197 198 /// Delete a Property, if existing and not protected from deletion. 199 // 200 /// 201 /// @param uri Name of the property. 202 /// @return a pair of boolean values expressing whether the property 203 /// was found (first) and whether it was deleted (second). 204 /// Of course a pair(false, true) would be invalid (deleted 205 /// a non-found property!?). Valid returns are: 206 /// - (false, false) : property not found 207 /// - (true, false) : property protected from deletion 208 /// - (true, true) : property successfully deleted 209 DSOTEXPORT std::pair<bool,bool> delProperty(const ObjectURI& uri); 210 211 /// Add a getter/setter property, if not already existing 212 // 213 /// TODO: this function has far too many arguments. 214 // 215 /// @param uri Name of the property. 216 /// @param getter A function to invoke when this property value is 217 /// requested. 218 /// @param setter A function to invoke when setting this property's value. 219 /// @param cacheVal The value to use as a cache. If null uses any cache 220 /// from pre-existing property with same name. 221 /// @param flagsIfMissing Flags to associate to the property if a new one 222 /// is created. 223 /// @return true if the property was successfully added, false 224 /// otherwise. 225 bool addGetterSetter(const ObjectURI& uri, as_function& getter, 226 as_function* setter, const as_value& cacheVal, 227 const PropFlags& flagsIfMissing = 0); 228 229 /// Add a getter/setter property, if not already existing 230 // 231 /// @param uri Name of the property. 232 /// @param getter A function to invoke when this property value is 233 /// requested. 234 /// @param setter A function to invoke when setting this property's value. 235 /// @return true if the property was successfully added, false 236 /// otherwise. 237 bool addGetterSetter(const ObjectURI& uri, as_c_function_ptr getter, 238 as_c_function_ptr setter, const PropFlags& flagsIfMissing); 239 240 /// Add a destructive getter property, if not already existant. 241 // 242 /// @param uri Name of the property. 243 /// @param getter A function to invoke when this property value is 244 /// requested. 245 /// @param flagsIfMissing Flags to associate to the property if a new 246 /// one is created. 247 /// @return true if the property was successfully added. 248 bool addDestructiveGetter(const ObjectURI& uri, as_function& getter, 249 const PropFlags& flagsIfMissing = 0); 250 251 /// Add a destructive getter property, if not already existant. 252 /// 253 /// @param uri Name of the property. 254 /// @param getter A function to invoke when this property value is 255 /// requested. 256 /// 257 /// @param flagsIfMissing Flags to associate to the property if a new 258 // one is created. 259 /// @return true if the property was successfully added, false 260 /// otherwise. 261 bool addDestructiveGetter(const ObjectURI& uri, as_c_function_ptr getter, 262 const PropFlags& flagsIfMissing = 0); 263 264 /// Set the flags of a property. 265 // 266 /// @param uri Name of the property. 267 /// @param setTrue The set of flags to set 268 /// @param setFalse The set of flags to clear 269 DSOTEXPORT void setFlags(const ObjectURI& uri, int setTrue, int setFalse); 270 271 /// Set the flags of all properties. 272 // 273 /// @param setTrue The set of flags to set 274 /// @param setFalse The set of flags to clear 275 void setFlagsAll(int setTrue, int setFalse); 276 277 /// Remove all entries in the container 278 void clear(); 279 280 /// Return number of properties in this list size()281 size_t size() const { 282 return _props.size(); 283 } 284 285 /// Dump all members (using log_debug) 286 // 287 /// This does not reflect the normal enumeration order. It is sorted 288 /// lexicographically by property. 289 void dump(); 290 291 /// Mark all properties reachable 292 // 293 /// This can be called very frequently, so is inlined to allow the 294 /// compiler to optimize it. setReachable()295 void setReachable() const { 296 std::for_each(_props.begin(), _props.end(), 297 std::mem_fn(&Property::setReachable)); 298 } 299 300 private: 301 302 container _props; 303 304 as_object& _owner; 305 306 }; 307 308 309 } // namespace gnash 310 311 #endif // GNASH_PROPERTYLIST_H 312