Revert "don't look for git here, we do it at runtime"
[gnash.git] / libcore / as_value.h
blob60093b99780ae9f1f03212995957b9a0a41a6d66
1 //
2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
3 // 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
19 #ifndef GNASH_AS_VALUE_H
20 #define GNASH_AS_VALUE_H
22 #include "dsodefs.h"
23 #include "CharacterProxy.h"
25 #include <limits>
26 #include <string>
27 #include <boost/variant.hpp>
28 #include <ostream> // 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>
33 #include "utility.h" // UNUSED
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;
49 namespace gnash {
52 // NaN constant for use in as_value implementation
53 static const double NaN = std::numeric_limits<double>::quiet_NaN();
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)
62 UNUSED(dummy);
63 return num != num;
66 template <typename T>
67 inline bool
68 isInf(const T& num)
70 return isNaN(num - num);
74 /// These are the primitive types, see the ECMAScript reference.
75 enum primitive_types
77 PTYPE_STRING,
78 PTYPE_NUMBER,
79 PTYPE_BOOLEAN
82 /// ActionScript value type.
84 /// The as_value class can store basic ActionScript types.
86 /// These are the primitive types (Number, Boolean, String, null, and
87 /// undefined), as well as complex types (Object and DisplayObject).
89 /// Most type handling is hidden within the class. There are two different
90 /// types of access to the as_value: converting and non-converting.
92 /// Non-converting access
93 /// Non-converting access is available for the complex types, for instance
94 /// to_function() and toMovieClip(). In these cases, an object pointer is
95 /// return only if the as_value is currently of the requested type. There
96 /// are no ActionScript side-effects in such cases.
98 /// Converting access
99 /// The primitive types and Objects have converting access. This means that
100 /// as_values of a different type are converted to the requested type. These
101 /// functions may have ActionScript side-effects, for instance the calling of
102 /// toString or valueOf, or construction of an object.
104 /// It is possible to check the current type of an as_value using is_string(),
105 /// is_number() etc. These functions have no ActionScript side effects.
106 class as_value
109 public:
111 // The exception type should always be one greater than the normal type.
112 enum AsType
114 UNDEFINED,
115 UNDEFINED_EXCEPT,
116 NULLTYPE,
117 NULLTYPE_EXCEPT,
118 BOOLEAN,
119 BOOLEAN_EXCEPT,
120 STRING,
121 STRING_EXCEPT,
122 NUMBER,
123 NUMBER_EXCEPT,
124 OBJECT,
125 OBJECT_EXCEPT,
126 DISPLAYOBJECT,
127 DISPLAYOBJECT_EXCEPT
130 /// Construct an undefined value
131 DSOEXPORT as_value()
133 _type(UNDEFINED),
134 _value(boost::blank())
138 /// Copy constructor.
139 DSOEXPORT as_value(const as_value& v)
141 _type(v._type),
142 _value(v._value)
146 ~as_value() {}
148 /// Construct a primitive String value
149 DSOEXPORT as_value(const char* str)
151 _type(STRING),
152 _value(std::string(str))
155 /// Construct a primitive String value
156 DSOEXPORT as_value(const std::string& str)
158 _type(STRING),
159 _value(std::string(str))
162 /// Construct a primitive Boolean value
163 template <typename T>
164 as_value(T val, typename boost::enable_if<boost::is_same<bool, T> >::type*
165 dummy = 0)
167 _type(BOOLEAN),
168 _value(val)
170 UNUSED(dummy);
173 /// Construct a primitive Number value
174 as_value(double num)
176 _type(NUMBER),
177 _value(num)
180 /// Construct a null, Object, or DisplayObject value
181 as_value(as_object* obj)
183 _type(UNDEFINED)
185 set_as_object(obj);
188 /// Assign to an as_value.
189 DSOEXPORT void operator=(const as_value& v)
191 _type = v._type;
192 _value = v._value;
195 friend std::ostream& operator<<(std::ostream& o, const as_value&);
197 /// Return the primitive type of this value as a string.
198 const char* typeOf() const;
200 /// Return true if this value is a function
201 bool is_function() const;
203 /// Return true if this value is a string
204 bool is_string() const {
205 return _type == STRING;
208 /// Return true if this value is strictly a number
209 bool is_number() const {
210 return _type == NUMBER;
213 /// Return true if this value is an object
215 /// Both DisplayObjects and Objects count as Objects
216 bool is_object() const {
217 return _type == OBJECT || _type == DISPLAYOBJECT;
220 /// Return true if this value is a DISPLAYOBJECT
221 bool is_sprite() const {
222 return _type == DISPLAYOBJECT;
225 /// Get a std::string representation for this value.
227 /// @param version The SWF version to use to transform the string.
228 /// This only affects undefined values, which trace
229 /// "undefined" for version 7 and above, nothing
230 /// for lower versions.
232 /// TODO: drop the default argument.
233 std::string to_string(int version = 7) const;
235 /// Get a number representation for this value
237 /// This function performs conversion if necessary.
238 double to_number(int version) const;
240 /// Conversion to boolean.
242 /// This function performs conversion if necessary.
243 bool to_bool(int version) const;
245 /// Return value as an object, converting primitive values as needed.
247 /// This function performs conversion where necessary.
249 /// string values are converted to String objects
250 /// numeric values are converted to Number objects
251 /// boolean values are converted to Boolean objects
253 /// If you want to avoid the conversion, check with is_object() before
254 /// calling this function.
256 /// @param global The global object object for the conversion. This
257 /// contains the prototypes or constructors necessary for
258 /// conversion.
259 as_object* to_object(VM& vm) const;
261 /// Return the value as an as_object only if it is an as_object.
263 /// Note that this performs no conversion, so returns 0 if the as_value
264 /// is not an object.
265 as_object* get_object() const;
267 /// Returns value as a MovieClip if it is a MovieClip.
269 /// This function performs no conversion, so returns 0 if the as_value is
270 /// not a MovieClip.
272 /// This is just a wrapper around toDisplayObject() performing
273 /// an additional final cast.
274 MovieClip* toMovieClip(bool skipRebinding = false) const;
276 /// Return value as a DisplayObject or NULL if this is not possible.
278 /// Note that this function performs no conversion, so returns 0 if the
279 /// as_value is not a DisplayObject.
281 /// If the value is a DisplayObject value, the stored DisplayObject target
282 /// is evaluated using the root movie's environment.
283 /// If the target points to something that doesn't cast to a DisplayObject,
284 /// 0 is returned.
286 /// @param skipRebinding If true a reference to a destroyed
287 /// DisplayObject is still returned, rather than
288 /// attempting to resolve it as a soft-reference.
289 /// Main use for this is during paths resolution,
290 /// to avoid infinite loops. See bug #21647.
291 DisplayObject* toDisplayObject(bool skipRebinding = false) const;
293 /// Return the value as a function only if it is a function.
295 /// Note that this performs no conversion, so returns 0 if the as_value
296 /// is not a function.
297 as_function* to_function() const;
299 AsType defaultPrimitive(int version) const;
301 /// Return value as a primitive type, with a preference
303 /// This function performs no conversion.
305 /// Primitive types are: undefined, null, boolean, string, number.
306 /// See ECMA-2.6.2 (sections 4.3.2 and 8.6.2.6).
308 /// @param hint
309 /// NUMBER or STRING, the preferred representation we're asking for.
311 /// @throw ActionTypeError if an object can't be converted to a primitive
313 as_value to_primitive(AsType hint) const;
315 /// Set to a primitive string.
316 void set_string(const std::string& str);
318 /// Set to a primitive number.
319 void set_double(double val);
321 /// Set to a primitive boolean.
322 void set_bool(bool val);
324 /// Make this value a NULL, OBJECT, DISPLAYOBJECT value
325 void set_as_object(as_object* obj);
327 /// Set to undefined.
328 void set_undefined();
330 /// Set this value to the NULL value
331 void set_null();
333 bool is_undefined() const {
334 return (_type == UNDEFINED);
337 bool is_null() const {
338 return (_type == NULLTYPE);
341 bool is_bool() const {
342 return (_type == BOOLEAN);
345 bool is_exception() const {
346 return (_type == UNDEFINED_EXCEPT || _type == NULLTYPE_EXCEPT
347 || _type == BOOLEAN_EXCEPT || _type == NUMBER_EXCEPT
348 || _type == OBJECT_EXCEPT || _type == DISPLAYOBJECT_EXCEPT
349 || _type == STRING_EXCEPT);
352 // Flag or unflag an as_value as an exception -- this gets flagged
353 // when an as_value is 'thrown'.
354 void flag_exception() {
355 if (!is_exception()) {
356 _type = static_cast<AsType>(static_cast<int>(_type) + 1);
360 void unflag_exception() {
361 if (is_exception()) {
362 _type = static_cast<AsType>(static_cast<int>(_type) - 1);
366 /// Return true if this value is strictly equal to the given one
368 /// Strict equality is defined as the two values being of the
369 /// same type and the same value.
370 bool strictly_equals(const as_value& v) const;
372 /// Return true if this value is abstractly equal to the given one
374 /// See ECMA-262 abstract equality comparison (sect 11.9.3)
376 /// NOTE: these invariants should hold
378 /// - A != B is equivalent to ! ( A == B )
379 /// - A == B is equivalent to B == A, except for order of
380 /// evaluation of A and B.
382 /// @param v The as_value to compare to
383 bool equals(const as_value& v, int version) const;
385 /// Set any object value as reachable (for the GC)
387 /// Object values are values stored by pointer (objects and functions)
388 void setReachable() const;
390 /// Serialize value in AMF0 format.
392 /// @param buf
393 /// The buffer to append serialized version of this value to.
395 /// @param offsetTable
396 /// A map of already-parsed objects, pass an empty map on first call as
397 /// it will be used internally.
399 /// @param vm
400 /// Virtual machine to use for serialization of property names
401 /// (string_table)
403 /// @param allowStrictArray
404 /// If true strict arrays will be encoded a STRICT_ARRAY types.
406 bool writeAMF0(amf::Writer& w) const;
408 private:
410 /// AsValueType handles the following AS types:
412 /// 1. undefined / null
413 /// 2. Number
414 /// 3. Boolean
415 /// 4. Object
416 /// 5. MovieClip
417 /// 6. String
418 typedef boost::variant<boost::blank,
419 double,
420 bool,
421 as_object*,
422 CharacterProxy,
423 std::string>
424 AsValueType;
426 /// Use the relevant equality function, not operator==
427 bool operator==(const as_value& v) const;
429 /// Use the relevant inequality function, not operator!=
430 bool operator!=(const as_value& v) const;
432 /// Compare values of the same type
434 /// NOTE: will abort if values are not of the same type!
436 bool equalsSameType(const as_value& v) const;
438 AsType _type;
440 AsValueType _value;
442 /// Get the object pointer variant member.
444 /// Callers must check that this is an Object (including DisplayObjects).
445 as_object* getObj() const;
447 /// Get the DisplayObject variant member.
449 /// The caller must check that this is a DisplayObject.
450 DisplayObject* getCharacter(bool skipRebinding = false) const;
452 /// Get the DisplayObject proxy variant member.
454 /// The caller must check that this value is a DisplayObject
455 CharacterProxy getCharacterProxy() const;
457 /// Get the number variant member.
459 /// The caller must check that this value is a Number.
460 double getNum() const {
461 assert(_type == NUMBER);
462 return boost::get<double>(_value);
465 /// Get the boolean variant member.
467 /// The caller must check that this value is a Boolean.
468 bool getBool() const {
469 assert(_type == BOOLEAN);
470 return boost::get<bool>(_value);
473 /// Get the boolean variant member.
475 /// The caller must check that this value is a String.
476 const std::string& getStr() const {
477 assert(_type == STRING);
478 return boost::get<std::string>(_value);
483 /// Stream operator.
484 std::ostream& operator<<(std::ostream& os, const as_value& v);
486 /// Convert numeric value to string value, following ECMA-262 specification
488 // Printing formats:
490 // If _val > 1, Print up to 15 significant digits, then switch
491 // to scientific notation, rounding at the last place and
492 // omitting trailing zeroes.
493 // For values < 1, print up to 4 leading zeroes after the
494 // decimal point, then switch to scientific notation with up
495 // to 15 significant digits, rounding with no trailing zeroes
496 // If the value is negative, just add a '-' to the start; this
497 // does not affect the precision of the printed value.
499 // This almost corresponds to iomanip's std::setprecision(15)
500 // format, except that iomanip switches to scientific notation
501 // at e-05 not e-06, and always prints at least two digits for the exponent.
502 std::string doubleToString(double val, int radix = 10);
504 /// Try to parse a string into a 32-bit signed int using base 8 or 16. //
505 /// This function will throw a boost::bad_lexical_cast (or a derived
506 /// exception) if the passed string cannot be converted.
508 /// @param s The string to parse
509 /// @param d The 32-bit int represented as a double. This is only a
510 /// valid number if the return value is true.
511 /// @param whole If true, expect the whole string to be valid, i.e.
512 /// throw if there are any invalid DisplayObjects. If false,
513 /// returns any valid number up to the first invalid
514 /// DisplayObject.
515 /// @return True if the string was non-decimal and successfully
516 /// parsed.
517 bool parseNonDecimalInt(const std::string& s, double& d, bool whole = true);
519 /// Set a value to NaN
520 inline void
521 setNaN(as_value& v) {
522 v.set_double(NaN);
525 } // namespace gnash
527 #endif // GNASH_AS_VALUE_H
529 // Local Variables:
530 // mode: C++
531 // indent-tabs-mode: nil
532 // End: