WebKitTools/DumpRenderTree/chromium/CppVariant.cpp
changeset 2 303757a437d3
parent 0 4f2f89ce4247
equal deleted inserted replaced
0:4f2f89ce4247 2:303757a437d3
     1 /*
       
     2  * Copyright (C) 2010 Google Inc. All rights reserved.
       
     3  *
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions are
       
     6  * met:
       
     7  *
       
     8  *     * Redistributions of source code must retain the above copyright
       
     9  * notice, this list of conditions and the following disclaimer.
       
    10  *     * Redistributions in binary form must reproduce the above
       
    11  * copyright notice, this list of conditions and the following disclaimer
       
    12  * in the documentation and/or other materials provided with the
       
    13  * distribution.
       
    14  *     * Neither the name of Google Inc. nor the names of its
       
    15  * contributors may be used to endorse or promote products derived from
       
    16  * this software without specific prior written permission.
       
    17  *
       
    18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       
    19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
       
    20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
       
    21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
       
    22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
    23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
       
    24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
       
    25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
       
    26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    29  */
       
    30 
       
    31 #include "config.h"
       
    32 #include "CppVariant.h"
       
    33 
       
    34 #include "public/WebBindings.h"
       
    35 #include <limits>
       
    36 #include <wtf/Assertions.h>
       
    37 #include <wtf/StringExtras.h>
       
    38 
       
    39 using namespace WebKit;
       
    40 using namespace std;
       
    41 
       
    42 CppVariant::CppVariant()
       
    43 {
       
    44     type = NPVariantType_Null;
       
    45 }
       
    46 
       
    47 // Note that Set() performs a deep copy, which is necessary to safely
       
    48 // call FreeData() on the value in the destructor.
       
    49 CppVariant::CppVariant(const CppVariant& original)
       
    50 {
       
    51     type = NPVariantType_Null;
       
    52     set(original);
       
    53 }
       
    54 
       
    55 // See comment for copy constructor, above.
       
    56 CppVariant& CppVariant::operator=(const CppVariant& original)
       
    57 {
       
    58     if (&original != this)
       
    59         set(original);
       
    60     return *this;
       
    61 }
       
    62 
       
    63 CppVariant::~CppVariant()
       
    64 {
       
    65     freeData();
       
    66 }
       
    67 
       
    68 void CppVariant::freeData()
       
    69 {
       
    70     WebBindings::releaseVariantValue(this);
       
    71 }
       
    72 
       
    73 bool CppVariant::isEqual(const CppVariant& other) const
       
    74 {
       
    75     if (type != other.type)
       
    76         return false;
       
    77 
       
    78     switch (type) {
       
    79     case NPVariantType_Bool:
       
    80         return (value.boolValue == other.value.boolValue);
       
    81     case NPVariantType_Int32:
       
    82         return (value.intValue == other.value.intValue);
       
    83     case NPVariantType_Double:
       
    84         return (value.doubleValue == other.value.doubleValue);
       
    85     case NPVariantType_String: {
       
    86         const NPString *this_value = &value.stringValue;
       
    87         const NPString *other_value = &other.value.stringValue;
       
    88         uint32_t len = this_value->UTF8Length;
       
    89         return len == other_value->UTF8Length
       
    90             && !strncmp(this_value->UTF8Characters,
       
    91                         other_value->UTF8Characters, len);
       
    92     }
       
    93     case NPVariantType_Null:
       
    94     case NPVariantType_Void:
       
    95         return true;
       
    96     case NPVariantType_Object: {
       
    97         NPObject* thisValue = value.objectValue;
       
    98         NPObject* otherValue = other.value.objectValue;
       
    99         return thisValue->_class == otherValue->_class
       
   100             && thisValue->referenceCount == otherValue->referenceCount;
       
   101     }
       
   102     }
       
   103     return false;
       
   104 }
       
   105 
       
   106 void CppVariant::copyToNPVariant(NPVariant* result) const
       
   107 {
       
   108     result->type = type;
       
   109     switch (type) {
       
   110     case NPVariantType_Bool:
       
   111         result->value.boolValue = value.boolValue;
       
   112         break;
       
   113     case NPVariantType_Int32:
       
   114         result->value.intValue = value.intValue;
       
   115         break;
       
   116     case NPVariantType_Double:
       
   117         result->value.doubleValue = value.doubleValue;
       
   118         break;
       
   119     case NPVariantType_String:
       
   120         WebBindings::initializeVariantWithStringCopy(result, &value.stringValue);
       
   121         break;
       
   122     case NPVariantType_Null:
       
   123     case NPVariantType_Void:
       
   124         // Nothing to set.
       
   125         break;
       
   126     case NPVariantType_Object:
       
   127         result->type = NPVariantType_Object;
       
   128         result->value.objectValue = WebBindings::retainObject(value.objectValue);
       
   129         break;
       
   130     }
       
   131 }
       
   132 
       
   133 void CppVariant::set(const NPVariant& newValue)
       
   134 {
       
   135     freeData();
       
   136     switch (newValue.type) {
       
   137     case NPVariantType_Bool:
       
   138         set(newValue.value.boolValue);
       
   139         break;
       
   140     case NPVariantType_Int32:
       
   141         set(newValue.value.intValue);
       
   142         break;
       
   143     case NPVariantType_Double:
       
   144         set(newValue.value.doubleValue);
       
   145         break;
       
   146     case NPVariantType_String:
       
   147         set(newValue.value.stringValue);
       
   148         break;
       
   149     case NPVariantType_Null:
       
   150     case NPVariantType_Void:
       
   151         type = newValue.type;
       
   152         break;
       
   153     case NPVariantType_Object:
       
   154         set(newValue.value.objectValue);
       
   155         break;
       
   156     }
       
   157 }
       
   158 
       
   159 void CppVariant::setNull()
       
   160 {
       
   161     freeData();
       
   162     type = NPVariantType_Null;
       
   163 }
       
   164 
       
   165 void CppVariant::set(bool newValue)
       
   166 {
       
   167     freeData();
       
   168     type = NPVariantType_Bool;
       
   169     value.boolValue = newValue;
       
   170 }
       
   171 
       
   172 void CppVariant::set(int32_t newValue)
       
   173 {
       
   174     freeData();
       
   175     type = NPVariantType_Int32;
       
   176     value.intValue = newValue;
       
   177 }
       
   178 
       
   179 void CppVariant::set(double newValue)
       
   180 {
       
   181     freeData();
       
   182     type = NPVariantType_Double;
       
   183     value.doubleValue = newValue;
       
   184 }
       
   185 
       
   186 // The newValue must be a null-terminated string.
       
   187 void CppVariant::set(const char* newValue)
       
   188 {
       
   189     freeData();
       
   190     type = NPVariantType_String;
       
   191     NPString newString = {newValue,
       
   192                           static_cast<uint32_t>(strlen(newValue))};
       
   193     WebBindings::initializeVariantWithStringCopy(this, &newString);
       
   194 }
       
   195 
       
   196 void CppVariant::set(const string& newValue)
       
   197 {
       
   198     freeData();
       
   199     type = NPVariantType_String;
       
   200     NPString newString = {newValue.data(),
       
   201                           static_cast<uint32_t>(newValue.size())};
       
   202     WebBindings::initializeVariantWithStringCopy(this, &newString);
       
   203 }
       
   204 
       
   205 void CppVariant::set(const NPString& newValue)
       
   206 {
       
   207     freeData();
       
   208     type = NPVariantType_String;
       
   209     WebBindings::initializeVariantWithStringCopy(this, &newValue);
       
   210 }
       
   211 
       
   212 void CppVariant::set(NPObject* newValue)
       
   213 {
       
   214     freeData();
       
   215     type = NPVariantType_Object;
       
   216     value.objectValue = WebBindings::retainObject(newValue);
       
   217 }
       
   218 
       
   219 string CppVariant::toString() const
       
   220 {
       
   221     ASSERT(isString());
       
   222     return string(value.stringValue.UTF8Characters,
       
   223                   value.stringValue.UTF8Length);
       
   224 }
       
   225 
       
   226 int32_t CppVariant::toInt32() const
       
   227 {
       
   228     if (isInt32())
       
   229         return value.intValue;
       
   230     if (isDouble())
       
   231         return static_cast<int32_t>(value.doubleValue);
       
   232     ASSERT_NOT_REACHED();
       
   233     return 0;
       
   234 }
       
   235 
       
   236 double CppVariant::toDouble() const
       
   237 {
       
   238     if (isInt32())
       
   239         return static_cast<double>(value.intValue);
       
   240     if (isDouble())
       
   241         return value.doubleValue;
       
   242     ASSERT_NOT_REACHED();
       
   243     return 0;
       
   244 }
       
   245 
       
   246 bool CppVariant::toBoolean() const
       
   247 {
       
   248     ASSERT(isBool());
       
   249     return value.boolValue;
       
   250 }
       
   251 
       
   252 Vector<string> CppVariant::toStringVector() const
       
   253 {
       
   254 
       
   255     ASSERT(isObject());
       
   256     Vector<string> stringVector;
       
   257     NPObject* npValue = value.objectValue;
       
   258     NPIdentifier lengthId = WebBindings::getStringIdentifier("length");
       
   259 
       
   260     if (!WebBindings::hasProperty(0, npValue, lengthId))
       
   261         return stringVector;
       
   262 
       
   263     NPVariant lengthValue;
       
   264     if (!WebBindings::getProperty(0, npValue, lengthId, &lengthValue))
       
   265         return stringVector;
       
   266 
       
   267     int length = 0;
       
   268     // The length is a double in some cases.
       
   269     if (NPVARIANT_IS_DOUBLE(lengthValue))
       
   270         length = static_cast<int>(NPVARIANT_TO_DOUBLE(lengthValue));
       
   271     else if (NPVARIANT_IS_INT32(lengthValue))
       
   272         length = NPVARIANT_TO_INT32(lengthValue);
       
   273     WebBindings::releaseVariantValue(&lengthValue);
       
   274 
       
   275     // For sanity, only allow 100 items.
       
   276     length = min(100, length);
       
   277     for (int i = 0; i < length; ++i) {
       
   278         // Get each of the items.
       
   279         char indexInChar[20]; // Enough size to store 32-bit integer
       
   280         snprintf(indexInChar, 20, "%d", i);
       
   281         string index(indexInChar);
       
   282         NPIdentifier indexId = WebBindings::getStringIdentifier(index.c_str());
       
   283         if (!WebBindings::hasProperty(0, npValue, indexId))
       
   284             continue;
       
   285         NPVariant indexValue;
       
   286         if (!WebBindings::getProperty(0, npValue, indexId, &indexValue))
       
   287             continue;
       
   288         if (NPVARIANT_IS_STRING(indexValue)) {
       
   289             string item(NPVARIANT_TO_STRING(indexValue).UTF8Characters,
       
   290                         NPVARIANT_TO_STRING(indexValue).UTF8Length);
       
   291             stringVector.append(item);
       
   292         }
       
   293         WebBindings::releaseVariantValue(&indexValue);
       
   294     }
       
   295     return stringVector;
       
   296 }
       
   297 
       
   298 bool CppVariant::invoke(const string& method, const CppVariant* arguments,
       
   299                         uint32_t argumentCount, CppVariant& result) const
       
   300 {
       
   301     ASSERT(isObject());
       
   302     NPIdentifier methodName = WebBindings::getStringIdentifier(method.c_str());
       
   303     NPObject* npObject = value.objectValue;
       
   304     if (!WebBindings::hasMethod(0, npObject, methodName))
       
   305         return false;
       
   306     NPVariant r;
       
   307     bool status = WebBindings::invoke(0, npObject, methodName, arguments, argumentCount, &r);
       
   308     result.set(r);
       
   309     return status;
       
   310 }