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