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