• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
Var(PassRef,const PP_Var & var)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>.
Var(DontManage,const PP_Var & var)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.
is_undefined()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.
is_null()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.
is_bool()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.
is_string()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.
is_object()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.
is_array()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.
is_dictionary()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.
is_resource()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.
is_int()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.
is_double()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.
is_number()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.
is_array_buffer()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>.
pp_var()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.
Detach()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.
OutException(Var * v)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.
~OutException()282     ~OutException() {
283       if (output_ && !originally_had_exception_)
284         *output_ = Var(PASS_REF, temp_);
285     }
286 
get()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