| // Copyright (c) 2010 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_module.h" |
| #include "ppapi/c/pp_var.h" |
| |
| namespace pp { |
| |
| class Instance; |
| |
| namespace deprecated { |
| class ScriptableObject; |
| } |
| |
| class Var { |
| public: |
| struct Null {}; // Special value passed to constructor to make NULL. |
| |
| Var(); // PP_Var of type Undefined. |
| Var(Null); // PP_Var of type Null. |
| Var(bool b); |
| Var(int32_t i); |
| Var(double d); |
| Var(const char* utf8_str); // Must be encoded in UTF-8. |
| Var(const std::string& utf8_str); // Must be encoded in UTF-8. |
| |
| // This magic constructor is used when we've gotten a PP_Var as a return |
| // value that has already been addref'ed for us. |
| struct PassRef {}; |
| Var(PassRef, PP_Var var) { |
| var_ = var; |
| needs_release_ = true; |
| } |
| |
| // TODO(brettw): remove DontManage when this bug is fixed |
| // http://code.google.com/p/chromium/issues/detail?id=52105 |
| // This magic 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 be AddRef'ed or Release'd by this |
| // class instance.. |
| struct DontManage {}; |
| Var(DontManage, PP_Var var) { |
| var_ = var; |
| needs_release_ = false; |
| } |
| |
| // Takes ownership of the given pointer. |
| Var(Instance* instance, deprecated::ScriptableObject* object); |
| |
| Var(const Var& other); |
| |
| virtual ~Var(); |
| |
| Var& operator=(const Var& other); |
| |
| bool operator==(const Var& other) const; |
| |
| bool is_undefined() const { return var_.type == PP_VARTYPE_UNDEFINED; } |
| bool is_null() const { return var_.type == PP_VARTYPE_NULL; } |
| bool is_bool() const { return var_.type == PP_VARTYPE_BOOL; } |
| bool is_string() const { return var_.type == PP_VARTYPE_STRING; } |
| bool is_object() const { return var_.type == PP_VARTYPE_OBJECT; } |
| |
| // IsInt and IsDouble return 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 IsNumber. |
| bool is_int() const { return var_.type == PP_VARTYPE_INT32; } |
| bool is_double() const { return var_.type == PP_VARTYPE_DOUBLE; } |
| bool is_number() const { |
| return var_.type == PP_VARTYPE_INT32 || |
| var_.type == PP_VARTYPE_DOUBLE; |
| } |
| |
| // Assumes the internal representation IsBool. If it's not, it will assert |
| // in debug mode, and return false. |
| bool AsBool() const; |
| |
| // AsInt and AsDouble implicitly convert between ints and doubles. This is |
| // 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 |
| // !IsDouble() before calling AsInt(). |
| // |
| // These functions will assert in debug mode and return 0 if the internal |
| // representation is not IsNumber(). |
| int32_t AsInt() const; |
| double AsDouble() const; |
| |
| // This assumes the object is of type string. If it's not, it will assert |
| // in debug mode, and return an empty string. |
| std::string AsString() const; |
| |
| // This assumes the object is of type object. If it's not, it will assert in |
| // debug mode. If it is not an object or not a ScriptableObject type, returns |
| // NULL. |
| deprecated::ScriptableObject* AsScriptableObject() const; |
| |
| bool HasProperty(const Var& name, Var* exception = NULL) const; |
| bool HasMethod(const Var& name, Var* exception = NULL) const; |
| Var GetProperty(const Var& name, Var* exception = NULL) const; |
| void GetAllPropertyNames(std::vector<Var>* properties, |
| Var* exception = NULL) const; |
| void SetProperty(const Var& name, const Var& value, Var* exception = NULL); |
| void RemoveProperty(const Var& name, Var* exception = NULL); |
| Var Call(const Var& method_name, uint32_t argc, Var* argv, |
| Var* exception = NULL); |
| Var Construct(uint32_t argc, Var* argv, Var* exception = NULL) const; |
| |
| // Convenience functions for calling functions with small # of args. |
| Var Call(const Var& method_name, Var* exception = NULL); |
| Var Call(const Var& method_name, const Var& arg1, Var* exception = NULL); |
| Var Call(const Var& method_name, const Var& arg1, const Var& arg2, |
| Var* exception = NULL); |
| Var Call(const Var& method_name, const Var& arg1, const Var& arg2, |
| const Var& arg3, Var* exception = NULL); |
| Var Call(const Var& method_name, const Var& arg1, const Var& arg2, |
| const Var& arg3, const Var& arg4, Var* exception = NULL); |
| |
| // Returns a const reference to the PP_Var managed by this Var object. |
| const PP_Var& pp_var() const { |
| return var_; |
| } |
| |
| // 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 be AddRef'ed for it. |
| PP_Var Detach() { |
| PP_Var ret = var_; |
| var_ = PP_MakeUndefined(); |
| needs_release_ = false; |
| return ret; |
| } |
| |
| // Prints 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. |
| std::string DebugString() const; |
| |
| // For use when calling the raw C PPAPI when using the C++ Var as a possibly |
| // NULL exception. This will handle getting the address of the internal value |
| // out if it's non-NULL and fixing up the reference count. |
| // |
| // Danger: 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: |
| OutException(Var* v) |
| : output_(v), |
| originally_had_exception_(v && v->is_null()) { |
| if (output_) |
| temp_ = output_->var_; |
| else |
| temp_.type = PP_VARTYPE_UNDEFINED; |
| } |
| ~OutException() { |
| if (output_ && !originally_had_exception_) |
| *output_ = Var(PassRef(), temp_); |
| } |
| |
| PP_Var* get() { |
| if (output_) |
| return &temp_; |
| return NULL; |
| } |
| |
| private: |
| Var* output_; |
| bool originally_had_exception_; |
| PP_Var temp_; |
| }; |
| |
| 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); |
| |
| PP_Var var_; |
| bool needs_release_; |
| }; |
| |
| } // namespace pp |
| |
| #endif // PPAPI_CPP_VAR_H_ |