2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
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.
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.
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
23 #include "CharacterProxy.h"
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
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).
59 isNaN(const T
& num
, typename
boost::enable_if
<boost::is_floating_point
<T
> >::
70 return isNaN(num
- num
);
74 /// These are the primitive types, see the ECMAScript reference.
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.
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.
111 // The exception type should always be one greater than the normal type.
130 /// Construct an undefined value
134 _value(boost::blank())
138 /// Copy constructor.
139 DSOEXPORT
as_value(const as_value
& v
)
148 /// Construct a primitive String value
149 DSOEXPORT
as_value(const char* str
)
152 _value(std::string(str
))
155 /// Construct a primitive String value
156 DSOEXPORT
as_value(const std::string
& str
)
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
*
173 /// Construct a primitive Number value
180 /// Construct a null, Object, or DisplayObject value
181 as_value(as_object
* obj
)
188 /// Assign to an as_value.
189 DSOEXPORT as_value
& operator=(const as_value
& v
)
196 friend std::ostream
& operator<<(std::ostream
& o
, const as_value
&);
198 /// Return the primitive type of this value as a string.
199 const char* typeOf() const;
201 /// Return true if this value is a function
202 bool is_function() const;
204 /// Return true if this value is a string
205 bool is_string() const {
206 return _type
== STRING
;
209 /// Return true if this value is strictly a number
210 bool is_number() const {
211 return _type
== NUMBER
;
214 /// Return true if this value is an object
216 /// Both DisplayObjects and Objects count as Objects
217 bool is_object() const {
218 return _type
== OBJECT
|| _type
== DISPLAYOBJECT
;
221 /// Return true if this value is a DISPLAYOBJECT
222 bool is_sprite() const {
223 return _type
== DISPLAYOBJECT
;
226 /// Get a std::string representation for this value.
228 /// @param version The SWF version to use to transform the string.
229 /// This only affects undefined values, which trace
230 /// "undefined" for version 7 and above, nothing
231 /// for lower versions.
233 /// TODO: drop the default argument.
234 std::string
to_string(int version
= 7) const;
236 /// Get a number representation for this value
238 /// This function performs conversion if necessary.
239 double to_number(int version
) const;
241 /// Conversion to boolean.
243 /// This function performs conversion if necessary.
244 bool to_bool(int version
) const;
246 /// Return value as an object, converting primitive values as needed.
248 /// This function performs conversion where necessary.
250 /// string values are converted to String objects
251 /// numeric values are converted to Number objects
252 /// boolean values are converted to Boolean objects
254 /// If you want to avoid the conversion, check with is_object() before
255 /// calling this function.
257 /// @param global The global object object for the conversion. This
258 /// contains the prototypes or constructors necessary for
260 as_object
* to_object(VM
& vm
) const;
262 /// Return the value as an as_object only if it is an as_object.
264 /// Note that this performs no conversion, so returns 0 if the as_value
265 /// is not an object.
266 as_object
* get_object() const;
268 /// Returns value as a MovieClip if it is a MovieClip.
270 /// This function performs no conversion, so returns 0 if the as_value is
273 /// This is just a wrapper around toDisplayObject() performing
274 /// an additional final cast.
275 MovieClip
* toMovieClip(bool skipRebinding
= false) const;
277 /// Return value as a DisplayObject or NULL if this is not possible.
279 /// Note that this function performs no conversion, so returns 0 if the
280 /// as_value is not a DisplayObject.
282 /// If the value is a DisplayObject value, the stored DisplayObject target
283 /// is evaluated using the root movie's environment.
284 /// If the target points to something that doesn't cast to a DisplayObject,
287 /// @param skipRebinding If true a reference to a destroyed
288 /// DisplayObject is still returned, rather than
289 /// attempting to resolve it as a soft-reference.
290 /// Main use for this is during paths resolution,
291 /// to avoid infinite loops. See bug #21647.
292 DisplayObject
* toDisplayObject(bool skipRebinding
= false) const;
294 /// Return the value as a function only if it is a function.
296 /// Note that this performs no conversion, so returns 0 if the as_value
297 /// is not a function.
298 as_function
* to_function() const;
300 AsType
defaultPrimitive(int version
) const;
302 /// Return value as a primitive type, with a preference
304 /// This function performs no conversion.
306 /// Primitive types are: undefined, null, boolean, string, number.
307 /// See ECMA-2.6.2 (sections 4.3.2 and 8.6.2.6).
310 /// NUMBER or STRING, the preferred representation we're asking for.
312 /// @throw ActionTypeError if an object can't be converted to a primitive
314 as_value
to_primitive(AsType hint
) const;
316 /// Set to a primitive string.
317 void set_string(const std::string
& str
);
319 /// Set to a primitive number.
320 void set_double(double val
);
322 /// Set to a primitive boolean.
323 void set_bool(bool val
);
325 /// Make this value a NULL, OBJECT, DISPLAYOBJECT value
326 void set_as_object(as_object
* obj
);
328 /// Set to undefined.
329 void set_undefined();
331 /// Set this value to the NULL value
334 bool is_undefined() const {
335 return (_type
== UNDEFINED
);
338 bool is_null() const {
339 return (_type
== NULLTYPE
);
342 bool is_bool() const {
343 return (_type
== BOOLEAN
);
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
);
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);
361 void unflag_exception() {
362 if (is_exception()) {
363 _type
= static_cast<AsType
>(static_cast<int>(_type
) - 1);
367 /// Return true if this value is strictly equal to the given one
369 /// Strict equality is defined as the two values being of the
370 /// same type and the same value.
371 bool strictly_equals(const as_value
& v
) const;
373 /// Return true if this value is abstractly equal to the given one
375 /// See ECMA-262 abstract equality comparison (sect 11.9.3)
377 /// NOTE: these invariants should hold
379 /// - A != B is equivalent to ! ( A == B )
380 /// - A == B is equivalent to B == A, except for order of
381 /// evaluation of A and B.
383 /// @param v The as_value to compare to
384 bool equals(const as_value
& v
, int version
) const;
386 /// Set any object value as reachable (for the GC)
388 /// Object values are values stored by pointer (objects and functions)
389 void setReachable() const;
391 /// Serialize value in AMF0 format.
394 /// The buffer to append serialized version of this value to.
396 /// @param offsetTable
397 /// A map of already-parsed objects, pass an empty map on first call as
398 /// it will be used internally.
401 /// Virtual machine to use for serialization of property names
404 /// @param allowStrictArray
405 /// If true strict arrays will be encoded a STRICT_ARRAY types.
407 bool writeAMF0(amf::Writer
& w
) const;
411 /// AsValueType handles the following AS types:
413 /// 1. undefined / null
419 typedef boost::variant
<boost::blank
,
427 /// Use the relevant equality function, not operator==
428 bool operator==(const as_value
& v
) const;
430 /// Use the relevant inequality function, not operator!=
431 bool operator!=(const as_value
& v
) const;
433 /// Compare values of the same type
435 /// NOTE: will abort if values are not of the same type!
437 bool equalsSameType(const as_value
& v
) const;
443 /// Get the object pointer variant member.
445 /// Callers must check that this is an Object (including DisplayObjects).
446 as_object
* getObj() const;
448 /// Get the DisplayObject variant member.
450 /// The caller must check that this is a DisplayObject.
451 DisplayObject
* getCharacter(bool skipRebinding
= false) const;
453 /// Get the DisplayObject proxy variant member.
455 /// The caller must check that this value is a DisplayObject
456 CharacterProxy
getCharacterProxy() const;
458 /// Get the number variant member.
460 /// The caller must check that this value is a Number.
461 double getNum() const {
462 assert(_type
== NUMBER
);
463 return boost::get
<double>(_value
);
466 /// Get the boolean variant member.
468 /// The caller must check that this value is a Boolean.
469 bool getBool() const {
470 assert(_type
== BOOLEAN
);
471 return boost::get
<bool>(_value
);
474 /// Get the boolean variant member.
476 /// The caller must check that this value is a String.
477 const std::string
& getStr() const {
478 assert(_type
== STRING
);
479 return boost::get
<std::string
>(_value
);
485 std::ostream
& operator<<(std::ostream
& os
, const as_value
& v
);
487 /// Convert numeric value to string value, following ECMA-262 specification
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.
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);
505 /// Try to parse a string into a 32-bit signed int using base 8 or 16. //
506 /// This function will throw a boost::bad_lexical_cast (or a derived
507 /// exception) if the passed string cannot be converted.
509 /// @param s The string to parse
510 /// @param d The 32-bit int represented as a double. This is only a
511 /// valid number if the return value is true.
512 /// @param whole If true, expect the whole string to be valid, i.e.
513 /// throw if there are any invalid DisplayObjects. If false,
514 /// returns any valid number up to the first invalid
516 /// @return True if the string was non-decimal and successfully
518 bool parseNonDecimalInt(const std::string
& s
, double& d
, bool whole
= true);
520 /// Set a value to NaN
522 setNaN(as_value
& v
) {
528 #endif // GNASH_AS_VALUE_H
532 // indent-tabs-mode: nil