// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef PPAPI_CPP_VAR_H_ #define PPAPI_CPP_VAR_H_ #include #include #include "ppapi/c/pp_var.h" #include "ppapi/cpp/pass_ref.h" /// @file /// This file defines the API for handling the passing of data types between /// your module and the page. namespace pp { /// A generic type used for passing data types between the module and the page. class Var { public: /// Special value passed to constructor to make NULL. struct Null {}; /// Default constructor. Creates a Var of type /// Undefined. Var(); /// A constructor used to create a Var of type Null. Var(Null); /// A constructor used to create a Var of type Bool. /// /// @param[in] b A boolean value. Var(bool b); /// A constructor used to create a 32 bit integer Var. /// /// @param[in] i A 32 bit integer value. Var(int32_t i); /// A constructor used to create a double value Var. /// /// @param[in] d A double value. Var(double d); /// A constructor used to create a UTF-8 character Var. Var(const char* utf8_str); // Must be encoded in UTF-8. /// A constructor used to create a UTF-8 character Var. Var(const std::string& utf8_str); // Must be encoded in UTF-8. /// A constructor used when you have received a Var as a return /// value that has had its reference count incremented for you. /// /// You will not normally need to use this constructor because /// the reference count will not normally be incremented for you. Var(PassRef, PP_Var var) { var_ = var; needs_release_ = true; } struct DontManage {}; // TODO(brettw): remove DontManage when this bug is fixed // http://code.google.com/p/chromium/issues/detail?id=52105 /// This constructor is used when we've given a PP_Var as an /// input argument from somewhere and that reference is managing the /// reference count for us. The object will not have its reference count /// increased or decreased by this class instance. /// /// @param[in] var A Var. Var(DontManage, PP_Var var) { var_ = var; needs_release_ = false; } /// A constructor for copying a Var. Var(const Var& other); /// Destructor. virtual ~Var(); /// This function assigns one Var to another Var. /// /// @param[in] other The Var to be assigned. /// /// @return A resulting Var. virtual Var& operator=(const Var& other); /// This function compares object identity (rather than value identity) for /// objects, dictionaries, and arrays /// /// @param[in] other The Var to be compared to this Var. /// /// @return true if the other Var is the same as /// this Var, otherwise false. bool operator==(const Var& other) const; /// This function determines if this Var is an undefined value. /// /// @return true if this Var is undefined, otherwise false. bool is_undefined() const { return var_.type == PP_VARTYPE_UNDEFINED; } /// This function determines if this Var is a null value. /// /// @return true if this Var is null, otherwise false. bool is_null() const { return var_.type == PP_VARTYPE_NULL; } /// This function determines if this Var is a bool value. /// /// @return true if this Var is a bool, otherwise false. bool is_bool() const { return var_.type == PP_VARTYPE_BOOL; } /// This function determines if this Var is a string value. /// /// @return true if this Var is a string, otherwise false. bool is_string() const { return var_.type == PP_VARTYPE_STRING; } /// This function determines if this Var is an object. /// /// @return true if this Var is an object, otherwise false. bool is_object() const { return var_.type == PP_VARTYPE_OBJECT; } /// This function determines if this Var is an integer value. /// The is_int function returns the internal representation. /// The JavaScript runtime may convert between the two as needed, so the /// distinction may not be relevant in all cases (int is really an /// optimization inside the runtime). So most of the time, you will want /// to check is_number(). /// /// @return true if this Var is an integer, otherwise false. bool is_int() const { return var_.type == PP_VARTYPE_INT32; } /// This function determines if this Var is a double value. /// The is_double function returns the internal representation. /// The JavaScript runtime may convert between the two as needed, so the /// distinction may not be relevant in all cases (int is really an /// optimization inside the runtime). So most of the time, you will want to /// check is_number(). /// /// @return true if this Var is a double, otherwise false. bool is_double() const { return var_.type == PP_VARTYPE_DOUBLE; } /// This function determines if this Var is a number. /// /// @return true if this Var is an int32 or double number, /// otherwise false. bool is_number() const { return var_.type == PP_VARTYPE_INT32 || var_.type == PP_VARTYPE_DOUBLE; } /// This function determines if this Var is an ArrayBuffer. bool is_array_buffer() const { return var_.type == PP_VARTYPE_ARRAY_BUFFER; } /// AsBool() converts this Var to a bool. Assumes the /// internal representation is_bool(). If it's not, it will assert in debug /// mode, and return false. /// /// @return A bool version of this Var. bool AsBool() const; /// AsInt() converts this Var to an int32_t. This function /// is required because JavaScript doesn't have a concept of ints and doubles, /// only numbers. The distinction between the two is an optimization inside /// the compiler. Since converting from a double to an int may be lossy, if /// you care about the distinction, either always work in doubles, or check /// !is_double() before calling AsInt(). /// /// These functions will assert in debug mode and return 0 if the internal /// representation is not is_number(). /// /// @return An int32_t version of this Var. int32_t AsInt() const; /// AsDouble() converts this Var to a double. This function is /// necessary because JavaScript doesn't have a concept of ints and doubles, /// only numbers. The distinction between the two is an optimization inside /// the compiler. Since converting from a double to an int may be lossy, if /// you care about the distinction, either always work in doubles, or check /// !is_double() before calling AsInt(). /// /// These functions will assert in debug mode and return 0 if the internal /// representation is not is_number(). /// /// @return An double version of this Var. double AsDouble() const; /// AsString() converts this Var to a string. If this object is /// not a string, it will assert in debug mode, and return an empty string. /// /// @return A string version of this Var. std::string AsString() const; /// This function returns the internal PP_Var /// managed by this Var object. /// /// @return A const reference to a PP_Var. const PP_Var& pp_var() const { return var_; } /// Detach() detaches from the internal PP_Var of this /// object, keeping the reference count the same. This is used when returning /// a PP_Var from an API function where the caller expects the /// return value to have the reference count incremented for it. /// /// @return A detached version of this object without affecting the reference /// count. PP_Var Detach() { PP_Var ret = var_; var_ = PP_MakeUndefined(); needs_release_ = false; return ret; } /// DebugString() returns a short description "Var" that can be used for /// logging, where "X" is the underlying scalar or "UNDEFINED" or "OBJ" as /// it does not call into the browser to get the object description. /// /// @return A string displaying the value of this Var. This /// function is used for debugging. std::string DebugString() const; /// This class is used when calling the raw C PPAPI when using the C++ /// Var as a possibe NULL exception. This class will handle /// getting the address of the internal value out if it's non-NULL and /// fixing up the reference count. /// /// Warning: this will only work for things with exception /// semantics, i.e. that the value will not be changed if it's a /// non-undefined exception. Otherwise, this class will mess up the /// refcounting. /// /// This is a bit subtle: /// - If NULL is passed, we return NULL from get() and do nothing. /// /// - If a undefined value is passed, we return the address of a undefined /// var from get and have the output value take ownership of that var. /// /// - If a non-undefined value is passed, we return the address of that var /// from get, and nothing else should change. /// /// Example: /// void FooBar(a, b, Var* exception = NULL) { /// foo_interface->Bar(a, b, Var::OutException(exception).get()); /// } class OutException { public: /// A constructor. OutException(Var* v) : output_(v), originally_had_exception_(v && !v->is_undefined()) { if (output_) { temp_ = output_->var_; } else { temp_.padding = 0; temp_.type = PP_VARTYPE_UNDEFINED; } } /// Destructor. ~OutException() { if (output_ && !originally_had_exception_) *output_ = Var(PASS_REF, temp_); } PP_Var* get() { if (output_) return &temp_; return NULL; } private: Var* output_; bool originally_had_exception_; PP_Var temp_; }; protected: PP_Var var_; bool needs_release_; private: // Prevent an arbitrary pointer argument from being implicitly converted to // a bool at Var construction. If somebody makes such a mistake, (s)he will // get a compilation error. Var(void* non_scriptable_object_pointer); }; } // namespace pp #endif // PPAPI_CPP_VAR_H_