don't add (LIBLTDL) to LDFLAGS, libltdl is part of libgnashbase.
[gnash.git] / libcore / PropertyList.cpp
blobb15ec3a3372f7e544093006f4e040b0ff311aa0a
1 // PropertyList.cpp: ActionScript property lists, for Gnash.
2 //
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
4 // Foundation, Inc
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #ifdef HAVE_CONFIG_H
22 #include "gnashconfig.h" // GNASH_STATS_PROPERTY_LOOKUPS
23 #endif
25 #include "PropertyList.h"
27 #include <utility>
28 #include <boost/bind.hpp>
29 #include <boost/tuple/tuple.hpp>
31 #include "Property.h"
32 #include "as_environment.h"
33 #include "log.h"
34 #include "as_function.h"
35 #include "as_value.h"
36 #include "VM.h"
37 #include "string_table.h"
38 #include "GnashAlgorithm.h"
40 // Define the following to enable printing address of each property added
41 //#define DEBUG_PROPERTY_ALLOC
43 // Define this to get verbosity of properties insertion and flags setting
44 //#define GNASH_DEBUG_PROPERTY 1
46 // Define this to get stats of property lookups
47 //#define GNASH_STATS_PROPERTY_LOOKUPS 1
49 #ifdef GNASH_STATS_PROPERTY_LOOKUPS
50 # include "Stats.h"
51 # include "namedStrings.h"
52 #endif
54 namespace gnash {
56 namespace {
58 inline
59 PropertyList::const_iterator
60 iterator_find(const PropertyList::container& p, const ObjectURI& uri, VM& vm)
62 const bool caseless = vm.getSWFVersion() < 7;
64 if (!caseless) {
65 return p.project<PropertyList::CreationOrder>(
66 p.get<PropertyList::Case>().find(uri));
69 return p.project<PropertyList::CreationOrder>(
70 p.get<PropertyList::NoCase>().find(uri));
75 PropertyList::PropertyList(as_object& obj)
77 _props(boost::make_tuple(
78 boost::tuple<>(),
79 boost::make_tuple(
80 KeyExtractor(),
81 ObjectURI::LessThan()
83 boost::make_tuple(
84 KeyExtractor(),
85 ObjectURI::CaseLessThan(getStringTable(obj), true)
89 _owner(obj)
93 bool
94 PropertyList::setValue(const ObjectURI& uri, const as_value& val,
95 const PropFlags& flagsIfMissing)
97 const_iterator found = iterator_find(_props, uri, getVM(_owner));
99 if (found == _props.end()) {
100 // create a new member
101 Property a(uri, val, flagsIfMissing);
102 // Non slot properties are negative ordering in insertion order
103 _props.push_back(a);
104 #ifdef GNASH_DEBUG_PROPERTY
105 ObjectURI::Logger l(getStringTable(_owner));
106 log_debug("Simple AS property %s inserted with flags %s",
107 l(uri), a.getFlags());
108 #endif
109 return true;
112 const Property& prop = *found;
113 if (readOnly(prop)) {
114 ObjectURI::Logger l(getStringTable(_owner));
115 log_error(_("Property %s is read-only %s, not setting it to %s"),
116 l(uri), prop.getFlags(), val);
117 return false;
120 prop.setValue(_owner, val);
122 return true;
125 void
126 PropertyList::setFlags(const ObjectURI& uri, int setFlags, int clearFlags)
128 iterator found = iterator_find(_props, uri, getVM(_owner));
129 if (found == _props.end()) return;
130 PropFlags f = found->getFlags();
131 f.set_flags(setFlags, clearFlags);
132 found->setFlags(f);
136 void
137 PropertyList::setFlagsAll(int setFlags, int clearFlags)
139 for (const_iterator it = _props.begin(); it != _props.end(); ++it) {
140 PropFlags f = it->getFlags();
141 f.set_flags(setFlags, clearFlags);
142 it->setFlags(f);
146 Property*
147 PropertyList::getProperty(const ObjectURI& uri) const
149 #ifdef GNASH_STATS_PROPERTY_LOOKUPS
150 // HINT: can add a final arg to KeyLookup ctor, like NSV::PROP_ON_MOUSE_MOVE
151 // to have *that* property lookup drive dump triggers
152 static stats::KeyLookup kcl("getProperty",
153 getStringTable(_owner), 10000000, NSV::PROP_uuPROTOuu, 10);
154 kcl.check(uri.name);
155 #endif // GNASH_STATS_PROPERTY_LOOKUPS
156 iterator found = iterator_find(_props, uri, getVM(_owner));
157 if (found == _props.end()) return 0;
158 return const_cast<Property*>(&(*found));
161 std::pair<bool,bool>
162 PropertyList::delProperty(const ObjectURI& uri)
164 //GNASH_REPORT_FUNCTION;
165 iterator found = iterator_find(_props, uri, getVM(_owner));
166 if (found == _props.end()) {
167 return std::make_pair(false, false);
170 // check if member is protected from deletion
171 if (found->getFlags().test<PropFlags::dontDelete>()) {
172 return std::make_pair(true, false);
175 _props.erase(found);
176 return std::make_pair(true, true);
179 void
180 PropertyList::visitKeys(KeyVisitor& visitor, PropertyTracker& donelist)
181 const
183 // We should enumerate in order of creation, not lexicographically.
184 for (const_iterator i = _props.begin(),
185 ie = _props.end(); i != ie; ++i) {
187 if (i->getFlags().test<PropFlags::dontEnum>()) continue;
189 const ObjectURI& uri = i->uri();
191 if (donelist.insert(uri).second) {
192 visitor(uri);
197 void
198 PropertyList::dump()
200 ObjectURI::Logger l(getStringTable(_owner));
201 for (const_iterator it=_props.begin(), itEnd=_props.end();
202 it != itEnd; ++it) {
203 log_debug(" %s: %s", l(it->uri()), it->getValue(_owner));
207 bool
208 PropertyList::addGetterSetter(const ObjectURI& uri, as_function& getter,
209 as_function* setter, const as_value& cacheVal,
210 const PropFlags& flagsIfMissing)
212 Property a(uri, &getter, setter, flagsIfMissing);
213 iterator found = iterator_find(_props, uri, getVM(_owner));
215 if (found != _props.end()) {
216 // copy flags from previous member (even if it's a normal member ?)
217 a.setFlags(found->getFlags());
218 a.setCache(found->getCache());
219 _props.replace(found, a);
221 #ifdef GNASH_DEBUG_PROPERTY
222 ObjectURI::Logger l(getStringTable(_owner));
223 log_debug("AS GetterSetter %s replaced copying flags %s", l(uri),
224 a.getFlags());
225 #endif
228 else {
229 a.setCache(cacheVal);
230 _props.push_back(a);
231 #ifdef GNASH_DEBUG_PROPERTY
232 ObjectURI::Logger l(getStringTable(_owner));
233 log_debug("AS GetterSetter %s inserted with flags %s", l(uri),
234 a.getFlags());
235 #endif
238 return true;
241 bool
242 PropertyList::addGetterSetter(const ObjectURI& uri, as_c_function_ptr getter,
243 as_c_function_ptr setter, const PropFlags& flagsIfMissing)
245 Property a(uri, getter, setter, flagsIfMissing);
247 const_iterator found = iterator_find(_props, uri, getVM(_owner));
248 if (found != _props.end())
250 // copy flags from previous member (even if it's a normal member ?)
251 a.setFlags(found->getFlags());
252 _props.replace(found, a);
254 #ifdef GNASH_DEBUG_PROPERTY
255 ObjectURI::Logger l(getStringTable(_owner));
256 log_debug("Native GetterSetter %s replaced copying flags %s", l(uri),
257 a.getFlags());
258 #endif
261 else
263 _props.push_back(a);
264 #ifdef GNASH_DEBUG_PROPERTY
265 string_table& st = getStringTable(_owner);
266 log_debug("Native GetterSetter %s in namespace %s inserted with "
267 "flags %s", st.value(key), st.value(nsId), a.getFlags());
268 #endif
271 return true;
274 bool
275 PropertyList::addDestructiveGetter(const ObjectURI& uri, as_function& getter,
276 const PropFlags& flagsIfMissing)
278 const_iterator found = iterator_find(_props, uri, getVM(_owner));
279 if (found != _props.end())
281 ObjectURI::Logger l(getStringTable(_owner));
282 log_error("Property %s already exists, can't addDestructiveGetter",
283 l(uri));
284 return false; // Already exists.
287 // destructive getter doesn't need a setter
288 Property a(uri, &getter, 0, flagsIfMissing, true);
290 _props.push_back(a);
292 #ifdef GNASH_DEBUG_PROPERTY
293 ObjectURI::Logger l(getStringTable(_owner));
294 log_debug("Destructive AS property %s inserted with flags %s",
295 l(uri), a.getFlags());
296 #endif
298 return true;
301 bool
302 PropertyList::addDestructiveGetter(const ObjectURI& uri,
303 as_c_function_ptr getter, const PropFlags& flagsIfMissing)
305 iterator found = iterator_find(_props, uri, getVM(_owner));
306 if (found != _props.end()) return false;
308 // destructive getter doesn't need a setter
309 Property a(uri, getter, 0, flagsIfMissing, true);
310 _props.push_back(a);
312 #ifdef GNASH_DEBUG_PROPERTY
313 ObjectURI::Logger l(getStringTable(_owner));
314 log_debug("Destructive native property %s with flags %s", l(uri),
315 a.getFlags());
316 #endif
317 return true;
320 void
321 PropertyList::clear()
323 _props.clear();
326 } // namespace gnash