15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/var.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_var.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_var.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/instance.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/logging.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/module.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/module_impl.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Define equivalent to snprintf on Windows.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(_MSC_VER)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#  define snprintf sprintf_s
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace pp {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template <> const char* interface_name<PPB_Var_1_2>() {
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return PPB_VAR_INTERFACE_1_2;
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <> const char* interface_name<PPB_Var_1_1>() {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PPB_VAR_INTERFACE_1_1;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <> const char* interface_name<PPB_Var_1_0>() {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PPB_VAR_INTERFACE_1_0;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Technically you can call AddRef and Release on any Var, but it may involve
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cross-process calls depending on the plugin. This is an optimization so we
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// only do refcounting on the necessary objects.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline bool NeedsRefcounting(const PP_Var& var) {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return var.type > PP_VARTYPE_DOUBLE;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This helper function uses the latest available version of VarFromUtf8. Note
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// that version 1.0 of this method has a different API to later versions.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Var VarFromUtf8Helper(const char* utf8_str, uint32_t len) {
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (has_interface<PPB_Var_1_2>()) {
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return get_interface<PPB_Var_1_2>()->VarFromUtf8(utf8_str, len);
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else if (has_interface<PPB_Var_1_1>()) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return get_interface<PPB_Var_1_1>()->VarFromUtf8(utf8_str, len);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (has_interface<PPB_Var_1_0>()) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return get_interface<PPB_Var_1_0>()->VarFromUtf8(Module::Get()->pp_module(),
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     utf8_str,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     len);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return PP_MakeNull();
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This helper function uses the latest available version of AddRef.
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Returns true on success, false if no appropriate interface was available.
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool AddRefHelper(const PP_Var& var) {
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (has_interface<PPB_Var_1_2>()) {
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    get_interface<PPB_Var_1_2>()->AddRef(var);
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return true;
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else if (has_interface<PPB_Var_1_1>()) {
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    get_interface<PPB_Var_1_1>()->AddRef(var);
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return true;
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else if (has_interface<PPB_Var_1_0>()) {
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    get_interface<PPB_Var_1_0>()->AddRef(var);
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return true;
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return false;
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This helper function uses the latest available version of Release.
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Returns true on success, false if no appropriate interface was available.
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ReleaseHelper(const PP_Var& var) {
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (has_interface<PPB_Var_1_2>()) {
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    get_interface<PPB_Var_1_2>()->Release(var);
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return true;
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else if (has_interface<PPB_Var_1_1>()) {
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    get_interface<PPB_Var_1_1>()->Release(var);
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return true;
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else if (has_interface<PPB_Var_1_0>()) {
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    get_interface<PPB_Var_1_0>()->Release(var);
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return true;
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return false;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Var::Var() {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&var_, 0, sizeof(var_));
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.type = PP_VARTYPE_UNDEFINED;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_managed_ = true;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Var::Var(Null) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&var_, 0, sizeof(var_));
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.type = PP_VARTYPE_NULL;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_managed_ = true;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Var::Var(bool b) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.type = PP_VARTYPE_BOOL;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.padding = 0;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.value.as_bool = PP_FromBool(b);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_managed_ = true;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Var::Var(int32_t i) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.type = PP_VARTYPE_INT32;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.padding = 0;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.value.as_int = i;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_managed_ = true;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Var::Var(double d) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.type = PP_VARTYPE_DOUBLE;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.padding = 0;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_.value.as_double = d;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_managed_ = true;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Var::Var(const char* utf8_str) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t len = utf8_str ? static_cast<uint32_t>(strlen(utf8_str)) : 0;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_ = VarFromUtf8Helper(utf8_str, len);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_managed_ = true;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Var::Var(const std::string& utf8_str) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_ = VarFromUtf8Helper(utf8_str.c_str(),
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           static_cast<uint32_t>(utf8_str.size()));
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_managed_ = true;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Var::Var(const pp::Resource& resource) {
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (has_interface<PPB_Var_1_2>()) {
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    var_ = get_interface<PPB_Var_1_2>()->VarFromResource(
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        resource.pp_resource());
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PP_NOTREACHED();
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Set |is_managed_| to true, so |var_| will be properly released upon
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // destruction.
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  is_managed_ = true;
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Var::Var(const PP_Var& var) {
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  var_ = var;
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  is_managed_ = true;
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (NeedsRefcounting(var_)) {
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!AddRefHelper(var_))
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      var_.type = PP_VARTYPE_NULL;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Var::Var(const Var& other) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_ = other.var_;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_managed_ = true;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NeedsRefcounting(var_)) {
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!AddRefHelper(var_))
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var_.type = PP_VARTYPE_NULL;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Var::~Var() {
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (NeedsRefcounting(var_) && is_managed_)
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ReleaseHelper(var_);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Var& Var::operator=(const Var& other) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Early return for self-assignment. Note however, that two distinct vars
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can refer to the same object, so we still need to be careful about the
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // refcounting below.
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (this == &other)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return *this;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Be careful to keep the ref alive for cases where we're assigning an
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // object to itself by addrefing the new one before releasing the old one.
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool old_is_managed = is_managed_;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_managed_ = true;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NeedsRefcounting(other.var_)) {
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AddRefHelper(other.var_);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NeedsRefcounting(var_) && old_is_managed)
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ReleaseHelper(var_);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var_ = other.var_;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *this;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Var::operator==(const Var& other) const {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (var_.type != other.var_.type)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (var_.type) {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_VARTYPE_UNDEFINED:
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_VARTYPE_NULL:
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_VARTYPE_BOOL:
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return AsBool() == other.AsBool();
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_VARTYPE_INT32:
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return AsInt() == other.AsInt();
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_VARTYPE_DOUBLE:
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return AsDouble() == other.AsDouble();
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_VARTYPE_STRING:
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (var_.value.as_id == other.var_.value.as_id)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return AsString() == other.AsString();
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_VARTYPE_OBJECT:
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_VARTYPE_ARRAY:
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_VARTYPE_ARRAY_BUFFER:
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PP_VARTYPE_DICTIONARY:
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case PP_VARTYPE_RESOURCE:
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    default:  // Objects, arrays, dictionaries, resources.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return var_.value.as_id == other.var_.value.as_id;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Var::AsBool() const {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_bool()) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_NOTREACHED();
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_ToBool(var_.value.as_bool);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t Var::AsInt() const {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_int())
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return var_.value.as_int;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_double())
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return static_cast<int>(var_.value.as_double);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_NOTREACHED();
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double Var::AsDouble() const {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_double())
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return var_.value.as_double;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_int())
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return static_cast<double>(var_.value.as_int);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_NOTREACHED();
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0.0;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Var::AsString() const {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_string()) {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_NOTREACHED();
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return std::string();
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t len;
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const char* str;
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (has_interface<PPB_Var_1_2>())
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    str = get_interface<PPB_Var_1_2>()->VarToUtf8(var_, &len);
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else if (has_interface<PPB_Var_1_1>())
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    str = get_interface<PPB_Var_1_1>()->VarToUtf8(var_, &len);
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else if (has_interface<PPB_Var_1_0>())
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    str = get_interface<PPB_Var_1_0>()->VarToUtf8(var_, &len);
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return std::string();
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::string(str, len);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)pp::Resource Var::AsResource() const {
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!is_resource()) {
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PP_NOTREACHED();
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return pp::Resource();
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (has_interface<PPB_Var_1_2>()) {
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return pp::Resource(pp::PASS_REF,
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        get_interface<PPB_Var_1_2>()->VarToResource(var_));
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return pp::Resource();
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Var::DebugString() const {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf[256];
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_undefined()) {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    snprintf(buf, sizeof(buf), "Var(UNDEFINED)");
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (is_null()) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    snprintf(buf, sizeof(buf), "Var(NULL)");
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (is_bool()) {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    snprintf(buf, sizeof(buf), AsBool() ? "Var(true)" : "Var(false)");
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (is_int()) {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    snprintf(buf, sizeof(buf), "Var(%d)", static_cast<int>(AsInt()));
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (is_double()) {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    snprintf(buf, sizeof(buf), "Var(%f)", AsDouble());
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (is_string()) {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char format[] = "Var<'%s'>";
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t decoration = sizeof(format) - 2;  // The %s is removed.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t available = sizeof(buf) - decoration;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string str = AsString();
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (str.length() > available) {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      str.resize(available - 3);  // Reserve space for ellipsis.
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      str.append("...");
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    snprintf(buf, sizeof(buf), format, str.c_str());
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (is_object()) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    snprintf(buf, sizeof(buf), "Var(OBJECT)");
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (is_array()) {
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    snprintf(buf, sizeof(buf), "Var(ARRAY)");
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (is_dictionary()) {
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    snprintf(buf, sizeof(buf), "Var(DICTIONARY)");
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (is_array_buffer()) {
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    snprintf(buf, sizeof(buf), "Var(ARRAY_BUFFER)");
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else if (is_resource()) {
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    snprintf(buf, sizeof(buf), "Var(RESOURCE)");
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    buf[0] = '\0';
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return buf;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace pp
322