• 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 #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.
Var(PassRef,const PP_Var & var)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>.
Var(DontManage,const PP_Var & var)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.
is_undefined()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.
is_null()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.
is_bool()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.
is_string()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.
is_object()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.
is_array()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.
is_dictionary()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.
is_resource()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.
is_int()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.
is_double()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.
is_number()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.
is_array_buffer()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>.
pp_var()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.
Detach()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.
OutException(Var * v)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.
~OutException()290     ~OutException() {
291       if (output_ && !originally_had_exception_)
292         *output_ = Var(PASS_REF, temp_);
293     }
294 
get()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