blob: e055cad74c3635b5452b8c3dcf875719bba91a46 [file] [log] [blame]
// 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_