Gnash  0.8.11dev
as_value.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 #ifndef GNASH_AS_VALUE_H
20 #define GNASH_AS_VALUE_H
21 
22 #include "dsodefs.h"
23 #include "CharacterProxy.h"
24 
25 #include <limits>
26 #include <string>
27 #include <boost/variant.hpp>
28 #include <iosfwd> // for inlined output operator
29 #include <boost/type_traits/is_floating_point.hpp>
30 #include <boost/utility/enable_if.hpp>
31 #include <boost/cstdint.hpp>
32 
33 #include "utility.h" // UNUSED
34 
35 // Forward declarations
36 namespace gnash {
37  class VM;
38  class as_object;
39  class Global_as;
40  class fn_call;
41  class as_function;
42  class MovieClip;
43  class DisplayObject;
44  namespace amf {
45  class Writer;
46  }
47 }
48 
49 namespace gnash {
50 
51 
52 // NaN constant for use in as_value implementation
53 static const double NaN = std::numeric_limits<double>::quiet_NaN();
54 
55 // The following template works just like its C counterpart, with added
56 // type safety (i.e., they will only compile for floating point arguments).
57 template <typename T>
58 inline bool
59 isNaN(const T& num, typename boost::enable_if<boost::is_floating_point<T> >::
60  type* dummy = 0)
61 {
62  UNUSED(dummy);
63  return num != num;
64 }
65 
66 template <typename T>
67 inline bool
68 isInf(const T& num)
69 {
70  return isNaN(num - num);
71 }
72 
73 
76 {
80 };
81 
83 //
85 //
88 //
91 //
97 //
103 //
106 class as_value
107 {
108 
109 public:
110 
111  // The exception type should always be one greater than the normal type.
112  enum AsType
113  {
128  };
129 
132  :
133  _type(UNDEFINED),
134  _value(boost::blank())
135  {
136  }
137 
140  :
141  _type(v._type),
142  _value(v._value)
143  {
144  }
145 
147 
149  DSOEXPORT as_value(const char* str)
150  :
151  _type(STRING),
152  _value(std::string(str))
153  {}
154 
156  DSOEXPORT as_value(const std::string& str)
157  :
158  _type(STRING),
159  _value(std::string(str))
160  {}
161 
163  template <typename T>
164  as_value(T val, typename boost::enable_if<boost::is_same<bool, T> >::type*
165  dummy = 0)
166  :
167  _type(BOOLEAN),
168  _value(val)
169  {
170  UNUSED(dummy);
171  }
172 
174  as_value(double num)
175  :
176  _type(NUMBER),
177  _value(num)
178  {}
179 
182  :
183  _type(UNDEFINED)
184  {
185  set_as_object(obj);
186  }
187 
190  {
191  _type = v._type;
192  _value = v._value;
193  return *this;
194  }
195 
196  friend std::ostream& operator<<(std::ostream& o, const as_value&);
197 
199  const char* typeOf() const;
200 
202  bool is_function() const;
203 
205  bool is_string() const {
206  return _type == STRING;
207  }
208 
210  bool is_number() const {
211  return _type == NUMBER;
212  }
213 
215  //
217  bool is_object() const {
218  return _type == OBJECT || _type == DISPLAYOBJECT;
219  }
220 
222  bool is_sprite() const {
223  return _type == DISPLAYOBJECT;
224  }
225 
227  //
232  //
234  std::string to_string(int version = 7) const;
235 
237  //
239  double to_number(int version) const;
240 
242  //
244  bool to_bool(int version) const;
245 
247  //
249  //
256  //
260  as_object* to_object(VM& vm) const;
261 
263  //
266  as_object* get_object() const;
267 
269  //
272  //
275  MovieClip* toMovieClip(bool skipRebinding = false) const;
276 
278  //
281  //
292  DisplayObject* toDisplayObject(bool skipRebinding = false) const;
293 
295  //
298  as_function* to_function() const;
299 
300  AsType defaultPrimitive(int version) const;
301 
303  //
305  //
314  as_value to_primitive(AsType hint) const;
315 
317  void set_string(const std::string& str);
318 
320  void set_double(double val);
321 
323  void set_bool(bool val);
324 
326  void set_as_object(as_object* obj);
327 
329  void set_undefined();
330 
332  void set_null();
333 
334  bool is_undefined() const {
335  return (_type == UNDEFINED);
336  }
337 
338  bool is_null() const {
339  return (_type == NULLTYPE);
340  }
341 
342  bool is_bool() const {
343  return (_type == BOOLEAN);
344  }
345 
346  bool is_exception() const {
347  return (_type == UNDEFINED_EXCEPT || _type == NULLTYPE_EXCEPT
348  || _type == BOOLEAN_EXCEPT || _type == NUMBER_EXCEPT
349  || _type == OBJECT_EXCEPT || _type == DISPLAYOBJECT_EXCEPT
350  || _type == STRING_EXCEPT);
351  }
352 
353  // Flag or unflag an as_value as an exception -- this gets flagged
354  // when an as_value is 'thrown'.
355  void flag_exception() {
356  if (!is_exception()) {
357  _type = static_cast<AsType>(static_cast<int>(_type) + 1);
358  }
359  }
360 
362  if (is_exception()) {
363  _type = static_cast<AsType>(static_cast<int>(_type) - 1);
364  }
365  }
366 
368  //
371  bool strictly_equals(const as_value& v) const;
372 
374  //
384  DSOEXPORT bool equals(const as_value& v, int version) const;
385 
387  //
389  void setReachable() const;
390 
392  //
407  bool writeAMF0(amf::Writer& w) const;
408 
409 private:
410 
412  //
419  typedef boost::variant<boost::blank,
420  double,
421  bool,
422  as_object*,
424  std::string>
425  AsValueType;
426 
428  bool operator==(const as_value& v) const;
429 
431  bool operator!=(const as_value& v) const;
432 
434  //
437  bool equalsSameType(const as_value& v) const;
438 
439  AsType _type;
440 
441  AsValueType _value;
442 
444  //
446  as_object* getObj() const;
447 
449  //
451  DisplayObject* getCharacter(bool skipRebinding = false) const;
452 
454  //
456  CharacterProxy getCharacterProxy() const;
457 
459  //
461  double getNum() const {
462  assert(_type == NUMBER);
463  return boost::get<double>(_value);
464  }
465 
467  //
469  bool getBool() const {
470  assert(_type == BOOLEAN);
471  return boost::get<bool>(_value);
472  }
473 
475  //
477  const std::string& getStr() const {
478  assert(_type == STRING);
479  return boost::get<std::string>(_value);
480  }
481 
482 };
483 
485 std::ostream& operator<<(std::ostream& os, const as_value& v);
486 
488 //
489 // Printing formats:
490 //
491 // If _val > 1, Print up to 15 significant digits, then switch
492 // to scientific notation, rounding at the last place and
493 // omitting trailing zeroes.
494 // For values < 1, print up to 4 leading zeroes after the
495 // decimal point, then switch to scientific notation with up
496 // to 15 significant digits, rounding with no trailing zeroes
497 // If the value is negative, just add a '-' to the start; this
498 // does not affect the precision of the printed value.
499 //
500 // This almost corresponds to iomanip's std::setprecision(15)
501 // format, except that iomanip switches to scientific notation
502 // at e-05 not e-06, and always prints at least two digits for the exponent.
503 std::string doubleToString(double val, int radix = 10);
504 
508 //
518 bool parseNonDecimalInt(const std::string& s, double& d, bool whole = true);
519 
521 inline void
523  v.set_double(NaN);
524 }
525 
526 } // namespace gnash
527 
528 #endif // GNASH_AS_VALUE_H
529 
530 // Local Variables:
531 // mode: C++
532 // indent-tabs-mode: nil
533 // End:
534