summaryrefslogtreecommitdiffstats
path: root/ppapi/cpp/var.cc
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-01 16:16:50 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-01 16:16:50 +0000
commit1758e88fd909ea0ffd49621e8066ffad5627ffdf (patch)
treec304a5eed047cae5665f5af1739d84655fb5815d /ppapi/cpp/var.cc
parente7d8b51953b7d3b2b8a0aba46132305b32f3efce (diff)
downloadchromium_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.cc365
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