diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-01 16:16:50 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-01 16:16:50 +0000 |
commit | 1758e88fd909ea0ffd49621e8066ffad5627ffdf (patch) | |
tree | c304a5eed047cae5665f5af1739d84655fb5815d /ppapi/cpp/var.cc | |
parent | e7d8b51953b7d3b2b8a0aba46132305b32f3efce (diff) | |
download | chromium_src-1758e88fd909ea0ffd49621e8066ffad5627ffdf.zip chromium_src-1758e88fd909ea0ffd49621e8066ffad5627ffdf.tar.gz chromium_src-1758e88fd909ea0ffd49621e8066ffad5627ffdf.tar.bz2 |
Move PPAPI into the Chrome repo. The old repo was
http://ppapi.googlecode.com/
TEST=none
BUG=none
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@64613 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/cpp/var.cc')
-rw-r--r-- | ppapi/cpp/var.cc | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/ppapi/cpp/var.cc b/ppapi/cpp/var.cc new file mode 100644 index 0000000..d48253a --- /dev/null +++ b/ppapi/cpp/var.cc @@ -0,0 +1,365 @@ +// 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. + +#include "ppapi/cpp/var.h" + +#include <string.h> + +#include <algorithm> + +#include "ppapi/c/pp_var.h" +#include "ppapi/c/dev/ppb_var_deprecated.h" +#include "ppapi/cpp/logging.h" +#include "ppapi/cpp/module.h" +#include "ppapi/cpp/module_impl.h" +#include "ppapi/cpp/dev/scriptable_object_deprecated.h" + +// Defining snprintf +#include <stdio.h> +#if defined(_MSC_VER) +# define snprintf _snprintf_s +#endif + +namespace { + +DeviceFuncs<PPB_Var_Deprecated> ppb_var_f(PPB_VAR_DEPRECATED_INTERFACE); + +// Technically you can call AddRef and Release on any Var, but it may involve +// cross-process calls depending on the plugin. This is an optimization so we +// only do refcounting on the necessary objects. +inline bool NeedsRefcounting(const PP_Var& var) { + return var.type == PP_VARTYPE_STRING || var.type == PP_VARTYPE_OBJECT; +} + +} // namespace + +namespace pp { + +using namespace deprecated; + +Var::Var() { + var_.type = PP_VARTYPE_UNDEFINED; + needs_release_ = false; +} + +Var::Var(Null) { + var_.type = PP_VARTYPE_NULL; + needs_release_ = false; +} + +Var::Var(bool b) { + var_.type = PP_VARTYPE_BOOL; + var_.value.as_bool = b; + needs_release_ = false; +} + +Var::Var(int32_t i) { + var_.type = PP_VARTYPE_INT32; + var_.value.as_int = i; + needs_release_ = false; +} + +Var::Var(double d) { + var_.type = PP_VARTYPE_DOUBLE; + var_.value.as_double = d; + needs_release_ = false; +} + +Var::Var(const char* utf8_str) { + if (ppb_var_f) { + uint32_t len = utf8_str ? static_cast<uint32_t>(strlen(utf8_str)) : 0; + var_ = ppb_var_f->VarFromUtf8(Module::Get()->pp_module(), utf8_str, len); + } else { + var_.type = PP_VARTYPE_NULL; + } + needs_release_ = (var_.type == PP_VARTYPE_STRING); +} + +Var::Var(const std::string& utf8_str) { + if (ppb_var_f) { + var_ = ppb_var_f->VarFromUtf8(Module::Get()->pp_module(), + utf8_str.c_str(), + static_cast<uint32_t>(utf8_str.size())); + } else { + var_.type = PP_VARTYPE_NULL; + } + needs_release_ = (var_.type == PP_VARTYPE_STRING); +} + +Var::Var(ScriptableObject* object) { + if (ppb_var_f) { + var_ = ppb_var_f->CreateObject(Module::Get()->pp_module(), + object->GetClass(), object); + needs_release_ = true; + } else { + var_.type = PP_VARTYPE_NULL; + needs_release_ = false; + } +} + +Var::Var(const Var& other) { + var_ = other.var_; + if (NeedsRefcounting(var_)) { + if (ppb_var_f) { + needs_release_ = true; + ppb_var_f->AddRef(var_); + } else { + var_.type = PP_VARTYPE_NULL; + needs_release_ = false; + } + } else { + needs_release_ = false; + } +} + +Var::~Var() { + if (needs_release_ && ppb_var_f) + ppb_var_f->Release(var_); +} + +Var& Var::operator=(const Var& other) { + if (needs_release_ && ppb_var_f) + ppb_var_f->Release(var_); + var_ = other.var_; + if (NeedsRefcounting(var_)) { + if (ppb_var_f) { + needs_release_ = true; + ppb_var_f->AddRef(var_); + } else { + var_.type = PP_VARTYPE_NULL; + needs_release_ = false; + } + } else { + needs_release_ = false; + } + return *this; +} + +bool Var::operator==(const Var& other) const { + if (var_.type != other.var_.type) + return false; + switch (var_.type) { + case PP_VARTYPE_UNDEFINED: + case PP_VARTYPE_NULL: + return true; + case PP_VARTYPE_BOOL: + return AsBool() == other.AsBool(); + case PP_VARTYPE_INT32: + return AsInt() == other.AsInt(); + case PP_VARTYPE_DOUBLE: + return AsDouble() == other.AsDouble(); + case PP_VARTYPE_STRING: + if (var_.value.as_id == other.var_.value.as_id) + return true; + return AsString() == other.AsString(); + // TODO(neb): Document that this is === and not ==, unlike strings. + case PP_VARTYPE_OBJECT: + return var_.value.as_id == other.var_.value.as_id; + default: + return false; + } +} + +bool Var::AsBool() const { + if (!is_bool()) { + PP_NOTREACHED(); + return false; + } + return var_.value.as_bool; +} + +int32_t Var::AsInt() const { + if (is_int()) + return var_.value.as_int; + if (is_double()) + return static_cast<int>(var_.value.as_double); + PP_NOTREACHED(); + return 0; +} + +double Var::AsDouble() const { + if (is_double()) + return var_.value.as_double; + if (is_int()) + return static_cast<double>(var_.value.as_int); + PP_NOTREACHED(); + return 0.0; +} + +std::string Var::AsString() const { + if (!is_string()) { + PP_NOTREACHED(); + return std::string(); + } + + if (!ppb_var_f) + return std::string(); + uint32_t len; + const char* str = ppb_var_f->VarToUtf8(var_, &len); + return std::string(str, len); +} + +ScriptableObject* Var::AsScriptableObject() const { + if (!is_object()) { + PP_NOTREACHED(); + } else if (ppb_var_f) { + void* object = NULL; + if (ppb_var_f->IsInstanceOf(var_, ScriptableObject::GetClass(), &object)) { + return reinterpret_cast<ScriptableObject*>(object); + } + } + return NULL; +} + +bool Var::HasProperty(const Var& name, Var* exception) const { + if (!ppb_var_f) + return false; + return ppb_var_f->HasProperty(var_, name.var_, OutException(exception).get()); +} + +bool Var::HasMethod(const Var& name, Var* exception) const { + if (!ppb_var_f) + return false; + return ppb_var_f->HasMethod(var_, name.var_, OutException(exception).get()); +} + +Var Var::GetProperty(const Var& name, Var* exception) const { + if (!ppb_var_f) + return Var(); + return Var(PassRef(), ppb_var_f->GetProperty(var_, name.var_, + OutException(exception).get())); +} + +void Var::GetAllPropertyNames(std::vector<Var>* properties, + Var* exception) const { + if (!ppb_var_f) + return; + PP_Var* props = NULL; + uint32_t prop_count = 0; + ppb_var_f->GetAllPropertyNames(var_, &prop_count, &props, + OutException(exception).get()); + if (!prop_count) + return; + properties->resize(prop_count); + for (uint32_t i = 0; i < prop_count; ++i) { + Var temp(PassRef(), props[i]); + (*properties)[i] = temp; + } + Module::Get()->core()->MemFree(props); +} + +void Var::SetProperty(const Var& name, const Var& value, Var* exception) { + if (!ppb_var_f) + return; + ppb_var_f->SetProperty(var_, name.var_, value.var_, + OutException(exception).get()); +} + +void Var::RemoveProperty(const Var& name, Var* exception) { + if (!ppb_var_f) + return; + ppb_var_f->RemoveProperty(var_, name.var_, OutException(exception).get()); +} + +Var Var::Call(const Var& method_name, uint32_t argc, Var* argv, + Var* exception) { + if (!ppb_var_f) + return Var(); + if (argc > 0) { + std::vector<PP_Var> args; + args.reserve(argc); + for (size_t i = 0; i < argc; i++) + args.push_back(argv[i].var_); + return Var(PassRef(), ppb_var_f->Call(var_, method_name.var_, + argc, &args[0], + OutException(exception).get())); + } else { + // Don't try to get the address of a vector if it's empty. + return Var(PassRef(), ppb_var_f->Call(var_, method_name.var_, 0, NULL, + OutException(exception).get())); + } +} + +Var Var::Construct(uint32_t argc, Var* argv, Var* exception) const { + if (!ppb_var_f) + return Var(); + if (argc > 0) { + std::vector<PP_Var> args; + args.reserve(argc); + for (size_t i = 0; i < argc; i++) + args.push_back(argv[i].var_); + return Var(PassRef(), ppb_var_f->Construct(var_, argc, &args[0], + OutException(exception).get())); + } else { + // Don't try to get the address of a vector if it's empty. + return Var(PassRef(), ppb_var_f->Construct(var_, 0, NULL, + OutException(exception).get())); + } +} + +Var Var::Call(const Var& method_name, Var* exception) { + if (!ppb_var_f) + return Var(); + return Var(PassRef(), ppb_var_f->Call(var_, method_name.var_, 0, NULL, + OutException(exception).get())); +} + +Var Var::Call(const Var& method_name, const Var& arg1, Var* exception) { + if (!ppb_var_f) + return Var(); + PP_Var args[1] = {arg1.var_}; + return Var(PassRef(), ppb_var_f->Call(var_, method_name.var_, 1, args, + OutException(exception).get())); +} + +Var Var::Call(const Var& method_name, const Var& arg1, const Var& arg2, + Var* exception) { + if (!ppb_var_f) + return Var(); + PP_Var args[2] = {arg1.var_, arg2.var_}; + return Var(PassRef(), ppb_var_f->Call(var_, method_name.var_, 2, args, + OutException(exception).get())); +} + +Var Var::Call(const Var& method_name, const Var& arg1, const Var& arg2, + const Var& arg3, Var* exception) { + if (!ppb_var_f) + return Var(); + PP_Var args[3] = {arg1.var_, arg2.var_, arg3.var_}; + return Var(PassRef(), ppb_var_f->Call(var_, method_name.var_, 3, args, + OutException(exception).get())); +} + +Var Var::Call(const Var& method_name, const Var& arg1, const Var& arg2, + const Var& arg3, const Var& arg4, Var* exception) { + if (!ppb_var_f) + return Var(); + PP_Var args[4] = {arg1.var_, arg2.var_, arg3.var_, arg4.var_}; + return Var(PassRef(), ppb_var_f->Call(var_, method_name.var_, 4, args, + OutException(exception).get())); +} + +std::string Var::DebugString() const { + char buf[256]; + if (is_undefined()) + snprintf(buf, sizeof(buf), "Var<UNDEFINED>"); + else if (is_null()) + snprintf(buf, sizeof(buf), "Var<NULL>"); + else if (is_bool()) + snprintf(buf, sizeof(buf), AsBool() ? "Var<true>" : "Var<false>"); + else if (is_int()) + // Note that the following static_cast is necessary because + // NativeClient's int32_t is actually "long". + // TODO(sehr,polina): remove this after newlib is changed. + snprintf(buf, sizeof(buf), "Var<%d>", static_cast<int>(AsInt())); + else if (is_double()) + snprintf(buf, sizeof(buf), "Var<%f>", AsDouble()); + else if (is_string()) + snprintf(buf, sizeof(buf), "Var<'%s'>", AsString().c_str()); + else if (is_object()) + snprintf(buf, sizeof(buf), "Var<OBJECT>"); + return buf; +} + +} // namespace pp |