Gnash  0.8.11dev
Property.h
Go to the documentation of this file.
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 
20 #ifndef GNASH_PROPERTY_H
21 #define GNASH_PROPERTY_H
22 
23 #include <boost/variant.hpp>
24 #include <cassert>
25 #include <boost/bind.hpp>
26 #include <typeinfo>
27 
28 #include "PropFlags.h"
29 #include "as_value.h"
30 #include "ObjectURI.h"
31 
32 namespace gnash {
33  typedef as_value (*as_c_function_ptr)(const fn_call& fn);
34  class as_function;
35 }
36 
37 namespace gnash {
38 
40 //
44 {
45  class NativeGetterSetter;
46 
47  // The following helper structs define common operations on the
48  // Two types of GetterSetter. Some operations are applicable only to
49  // one type.
50 
52  //
56  template<typename Arg, typename S>
57  struct GetSetVisitor : boost::static_visitor<typename S::result_type>
58  {
59  GetSetVisitor(const Arg& arg) : _arg(arg) {}
60  template<typename T> typename S::result_type operator()(T& t) const {
61  return S()(t, _arg);
62  }
63  private:
64  const Arg& _arg;
65  };
66 
68  struct Set
69  {
70  typedef void result_type;
71  template<typename T, typename Arg>
72  result_type operator()(T& t, Arg& a) const {
73  t.set(a);
74  }
75  };
76 
78  struct Get
79  {
80  typedef as_value result_type;
81  template<typename T, typename Arg>
82  result_type operator()(T& t, Arg& a) const {
83  return t.get(a);
84  }
85  };
86 
88  //
90  struct SetUnderlying : boost::static_visitor<>
91  {
92  template<typename T>
93  result_type operator()(T& gs, const as_value& val) const {
94  gs.setUnderlying(val);
95  }
96  result_type operator()(NativeGetterSetter&, const as_value&) const {}
97  };
98 
100  //
102  struct GetUnderlying : boost::static_visitor<as_value>
103  {
104  template<typename T>
105  result_type operator()(const T& gs) const {
106  return gs.getUnderlying();
107  }
108  result_type operator()(const NativeGetterSetter&) const {
109  return result_type();
110  }
111  };
112 
114  struct MarkReachable : boost::static_visitor<>
115  {
116  template<typename T>
117  result_type operator()(const T& gs) const {
118  gs.markReachableResources();
119  }
120  };
121 
122 public:
123 
126  :
127  _getset(UserDefinedGetterSetter(getter, setter))
128  {}
129 
132  :
133  _getset(NativeGetterSetter(getter, setter))
134  {}
135 
137  as_value get(fn_call& fn) const {
138  GetSetVisitor<const fn_call, Get> s(fn);
139  return boost::apply_visitor(s, _getset);
140  }
141 
143  void set(const fn_call& fn) {
144  GetSetVisitor<fn_call, Set> s(fn);
145  boost::apply_visitor(s, _getset);
146  }
147 
149  void setCache(const as_value& v) {
150  boost::apply_visitor(boost::bind(SetUnderlying(), _1, v), _getset);
151  }
152 
154  as_value getCache() const {
155  return boost::apply_visitor(GetUnderlying(), _getset);
156  }
157 
158  void markReachableResources() const {
159  boost::apply_visitor(MarkReachable(), _getset);
160  }
161 
162 private:
163 
165  class UserDefinedGetterSetter
166  {
167  public:
168 
169  UserDefinedGetterSetter(as_function* get, as_function* set)
170  :
171  _getter(get),
172  _setter(set),
173  _underlyingValue(),
174  _beingAccessed(false)
175  {}
176 
178  as_value get(const fn_call& fn) const;
179 
181  void set(const fn_call& fn);
182 
184  const as_value& getUnderlying() const { return _underlyingValue; }
185 
187  void setUnderlying(const as_value& v) { _underlyingValue = v; }
188 
189  void markReachableResources() const;
190 
191  private:
192 
196  //
199  class ScopedLock : boost::noncopyable
200  {
201  public:
202 
203  explicit ScopedLock(const UserDefinedGetterSetter& na)
204  :
205  _a(na),
206  _obtainedLock(_a._beingAccessed ? false : true)
207  {
208  // If we didn't obtain the lock it would be true anyway,
209  // but it's probably polite to avoid touching it.
210  if (_obtainedLock) _a._beingAccessed = true;
211  }
212 
213  ~ScopedLock() { if ( _obtainedLock) _a._beingAccessed = false; }
214 
216  //
221  bool obtainedLock() const { return _obtainedLock; }
222 
223  private:
224 
225  const UserDefinedGetterSetter& _a;
226  bool _obtainedLock;
227 
228  };
229 
230  as_function* _getter;
231  as_function* _setter;
232  as_value _underlyingValue;
233  mutable bool _beingAccessed;
234  };
235 
237  class NativeGetterSetter
238  {
239  public:
240 
241  NativeGetterSetter(as_c_function_ptr get, as_c_function_ptr set)
242  :
243  _getter(get), _setter(set) {}
244 
246  as_value get(const fn_call& fn) const {
247  return _getter(fn);
248  }
249 
251  void set(const fn_call& fn) {
252  _setter(fn);
253  }
254 
256  void markReachableResources() const {}
257 
258  private:
259  as_c_function_ptr _getter;
260  as_c_function_ptr _setter;
261  };
262 
263  boost::variant<UserDefinedGetterSetter, NativeGetterSetter> _getset;
264 
265 };
266 
268 //
270 //
274 class Property
275 {
276 
278  struct SetReachable : boost::static_visitor<>
279  {
280  result_type operator()(const as_value& val) const {
281  val.setReachable();
282  }
283  result_type operator()(const GetterSetter& gs) const {
284  return gs.markReachableResources();
285  }
286  };
287 
288 public:
289 
290  Property(const ObjectURI& uri, const as_value& value,
291  const PropFlags& flags)
292  :
293  _bound(value),
294  _uri(uri),
295  _flags(flags),
296  _destructive(false)
297  {}
298 
300  as_function* getter, as_function* setter,
301  const PropFlags& flags, bool destroy = false)
302  :
303  _bound(GetterSetter(getter, setter)),
304  _uri(uri),
305  _flags(flags),
306  _destructive(destroy)
307  {}
308 
310  as_c_function_ptr setter, const PropFlags& flags,
311  bool destroy = false)
312  :
313  _bound(GetterSetter(getter, setter)),
314  _uri(uri),
315  _flags(flags),
316  _destructive(destroy)
317  {}
318 
321  :
322  _bound(p._bound),
323  _uri(p._uri),
324  _flags(p._flags),
325  _destructive(p._destructive)
326  {}
327 
329  const PropFlags& getFlags() const { return _flags; }
330 
332  void setFlags(const PropFlags& flags) const {
333  _flags = flags;
334  }
335 
337  //
345  as_value getValue(const as_object& this_ptr) const;
346 
348  //
354  as_value getCache() const;
355 
357  //
363  void setCache(const as_value& v);
364 
366  //
381  bool setValue(as_object& this_ptr, const as_value &value) const;
382 
384  bool isGetterSetter() const {
385  return _bound.type() == typeid(GetterSetter);
386  }
387 
389  void clearVisible(int swfVersion) { _flags.clear_visible(swfVersion); }
390 
392  const ObjectURI& uri() const {
393  return _uri;
394  }
395 
397  void setReachable() const {
398  return boost::apply_visitor(SetReachable(), _bound);
399  }
400 
401 private:
402 
403  // Store the various types of things that can be held.
404  typedef boost::variant<as_value, GetterSetter> BoundType;
405 
407  mutable BoundType _bound;
408 
410  ObjectURI _uri;
411 
413  mutable PropFlags _flags;
414 
415  // If true, as soon as getValue has been invoked once, the
416  // returned value becomes a fixed return (though it can be
417  // overwritten if not readOnly)
418  mutable bool _destructive;
419 
420 };
421 
423 inline bool
424 readOnly(const Property& prop) {
425  return prop.getFlags().test<PropFlags::readOnly>();
426 }
427 
429 inline bool
430 visible(const Property& prop, int version) {
431  return prop.getFlags().get_visible(version);
432 }
433 
434 } // namespace gnash
435 
436 #endif // GNASH_PROPERTY_H