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