// 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 <string> #include <vector> #include "ppapi/c/pp_var.h" #include "ppapi/cpp/pass_ref.h" #include "ppapi/cpp/resource.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 <code>NULL</code>. struct Null {}; /// Default constructor. Creates a <code>Var</code> of type /// <code>Undefined</code>. Var(); /// A constructor used to create a <code>Var</code> of type <code>Null</code>. Var(Null); /// A constructor used to create a <code>Var</code> of type <code>Bool</code>. /// /// @param[in] b A boolean value. Var(bool b); /// A constructor used to create a 32 bit integer <code>Var</code>. /// /// @param[in] i A 32 bit integer value. Var(int32_t i); /// A constructor used to create a double value <code>Var</code>. /// /// @param[in] d A double value. Var(double d); /// A constructor used to create a UTF-8 character <code>Var</code>. Var(const char* utf8_str); // Must be encoded in UTF-8. /// A constructor used to create a UTF-8 character <code>Var</code>. Var(const std::string& utf8_str); // Must be encoded in UTF-8. /// A constructor used to create a resource <code>Var</code>. explicit Var(const pp::Resource& resource); /// A constructor used when you have received a <code>Var</code> 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, const PP_Var& var) { var_ = var; is_managed_ = true; } /// A constructor that increments the reference count. explicit Var(const PP_Var& var); struct DontManage {}; /// This constructor is used when we've given a <code>PP_Var</code> 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 <code>Var</code>. Var(DontManage, const PP_Var& var) { var_ = var; is_managed_ = false; } /// A constructor for copying a <code>Var</code>. Var(const Var& other); /// Destructor. virtual ~Var(); /// This function assigns one <code>Var</code> to another <code>Var</code>. /// /// @param[in] other The <code>Var</code> to be assigned. /// /// @return A resulting <code>Var</code>. virtual Var& operator=(const Var& other); /// This function compares object identity (rather than value identity) for /// objects, dictionaries, and arrays /// /// @param[in] other The <code>Var</code> to be compared to this Var. /// /// @return true if the <code>other</code> <code>Var</code> is the same as /// this <code>Var</code>, otherwise false. bool operator==(const Var& other) const; /// This function determines if this <code>Var</code> is an undefined value. /// /// @return true if this <code>Var</code> is undefined, otherwise false. bool is_undefined() const { return var_.type == PP_VARTYPE_UNDEFINED; } /// This function determines if this <code>Var</code> is a null value. /// /// @return true if this <code>Var</code> is null, otherwise false. bool is_null() const { return var_.type == PP_VARTYPE_NULL; } /// This function determines if this <code>Var</code> is a bool value. /// /// @return true if this <code>Var</code> is a bool, otherwise false. bool is_bool() const { return var_.type == PP_VARTYPE_BOOL; } /// This function determines if this <code>Var</code> is a string value. /// /// @return true if this <code>Var</code> is a string, otherwise false. bool is_string() const { return var_.type == PP_VARTYPE_STRING; } /// This function determines if this <code>Var</code> is an object. /// /// @return true if this <code>Var</code> is an object, otherwise false. bool is_object() const { return var_.type == PP_VARTYPE_OBJECT; } /// This function determines if this <code>Var</code> is an array. /// /// @return true if this <code>Var</code> is an array, otherwise false. bool is_array() const { return var_.type == PP_VARTYPE_ARRAY; } /// This function determines if this <code>Var</code> is a dictionary. /// /// @return true if this <code>Var</code> is a dictionary, otherwise false. bool is_dictionary() const { return var_.type == PP_VARTYPE_DICTIONARY; } /// This function determines if this <code>Var</code> is a resource. /// /// @return true if this <code>Var</code> is a resource, otherwise false. bool is_resource() const { return var_.type == PP_VARTYPE_RESOURCE; } /// This function determines if this <code>Var</code> is an integer value. /// The <code>is_int</code> 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 <code>Var</code> is an integer, otherwise false. bool is_int() const { return var_.type == PP_VARTYPE_INT32; } /// This function determines if this <code>Var</code> is a double value. /// The <code>is_double</code> 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 <code>Var</code> is a double, otherwise false. bool is_double() const { return var_.type == PP_VARTYPE_DOUBLE; } /// This function determines if this <code>Var</code> is a number. /// /// @return true if this <code>Var</code> 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 <code>Var</code> is an ArrayBuffer. bool is_array_buffer() const { return var_.type == PP_VARTYPE_ARRAY_BUFFER; } /// AsBool() converts this <code>Var</code> 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 <code>Var</code>. bool AsBool() const; /// AsInt() converts this <code>Var</code> 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 <code>Var</code>. int32_t AsInt() const; /// AsDouble() converts this <code>Var</code> 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 <code>Var</code>. double AsDouble() const; /// AsString() converts this <code>Var</code> 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 <code>Var</code>. std::string AsString() const; /// Gets the resource contained in the var. If this object is not a resource, /// it will assert in debug mode, and return a null resource. /// /// @return The <code>pp::Resource</code> that is contained in the var. pp::Resource AsResource() const; /// This function returns the internal <code>PP_Var</code> /// managed by this <code>Var</code> object. /// /// @return A const reference to a <code>PP_Var</code>. const PP_Var& pp_var() const { return var_; } /// Detach() detaches from the internal <code>PP_Var</code> of this /// object, keeping the reference count the same. This is used when returning /// a <code>PP_Var</code> 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(); is_managed_ = true; return ret; } /// DebugString() returns a short description "Var<X>" 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 <code>Var</code>. This /// function is used for debugging. std::string DebugString() const; /// This class is used when calling the raw C PPAPI when using the C++ /// <code>Var</code> as a possible 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. /// /// <strong>Warning:</strong> 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_; // |is_managed_| indicates if the instance manages |var_|. // You need to check if |var_| is refcounted to call Release(). bool is_managed_; 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_