Gnash  0.8.10
as_value.h
Go to the documentation of this file.
00001 // 
00002 //   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
00003 //   Free Software Foundation, Inc
00004 // 
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 3 of the License, or
00008 // (at your option) any later version.
00009 // 
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018 
00019 #ifndef GNASH_AS_VALUE_H
00020 #define GNASH_AS_VALUE_H
00021 
00022 #include "dsodefs.h"
00023 #include "CharacterProxy.h"
00024 
00025 #include <limits>
00026 #include <string>
00027 #include <boost/variant.hpp>
00028 #include <iosfwd> // for inlined output operator
00029 #include <boost/type_traits/is_floating_point.hpp>
00030 #include <boost/utility/enable_if.hpp>
00031 #include <boost/cstdint.hpp>
00032 
00033 #include "utility.h" // UNUSED
00034 
00035 // Forward declarations
00036 namespace gnash {
00037     class VM;
00038         class as_object;
00039         class Global_as;
00040         class fn_call;
00041         class as_function;
00042         class MovieClip;
00043         class DisplayObject;
00044     namespace amf {
00045         class Writer;
00046     }
00047 }
00048 
00049 namespace gnash {
00050 
00051 
00052 // NaN constant for use in as_value implementation
00053 static const double NaN = std::numeric_limits<double>::quiet_NaN();
00054 
00055 // The following template works just like its C counterpart, with added
00056 // type safety (i.e., they will only compile for floating point arguments).
00057 template <typename T>
00058 inline bool
00059 isNaN(const T& num, typename boost::enable_if<boost::is_floating_point<T> >::
00060         type* dummy = 0)
00061 {
00062         UNUSED(dummy);
00063         return num != num;
00064 }
00065 
00066 template <typename T>
00067 inline bool
00068 isInf(const T& num)
00069 {
00070         return isNaN(num - num);
00071 }
00072 
00073 
00075 enum primitive_types
00076 {
00077         PTYPE_STRING,
00078         PTYPE_NUMBER,
00079         PTYPE_BOOLEAN
00080 };
00081 
00083 //
00085 //
00088 //
00091 //
00097 //
00103 //
00106 class as_value
00107 {
00108 
00109 public:
00110 
00111     // The exception type should always be one greater than the normal type.
00112     enum AsType
00113     {
00114         UNDEFINED,
00115         UNDEFINED_EXCEPT,
00116         NULLTYPE,
00117         NULLTYPE_EXCEPT,
00118         BOOLEAN,
00119         BOOLEAN_EXCEPT,
00120         STRING,
00121         STRING_EXCEPT,
00122         NUMBER, 
00123         NUMBER_EXCEPT,
00124         OBJECT,
00125         OBJECT_EXCEPT,
00126         DISPLAYOBJECT,
00127         DISPLAYOBJECT_EXCEPT
00128     };
00129     
00131     DSOEXPORT as_value()
00132         :
00133         _type(UNDEFINED),
00134         _value(boost::blank())
00135     {
00136     }
00137     
00139     DSOEXPORT as_value(const as_value& v)
00140         :
00141         _type(v._type),
00142         _value(v._value)
00143     {
00144     }
00145 
00146     ~as_value() {}
00147     
00149     DSOEXPORT as_value(const char* str)
00150         :
00151         _type(STRING),
00152         _value(std::string(str))
00153     {}
00154 
00156     DSOEXPORT as_value(const std::string& str)
00157         :
00158         _type(STRING),
00159         _value(std::string(str))
00160     {}
00161     
00163     template <typename T>
00164     as_value(T val, typename boost::enable_if<boost::is_same<bool, T> >::type*
00165              dummy = 0)
00166         :
00167         _type(BOOLEAN),
00168         _value(val)
00169         {
00170         UNUSED(dummy);
00171         }
00172     
00174     as_value(double num)
00175         :
00176         _type(NUMBER),
00177         _value(num)
00178     {}
00179     
00181     as_value(as_object* obj)
00182         :
00183         _type(UNDEFINED)
00184     {
00185         set_as_object(obj);
00186     }
00187     
00189     DSOEXPORT as_value& operator=(const as_value& v)
00190     {
00191         _type = v._type;
00192         _value = v._value;
00193         return *this;
00194     }
00195 
00196     friend std::ostream& operator<<(std::ostream& o, const as_value&);
00197     
00199     const char* typeOf() const;
00200     
00202     bool is_function() const;
00203     
00205     bool is_string() const {
00206         return _type == STRING;
00207     }
00208     
00210     bool is_number() const {
00211         return _type == NUMBER;
00212     }
00213     
00215     //
00217     bool is_object() const {
00218         return _type == OBJECT || _type == DISPLAYOBJECT;
00219     }
00220     
00222     bool is_sprite() const {
00223         return _type == DISPLAYOBJECT;
00224     }
00225     
00227     //
00232     //
00234     std::string to_string(int version = 7) const;
00235     
00237     //
00239     double to_number(int version) const;
00240     
00242     //
00244     bool to_bool(int version) const;
00245     
00247     //
00249     //
00256     //
00260     as_object* to_object(VM& vm) const;
00261 
00263     //
00266     as_object* get_object() const;
00267     
00269     //
00272     //
00275     MovieClip* toMovieClip(bool skipRebinding = false) const;
00276     
00278     //
00281     //
00292     DisplayObject* toDisplayObject(bool skipRebinding = false) const;
00293 
00295     //
00298     as_function* to_function() const;
00299     
00300     AsType defaultPrimitive(int version) const;
00301     
00303     //
00305     //
00314     as_value to_primitive(AsType hint) const;
00315     
00317     void set_string(const std::string& str);
00318     
00320     void set_double(double val);
00321     
00323     void set_bool(bool val);
00324 
00326     void set_as_object(as_object* obj);
00327     
00329     void set_undefined();
00330     
00332     void set_null();
00333     
00334     bool is_undefined() const {
00335         return (_type == UNDEFINED);
00336     }
00337     
00338     bool is_null() const {
00339         return (_type == NULLTYPE);
00340     }
00341     
00342     bool is_bool() const {
00343         return (_type == BOOLEAN);
00344     }
00345     
00346     bool is_exception() const {
00347         return (_type == UNDEFINED_EXCEPT || _type == NULLTYPE_EXCEPT
00348                 || _type == BOOLEAN_EXCEPT || _type == NUMBER_EXCEPT
00349                 || _type == OBJECT_EXCEPT || _type == DISPLAYOBJECT_EXCEPT
00350                 || _type == STRING_EXCEPT);
00351     }
00352     
00353     // Flag or unflag an as_value as an exception -- this gets flagged
00354     // when an as_value is 'thrown'.
00355     void flag_exception() {
00356         if (!is_exception()) {
00357             _type = static_cast<AsType>(static_cast<int>(_type) + 1);
00358         }
00359     }
00360     
00361     void unflag_exception() {
00362         if (is_exception()) {
00363             _type = static_cast<AsType>(static_cast<int>(_type) - 1);
00364         }
00365     }
00366     
00368     //
00371     bool strictly_equals(const as_value& v) const;
00372     
00374     //
00384     bool equals(const as_value& v, int version) const;
00385     
00387     //
00389     void setReachable() const;
00390     
00392     //
00407     bool writeAMF0(amf::Writer& w) const;
00408 
00409 private:
00410 
00412     //
00419     typedef boost::variant<boost::blank,
00420                            double,
00421                            bool,
00422                            as_object*,
00423                            CharacterProxy,
00424                            std::string>
00425     AsValueType;
00426     
00428     bool operator==(const as_value& v) const;
00429     
00431     bool operator!=(const as_value& v) const;
00432     
00434     //
00437     bool equalsSameType(const as_value& v) const;
00438     
00439     AsType _type;
00440     
00441     AsValueType _value;
00442     
00444     //
00446     as_object* getObj() const;
00447     
00449     //
00451     DisplayObject* getCharacter(bool skipRebinding = false) const;
00452 
00454     //
00456     CharacterProxy getCharacterProxy() const;
00457 
00459     //
00461     double getNum() const {
00462         assert(_type == NUMBER);
00463         return boost::get<double>(_value);
00464     }
00465     
00467     //
00469     bool getBool() const {
00470         assert(_type == BOOLEAN);
00471         return boost::get<bool>(_value);
00472     }
00473 
00475     //
00477     const std::string& getStr() const {
00478         assert(_type == STRING);
00479         return boost::get<std::string>(_value);
00480     }
00481     
00482 };
00483 
00485 std::ostream& operator<<(std::ostream& os, const as_value& v);
00486 
00488 //
00489 // Printing formats:
00490 //
00491 // If _val > 1, Print up to 15 significant digits, then switch
00492 // to scientific notation, rounding at the last place and
00493 // omitting trailing zeroes.
00494 // For values < 1, print up to 4 leading zeroes after the
00495 // decimal point, then switch to scientific notation with up
00496 // to 15 significant digits, rounding with no trailing zeroes
00497 // If the value is negative, just add a '-' to the start; this
00498 // does not affect the precision of the printed value.
00499 //
00500 // This almost corresponds to iomanip's std::setprecision(15)
00501 // format, except that iomanip switches to scientific notation
00502 // at e-05 not e-06, and always prints at least two digits for the exponent.
00503 std::string doubleToString(double val, int radix = 10);
00504 
00508 //
00518 bool parseNonDecimalInt(const std::string& s, double& d, bool whole = true);
00519 
00521 inline void
00522 setNaN(as_value& v) {
00523     v.set_double(NaN);
00524 }
00525 
00526 } // namespace gnash
00527 
00528 #endif // GNASH_AS_VALUE_H
00529 
00530 // Local Variables:
00531 // mode: C++
00532 // indent-tabs-mode: nil
00533 // End:
00534