WebKitTools/DumpRenderTree/chromium/CppVariant.cpp
changeset 0 4f2f89ce4247
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebKitTools/DumpRenderTree/chromium/CppVariant.cpp	Fri Sep 17 09:02:29 2010 +0300
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CppVariant.h"
+
+#include "public/WebBindings.h"
+#include <limits>
+#include <wtf/Assertions.h>
+#include <wtf/StringExtras.h>
+
+using namespace WebKit;
+using namespace std;
+
+CppVariant::CppVariant()
+{
+    type = NPVariantType_Null;
+}
+
+// Note that Set() performs a deep copy, which is necessary to safely
+// call FreeData() on the value in the destructor.
+CppVariant::CppVariant(const CppVariant& original)
+{
+    type = NPVariantType_Null;
+    set(original);
+}
+
+// See comment for copy constructor, above.
+CppVariant& CppVariant::operator=(const CppVariant& original)
+{
+    if (&original != this)
+        set(original);
+    return *this;
+}
+
+CppVariant::~CppVariant()
+{
+    freeData();
+}
+
+void CppVariant::freeData()
+{
+    WebBindings::releaseVariantValue(this);
+}
+
+bool CppVariant::isEqual(const CppVariant& other) const
+{
+    if (type != other.type)
+        return false;
+
+    switch (type) {
+    case NPVariantType_Bool:
+        return (value.boolValue == other.value.boolValue);
+    case NPVariantType_Int32:
+        return (value.intValue == other.value.intValue);
+    case NPVariantType_Double:
+        return (value.doubleValue == other.value.doubleValue);
+    case NPVariantType_String: {
+        const NPString *this_value = &value.stringValue;
+        const NPString *other_value = &other.value.stringValue;
+        uint32_t len = this_value->UTF8Length;
+        return len == other_value->UTF8Length
+            && !strncmp(this_value->UTF8Characters,
+                        other_value->UTF8Characters, len);
+    }
+    case NPVariantType_Null:
+    case NPVariantType_Void:
+        return true;
+    case NPVariantType_Object: {
+        NPObject* thisValue = value.objectValue;
+        NPObject* otherValue = other.value.objectValue;
+        return thisValue->_class == otherValue->_class
+            && thisValue->referenceCount == otherValue->referenceCount;
+    }
+    }
+    return false;
+}
+
+void CppVariant::copyToNPVariant(NPVariant* result) const
+{
+    result->type = type;
+    switch (type) {
+    case NPVariantType_Bool:
+        result->value.boolValue = value.boolValue;
+        break;
+    case NPVariantType_Int32:
+        result->value.intValue = value.intValue;
+        break;
+    case NPVariantType_Double:
+        result->value.doubleValue = value.doubleValue;
+        break;
+    case NPVariantType_String:
+        WebBindings::initializeVariantWithStringCopy(result, &value.stringValue);
+        break;
+    case NPVariantType_Null:
+    case NPVariantType_Void:
+        // Nothing to set.
+        break;
+    case NPVariantType_Object:
+        result->type = NPVariantType_Object;
+        result->value.objectValue = WebBindings::retainObject(value.objectValue);
+        break;
+    }
+}
+
+void CppVariant::set(const NPVariant& newValue)
+{
+    freeData();
+    switch (newValue.type) {
+    case NPVariantType_Bool:
+        set(newValue.value.boolValue);
+        break;
+    case NPVariantType_Int32:
+        set(newValue.value.intValue);
+        break;
+    case NPVariantType_Double:
+        set(newValue.value.doubleValue);
+        break;
+    case NPVariantType_String:
+        set(newValue.value.stringValue);
+        break;
+    case NPVariantType_Null:
+    case NPVariantType_Void:
+        type = newValue.type;
+        break;
+    case NPVariantType_Object:
+        set(newValue.value.objectValue);
+        break;
+    }
+}
+
+void CppVariant::setNull()
+{
+    freeData();
+    type = NPVariantType_Null;
+}
+
+void CppVariant::set(bool newValue)
+{
+    freeData();
+    type = NPVariantType_Bool;
+    value.boolValue = newValue;
+}
+
+void CppVariant::set(int32_t newValue)
+{
+    freeData();
+    type = NPVariantType_Int32;
+    value.intValue = newValue;
+}
+
+void CppVariant::set(double newValue)
+{
+    freeData();
+    type = NPVariantType_Double;
+    value.doubleValue = newValue;
+}
+
+// The newValue must be a null-terminated string.
+void CppVariant::set(const char* newValue)
+{
+    freeData();
+    type = NPVariantType_String;
+    NPString newString = {newValue,
+                          static_cast<uint32_t>(strlen(newValue))};
+    WebBindings::initializeVariantWithStringCopy(this, &newString);
+}
+
+void CppVariant::set(const string& newValue)
+{
+    freeData();
+    type = NPVariantType_String;
+    NPString newString = {newValue.data(),
+                          static_cast<uint32_t>(newValue.size())};
+    WebBindings::initializeVariantWithStringCopy(this, &newString);
+}
+
+void CppVariant::set(const NPString& newValue)
+{
+    freeData();
+    type = NPVariantType_String;
+    WebBindings::initializeVariantWithStringCopy(this, &newValue);
+}
+
+void CppVariant::set(NPObject* newValue)
+{
+    freeData();
+    type = NPVariantType_Object;
+    value.objectValue = WebBindings::retainObject(newValue);
+}
+
+string CppVariant::toString() const
+{
+    ASSERT(isString());
+    return string(value.stringValue.UTF8Characters,
+                  value.stringValue.UTF8Length);
+}
+
+int32_t CppVariant::toInt32() const
+{
+    if (isInt32())
+        return value.intValue;
+    if (isDouble())
+        return static_cast<int32_t>(value.doubleValue);
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+double CppVariant::toDouble() const
+{
+    if (isInt32())
+        return static_cast<double>(value.intValue);
+    if (isDouble())
+        return value.doubleValue;
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+bool CppVariant::toBoolean() const
+{
+    ASSERT(isBool());
+    return value.boolValue;
+}
+
+Vector<string> CppVariant::toStringVector() const
+{
+
+    ASSERT(isObject());
+    Vector<string> stringVector;
+    NPObject* npValue = value.objectValue;
+    NPIdentifier lengthId = WebBindings::getStringIdentifier("length");
+
+    if (!WebBindings::hasProperty(0, npValue, lengthId))
+        return stringVector;
+
+    NPVariant lengthValue;
+    if (!WebBindings::getProperty(0, npValue, lengthId, &lengthValue))
+        return stringVector;
+
+    int length = 0;
+    // The length is a double in some cases.
+    if (NPVARIANT_IS_DOUBLE(lengthValue))
+        length = static_cast<int>(NPVARIANT_TO_DOUBLE(lengthValue));
+    else if (NPVARIANT_IS_INT32(lengthValue))
+        length = NPVARIANT_TO_INT32(lengthValue);
+    WebBindings::releaseVariantValue(&lengthValue);
+
+    // For sanity, only allow 100 items.
+    length = min(100, length);
+    for (int i = 0; i < length; ++i) {
+        // Get each of the items.
+        char indexInChar[20]; // Enough size to store 32-bit integer
+        snprintf(indexInChar, 20, "%d", i);
+        string index(indexInChar);
+        NPIdentifier indexId = WebBindings::getStringIdentifier(index.c_str());
+        if (!WebBindings::hasProperty(0, npValue, indexId))
+            continue;
+        NPVariant indexValue;
+        if (!WebBindings::getProperty(0, npValue, indexId, &indexValue))
+            continue;
+        if (NPVARIANT_IS_STRING(indexValue)) {
+            string item(NPVARIANT_TO_STRING(indexValue).UTF8Characters,
+                        NPVARIANT_TO_STRING(indexValue).UTF8Length);
+            stringVector.append(item);
+        }
+        WebBindings::releaseVariantValue(&indexValue);
+    }
+    return stringVector;
+}
+
+bool CppVariant::invoke(const string& method, const CppVariant* arguments,
+                        uint32_t argumentCount, CppVariant& result) const
+{
+    ASSERT(isObject());
+    NPIdentifier methodName = WebBindings::getStringIdentifier(method.c_str());
+    NPObject* npObject = value.objectValue;
+    if (!WebBindings::hasMethod(0, npObject, methodName))
+        return false;
+    NPVariant r;
+    bool status = WebBindings::invoke(0, npObject, methodName, arguments, argumentCount, &r);
+    result.set(r);
+    return status;
+}