Home | History | Annotate | Download | only in cpp
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef PPAPI_CPP_VAR_H_
      6 #define PPAPI_CPP_VAR_H_
      7 
      8 #include <string>
      9 #include <vector>
     10 
     11 #include "ppapi/c/pp_var.h"
     12 #include "ppapi/cpp/pass_ref.h"
     13 
     14 /// @file
     15 /// This file defines the API for handling the passing of data types between
     16 /// your module and the page.
     17 namespace pp {
     18 
     19 /// A generic type used for passing data types between the module and the page.
     20 class Var {
     21  public:
     22   /// Special value passed to constructor to make <code>NULL</code>.
     23   struct Null {};
     24 
     25   /// Default constructor. Creates a <code>Var</code> of type
     26   /// <code>Undefined</code>.
     27   Var();
     28 
     29   /// A constructor used to create a <code>Var</code> of type <code>Null</code>.
     30   Var(Null);
     31 
     32   /// A constructor used to create a <code>Var</code> of type <code>Bool</code>.
     33   ///
     34   /// @param[in] b A boolean value.
     35   Var(bool b);
     36 
     37   /// A constructor used to create a 32 bit integer <code>Var</code>.
     38   ///
     39   /// @param[in] i A 32 bit integer value.
     40   Var(int32_t i);
     41 
     42   /// A constructor used to create a double value <code>Var</code>.
     43   ///
     44   /// @param[in] d A double value.
     45   Var(double d);
     46 
     47   /// A constructor used to create a UTF-8 character <code>Var</code>.
     48   Var(const char* utf8_str);  // Must be encoded in UTF-8.
     49 
     50   /// A constructor used to create a UTF-8 character <code>Var</code>.
     51   Var(const std::string& utf8_str);  // Must be encoded in UTF-8.
     52 
     53   /// A constructor used when you have received a <code>Var</code> as a return
     54   /// value that has had its reference count incremented for you.
     55   ///
     56   /// You will not normally need to use this constructor because
     57   /// the reference count will not normally be incremented for you.
     58   Var(PassRef, const PP_Var& var) {
     59     var_ = var;
     60     is_managed_ = true;
     61   }
     62 
     63   /// A constructor that increments the reference count.
     64   explicit Var(const PP_Var& var);
     65 
     66   struct DontManage {};
     67 
     68   // TODO(brettw): remove DontManage when this bug is fixed
     69   //               http://code.google.com/p/chromium/issues/detail?id=52105
     70   /// This constructor is used when we've given a <code>PP_Var</code> as an
     71   /// input argument from somewhere and that reference is managing the
     72   /// reference count for us. The object will not have its reference count
     73   /// increased or decreased by this class instance.
     74   ///
     75   /// @param[in] var A <code>Var</code>.
     76   Var(DontManage, const PP_Var& var) {
     77     var_ = var;
     78     is_managed_ = false;
     79   }
     80 
     81   /// A constructor for copying a <code>Var</code>.
     82   Var(const Var& other);
     83 
     84   /// Destructor.
     85   virtual ~Var();
     86 
     87   /// This function assigns one <code>Var</code> to another <code>Var</code>.
     88   ///
     89   /// @param[in] other The <code>Var</code> to be assigned.
     90   ///
     91   /// @return A resulting <code>Var</code>.
     92   virtual Var& operator=(const Var& other);
     93 
     94   /// This function compares object identity (rather than value identity) for
     95   /// objects, dictionaries, and arrays
     96   ///
     97   /// @param[in] other The <code>Var</code> to be compared to this Var.
     98   ///
     99   /// @return true if the <code>other</code> <code>Var</code> is the same as
    100   /// this <code>Var</code>, otherwise false.
    101   bool operator==(const Var& other) const;
    102 
    103   /// This function determines if this <code>Var</code> is an undefined value.
    104   ///
    105   /// @return true if this <code>Var</code> is undefined, otherwise false.
    106   bool is_undefined() const { return var_.type == PP_VARTYPE_UNDEFINED; }
    107 
    108   /// This function determines if this <code>Var</code> is a null value.
    109   ///
    110   /// @return true if this <code>Var</code> is null, otherwise false.
    111   bool is_null() const { return var_.type == PP_VARTYPE_NULL; }
    112 
    113   /// This function determines if this <code>Var</code> is a bool value.
    114   ///
    115   /// @return true if this <code>Var</code> is a bool, otherwise false.
    116   bool is_bool() const { return var_.type == PP_VARTYPE_BOOL; }
    117 
    118   /// This function determines if this <code>Var</code> is a string value.
    119   ///
    120   /// @return true if this <code>Var</code> is a string, otherwise false.
    121   bool is_string() const { return var_.type == PP_VARTYPE_STRING; }
    122 
    123   /// This function determines if this <code>Var</code> is an object.
    124   ///
    125   /// @return true if this <code>Var</code> is an object, otherwise false.
    126   bool is_object() const { return var_.type == PP_VARTYPE_OBJECT; }
    127 
    128   /// This function determines if this <code>Var</code> is an array.
    129   ///
    130   /// @return true if this <code>Var</code> is an array, otherwise false.
    131   bool is_array() const { return var_.type == PP_VARTYPE_ARRAY; }
    132 
    133   /// This function determines if this <code>Var</code> is a dictionary.
    134   ///
    135   /// @return true if this <code>Var</code> is a dictionary, otherwise false.
    136   bool is_dictionary() const { return var_.type == PP_VARTYPE_DICTIONARY; }
    137 
    138   /// This function determines if this <code>Var</code> is a resource.
    139   ///
    140   /// @return true if this <code>Var</code> is a resource, otherwise false.
    141   bool is_resource() const { return var_.type == PP_VARTYPE_RESOURCE; }
    142 
    143   /// This function determines if this <code>Var</code> is an integer value.
    144   /// The <code>is_int</code> function returns the internal representation.
    145   /// The JavaScript runtime may convert between the two as needed, so the
    146   /// distinction may not be relevant in all cases (int is really an
    147   /// optimization inside the runtime). So most of the time, you will want
    148   /// to check is_number().
    149   ///
    150   /// @return true if this <code>Var</code> is an integer, otherwise false.
    151   bool is_int() const { return var_.type == PP_VARTYPE_INT32; }
    152 
    153   /// This function determines if this <code>Var</code> is a double value.
    154   /// The <code>is_double</code> function returns the internal representation.
    155   /// The JavaScript runtime may convert between the two as needed, so the
    156   /// distinction may not be relevant in all cases (int is really an
    157   /// optimization inside the runtime). So most of the time, you will want to
    158   /// check is_number().
    159   ///
    160   /// @return true if this <code>Var</code> is a double, otherwise false.
    161   bool is_double() const { return var_.type == PP_VARTYPE_DOUBLE; }
    162 
    163   /// This function determines if this <code>Var</code> is a number.
    164   ///
    165   /// @return true if this <code>Var</code> is an int32 or double number,
    166   /// otherwise false.
    167   bool is_number() const {
    168     return var_.type == PP_VARTYPE_INT32 ||
    169            var_.type == PP_VARTYPE_DOUBLE;
    170   }
    171 
    172   /// This function determines if this <code>Var</code> is an ArrayBuffer.
    173   bool is_array_buffer() const { return var_.type == PP_VARTYPE_ARRAY_BUFFER; }
    174 
    175   /// AsBool() converts this <code>Var</code> to a bool. Assumes the
    176   /// internal representation is_bool(). If it's not, it will assert in debug
    177   /// mode, and return false.
    178   ///
    179   /// @return A bool version of this <code>Var</code>.
    180   bool AsBool() const;
    181 
    182   /// AsInt() converts this <code>Var</code> to an int32_t. This function
    183   /// is required because JavaScript doesn't have a concept of ints and doubles,
    184   /// only numbers. The distinction between the two is an optimization inside
    185   /// the compiler. Since converting from a double to an int may be lossy, if
    186   /// you care about the distinction, either always work in doubles, or check
    187   /// !is_double() before calling AsInt().
    188   ///
    189   /// These functions will assert in debug mode and return 0 if the internal
    190   /// representation is not is_number().
    191   ///
    192   /// @return An int32_t version of this <code>Var</code>.
    193   int32_t AsInt() const;
    194 
    195   /// AsDouble() converts this <code>Var</code> to a double. This function is
    196   /// necessary because JavaScript doesn't have a concept of ints and doubles,
    197   /// only numbers. The distinction between the two is an optimization inside
    198   /// the compiler. Since converting from a double to an int may be lossy, if
    199   /// you care about the distinction, either always work in doubles, or check
    200   /// !is_double() before calling AsInt().
    201   ///
    202   /// These functions will assert in debug mode and return 0 if the internal
    203   /// representation is not is_number().
    204   ///
    205   /// @return An double version of this <code>Var</code>.
    206   double AsDouble() const;
    207 
    208   /// AsString() converts this <code>Var</code> to a string. If this object is
    209   /// not a string, it will assert in debug mode, and return an empty string.
    210   ///
    211   /// @return A string version of this <code>Var</code>.
    212   std::string AsString() const;
    213 
    214   /// This function returns the internal <code>PP_Var</code>
    215   /// managed by this <code>Var</code> object.
    216   ///
    217   /// @return A const reference to a <code>PP_Var</code>.
    218   const PP_Var& pp_var() const {
    219     return var_;
    220   }
    221 
    222   /// Detach() detaches from the internal <code>PP_Var</code> of this
    223   /// object, keeping the reference count the same. This is used when returning
    224   /// a <code>PP_Var</code> from an API function where the caller expects the
    225   /// return value to have the reference count incremented for it.
    226   ///
    227   /// @return A detached version of this object without affecting the reference
    228   /// count.
    229   PP_Var Detach() {
    230     PP_Var ret = var_;
    231     var_ = PP_MakeUndefined();
    232     is_managed_ = true;
    233     return ret;
    234   }
    235 
    236   /// DebugString() returns a short description "Var<X>" that can be used for
    237   /// logging, where "X" is the underlying scalar or "UNDEFINED" or "OBJ" as
    238   /// it does not call into the browser to get the object description.
    239   ///
    240   /// @return A string displaying the value of this <code>Var</code>. This
    241   /// function is used for debugging.
    242   std::string DebugString() const;
    243 
    244   /// This class is used when calling the raw C PPAPI when using the C++
    245   /// <code>Var</code> as a possible NULL exception. This class will handle
    246   /// getting the address of the internal value out if it's non-NULL and
    247   /// fixing up the reference count.
    248   ///
    249   /// <strong>Warning:</strong> this will only work for things with exception
    250   /// semantics, i.e. that the value will not be changed if it's a
    251   /// non-undefined exception. Otherwise, this class will mess up the
    252   /// refcounting.
    253   ///
    254   /// This is a bit subtle:
    255   /// - If NULL is passed, we return NULL from get() and do nothing.
    256   ///
    257   /// - If a undefined value is passed, we return the address of a undefined
    258   ///   var from get and have the output value take ownership of that var.
    259   ///
    260   /// - If a non-undefined value is passed, we return the address of that var
    261   ///   from get, and nothing else should change.
    262   ///
    263   /// Example:
    264   ///   void FooBar(a, b, Var* exception = NULL) {
    265   ///     foo_interface->Bar(a, b, Var::OutException(exception).get());
    266   ///   }
    267   class OutException {
    268    public:
    269     /// A constructor.
    270     OutException(Var* v)
    271         : output_(v),
    272           originally_had_exception_(v && !v->is_undefined()) {
    273       if (output_) {
    274         temp_ = output_->var_;
    275       } else {
    276         temp_.padding = 0;
    277         temp_.type = PP_VARTYPE_UNDEFINED;
    278       }
    279     }
    280 
    281     /// Destructor.
    282     ~OutException() {
    283       if (output_ && !originally_had_exception_)
    284         *output_ = Var(PASS_REF, temp_);
    285     }
    286 
    287     PP_Var* get() {
    288       if (output_)
    289         return &temp_;
    290       return NULL;
    291     }
    292 
    293    private:
    294     Var* output_;
    295     bool originally_had_exception_;
    296     PP_Var temp_;
    297   };
    298 
    299  protected:
    300   PP_Var var_;
    301 
    302   // |is_managed_| indicates if the instance manages |var_|.
    303   // You need to check if |var_| is refcounted to call Release().
    304   bool is_managed_;
    305 
    306  private:
    307   // Prevent an arbitrary pointer argument from being implicitly converted to
    308   // a bool at Var construction. If somebody makes such a mistake, (s)he will
    309   // get a compilation error.
    310   Var(void* non_scriptable_object_pointer);
    311 };
    312 
    313 }  // namespace pp
    314 
    315 #endif  // PPAPI_CPP_VAR_H_
    316