xpcom/ds/nsVariant.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/xpcom/ds/nsVariant.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2119 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + *
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +/* The long avoided variant support for xpcom. */
    1.11 +
    1.12 +#include "nsVariant.h"
    1.13 +#include "prprf.h"
    1.14 +#include "prdtoa.h"
    1.15 +#include <math.h>
    1.16 +#include "nsCycleCollectionParticipant.h"
    1.17 +#include "xpt_struct.h"
    1.18 +#include "nsReadableUtils.h"
    1.19 +#include "nsMemory.h"
    1.20 +#include "nsString.h"
    1.21 +#include "nsCRTGlue.h"
    1.22 +
    1.23 +/***************************************************************************/
    1.24 +// Helpers for static convert functions...
    1.25 +
    1.26 +static nsresult String2Double(const char* aString, double* retval)
    1.27 +{
    1.28 +    char* next;
    1.29 +    double value = PR_strtod(aString, &next);
    1.30 +    if(next == aString)
    1.31 +        return NS_ERROR_CANNOT_CONVERT_DATA;
    1.32 +    *retval = value;
    1.33 +    return NS_OK;
    1.34 +}
    1.35 +
    1.36 +static nsresult AString2Double(const nsAString& aString, double* retval)
    1.37 +{
    1.38 +    char* pChars = ToNewCString(aString);
    1.39 +    if(!pChars)
    1.40 +        return NS_ERROR_OUT_OF_MEMORY;
    1.41 +    nsresult rv = String2Double(pChars, retval);
    1.42 +    nsMemory::Free(pChars);
    1.43 +    return rv;
    1.44 +}
    1.45 +
    1.46 +static nsresult AUTF8String2Double(const nsAUTF8String& aString, double* retval)
    1.47 +{
    1.48 +    return String2Double(PromiseFlatUTF8String(aString).get(), retval);
    1.49 +}
    1.50 +
    1.51 +static nsresult ACString2Double(const nsACString& aString, double* retval)
    1.52 +{
    1.53 +    return String2Double(PromiseFlatCString(aString).get(), retval);
    1.54 +}
    1.55 +
    1.56 +// Fills outVariant with double, uint32_t, or int32_t.
    1.57 +// Returns NS_OK, an error code, or a non-NS_OK success code
    1.58 +static nsresult ToManageableNumber(const nsDiscriminatedUnion& inData,
    1.59 +                                   nsDiscriminatedUnion* outData)
    1.60 +{
    1.61 +    nsresult rv;
    1.62 +
    1.63 +    switch(inData.mType)
    1.64 +    {
    1.65 +    // This group results in a int32_t...
    1.66 +
    1.67 +#define CASE__NUMBER_INT32(type_, member_)                                    \
    1.68 +    case nsIDataType :: type_ :                                               \
    1.69 +        outData->u.mInt32Value = inData.u. member_ ;                          \
    1.70 +        outData->mType = nsIDataType::VTYPE_INT32;                            \
    1.71 +        return NS_OK;
    1.72 +
    1.73 +    CASE__NUMBER_INT32(VTYPE_INT8,   mInt8Value)
    1.74 +    CASE__NUMBER_INT32(VTYPE_INT16,  mInt16Value)
    1.75 +    CASE__NUMBER_INT32(VTYPE_INT32,  mInt32Value)
    1.76 +    CASE__NUMBER_INT32(VTYPE_UINT8,  mUint8Value)
    1.77 +    CASE__NUMBER_INT32(VTYPE_UINT16, mUint16Value)
    1.78 +    CASE__NUMBER_INT32(VTYPE_BOOL,   mBoolValue)
    1.79 +    CASE__NUMBER_INT32(VTYPE_CHAR,   mCharValue)
    1.80 +    CASE__NUMBER_INT32(VTYPE_WCHAR,  mWCharValue)
    1.81 +
    1.82 +#undef CASE__NUMBER_INT32
    1.83 +
    1.84 +    // This group results in a uint32_t...
    1.85 +
    1.86 +    case nsIDataType::VTYPE_UINT32:
    1.87 +        outData->u.mInt32Value = inData.u.mUint32Value;
    1.88 +        outData->mType = nsIDataType::VTYPE_INT32;
    1.89 +        return NS_OK;
    1.90 +
    1.91 +    // This group results in a double...
    1.92 +
    1.93 +    case nsIDataType::VTYPE_INT64:
    1.94 +    case nsIDataType::VTYPE_UINT64:
    1.95 +        // XXX Need boundary checking here.
    1.96 +        // We may need to return NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA
    1.97 +        outData->u.mDoubleValue = double(inData.u.mInt64Value);
    1.98 +        outData->mType = nsIDataType::VTYPE_DOUBLE;
    1.99 +        return NS_OK;
   1.100 +    case nsIDataType::VTYPE_FLOAT:
   1.101 +        outData->u.mDoubleValue = inData.u.mFloatValue;
   1.102 +        outData->mType = nsIDataType::VTYPE_DOUBLE;
   1.103 +        return NS_OK;
   1.104 +    case nsIDataType::VTYPE_DOUBLE:
   1.105 +        outData->u.mDoubleValue = inData.u.mDoubleValue;
   1.106 +        outData->mType = nsIDataType::VTYPE_DOUBLE;
   1.107 +        return NS_OK;
   1.108 +    case nsIDataType::VTYPE_CHAR_STR:
   1.109 +    case nsIDataType::VTYPE_STRING_SIZE_IS:
   1.110 +        rv = String2Double(inData.u.str.mStringValue, &outData->u.mDoubleValue);
   1.111 +        if(NS_FAILED(rv))
   1.112 +            return rv;
   1.113 +        outData->mType = nsIDataType::VTYPE_DOUBLE;
   1.114 +        return NS_OK;
   1.115 +    case nsIDataType::VTYPE_DOMSTRING:
   1.116 +    case nsIDataType::VTYPE_ASTRING:
   1.117 +        rv = AString2Double(*inData.u.mAStringValue, &outData->u.mDoubleValue);
   1.118 +        if(NS_FAILED(rv))
   1.119 +            return rv;
   1.120 +        outData->mType = nsIDataType::VTYPE_DOUBLE;
   1.121 +        return NS_OK;
   1.122 +    case nsIDataType::VTYPE_UTF8STRING:
   1.123 +        rv = AUTF8String2Double(*inData.u.mUTF8StringValue,
   1.124 +                                &outData->u.mDoubleValue);
   1.125 +        if(NS_FAILED(rv))
   1.126 +            return rv;
   1.127 +        outData->mType = nsIDataType::VTYPE_DOUBLE;
   1.128 +        return NS_OK;
   1.129 +    case nsIDataType::VTYPE_CSTRING:
   1.130 +        rv = ACString2Double(*inData.u.mCStringValue,
   1.131 +                             &outData->u.mDoubleValue);
   1.132 +        if(NS_FAILED(rv))
   1.133 +            return rv;
   1.134 +        outData->mType = nsIDataType::VTYPE_DOUBLE;
   1.135 +        return NS_OK;
   1.136 +    case nsIDataType::VTYPE_WCHAR_STR:
   1.137 +    case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   1.138 +        rv = AString2Double(nsDependentString(inData.u.wstr.mWStringValue),
   1.139 +                            &outData->u.mDoubleValue);
   1.140 +        if(NS_FAILED(rv))
   1.141 +            return rv;
   1.142 +        outData->mType = nsIDataType::VTYPE_DOUBLE;
   1.143 +        return NS_OK;
   1.144 +
   1.145 +    // This group fails...
   1.146 +
   1.147 +    case nsIDataType::VTYPE_VOID:
   1.148 +    case nsIDataType::VTYPE_ID:
   1.149 +    case nsIDataType::VTYPE_INTERFACE:
   1.150 +    case nsIDataType::VTYPE_INTERFACE_IS:
   1.151 +    case nsIDataType::VTYPE_ARRAY:
   1.152 +    case nsIDataType::VTYPE_EMPTY_ARRAY:
   1.153 +    case nsIDataType::VTYPE_EMPTY:
   1.154 +    default:
   1.155 +        return NS_ERROR_CANNOT_CONVERT_DATA;
   1.156 +    }
   1.157 +}
   1.158 +
   1.159 +/***************************************************************************/
   1.160 +// Array helpers...
   1.161 +
   1.162 +static void FreeArray(nsDiscriminatedUnion* data)
   1.163 +{
   1.164 +    NS_ASSERTION(data->mType == nsIDataType::VTYPE_ARRAY, "bad FreeArray call");
   1.165 +    NS_ASSERTION(data->u.array.mArrayValue, "bad array");
   1.166 +    NS_ASSERTION(data->u.array.mArrayCount, "bad array count");
   1.167 +
   1.168 +#define CASE__FREE_ARRAY_PTR(type_, ctype_)                                   \
   1.169 +        case nsIDataType:: type_ :                                            \
   1.170 +        {                                                                     \
   1.171 +            ctype_ ** p = (ctype_ **) data->u.array.mArrayValue;              \
   1.172 +            for(uint32_t i = data->u.array.mArrayCount; i > 0; p++, i--)      \
   1.173 +                if(*p)                                                        \
   1.174 +                    nsMemory::Free((char*)*p);                                \
   1.175 +            break;                                                            \
   1.176 +        }
   1.177 +
   1.178 +#define CASE__FREE_ARRAY_IFACE(type_, ctype_)                                 \
   1.179 +        case nsIDataType:: type_ :                                            \
   1.180 +        {                                                                     \
   1.181 +            ctype_ ** p = (ctype_ **) data->u.array.mArrayValue;              \
   1.182 +            for(uint32_t i = data->u.array.mArrayCount; i > 0; p++, i--)      \
   1.183 +                if(*p)                                                        \
   1.184 +                    (*p)->Release();                                          \
   1.185 +            break;                                                            \
   1.186 +        }
   1.187 +
   1.188 +    switch(data->u.array.mArrayType)
   1.189 +    {
   1.190 +        case nsIDataType::VTYPE_INT8:
   1.191 +        case nsIDataType::VTYPE_INT16:
   1.192 +        case nsIDataType::VTYPE_INT32:
   1.193 +        case nsIDataType::VTYPE_INT64:
   1.194 +        case nsIDataType::VTYPE_UINT8:
   1.195 +        case nsIDataType::VTYPE_UINT16:
   1.196 +        case nsIDataType::VTYPE_UINT32:
   1.197 +        case nsIDataType::VTYPE_UINT64:
   1.198 +        case nsIDataType::VTYPE_FLOAT:
   1.199 +        case nsIDataType::VTYPE_DOUBLE:
   1.200 +        case nsIDataType::VTYPE_BOOL:
   1.201 +        case nsIDataType::VTYPE_CHAR:
   1.202 +        case nsIDataType::VTYPE_WCHAR:
   1.203 +            break;
   1.204 +
   1.205 +        // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
   1.206 +        CASE__FREE_ARRAY_PTR(VTYPE_ID, nsID)
   1.207 +        CASE__FREE_ARRAY_PTR(VTYPE_CHAR_STR, char)
   1.208 +        CASE__FREE_ARRAY_PTR(VTYPE_WCHAR_STR, char16_t)
   1.209 +        CASE__FREE_ARRAY_IFACE(VTYPE_INTERFACE, nsISupports)
   1.210 +        CASE__FREE_ARRAY_IFACE(VTYPE_INTERFACE_IS, nsISupports)
   1.211 +
   1.212 +        // The rest are illegal.
   1.213 +        case nsIDataType::VTYPE_VOID:
   1.214 +        case nsIDataType::VTYPE_ASTRING:
   1.215 +        case nsIDataType::VTYPE_DOMSTRING:
   1.216 +        case nsIDataType::VTYPE_UTF8STRING:
   1.217 +        case nsIDataType::VTYPE_CSTRING:
   1.218 +        case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   1.219 +        case nsIDataType::VTYPE_STRING_SIZE_IS:
   1.220 +        case nsIDataType::VTYPE_ARRAY:
   1.221 +        case nsIDataType::VTYPE_EMPTY_ARRAY:
   1.222 +        case nsIDataType::VTYPE_EMPTY:
   1.223 +        default:
   1.224 +            NS_ERROR("bad type in array!");
   1.225 +            break;
   1.226 +    }
   1.227 +
   1.228 +    // Free the array memory.
   1.229 +    nsMemory::Free((char*)data->u.array.mArrayValue);
   1.230 +
   1.231 +#undef CASE__FREE_ARRAY_PTR
   1.232 +#undef CASE__FREE_ARRAY_IFACE
   1.233 +}
   1.234 +
   1.235 +static nsresult CloneArray(uint16_t inType, const nsIID* inIID,
   1.236 +                           uint32_t inCount, void* inValue,
   1.237 +                           uint16_t* outType,
   1.238 +                           nsIID* outIID,
   1.239 +                           uint32_t* outCount,
   1.240 +                           void** outValue)
   1.241 +{
   1.242 +    NS_ASSERTION(inCount, "bad param");
   1.243 +    NS_ASSERTION(inValue, "bad param");
   1.244 +    NS_ASSERTION(outType, "bad param");
   1.245 +    NS_ASSERTION(outCount, "bad param");
   1.246 +    NS_ASSERTION(outValue, "bad param");
   1.247 +
   1.248 +    uint32_t allocatedValueCount = 0;
   1.249 +    nsresult rv = NS_OK;
   1.250 +    uint32_t i;
   1.251 +
   1.252 +    // First we figure out the size of the elements for the new u.array.
   1.253 +
   1.254 +    size_t elementSize;
   1.255 +    size_t allocSize;
   1.256 +
   1.257 +    switch(inType)
   1.258 +    {
   1.259 +        case nsIDataType::VTYPE_INT8:
   1.260 +            elementSize = sizeof(int8_t);
   1.261 +            break;
   1.262 +        case nsIDataType::VTYPE_INT16:
   1.263 +            elementSize = sizeof(int16_t);
   1.264 +            break;
   1.265 +        case nsIDataType::VTYPE_INT32:
   1.266 +            elementSize = sizeof(int32_t);
   1.267 +            break;
   1.268 +        case nsIDataType::VTYPE_INT64:
   1.269 +            elementSize = sizeof(int64_t);
   1.270 +            break;
   1.271 +        case nsIDataType::VTYPE_UINT8:
   1.272 +            elementSize = sizeof(uint8_t);
   1.273 +            break;
   1.274 +        case nsIDataType::VTYPE_UINT16:
   1.275 +            elementSize = sizeof(uint16_t);
   1.276 +            break;
   1.277 +        case nsIDataType::VTYPE_UINT32:
   1.278 +            elementSize = sizeof(uint32_t);
   1.279 +            break;
   1.280 +        case nsIDataType::VTYPE_UINT64:
   1.281 +            elementSize = sizeof(uint64_t);
   1.282 +            break;
   1.283 +        case nsIDataType::VTYPE_FLOAT:
   1.284 +            elementSize = sizeof(float);
   1.285 +            break;
   1.286 +        case nsIDataType::VTYPE_DOUBLE:
   1.287 +            elementSize = sizeof(double);
   1.288 +            break;
   1.289 +        case nsIDataType::VTYPE_BOOL:
   1.290 +            elementSize = sizeof(bool);
   1.291 +            break;
   1.292 +        case nsIDataType::VTYPE_CHAR:
   1.293 +            elementSize = sizeof(char);
   1.294 +            break;
   1.295 +        case nsIDataType::VTYPE_WCHAR:
   1.296 +            elementSize = sizeof(char16_t);
   1.297 +            break;
   1.298 +
   1.299 +        // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
   1.300 +        case nsIDataType::VTYPE_ID:
   1.301 +        case nsIDataType::VTYPE_CHAR_STR:
   1.302 +        case nsIDataType::VTYPE_WCHAR_STR:
   1.303 +        case nsIDataType::VTYPE_INTERFACE:
   1.304 +        case nsIDataType::VTYPE_INTERFACE_IS:
   1.305 +            elementSize = sizeof(void*);
   1.306 +            break;
   1.307 +
   1.308 +        // The rest are illegal.
   1.309 +        case nsIDataType::VTYPE_ASTRING:
   1.310 +        case nsIDataType::VTYPE_DOMSTRING:
   1.311 +        case nsIDataType::VTYPE_UTF8STRING:
   1.312 +        case nsIDataType::VTYPE_CSTRING:
   1.313 +        case nsIDataType::VTYPE_STRING_SIZE_IS:
   1.314 +        case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   1.315 +        case nsIDataType::VTYPE_VOID:
   1.316 +        case nsIDataType::VTYPE_ARRAY:
   1.317 +        case nsIDataType::VTYPE_EMPTY_ARRAY:
   1.318 +        case nsIDataType::VTYPE_EMPTY:
   1.319 +        default:
   1.320 +            NS_ERROR("bad type in array!");
   1.321 +            return NS_ERROR_CANNOT_CONVERT_DATA;
   1.322 +    }
   1.323 +
   1.324 +
   1.325 +    // Alloc the u.array.
   1.326 +
   1.327 +    allocSize = inCount * elementSize;
   1.328 +    *outValue = nsMemory::Alloc(allocSize);
   1.329 +    if(!*outValue)
   1.330 +        return NS_ERROR_OUT_OF_MEMORY;
   1.331 +
   1.332 +    // Clone the elements.
   1.333 +
   1.334 +    switch(inType)
   1.335 +    {
   1.336 +        case nsIDataType::VTYPE_INT8:
   1.337 +        case nsIDataType::VTYPE_INT16:
   1.338 +        case nsIDataType::VTYPE_INT32:
   1.339 +        case nsIDataType::VTYPE_INT64:
   1.340 +        case nsIDataType::VTYPE_UINT8:
   1.341 +        case nsIDataType::VTYPE_UINT16:
   1.342 +        case nsIDataType::VTYPE_UINT32:
   1.343 +        case nsIDataType::VTYPE_UINT64:
   1.344 +        case nsIDataType::VTYPE_FLOAT:
   1.345 +        case nsIDataType::VTYPE_DOUBLE:
   1.346 +        case nsIDataType::VTYPE_BOOL:
   1.347 +        case nsIDataType::VTYPE_CHAR:
   1.348 +        case nsIDataType::VTYPE_WCHAR:
   1.349 +            memcpy(*outValue, inValue, allocSize);
   1.350 +            break;
   1.351 +
   1.352 +        case nsIDataType::VTYPE_INTERFACE_IS:
   1.353 +            if(outIID)
   1.354 +                *outIID = *inIID;
   1.355 +            // fall through...
   1.356 +        case nsIDataType::VTYPE_INTERFACE:
   1.357 +        {
   1.358 +            memcpy(*outValue, inValue, allocSize);
   1.359 +
   1.360 +            nsISupports** p = (nsISupports**) *outValue;
   1.361 +            for(i = inCount; i > 0; p++, i--)
   1.362 +                if(*p)
   1.363 +                    (*p)->AddRef();
   1.364 +            break;
   1.365 +        }
   1.366 +
   1.367 +        // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
   1.368 +        case nsIDataType::VTYPE_ID:
   1.369 +        {
   1.370 +            nsID** inp  = (nsID**) inValue;
   1.371 +            nsID** outp = (nsID**) *outValue;
   1.372 +            for(i = inCount; i > 0; i--)
   1.373 +            {
   1.374 +                nsID* idp = *(inp++);
   1.375 +                if(idp)
   1.376 +                {
   1.377 +                    if(nullptr == (*(outp++) = (nsID*)
   1.378 +                       nsMemory::Clone((char*)idp, sizeof(nsID))))
   1.379 +                        goto bad;
   1.380 +                }
   1.381 +                else
   1.382 +                    *(outp++) = nullptr;
   1.383 +                allocatedValueCount++;
   1.384 +            }
   1.385 +            break;
   1.386 +        }
   1.387 +
   1.388 +        case nsIDataType::VTYPE_CHAR_STR:
   1.389 +        {
   1.390 +            char** inp  = (char**) inValue;
   1.391 +            char** outp = (char**) *outValue;
   1.392 +            for(i = inCount; i > 0; i--)
   1.393 +            {
   1.394 +                char* str = *(inp++);
   1.395 +                if(str)
   1.396 +                {
   1.397 +                    if(nullptr == (*(outp++) = (char*)
   1.398 +                       nsMemory::Clone(str, (strlen(str)+1)*sizeof(char))))
   1.399 +                        goto bad;
   1.400 +                }
   1.401 +                else
   1.402 +                    *(outp++) = nullptr;
   1.403 +                allocatedValueCount++;
   1.404 +            }
   1.405 +            break;
   1.406 +        }
   1.407 +
   1.408 +        case nsIDataType::VTYPE_WCHAR_STR:
   1.409 +        {
   1.410 +            char16_t** inp  = (char16_t**) inValue;
   1.411 +            char16_t** outp = (char16_t**) *outValue;
   1.412 +            for(i = inCount; i > 0; i--)
   1.413 +            {
   1.414 +                char16_t* str = *(inp++);
   1.415 +                if(str)
   1.416 +                {
   1.417 +                    if(nullptr == (*(outp++) = (char16_t*)
   1.418 +                       nsMemory::Clone(str,
   1.419 +                        (NS_strlen(str) + 1) * sizeof(char16_t))))
   1.420 +                        goto bad;
   1.421 +                }
   1.422 +                else
   1.423 +                    *(outp++) = nullptr;
   1.424 +                allocatedValueCount++;
   1.425 +            }
   1.426 +            break;
   1.427 +        }
   1.428 +
   1.429 +        // The rest are illegal.
   1.430 +        case nsIDataType::VTYPE_VOID:
   1.431 +        case nsIDataType::VTYPE_ARRAY:
   1.432 +        case nsIDataType::VTYPE_EMPTY_ARRAY:
   1.433 +        case nsIDataType::VTYPE_EMPTY:
   1.434 +        case nsIDataType::VTYPE_ASTRING:
   1.435 +        case nsIDataType::VTYPE_DOMSTRING:
   1.436 +        case nsIDataType::VTYPE_UTF8STRING:
   1.437 +        case nsIDataType::VTYPE_CSTRING:
   1.438 +        case nsIDataType::VTYPE_STRING_SIZE_IS:
   1.439 +        case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   1.440 +        default:
   1.441 +            NS_ERROR("bad type in array!");
   1.442 +            return NS_ERROR_CANNOT_CONVERT_DATA;
   1.443 +    }
   1.444 +
   1.445 +    *outType = inType;
   1.446 +    *outCount = inCount;
   1.447 +    return NS_OK;
   1.448 +
   1.449 +bad:
   1.450 +    if(*outValue)
   1.451 +    {
   1.452 +        char** p = (char**) *outValue;
   1.453 +        for(i = allocatedValueCount; i > 0; p++, i--)
   1.454 +            if(*p)
   1.455 +                nsMemory::Free(*p);
   1.456 +        nsMemory::Free((char*)*outValue);
   1.457 +        *outValue = nullptr;
   1.458 +    }
   1.459 +    return rv;
   1.460 +}
   1.461 +
   1.462 +/***************************************************************************/
   1.463 +
   1.464 +#define TRIVIAL_DATA_CONVERTER(type_, data_, member_, retval_)                \
   1.465 +    if(data_.mType == nsIDataType :: type_) {                                 \
   1.466 +        *retval_ = data_.u.member_;                                           \
   1.467 +        return NS_OK;                                                         \
   1.468 +    }
   1.469 +
   1.470 +#define NUMERIC_CONVERSION_METHOD_BEGIN(type_, Ctype_, name_)                 \
   1.471 +/* static */ nsresult                                                         \
   1.472 +nsVariant::ConvertTo##name_ (const nsDiscriminatedUnion& data,                \
   1.473 +                             Ctype_ *_retval)                                 \
   1.474 +{                                                                             \
   1.475 +    TRIVIAL_DATA_CONVERTER(type_, data, m##name_##Value, _retval)             \
   1.476 +    nsDiscriminatedUnion tempData;                                            \
   1.477 +    nsVariant::Initialize(&tempData);                                         \
   1.478 +    nsresult rv = ToManageableNumber(data, &tempData);                        \
   1.479 +    /*                                                                     */ \
   1.480 +    /* NOTE: rv may indicate a success code that we want to preserve       */ \
   1.481 +    /* For the final return. So all the return cases below should return   */ \
   1.482 +    /* this rv when indicating success.                                    */ \
   1.483 +    /*                                                                     */ \
   1.484 +    if(NS_FAILED(rv))                                                         \
   1.485 +        return rv;                                                            \
   1.486 +    switch(tempData.mType)                                                    \
   1.487 +    {
   1.488 +
   1.489 +#define CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(Ctype_)                      \
   1.490 +    case nsIDataType::VTYPE_INT32:                                            \
   1.491 +        *_retval = ( Ctype_ ) tempData.u.mInt32Value;                         \
   1.492 +        return rv;
   1.493 +
   1.494 +#define CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(Ctype_, min_, max_)            \
   1.495 +    case nsIDataType::VTYPE_INT32:                                            \
   1.496 +    {                                                                         \
   1.497 +        int32_t value = tempData.u.mInt32Value;                               \
   1.498 +        if(value < min_ || value > max_)                                      \
   1.499 +            return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;                         \
   1.500 +        *_retval = ( Ctype_ ) value;                                          \
   1.501 +        return rv;                                                            \
   1.502 +    }
   1.503 +
   1.504 +#define CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(Ctype_)                     \
   1.505 +    case nsIDataType::VTYPE_UINT32:                                           \
   1.506 +        *_retval = ( Ctype_ ) tempData.u.mUint32Value;                        \
   1.507 +        return rv;
   1.508 +
   1.509 +#define CASE__NUMERIC_CONVERSION_UINT32_MAX(Ctype_, max_)                     \
   1.510 +    case nsIDataType::VTYPE_UINT32:                                           \
   1.511 +    {                                                                         \
   1.512 +        uint32_t value = tempData.u.mUint32Value;                             \
   1.513 +        if(value > max_)                                                      \
   1.514 +            return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;                         \
   1.515 +        *_retval = ( Ctype_ ) value;                                          \
   1.516 +        return rv;                                                            \
   1.517 +    }
   1.518 +
   1.519 +#define CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(Ctype_)                     \
   1.520 +    case nsIDataType::VTYPE_DOUBLE:                                           \
   1.521 +        *_retval = ( Ctype_ ) tempData.u.mDoubleValue;                        \
   1.522 +        return rv;
   1.523 +
   1.524 +#define CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX(Ctype_, min_, max_)           \
   1.525 +    case nsIDataType::VTYPE_DOUBLE:                                           \
   1.526 +    {                                                                         \
   1.527 +        double value = tempData.u.mDoubleValue;                               \
   1.528 +        if(value < min_ || value > max_)                                      \
   1.529 +            return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;                         \
   1.530 +        *_retval = ( Ctype_ ) value;                                          \
   1.531 +        return rv;                                                            \
   1.532 +    }
   1.533 +
   1.534 +#define CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(Ctype_, min_, max_)       \
   1.535 +    case nsIDataType::VTYPE_DOUBLE:                                           \
   1.536 +    {                                                                         \
   1.537 +        double value = tempData.u.mDoubleValue;                               \
   1.538 +        if(value < min_ || value > max_)                                      \
   1.539 +            return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;                         \
   1.540 +        *_retval = ( Ctype_ ) value;                                          \
   1.541 +        return (0.0 == fmod(value,1.0)) ?                                     \
   1.542 +            rv : NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA;                       \
   1.543 +    }
   1.544 +
   1.545 +#define CASES__NUMERIC_CONVERSION_NORMAL(Ctype_, min_, max_)                  \
   1.546 +    CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(Ctype_, min_, max_)                \
   1.547 +    CASE__NUMERIC_CONVERSION_UINT32_MAX(Ctype_, max_)                         \
   1.548 +    CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(Ctype_, min_, max_)
   1.549 +
   1.550 +#define NUMERIC_CONVERSION_METHOD_END                                         \
   1.551 +    default:                                                                  \
   1.552 +        NS_ERROR("bad type returned from ToManageableNumber");                \
   1.553 +        return NS_ERROR_CANNOT_CONVERT_DATA;                                  \
   1.554 +    }                                                                         \
   1.555 +}
   1.556 +
   1.557 +#define NUMERIC_CONVERSION_METHOD_NORMAL(type_, Ctype_, name_, min_, max_)    \
   1.558 +    NUMERIC_CONVERSION_METHOD_BEGIN(type_, Ctype_, name_)                     \
   1.559 +        CASES__NUMERIC_CONVERSION_NORMAL(Ctype_, min_, max_)                  \
   1.560 +    NUMERIC_CONVERSION_METHOD_END
   1.561 +
   1.562 +/***************************************************************************/
   1.563 +// These expand into full public methods...
   1.564 +
   1.565 +NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_INT8, uint8_t, Int8, (-127-1), 127)
   1.566 +NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_INT16, int16_t, Int16, (-32767-1), 32767)
   1.567 +
   1.568 +NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_INT32, int32_t, Int32)
   1.569 +    CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(int32_t)
   1.570 +    CASE__NUMERIC_CONVERSION_UINT32_MAX(int32_t, 2147483647)
   1.571 +    CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(int32_t, (-2147483647-1), 2147483647)
   1.572 +NUMERIC_CONVERSION_METHOD_END
   1.573 +
   1.574 +NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_UINT8, uint8_t, Uint8, 0, 255)
   1.575 +NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_UINT16, uint16_t, Uint16, 0, 65535)
   1.576 +
   1.577 +NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_UINT32, uint32_t, Uint32)
   1.578 +    CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(uint32_t, 0, 2147483647)
   1.579 +    CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(uint32_t)
   1.580 +    CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(uint32_t, 0, 4294967295U)
   1.581 +NUMERIC_CONVERSION_METHOD_END
   1.582 +
   1.583 +// XXX toFloat convertions need to be fixed!
   1.584 +NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_FLOAT, float, Float)
   1.585 +    CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(float)
   1.586 +    CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(float)
   1.587 +    CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(float)
   1.588 +NUMERIC_CONVERSION_METHOD_END
   1.589 +
   1.590 +NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_DOUBLE, double, Double)
   1.591 +    CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(double)
   1.592 +    CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(double)
   1.593 +    CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(double)
   1.594 +NUMERIC_CONVERSION_METHOD_END
   1.595 +
   1.596 +// XXX toChar convertions need to be fixed!
   1.597 +NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_CHAR, char, Char)
   1.598 +    CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(char)
   1.599 +    CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(char)
   1.600 +    CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(char)
   1.601 +NUMERIC_CONVERSION_METHOD_END
   1.602 +
   1.603 +// XXX toWChar convertions need to be fixed!
   1.604 +NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_WCHAR, char16_t, WChar)
   1.605 +    CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(char16_t)
   1.606 +    CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(char16_t)
   1.607 +    CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(char16_t)
   1.608 +NUMERIC_CONVERSION_METHOD_END
   1.609 +
   1.610 +#undef NUMERIC_CONVERSION_METHOD_BEGIN
   1.611 +#undef CASE__NUMERIC_CONVERSION_INT32_JUST_CAST
   1.612 +#undef CASE__NUMERIC_CONVERSION_INT32_MIN_MAX
   1.613 +#undef CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST
   1.614 +#undef CASE__NUMERIC_CONVERSION_UINT32_MIN_MAX
   1.615 +#undef CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST
   1.616 +#undef CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX
   1.617 +#undef CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT
   1.618 +#undef CASES__NUMERIC_CONVERSION_NORMAL
   1.619 +#undef NUMERIC_CONVERSION_METHOD_END
   1.620 +#undef NUMERIC_CONVERSION_METHOD_NORMAL
   1.621 +
   1.622 +/***************************************************************************/
   1.623 +
   1.624 +// Just leverage a numeric converter for bool (but restrict the values).
   1.625 +// XXX Is this really what we want to do?
   1.626 +
   1.627 +/* static */ nsresult
   1.628 +nsVariant::ConvertToBool(const nsDiscriminatedUnion& data, bool *_retval)
   1.629 +{
   1.630 +    TRIVIAL_DATA_CONVERTER(VTYPE_BOOL, data, mBoolValue, _retval)
   1.631 +
   1.632 +    double val;
   1.633 +    nsresult rv = nsVariant::ConvertToDouble(data, &val);
   1.634 +    if(NS_FAILED(rv))
   1.635 +        return rv;
   1.636 +    *_retval = 0.0 != val;
   1.637 +    return rv;
   1.638 +}
   1.639 +
   1.640 +/***************************************************************************/
   1.641 +
   1.642 +/* static */ nsresult
   1.643 +nsVariant::ConvertToInt64(const nsDiscriminatedUnion& data, int64_t *_retval)
   1.644 +{
   1.645 +    TRIVIAL_DATA_CONVERTER(VTYPE_INT64, data, mInt64Value, _retval)
   1.646 +    TRIVIAL_DATA_CONVERTER(VTYPE_UINT64, data, mUint64Value, _retval)
   1.647 +
   1.648 +    nsDiscriminatedUnion tempData;
   1.649 +    nsVariant::Initialize(&tempData);
   1.650 +    nsresult rv = ToManageableNumber(data, &tempData);
   1.651 +    if(NS_FAILED(rv))
   1.652 +        return rv;
   1.653 +    switch(tempData.mType)
   1.654 +    {
   1.655 +    case nsIDataType::VTYPE_INT32:
   1.656 +        *_retval = tempData.u.mInt32Value;
   1.657 +        return rv;
   1.658 +    case nsIDataType::VTYPE_UINT32:
   1.659 +        *_retval = tempData.u.mUint32Value;
   1.660 +        return rv;
   1.661 +    case nsIDataType::VTYPE_DOUBLE:
   1.662 +        // XXX should check for data loss here!
   1.663 +        *_retval = tempData.u.mDoubleValue;
   1.664 +        return rv;
   1.665 +    default:
   1.666 +        NS_ERROR("bad type returned from ToManageableNumber");
   1.667 +        return NS_ERROR_CANNOT_CONVERT_DATA;
   1.668 +    }
   1.669 +}
   1.670 +
   1.671 +/* static */ nsresult
   1.672 +nsVariant::ConvertToUint64(const nsDiscriminatedUnion& data, uint64_t *_retval)
   1.673 +{
   1.674 +    return nsVariant::ConvertToInt64(data, (int64_t *)_retval);
   1.675 +}
   1.676 +
   1.677 +/***************************************************************************/
   1.678 +
   1.679 +static bool String2ID(const nsDiscriminatedUnion& data, nsID* pid)
   1.680 +{
   1.681 +    nsAutoString tempString;
   1.682 +    nsAString* pString;
   1.683 +
   1.684 +    switch(data.mType)
   1.685 +    {
   1.686 +        case nsIDataType::VTYPE_CHAR_STR:
   1.687 +        case nsIDataType::VTYPE_STRING_SIZE_IS:
   1.688 +            return pid->Parse(data.u.str.mStringValue);
   1.689 +        case nsIDataType::VTYPE_CSTRING:
   1.690 +            return pid->Parse(PromiseFlatCString(*data.u.mCStringValue).get());
   1.691 +        case nsIDataType::VTYPE_UTF8STRING:
   1.692 +            return pid->Parse(PromiseFlatUTF8String(*data.u.mUTF8StringValue).get());
   1.693 +        case nsIDataType::VTYPE_ASTRING:
   1.694 +        case nsIDataType::VTYPE_DOMSTRING:
   1.695 +            pString = data.u.mAStringValue;
   1.696 +            break;
   1.697 +        case nsIDataType::VTYPE_WCHAR_STR:
   1.698 +        case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   1.699 +            tempString.Assign(data.u.wstr.mWStringValue);
   1.700 +            pString = &tempString;
   1.701 +            break;
   1.702 +        default:
   1.703 +            NS_ERROR("bad type in call to String2ID");
   1.704 +            return false;
   1.705 +    }
   1.706 +
   1.707 +    char* pChars = ToNewCString(*pString);
   1.708 +    if(!pChars)
   1.709 +        return false;
   1.710 +    bool result = pid->Parse(pChars);
   1.711 +    nsMemory::Free(pChars);
   1.712 +    return result;
   1.713 +}
   1.714 +
   1.715 +/* static */ nsresult
   1.716 +nsVariant::ConvertToID(const nsDiscriminatedUnion& data, nsID * _retval)
   1.717 +{
   1.718 +    nsID id;
   1.719 +
   1.720 +    switch(data.mType)
   1.721 +    {
   1.722 +    case nsIDataType::VTYPE_ID:
   1.723 +        *_retval = data.u.mIDValue;
   1.724 +        return NS_OK;
   1.725 +    case nsIDataType::VTYPE_INTERFACE:
   1.726 +        *_retval = NS_GET_IID(nsISupports);
   1.727 +        return NS_OK;
   1.728 +    case nsIDataType::VTYPE_INTERFACE_IS:
   1.729 +        *_retval = data.u.iface.mInterfaceID;
   1.730 +        return NS_OK;
   1.731 +    case nsIDataType::VTYPE_ASTRING:
   1.732 +    case nsIDataType::VTYPE_DOMSTRING:
   1.733 +    case nsIDataType::VTYPE_UTF8STRING:
   1.734 +    case nsIDataType::VTYPE_CSTRING:
   1.735 +    case nsIDataType::VTYPE_CHAR_STR:
   1.736 +    case nsIDataType::VTYPE_WCHAR_STR:
   1.737 +    case nsIDataType::VTYPE_STRING_SIZE_IS:
   1.738 +    case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   1.739 +        if(!String2ID(data, &id))
   1.740 +            return NS_ERROR_CANNOT_CONVERT_DATA;
   1.741 +        *_retval = id;
   1.742 +        return NS_OK;
   1.743 +    default:
   1.744 +        return NS_ERROR_CANNOT_CONVERT_DATA;
   1.745 +    }
   1.746 +}
   1.747 +
   1.748 +/***************************************************************************/
   1.749 +
   1.750 +static nsresult ToString(const nsDiscriminatedUnion& data,
   1.751 +                         nsACString & outString)
   1.752 +{
   1.753 +    char* ptr;
   1.754 +
   1.755 +    switch(data.mType)
   1.756 +    {
   1.757 +    // all the stuff we don't handle...
   1.758 +    case nsIDataType::VTYPE_ASTRING:
   1.759 +    case nsIDataType::VTYPE_DOMSTRING:
   1.760 +    case nsIDataType::VTYPE_UTF8STRING:
   1.761 +    case nsIDataType::VTYPE_CSTRING:
   1.762 +    case nsIDataType::VTYPE_CHAR_STR:
   1.763 +    case nsIDataType::VTYPE_WCHAR_STR:
   1.764 +    case nsIDataType::VTYPE_STRING_SIZE_IS:
   1.765 +    case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   1.766 +    case nsIDataType::VTYPE_WCHAR:
   1.767 +        NS_ERROR("ToString being called for a string type - screwy logic!");
   1.768 +        // fall through...
   1.769 +
   1.770 +    // XXX We might want stringified versions of these... ???
   1.771 +
   1.772 +    case nsIDataType::VTYPE_VOID:
   1.773 +    case nsIDataType::VTYPE_EMPTY:
   1.774 +        outString.Truncate();
   1.775 +        outString.SetIsVoid(true);
   1.776 +        return NS_OK;
   1.777 +
   1.778 +    case nsIDataType::VTYPE_EMPTY_ARRAY:
   1.779 +    case nsIDataType::VTYPE_ARRAY:
   1.780 +    case nsIDataType::VTYPE_INTERFACE:
   1.781 +    case nsIDataType::VTYPE_INTERFACE_IS:
   1.782 +    default:
   1.783 +        return NS_ERROR_CANNOT_CONVERT_DATA;
   1.784 +
   1.785 +    // nsID has its own text formatter.
   1.786 +
   1.787 +    case nsIDataType::VTYPE_ID:
   1.788 +        ptr = data.u.mIDValue.ToString();
   1.789 +        if(!ptr)
   1.790 +            return NS_ERROR_OUT_OF_MEMORY;
   1.791 +        outString.Assign(ptr);
   1.792 +        nsMemory::Free(ptr);
   1.793 +        return NS_OK;
   1.794 +
   1.795 +    // Can't use PR_smprintf for floats, since it's locale-dependent
   1.796 +#define CASE__APPENDFLOAT_NUMBER(type_, member_)                        \
   1.797 +    case nsIDataType :: type_ :                                         \
   1.798 +    {                                                                   \
   1.799 +        nsAutoCString str;                                              \
   1.800 +        str.AppendFloat(data.u. member_);                               \
   1.801 +        outString.Assign(str);                                          \
   1.802 +        return NS_OK;                                                   \
   1.803 +    }
   1.804 +
   1.805 +    CASE__APPENDFLOAT_NUMBER(VTYPE_FLOAT,  mFloatValue)
   1.806 +    CASE__APPENDFLOAT_NUMBER(VTYPE_DOUBLE, mDoubleValue)
   1.807 +
   1.808 +#undef CASE__APPENDFLOAT_NUMBER
   1.809 +
   1.810 +    // the rest can be PR_smprintf'd and use common code.
   1.811 +
   1.812 +#define CASE__SMPRINTF_NUMBER(type_, format_, cast_, member_)                 \
   1.813 +    case nsIDataType :: type_ :                                               \
   1.814 +        ptr = PR_smprintf( format_ , (cast_) data.u. member_ );               \
   1.815 +        break;
   1.816 +
   1.817 +    CASE__SMPRINTF_NUMBER(VTYPE_INT8,   "%d",   int,      mInt8Value)
   1.818 +    CASE__SMPRINTF_NUMBER(VTYPE_INT16,  "%d",   int,      mInt16Value)
   1.819 +    CASE__SMPRINTF_NUMBER(VTYPE_INT32,  "%d",   int,      mInt32Value)
   1.820 +    CASE__SMPRINTF_NUMBER(VTYPE_INT64,  "%lld", int64_t,  mInt64Value)
   1.821 +
   1.822 +    CASE__SMPRINTF_NUMBER(VTYPE_UINT8,  "%u",   unsigned, mUint8Value)
   1.823 +    CASE__SMPRINTF_NUMBER(VTYPE_UINT16, "%u",   unsigned, mUint16Value)
   1.824 +    CASE__SMPRINTF_NUMBER(VTYPE_UINT32, "%u",   unsigned, mUint32Value)
   1.825 +    CASE__SMPRINTF_NUMBER(VTYPE_UINT64, "%llu", int64_t,  mUint64Value)
   1.826 +
   1.827 +    // XXX Would we rather print "true" / "false" ?
   1.828 +    CASE__SMPRINTF_NUMBER(VTYPE_BOOL,   "%d",   int,      mBoolValue)
   1.829 +
   1.830 +    CASE__SMPRINTF_NUMBER(VTYPE_CHAR,   "%c",   char,     mCharValue)
   1.831 +
   1.832 +#undef CASE__SMPRINTF_NUMBER
   1.833 +    }
   1.834 +
   1.835 +    if(!ptr)
   1.836 +        return NS_ERROR_OUT_OF_MEMORY;
   1.837 +    outString.Assign(ptr);
   1.838 +    PR_smprintf_free(ptr);
   1.839 +    return NS_OK;
   1.840 +}
   1.841 +
   1.842 +/* static */ nsresult
   1.843 +nsVariant::ConvertToAString(const nsDiscriminatedUnion& data,
   1.844 +                            nsAString & _retval)
   1.845 +{
   1.846 +    switch(data.mType)
   1.847 +    {
   1.848 +    case nsIDataType::VTYPE_ASTRING:
   1.849 +    case nsIDataType::VTYPE_DOMSTRING:
   1.850 +        _retval.Assign(*data.u.mAStringValue);
   1.851 +        return NS_OK;
   1.852 +    case nsIDataType::VTYPE_CSTRING:
   1.853 +        CopyASCIItoUTF16(*data.u.mCStringValue, _retval);
   1.854 +        return NS_OK;
   1.855 +    case nsIDataType::VTYPE_UTF8STRING:
   1.856 +        CopyUTF8toUTF16(*data.u.mUTF8StringValue, _retval);
   1.857 +        return NS_OK;
   1.858 +    case nsIDataType::VTYPE_CHAR_STR:
   1.859 +        CopyASCIItoUTF16(data.u.str.mStringValue, _retval);
   1.860 +        return NS_OK;
   1.861 +    case nsIDataType::VTYPE_WCHAR_STR:
   1.862 +        _retval.Assign(data.u.wstr.mWStringValue);
   1.863 +        return NS_OK;
   1.864 +    case nsIDataType::VTYPE_STRING_SIZE_IS:
   1.865 +        CopyASCIItoUTF16(nsDependentCString(data.u.str.mStringValue,
   1.866 +                                           data.u.str.mStringLength),
   1.867 +                        _retval);
   1.868 +        return NS_OK;
   1.869 +    case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   1.870 +        _retval.Assign(data.u.wstr.mWStringValue, data.u.wstr.mWStringLength);
   1.871 +        return NS_OK;
   1.872 +    case nsIDataType::VTYPE_WCHAR:
   1.873 +        _retval.Assign(data.u.mWCharValue);
   1.874 +        return NS_OK;
   1.875 +    default:
   1.876 +    {
   1.877 +        nsAutoCString tempCString;
   1.878 +        nsresult rv = ToString(data, tempCString);
   1.879 +        if(NS_FAILED(rv))
   1.880 +            return rv;
   1.881 +        CopyASCIItoUTF16(tempCString, _retval);
   1.882 +        return NS_OK;
   1.883 +    }
   1.884 +    }
   1.885 +}
   1.886 +
   1.887 +/* static */ nsresult
   1.888 +nsVariant::ConvertToACString(const nsDiscriminatedUnion& data,
   1.889 +                             nsACString & _retval)
   1.890 +{
   1.891 +    switch(data.mType)
   1.892 +    {
   1.893 +    case nsIDataType::VTYPE_ASTRING:
   1.894 +    case nsIDataType::VTYPE_DOMSTRING:
   1.895 +        LossyCopyUTF16toASCII(*data.u.mAStringValue, _retval);
   1.896 +        return NS_OK;
   1.897 +    case nsIDataType::VTYPE_CSTRING:
   1.898 +        _retval.Assign(*data.u.mCStringValue);
   1.899 +        return NS_OK;
   1.900 +    case nsIDataType::VTYPE_UTF8STRING:
   1.901 +        // XXX This is an extra copy that should be avoided
   1.902 +        // once Jag lands support for UTF8String and associated
   1.903 +        // conversion methods.
   1.904 +        LossyCopyUTF16toASCII(NS_ConvertUTF8toUTF16(*data.u.mUTF8StringValue),
   1.905 +                        _retval);
   1.906 +        return NS_OK;
   1.907 +    case nsIDataType::VTYPE_CHAR_STR:
   1.908 +        _retval.Assign(*data.u.str.mStringValue);
   1.909 +        return NS_OK;
   1.910 +    case nsIDataType::VTYPE_WCHAR_STR:
   1.911 +        LossyCopyUTF16toASCII(nsDependentString(data.u.wstr.mWStringValue),
   1.912 +                        _retval);
   1.913 +        return NS_OK;
   1.914 +    case nsIDataType::VTYPE_STRING_SIZE_IS:
   1.915 +        _retval.Assign(data.u.str.mStringValue, data.u.str.mStringLength);
   1.916 +        return NS_OK;
   1.917 +    case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   1.918 +        LossyCopyUTF16toASCII(nsDependentString(data.u.wstr.mWStringValue,
   1.919 +                        data.u.wstr.mWStringLength), _retval);
   1.920 +        return NS_OK;
   1.921 +    case nsIDataType::VTYPE_WCHAR:
   1.922 +    {
   1.923 +        const char16_t* str = &data.u.mWCharValue;
   1.924 +        LossyCopyUTF16toASCII(Substring(str, 1), _retval);
   1.925 +        return NS_OK;
   1.926 +    }
   1.927 +    default:
   1.928 +        return ToString(data, _retval);
   1.929 +    }
   1.930 +}
   1.931 +
   1.932 +/* static */ nsresult
   1.933 +nsVariant::ConvertToAUTF8String(const nsDiscriminatedUnion& data,
   1.934 +                                nsAUTF8String & _retval)
   1.935 +{
   1.936 +    switch(data.mType)
   1.937 +    {
   1.938 +    case nsIDataType::VTYPE_ASTRING:
   1.939 +    case nsIDataType::VTYPE_DOMSTRING:
   1.940 +        CopyUTF16toUTF8(*data.u.mAStringValue, _retval);
   1.941 +        return NS_OK;
   1.942 +    case nsIDataType::VTYPE_CSTRING:
   1.943 +        // XXX Extra copy, can be removed if we're sure CSTRING can
   1.944 +        //     only contain ASCII.
   1.945 +        CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(*data.u.mCStringValue),
   1.946 +                        _retval);
   1.947 +        return NS_OK;
   1.948 +    case nsIDataType::VTYPE_UTF8STRING:
   1.949 +        _retval.Assign(*data.u.mUTF8StringValue);
   1.950 +        return NS_OK;
   1.951 +    case nsIDataType::VTYPE_CHAR_STR:
   1.952 +        // XXX Extra copy, can be removed if we're sure CHAR_STR can
   1.953 +        //     only contain ASCII.
   1.954 +        CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(data.u.str.mStringValue),
   1.955 +                        _retval);
   1.956 +        return NS_OK;
   1.957 +    case nsIDataType::VTYPE_WCHAR_STR:
   1.958 +        CopyUTF16toUTF8(data.u.wstr.mWStringValue, _retval);
   1.959 +        return NS_OK;
   1.960 +    case nsIDataType::VTYPE_STRING_SIZE_IS:
   1.961 +        // XXX Extra copy, can be removed if we're sure CHAR_STR can
   1.962 +        //     only contain ASCII.
   1.963 +        CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(
   1.964 +            nsDependentCString(data.u.str.mStringValue,
   1.965 +                               data.u.str.mStringLength)), _retval);
   1.966 +        return NS_OK;
   1.967 +    case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   1.968 +        CopyUTF16toUTF8(nsDependentString(data.u.wstr.mWStringValue,
   1.969 +                                          data.u.wstr.mWStringLength),
   1.970 +                        _retval);
   1.971 +        return NS_OK;
   1.972 +    case nsIDataType::VTYPE_WCHAR:
   1.973 +    {
   1.974 +        const char16_t* str = &data.u.mWCharValue;
   1.975 +        CopyUTF16toUTF8(Substring(str, 1), _retval);
   1.976 +        return NS_OK;
   1.977 +    }
   1.978 +    default:
   1.979 +    {
   1.980 +        nsAutoCString tempCString;
   1.981 +        nsresult rv = ToString(data, tempCString);
   1.982 +        if(NS_FAILED(rv))
   1.983 +            return rv;
   1.984 +        // XXX Extra copy, can be removed if we're sure tempCString can
   1.985 +        //     only contain ASCII.
   1.986 +        CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(tempCString), _retval);
   1.987 +        return NS_OK;
   1.988 +    }
   1.989 +    }
   1.990 +}
   1.991 +
   1.992 +/* static */ nsresult
   1.993 +nsVariant::ConvertToString(const nsDiscriminatedUnion& data, char **_retval)
   1.994 +{
   1.995 +    uint32_t ignored;
   1.996 +    return nsVariant::ConvertToStringWithSize(data, &ignored, _retval);
   1.997 +}
   1.998 +
   1.999 +/* static */ nsresult
  1.1000 +nsVariant::ConvertToWString(const nsDiscriminatedUnion& data, char16_t **_retval)
  1.1001 +{
  1.1002 +    uint32_t ignored;
  1.1003 +    return nsVariant::ConvertToWStringWithSize(data, &ignored, _retval);
  1.1004 +}
  1.1005 +
  1.1006 +/* static */ nsresult
  1.1007 +nsVariant::ConvertToStringWithSize(const nsDiscriminatedUnion& data,
  1.1008 +                                   uint32_t *size, char **str)
  1.1009 +{
  1.1010 +    nsAutoString  tempString;
  1.1011 +    nsAutoCString tempCString;
  1.1012 +    nsresult rv;
  1.1013 +
  1.1014 +    switch(data.mType)
  1.1015 +    {
  1.1016 +    case nsIDataType::VTYPE_ASTRING:
  1.1017 +    case nsIDataType::VTYPE_DOMSTRING:
  1.1018 +        *size = data.u.mAStringValue->Length();
  1.1019 +        *str = ToNewCString(*data.u.mAStringValue);
  1.1020 +        break;
  1.1021 +    case nsIDataType::VTYPE_CSTRING:
  1.1022 +        *size = data.u.mCStringValue->Length();
  1.1023 +        *str = ToNewCString(*data.u.mCStringValue);
  1.1024 +        break;
  1.1025 +    case nsIDataType::VTYPE_UTF8STRING:
  1.1026 +    {
  1.1027 +        // XXX This is doing 1 extra copy.  Need to fix this
  1.1028 +        // when Jag lands UTF8String
  1.1029 +        // we want:
  1.1030 +        // *size = *data.mUTF8StringValue->Length();
  1.1031 +        // *str = ToNewCString(*data.mUTF8StringValue);
  1.1032 +        // But this will have to do for now.
  1.1033 +        NS_ConvertUTF8toUTF16 tempString(*data.u.mUTF8StringValue);
  1.1034 +        *size = tempString.Length();
  1.1035 +        *str = ToNewCString(tempString);
  1.1036 +        break;
  1.1037 +    }
  1.1038 +    case nsIDataType::VTYPE_CHAR_STR:
  1.1039 +    {
  1.1040 +        nsDependentCString cString(data.u.str.mStringValue);
  1.1041 +        *size = cString.Length();
  1.1042 +        *str = ToNewCString(cString);
  1.1043 +        break;
  1.1044 +    }
  1.1045 +    case nsIDataType::VTYPE_WCHAR_STR:
  1.1046 +    {
  1.1047 +        nsDependentString string(data.u.wstr.mWStringValue);
  1.1048 +        *size = string.Length();
  1.1049 +        *str = ToNewCString(string);
  1.1050 +        break;
  1.1051 +    }
  1.1052 +    case nsIDataType::VTYPE_STRING_SIZE_IS:
  1.1053 +    {
  1.1054 +        nsDependentCString cString(data.u.str.mStringValue,
  1.1055 +                                   data.u.str.mStringLength);
  1.1056 +        *size = cString.Length();
  1.1057 +        *str = ToNewCString(cString);
  1.1058 +        break;
  1.1059 +    }
  1.1060 +    case nsIDataType::VTYPE_WSTRING_SIZE_IS:
  1.1061 +    {
  1.1062 +        nsDependentString string(data.u.wstr.mWStringValue,
  1.1063 +                                 data.u.wstr.mWStringLength);
  1.1064 +        *size = string.Length();
  1.1065 +        *str = ToNewCString(string);
  1.1066 +        break;
  1.1067 +    }
  1.1068 +    case nsIDataType::VTYPE_WCHAR:
  1.1069 +        tempString.Assign(data.u.mWCharValue);
  1.1070 +        *size = tempString.Length();
  1.1071 +        *str = ToNewCString(tempString);
  1.1072 +        break;
  1.1073 +    default:
  1.1074 +        rv = ToString(data, tempCString);
  1.1075 +        if(NS_FAILED(rv))
  1.1076 +            return rv;
  1.1077 +        *size = tempCString.Length();
  1.1078 +        *str = ToNewCString(tempCString);
  1.1079 +        break;
  1.1080 +    }
  1.1081 +
  1.1082 +    return *str ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
  1.1083 +}
  1.1084 +/* static */ nsresult
  1.1085 +nsVariant::ConvertToWStringWithSize(const nsDiscriminatedUnion& data,
  1.1086 +                                    uint32_t *size, char16_t **str)
  1.1087 +{
  1.1088 +    nsAutoString  tempString;
  1.1089 +    nsAutoCString tempCString;
  1.1090 +    nsresult rv;
  1.1091 +
  1.1092 +    switch(data.mType)
  1.1093 +    {
  1.1094 +    case nsIDataType::VTYPE_ASTRING:
  1.1095 +    case nsIDataType::VTYPE_DOMSTRING:
  1.1096 +        *size = data.u.mAStringValue->Length();
  1.1097 +        *str = ToNewUnicode(*data.u.mAStringValue);
  1.1098 +        break;
  1.1099 +    case nsIDataType::VTYPE_CSTRING:
  1.1100 +        *size = data.u.mCStringValue->Length();
  1.1101 +        *str = ToNewUnicode(*data.u.mCStringValue);
  1.1102 +        break;
  1.1103 +    case nsIDataType::VTYPE_UTF8STRING:
  1.1104 +    {
  1.1105 +        *str = UTF8ToNewUnicode(*data.u.mUTF8StringValue, size);
  1.1106 +        break;
  1.1107 +    }
  1.1108 +    case nsIDataType::VTYPE_CHAR_STR:
  1.1109 +    {
  1.1110 +        nsDependentCString cString(data.u.str.mStringValue);
  1.1111 +        *size = cString.Length();
  1.1112 +        *str = ToNewUnicode(cString);
  1.1113 +        break;
  1.1114 +    }
  1.1115 +    case nsIDataType::VTYPE_WCHAR_STR:
  1.1116 +    {
  1.1117 +        nsDependentString string(data.u.wstr.mWStringValue);
  1.1118 +        *size = string.Length();
  1.1119 +        *str = ToNewUnicode(string);
  1.1120 +        break;
  1.1121 +    }
  1.1122 +    case nsIDataType::VTYPE_STRING_SIZE_IS:
  1.1123 +    {
  1.1124 +        nsDependentCString cString(data.u.str.mStringValue,
  1.1125 +                                   data.u.str.mStringLength);
  1.1126 +        *size = cString.Length();
  1.1127 +        *str = ToNewUnicode(cString);
  1.1128 +        break;
  1.1129 +    }
  1.1130 +    case nsIDataType::VTYPE_WSTRING_SIZE_IS:
  1.1131 +    {
  1.1132 +        nsDependentString string(data.u.wstr.mWStringValue,
  1.1133 +                                 data.u.wstr.mWStringLength);
  1.1134 +        *size = string.Length();
  1.1135 +        *str = ToNewUnicode(string);
  1.1136 +        break;
  1.1137 +    }
  1.1138 +    case nsIDataType::VTYPE_WCHAR:
  1.1139 +        tempString.Assign(data.u.mWCharValue);
  1.1140 +        *size = tempString.Length();
  1.1141 +        *str = ToNewUnicode(tempString);
  1.1142 +        break;
  1.1143 +    default:
  1.1144 +        rv = ToString(data, tempCString);
  1.1145 +        if(NS_FAILED(rv))
  1.1146 +            return rv;
  1.1147 +        *size = tempCString.Length();
  1.1148 +        *str = ToNewUnicode(tempCString);
  1.1149 +        break;
  1.1150 +    }
  1.1151 +
  1.1152 +    return *str ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
  1.1153 +}
  1.1154 +
  1.1155 +/* static */ nsresult
  1.1156 +nsVariant::ConvertToISupports(const nsDiscriminatedUnion& data,
  1.1157 +                              nsISupports **_retval)
  1.1158 +{
  1.1159 +    switch(data.mType)
  1.1160 +    {
  1.1161 +    case nsIDataType::VTYPE_INTERFACE:
  1.1162 +    case nsIDataType::VTYPE_INTERFACE_IS:
  1.1163 +        if (data.u.iface.mInterfaceValue) {
  1.1164 +            return data.u.iface.mInterfaceValue->
  1.1165 +                QueryInterface(NS_GET_IID(nsISupports), (void**)_retval);
  1.1166 +        } else {
  1.1167 +            *_retval = nullptr;
  1.1168 +            return NS_OK;
  1.1169 +        }
  1.1170 +    default:
  1.1171 +        return NS_ERROR_CANNOT_CONVERT_DATA;
  1.1172 +    }
  1.1173 +}
  1.1174 +
  1.1175 +/* static */ nsresult
  1.1176 +nsVariant::ConvertToInterface(const nsDiscriminatedUnion& data, nsIID * *iid,
  1.1177 +                              void * *iface)
  1.1178 +{
  1.1179 +    const nsIID* piid;
  1.1180 +
  1.1181 +    switch(data.mType)
  1.1182 +    {
  1.1183 +    case nsIDataType::VTYPE_INTERFACE:
  1.1184 +        piid = &NS_GET_IID(nsISupports);
  1.1185 +        break;
  1.1186 +    case nsIDataType::VTYPE_INTERFACE_IS:
  1.1187 +        piid = &data.u.iface.mInterfaceID;
  1.1188 +        break;
  1.1189 +    default:
  1.1190 +        return NS_ERROR_CANNOT_CONVERT_DATA;
  1.1191 +    }
  1.1192 +
  1.1193 +    *iid = (nsIID*) nsMemory::Clone(piid, sizeof(nsIID));
  1.1194 +    if(!*iid)
  1.1195 +        return NS_ERROR_OUT_OF_MEMORY;
  1.1196 +
  1.1197 +    if (data.u.iface.mInterfaceValue) {
  1.1198 +        return data.u.iface.mInterfaceValue->QueryInterface(*piid, iface);
  1.1199 +    }
  1.1200 +
  1.1201 +    *iface = nullptr;
  1.1202 +    return NS_OK;
  1.1203 +}
  1.1204 +
  1.1205 +/* static */ nsresult
  1.1206 +nsVariant::ConvertToArray(const nsDiscriminatedUnion& data, uint16_t *type,
  1.1207 +                          nsIID* iid, uint32_t *count, void * *ptr)
  1.1208 +{
  1.1209 +    // XXX perhaps we'd like to add support for converting each of the various
  1.1210 +    // types into an array containing one element of that type. We can leverage
  1.1211 +    // CloneArray to do this if we want to support this.
  1.1212 +
  1.1213 +    if(data.mType == nsIDataType::VTYPE_ARRAY)
  1.1214 +        return CloneArray(data.u.array.mArrayType, &data.u.array.mArrayInterfaceID,
  1.1215 +                          data.u.array.mArrayCount, data.u.array.mArrayValue,
  1.1216 +                          type, iid, count, ptr);
  1.1217 +    return NS_ERROR_CANNOT_CONVERT_DATA;
  1.1218 +}
  1.1219 +
  1.1220 +/***************************************************************************/
  1.1221 +// static setter functions...
  1.1222 +
  1.1223 +#define DATA_SETTER_PROLOGUE(data_)                                           \
  1.1224 +    nsVariant::Cleanup(data_);
  1.1225 +
  1.1226 +#define DATA_SETTER_EPILOGUE(data_, type_)                                    \
  1.1227 +    data_->mType = nsIDataType :: type_;                                      \
  1.1228 +    return NS_OK;
  1.1229 +
  1.1230 +#define DATA_SETTER(data_, type_, member_, value_)                            \
  1.1231 +    DATA_SETTER_PROLOGUE(data_)                                               \
  1.1232 +    data_->u.member_ = value_;                                                \
  1.1233 +    DATA_SETTER_EPILOGUE(data_, type_)
  1.1234 +
  1.1235 +#define DATA_SETTER_WITH_CAST(data_, type_, member_, cast_, value_)           \
  1.1236 +    DATA_SETTER_PROLOGUE(data_)                                               \
  1.1237 +    data_->u.member_ = cast_ value_;                                          \
  1.1238 +    DATA_SETTER_EPILOGUE(data_, type_)
  1.1239 +
  1.1240 +
  1.1241 +/********************************************/
  1.1242 +
  1.1243 +#define CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_)                          \
  1.1244 +    {                                                                         \
  1.1245 +
  1.1246 +#define CASE__SET_FROM_VARIANT_VTYPE__GETTER(member_, name_)                  \
  1.1247 +        rv = aValue->GetAs##name_ (&(data->u. member_ ));
  1.1248 +
  1.1249 +#define CASE__SET_FROM_VARIANT_VTYPE__GETTER_CAST(cast_, member_, name_)      \
  1.1250 +        rv = aValue->GetAs##name_ ( cast_ &(data->u. member_ ));
  1.1251 +
  1.1252 +#define CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)                          \
  1.1253 +        if(NS_SUCCEEDED(rv))                                                  \
  1.1254 +        {                                                                     \
  1.1255 +            data->mType  = nsIDataType :: type_ ;                             \
  1.1256 +        }                                                                     \
  1.1257 +        break;                                                                \
  1.1258 +    }
  1.1259 +
  1.1260 +#define CASE__SET_FROM_VARIANT_TYPE(type_, member_, name_)                    \
  1.1261 +    case nsIDataType :: type_ :                                               \
  1.1262 +        CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_)                          \
  1.1263 +        CASE__SET_FROM_VARIANT_VTYPE__GETTER(member_, name_)                  \
  1.1264 +        CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)
  1.1265 +
  1.1266 +#define CASE__SET_FROM_VARIANT_VTYPE_CAST(type_, cast_, member_, name_)       \
  1.1267 +    case nsIDataType :: type_ :                                               \
  1.1268 +        CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_)                          \
  1.1269 +        CASE__SET_FROM_VARIANT_VTYPE__GETTER_CAST(cast_, member_, name_)      \
  1.1270 +        CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)
  1.1271 +
  1.1272 +
  1.1273 +/* static */ nsresult
  1.1274 +nsVariant::SetFromVariant(nsDiscriminatedUnion* data, nsIVariant* aValue)
  1.1275 +{
  1.1276 +    uint16_t type;
  1.1277 +    nsresult rv;
  1.1278 +
  1.1279 +    nsVariant::Cleanup(data);
  1.1280 +
  1.1281 +    rv = aValue->GetDataType(&type);
  1.1282 +    if(NS_FAILED(rv))
  1.1283 +        return rv;
  1.1284 +
  1.1285 +    switch(type)
  1.1286 +    {
  1.1287 +        CASE__SET_FROM_VARIANT_VTYPE_CAST(VTYPE_INT8, (uint8_t*), mInt8Value,
  1.1288 +                                          Int8)
  1.1289 +        CASE__SET_FROM_VARIANT_TYPE(VTYPE_INT16,  mInt16Value,  Int16)
  1.1290 +        CASE__SET_FROM_VARIANT_TYPE(VTYPE_INT32,  mInt32Value,  Int32)
  1.1291 +        CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT8,  mUint8Value,  Uint8)
  1.1292 +        CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT16, mUint16Value, Uint16)
  1.1293 +        CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT32, mUint32Value, Uint32)
  1.1294 +        CASE__SET_FROM_VARIANT_TYPE(VTYPE_FLOAT,  mFloatValue,  Float)
  1.1295 +        CASE__SET_FROM_VARIANT_TYPE(VTYPE_DOUBLE, mDoubleValue, Double)
  1.1296 +        CASE__SET_FROM_VARIANT_TYPE(VTYPE_BOOL ,  mBoolValue,   Bool)
  1.1297 +        CASE__SET_FROM_VARIANT_TYPE(VTYPE_CHAR,   mCharValue,   Char)
  1.1298 +        CASE__SET_FROM_VARIANT_TYPE(VTYPE_WCHAR,  mWCharValue,  WChar)
  1.1299 +        CASE__SET_FROM_VARIANT_TYPE(VTYPE_ID,     mIDValue,     ID)
  1.1300 +
  1.1301 +        case nsIDataType::VTYPE_ASTRING:
  1.1302 +        case nsIDataType::VTYPE_DOMSTRING:
  1.1303 +        case nsIDataType::VTYPE_WCHAR_STR:
  1.1304 +        case nsIDataType::VTYPE_WSTRING_SIZE_IS:
  1.1305 +            CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_ASTRING);
  1.1306 +            data->u.mAStringValue = new nsString();
  1.1307 +            if(!data->u.mAStringValue)
  1.1308 +                return NS_ERROR_OUT_OF_MEMORY;
  1.1309 +            rv = aValue->GetAsAString(*data->u.mAStringValue);
  1.1310 +            if(NS_FAILED(rv))
  1.1311 +                delete data->u.mAStringValue;
  1.1312 +            CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_ASTRING)
  1.1313 +
  1.1314 +        case nsIDataType::VTYPE_CSTRING:
  1.1315 +            CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_CSTRING);
  1.1316 +            data->u.mCStringValue = new nsCString();
  1.1317 +            if(!data->u.mCStringValue)
  1.1318 +                return NS_ERROR_OUT_OF_MEMORY;
  1.1319 +            rv = aValue->GetAsACString(*data->u.mCStringValue);
  1.1320 +            if(NS_FAILED(rv))
  1.1321 +                delete data->u.mCStringValue;
  1.1322 +            CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_CSTRING)
  1.1323 +
  1.1324 +        case nsIDataType::VTYPE_UTF8STRING:
  1.1325 +            CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_UTF8STRING);
  1.1326 +            data->u.mUTF8StringValue = new nsUTF8String();
  1.1327 +            if(!data->u.mUTF8StringValue)
  1.1328 +                return NS_ERROR_OUT_OF_MEMORY;
  1.1329 +            rv = aValue->GetAsAUTF8String(*data->u.mUTF8StringValue);
  1.1330 +            if(NS_FAILED(rv))
  1.1331 +                delete data->u.mUTF8StringValue;
  1.1332 +            CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_UTF8STRING)
  1.1333 +
  1.1334 +        case nsIDataType::VTYPE_CHAR_STR:
  1.1335 +        case nsIDataType::VTYPE_STRING_SIZE_IS:
  1.1336 +            CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_STRING_SIZE_IS);
  1.1337 +            rv = aValue->GetAsStringWithSize(&data->u.str.mStringLength,
  1.1338 +                                             &data->u.str.mStringValue);
  1.1339 +            CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_STRING_SIZE_IS)
  1.1340 +
  1.1341 +        case nsIDataType::VTYPE_INTERFACE:
  1.1342 +        case nsIDataType::VTYPE_INTERFACE_IS:
  1.1343 +            CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_INTERFACE_IS);
  1.1344 +            // XXX This iid handling is ugly!
  1.1345 +            nsIID* iid;
  1.1346 +            rv = aValue->GetAsInterface(&iid, (void**)&data->u.iface.mInterfaceValue);
  1.1347 +            if(NS_SUCCEEDED(rv))
  1.1348 +            {
  1.1349 +                data->u.iface.mInterfaceID = *iid;
  1.1350 +                nsMemory::Free((char*)iid);
  1.1351 +            }
  1.1352 +            CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_INTERFACE_IS)
  1.1353 +
  1.1354 +        case nsIDataType::VTYPE_ARRAY:
  1.1355 +            CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_ARRAY);
  1.1356 +            rv = aValue->GetAsArray(&data->u.array.mArrayType,
  1.1357 +                                    &data->u.array.mArrayInterfaceID,
  1.1358 +                                    &data->u.array.mArrayCount,
  1.1359 +                                    &data->u.array.mArrayValue);
  1.1360 +            CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_ARRAY)
  1.1361 +
  1.1362 +        case nsIDataType::VTYPE_VOID:
  1.1363 +            rv = nsVariant::SetToVoid(data);
  1.1364 +            break;
  1.1365 +        case nsIDataType::VTYPE_EMPTY_ARRAY:
  1.1366 +            rv = nsVariant::SetToEmptyArray(data);
  1.1367 +            break;
  1.1368 +        case nsIDataType::VTYPE_EMPTY:
  1.1369 +            rv = nsVariant::SetToEmpty(data);
  1.1370 +            break;
  1.1371 +        default:
  1.1372 +            NS_ERROR("bad type in variant!");
  1.1373 +            rv = NS_ERROR_FAILURE;
  1.1374 +            break;
  1.1375 +    }
  1.1376 +    return rv;
  1.1377 +}
  1.1378 +
  1.1379 +/* static */ nsresult
  1.1380 +nsVariant::SetFromInt8(nsDiscriminatedUnion* data, uint8_t aValue)
  1.1381 +{
  1.1382 +    DATA_SETTER_WITH_CAST(data, VTYPE_INT8, mInt8Value, (uint8_t), aValue)
  1.1383 +}
  1.1384 +/* static */ nsresult
  1.1385 +nsVariant::SetFromInt16(nsDiscriminatedUnion* data, int16_t aValue)
  1.1386 +{
  1.1387 +    DATA_SETTER(data, VTYPE_INT16, mInt16Value, aValue)
  1.1388 +}
  1.1389 +/* static */ nsresult
  1.1390 +nsVariant::SetFromInt32(nsDiscriminatedUnion* data, int32_t aValue)
  1.1391 +{
  1.1392 +    DATA_SETTER(data, VTYPE_INT32, mInt32Value, aValue)
  1.1393 +}
  1.1394 +/* static */ nsresult
  1.1395 +nsVariant::SetFromInt64(nsDiscriminatedUnion* data, int64_t aValue)
  1.1396 +{
  1.1397 +    DATA_SETTER(data, VTYPE_INT64, mInt64Value, aValue)
  1.1398 +}
  1.1399 +/* static */ nsresult
  1.1400 +nsVariant::SetFromUint8(nsDiscriminatedUnion* data, uint8_t aValue)
  1.1401 +{
  1.1402 +    DATA_SETTER(data, VTYPE_UINT8, mUint8Value, aValue)
  1.1403 +}
  1.1404 +/* static */ nsresult
  1.1405 +nsVariant::SetFromUint16(nsDiscriminatedUnion* data, uint16_t aValue)
  1.1406 +{
  1.1407 +    DATA_SETTER(data, VTYPE_UINT16, mUint16Value, aValue)
  1.1408 +}
  1.1409 +/* static */ nsresult
  1.1410 +nsVariant::SetFromUint32(nsDiscriminatedUnion* data, uint32_t aValue)
  1.1411 +{
  1.1412 +    DATA_SETTER(data, VTYPE_UINT32, mUint32Value, aValue)
  1.1413 +}
  1.1414 +/* static */ nsresult
  1.1415 +nsVariant::SetFromUint64(nsDiscriminatedUnion* data, uint64_t aValue)
  1.1416 +{
  1.1417 +    DATA_SETTER(data, VTYPE_UINT64, mUint64Value, aValue)
  1.1418 +}
  1.1419 +/* static */ nsresult
  1.1420 +nsVariant::SetFromFloat(nsDiscriminatedUnion* data, float aValue)
  1.1421 +{
  1.1422 +    DATA_SETTER(data, VTYPE_FLOAT, mFloatValue, aValue)
  1.1423 +}
  1.1424 +/* static */ nsresult
  1.1425 +nsVariant::SetFromDouble(nsDiscriminatedUnion* data, double aValue)
  1.1426 +{
  1.1427 +    DATA_SETTER(data, VTYPE_DOUBLE, mDoubleValue, aValue)
  1.1428 +}
  1.1429 +/* static */ nsresult
  1.1430 +nsVariant::SetFromBool(nsDiscriminatedUnion* data, bool aValue)
  1.1431 +{
  1.1432 +    DATA_SETTER(data, VTYPE_BOOL, mBoolValue, aValue)
  1.1433 +}
  1.1434 +/* static */ nsresult
  1.1435 +nsVariant::SetFromChar(nsDiscriminatedUnion* data, char aValue)
  1.1436 +{
  1.1437 +    DATA_SETTER(data, VTYPE_CHAR, mCharValue, aValue)
  1.1438 +}
  1.1439 +/* static */ nsresult
  1.1440 +nsVariant::SetFromWChar(nsDiscriminatedUnion* data, char16_t aValue)
  1.1441 +{
  1.1442 +    DATA_SETTER(data, VTYPE_WCHAR, mWCharValue, aValue)
  1.1443 +}
  1.1444 +/* static */ nsresult
  1.1445 +nsVariant::SetFromID(nsDiscriminatedUnion* data, const nsID & aValue)
  1.1446 +{
  1.1447 +    DATA_SETTER(data, VTYPE_ID, mIDValue, aValue)
  1.1448 +}
  1.1449 +/* static */ nsresult
  1.1450 +nsVariant::SetFromAString(nsDiscriminatedUnion* data, const nsAString & aValue)
  1.1451 +{
  1.1452 +    DATA_SETTER_PROLOGUE(data);
  1.1453 +    if(!(data->u.mAStringValue = new nsString(aValue)))
  1.1454 +        return NS_ERROR_OUT_OF_MEMORY;
  1.1455 +    DATA_SETTER_EPILOGUE(data, VTYPE_ASTRING);
  1.1456 +}
  1.1457 +
  1.1458 +/* static */ nsresult
  1.1459 +nsVariant::SetFromACString(nsDiscriminatedUnion* data,
  1.1460 +                           const nsACString & aValue)
  1.1461 +{
  1.1462 +    DATA_SETTER_PROLOGUE(data);
  1.1463 +    if(!(data->u.mCStringValue = new nsCString(aValue)))
  1.1464 +        return NS_ERROR_OUT_OF_MEMORY;
  1.1465 +    DATA_SETTER_EPILOGUE(data, VTYPE_CSTRING);
  1.1466 +}
  1.1467 +
  1.1468 +/* static */ nsresult
  1.1469 +nsVariant::SetFromAUTF8String(nsDiscriminatedUnion* data,
  1.1470 +                              const nsAUTF8String & aValue)
  1.1471 +{
  1.1472 +    DATA_SETTER_PROLOGUE(data);
  1.1473 +    if(!(data->u.mUTF8StringValue = new nsUTF8String(aValue)))
  1.1474 +        return NS_ERROR_OUT_OF_MEMORY;
  1.1475 +    DATA_SETTER_EPILOGUE(data, VTYPE_UTF8STRING);
  1.1476 +}
  1.1477 +
  1.1478 +/* static */ nsresult
  1.1479 +nsVariant::SetFromString(nsDiscriminatedUnion* data, const char *aValue)
  1.1480 +{
  1.1481 +    DATA_SETTER_PROLOGUE(data);
  1.1482 +    if(!aValue)
  1.1483 +        return NS_ERROR_NULL_POINTER;
  1.1484 +    return SetFromStringWithSize(data, strlen(aValue), aValue);
  1.1485 +}
  1.1486 +/* static */ nsresult
  1.1487 +nsVariant::SetFromWString(nsDiscriminatedUnion* data, const char16_t *aValue)
  1.1488 +{
  1.1489 +    DATA_SETTER_PROLOGUE(data);
  1.1490 +    if(!aValue)
  1.1491 +        return NS_ERROR_NULL_POINTER;
  1.1492 +    return SetFromWStringWithSize(data, NS_strlen(aValue), aValue);
  1.1493 +}
  1.1494 +/* static */ nsresult
  1.1495 +nsVariant::SetFromISupports(nsDiscriminatedUnion* data, nsISupports *aValue)
  1.1496 +{
  1.1497 +    return SetFromInterface(data, NS_GET_IID(nsISupports), aValue);
  1.1498 +}
  1.1499 +/* static */ nsresult
  1.1500 +nsVariant::SetFromInterface(nsDiscriminatedUnion* data, const nsIID& iid,
  1.1501 +                            nsISupports *aValue)
  1.1502 +{
  1.1503 +    DATA_SETTER_PROLOGUE(data);
  1.1504 +    NS_IF_ADDREF(aValue);
  1.1505 +    data->u.iface.mInterfaceValue = aValue;
  1.1506 +    data->u.iface.mInterfaceID = iid;
  1.1507 +    DATA_SETTER_EPILOGUE(data, VTYPE_INTERFACE_IS);
  1.1508 +}
  1.1509 +/* static */ nsresult
  1.1510 +nsVariant::SetFromArray(nsDiscriminatedUnion* data, uint16_t type,
  1.1511 +                        const nsIID* iid, uint32_t count, void * aValue)
  1.1512 +{
  1.1513 +    DATA_SETTER_PROLOGUE(data);
  1.1514 +    if(!aValue || !count)
  1.1515 +        return NS_ERROR_NULL_POINTER;
  1.1516 +
  1.1517 +    nsresult rv = CloneArray(type, iid, count, aValue,
  1.1518 +                             &data->u.array.mArrayType,
  1.1519 +                             &data->u.array.mArrayInterfaceID,
  1.1520 +                             &data->u.array.mArrayCount,
  1.1521 +                             &data->u.array.mArrayValue);
  1.1522 +    if(NS_FAILED(rv))
  1.1523 +        return rv;
  1.1524 +    DATA_SETTER_EPILOGUE(data, VTYPE_ARRAY);
  1.1525 +}
  1.1526 +/* static */ nsresult
  1.1527 +nsVariant::SetFromStringWithSize(nsDiscriminatedUnion* data, uint32_t size, const char *aValue)
  1.1528 +{
  1.1529 +    DATA_SETTER_PROLOGUE(data);
  1.1530 +    if(!aValue)
  1.1531 +        return NS_ERROR_NULL_POINTER;
  1.1532 +    if(!(data->u.str.mStringValue =
  1.1533 +         (char*) nsMemory::Clone(aValue, (size+1)*sizeof(char))))
  1.1534 +        return NS_ERROR_OUT_OF_MEMORY;
  1.1535 +    data->u.str.mStringLength = size;
  1.1536 +    DATA_SETTER_EPILOGUE(data, VTYPE_STRING_SIZE_IS);
  1.1537 +}
  1.1538 +/* static */ nsresult
  1.1539 +nsVariant::SetFromWStringWithSize(nsDiscriminatedUnion* data, uint32_t size, const char16_t *aValue)
  1.1540 +{
  1.1541 +    DATA_SETTER_PROLOGUE(data);
  1.1542 +    if(!aValue)
  1.1543 +        return NS_ERROR_NULL_POINTER;
  1.1544 +    if(!(data->u.wstr.mWStringValue =
  1.1545 +         (char16_t*) nsMemory::Clone(aValue, (size+1)*sizeof(char16_t))))
  1.1546 +        return NS_ERROR_OUT_OF_MEMORY;
  1.1547 +    data->u.wstr.mWStringLength = size;
  1.1548 +    DATA_SETTER_EPILOGUE(data, VTYPE_WSTRING_SIZE_IS);
  1.1549 +}
  1.1550 +/* static */ nsresult
  1.1551 +nsVariant::SetToVoid(nsDiscriminatedUnion* data)
  1.1552 +{
  1.1553 +    DATA_SETTER_PROLOGUE(data);
  1.1554 +    DATA_SETTER_EPILOGUE(data, VTYPE_VOID);
  1.1555 +}
  1.1556 +/* static */ nsresult
  1.1557 +nsVariant::SetToEmpty(nsDiscriminatedUnion* data)
  1.1558 +{
  1.1559 +    DATA_SETTER_PROLOGUE(data);
  1.1560 +    DATA_SETTER_EPILOGUE(data, VTYPE_EMPTY);
  1.1561 +}
  1.1562 +/* static */ nsresult
  1.1563 +nsVariant::SetToEmptyArray(nsDiscriminatedUnion* data)
  1.1564 +{
  1.1565 +    DATA_SETTER_PROLOGUE(data);
  1.1566 +    DATA_SETTER_EPILOGUE(data, VTYPE_EMPTY_ARRAY);
  1.1567 +}
  1.1568 +
  1.1569 +/***************************************************************************/
  1.1570 +
  1.1571 +/* static */ nsresult
  1.1572 +nsVariant::Initialize(nsDiscriminatedUnion* data)
  1.1573 +{
  1.1574 +    data->mType = nsIDataType::VTYPE_EMPTY;
  1.1575 +    return NS_OK;
  1.1576 +}
  1.1577 +
  1.1578 +/* static */ nsresult
  1.1579 +nsVariant::Cleanup(nsDiscriminatedUnion* data)
  1.1580 +{
  1.1581 +    switch(data->mType)
  1.1582 +    {
  1.1583 +        case nsIDataType::VTYPE_INT8:
  1.1584 +        case nsIDataType::VTYPE_INT16:
  1.1585 +        case nsIDataType::VTYPE_INT32:
  1.1586 +        case nsIDataType::VTYPE_INT64:
  1.1587 +        case nsIDataType::VTYPE_UINT8:
  1.1588 +        case nsIDataType::VTYPE_UINT16:
  1.1589 +        case nsIDataType::VTYPE_UINT32:
  1.1590 +        case nsIDataType::VTYPE_UINT64:
  1.1591 +        case nsIDataType::VTYPE_FLOAT:
  1.1592 +        case nsIDataType::VTYPE_DOUBLE:
  1.1593 +        case nsIDataType::VTYPE_BOOL:
  1.1594 +        case nsIDataType::VTYPE_CHAR:
  1.1595 +        case nsIDataType::VTYPE_WCHAR:
  1.1596 +        case nsIDataType::VTYPE_VOID:
  1.1597 +        case nsIDataType::VTYPE_ID:
  1.1598 +            break;
  1.1599 +        case nsIDataType::VTYPE_ASTRING:
  1.1600 +        case nsIDataType::VTYPE_DOMSTRING:
  1.1601 +            delete data->u.mAStringValue;
  1.1602 +            break;
  1.1603 +        case nsIDataType::VTYPE_CSTRING:
  1.1604 +            delete data->u.mCStringValue;
  1.1605 +            break;
  1.1606 +        case nsIDataType::VTYPE_UTF8STRING:
  1.1607 +            delete data->u.mUTF8StringValue;
  1.1608 +            break;
  1.1609 +        case nsIDataType::VTYPE_CHAR_STR:
  1.1610 +        case nsIDataType::VTYPE_STRING_SIZE_IS:
  1.1611 +            nsMemory::Free((char*)data->u.str.mStringValue);
  1.1612 +            break;
  1.1613 +        case nsIDataType::VTYPE_WCHAR_STR:
  1.1614 +        case nsIDataType::VTYPE_WSTRING_SIZE_IS:
  1.1615 +            nsMemory::Free((char*)data->u.wstr.mWStringValue);
  1.1616 +            break;
  1.1617 +        case nsIDataType::VTYPE_INTERFACE:
  1.1618 +        case nsIDataType::VTYPE_INTERFACE_IS:
  1.1619 +            NS_IF_RELEASE(data->u.iface.mInterfaceValue);
  1.1620 +            break;
  1.1621 +        case nsIDataType::VTYPE_ARRAY:
  1.1622 +            FreeArray(data);
  1.1623 +            break;
  1.1624 +        case nsIDataType::VTYPE_EMPTY_ARRAY:
  1.1625 +        case nsIDataType::VTYPE_EMPTY:
  1.1626 +            break;
  1.1627 +        default:
  1.1628 +            NS_ERROR("bad type in variant!");
  1.1629 +            break;
  1.1630 +    }
  1.1631 +
  1.1632 +    data->mType = nsIDataType::VTYPE_EMPTY;
  1.1633 +    return NS_OK;
  1.1634 +}
  1.1635 +
  1.1636 +/* static */ void
  1.1637 +nsVariant::Traverse(const nsDiscriminatedUnion& data,
  1.1638 +                    nsCycleCollectionTraversalCallback &cb)
  1.1639 +{
  1.1640 +    switch(data.mType)
  1.1641 +    {
  1.1642 +        case nsIDataType::VTYPE_INTERFACE:
  1.1643 +        case nsIDataType::VTYPE_INTERFACE_IS:
  1.1644 +            NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mData");
  1.1645 +            cb.NoteXPCOMChild(data.u.iface.mInterfaceValue);
  1.1646 +            break;
  1.1647 +        case nsIDataType::VTYPE_ARRAY:
  1.1648 +            switch(data.u.array.mArrayType) {
  1.1649 +                case nsIDataType::VTYPE_INTERFACE:
  1.1650 +                case nsIDataType::VTYPE_INTERFACE_IS:
  1.1651 +                {
  1.1652 +                    nsISupports** p = (nsISupports**) data.u.array.mArrayValue;
  1.1653 +                    for(uint32_t i = data.u.array.mArrayCount; i > 0; p++, i--) {
  1.1654 +                        NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mData[i]");
  1.1655 +                        cb.NoteXPCOMChild(*p);
  1.1656 +                    }
  1.1657 +                }
  1.1658 +                default:
  1.1659 +                    break;
  1.1660 +            }
  1.1661 +        default:
  1.1662 +            break;
  1.1663 +    }
  1.1664 +}
  1.1665 +
  1.1666 +/***************************************************************************/
  1.1667 +/***************************************************************************/
  1.1668 +// members...
  1.1669 +
  1.1670 +NS_IMPL_ISUPPORTS(nsVariant, nsIVariant, nsIWritableVariant)
  1.1671 +
  1.1672 +nsVariant::nsVariant()
  1.1673 +    : mWritable(true)
  1.1674 +{
  1.1675 +    nsVariant::Initialize(&mData);
  1.1676 +
  1.1677 +#ifdef DEBUG
  1.1678 +    {
  1.1679 +        // Assert that the nsIDataType consts match the values #defined in
  1.1680 +        // xpt_struct.h. Bad things happen somewhere if they don't.
  1.1681 +        struct THE_TYPES {uint16_t a; uint16_t b;};
  1.1682 +        static const THE_TYPES array[] = {
  1.1683 +            {nsIDataType::VTYPE_INT8              , TD_INT8             },
  1.1684 +            {nsIDataType::VTYPE_INT16             , TD_INT16            },
  1.1685 +            {nsIDataType::VTYPE_INT32             , TD_INT32            },
  1.1686 +            {nsIDataType::VTYPE_INT64             , TD_INT64            },
  1.1687 +            {nsIDataType::VTYPE_UINT8             , TD_UINT8            },
  1.1688 +            {nsIDataType::VTYPE_UINT16            , TD_UINT16           },
  1.1689 +            {nsIDataType::VTYPE_UINT32            , TD_UINT32           },
  1.1690 +            {nsIDataType::VTYPE_UINT64            , TD_UINT64           },
  1.1691 +            {nsIDataType::VTYPE_FLOAT             , TD_FLOAT            },
  1.1692 +            {nsIDataType::VTYPE_DOUBLE            , TD_DOUBLE           },
  1.1693 +            {nsIDataType::VTYPE_BOOL              , TD_BOOL             },
  1.1694 +            {nsIDataType::VTYPE_CHAR              , TD_CHAR             },
  1.1695 +            {nsIDataType::VTYPE_WCHAR             , TD_WCHAR            },
  1.1696 +            {nsIDataType::VTYPE_VOID              , TD_VOID             },
  1.1697 +            {nsIDataType::VTYPE_ID                , TD_PNSIID           },
  1.1698 +            {nsIDataType::VTYPE_DOMSTRING         , TD_DOMSTRING        },
  1.1699 +            {nsIDataType::VTYPE_CHAR_STR          , TD_PSTRING          },
  1.1700 +            {nsIDataType::VTYPE_WCHAR_STR         , TD_PWSTRING         },
  1.1701 +            {nsIDataType::VTYPE_INTERFACE         , TD_INTERFACE_TYPE   },
  1.1702 +            {nsIDataType::VTYPE_INTERFACE_IS      , TD_INTERFACE_IS_TYPE},
  1.1703 +            {nsIDataType::VTYPE_ARRAY             , TD_ARRAY            },
  1.1704 +            {nsIDataType::VTYPE_STRING_SIZE_IS    , TD_PSTRING_SIZE_IS  },
  1.1705 +            {nsIDataType::VTYPE_WSTRING_SIZE_IS   , TD_PWSTRING_SIZE_IS },
  1.1706 +            {nsIDataType::VTYPE_UTF8STRING        , TD_UTF8STRING       },
  1.1707 +            {nsIDataType::VTYPE_CSTRING           , TD_CSTRING          },
  1.1708 +            {nsIDataType::VTYPE_ASTRING           , TD_ASTRING          }
  1.1709 +        };
  1.1710 +        static const int length = sizeof(array)/sizeof(array[0]);
  1.1711 +        static bool inited = false;
  1.1712 +        if(!inited)
  1.1713 +        {
  1.1714 +            for(int i = 0; i < length; i++)
  1.1715 +                NS_ASSERTION(array[i].a == array[i].b, "bad const declaration");
  1.1716 +            inited = true;
  1.1717 +        }
  1.1718 +    }
  1.1719 +#endif
  1.1720 +}
  1.1721 +
  1.1722 +nsVariant::~nsVariant()
  1.1723 +{
  1.1724 +    nsVariant::Cleanup(&mData);
  1.1725 +}
  1.1726 +
  1.1727 +// For all the data getters we just forward to the static (and sharable)
  1.1728 +// 'ConvertTo' functions.
  1.1729 +
  1.1730 +/* readonly attribute uint16_t dataType; */
  1.1731 +NS_IMETHODIMP nsVariant::GetDataType(uint16_t *aDataType)
  1.1732 +{
  1.1733 +    *aDataType = mData.mType;
  1.1734 +    return NS_OK;
  1.1735 +}
  1.1736 +
  1.1737 +/* uint8_t getAsInt8 (); */
  1.1738 +NS_IMETHODIMP nsVariant::GetAsInt8(uint8_t *_retval)
  1.1739 +{
  1.1740 +    return nsVariant::ConvertToInt8(mData, _retval);
  1.1741 +}
  1.1742 +
  1.1743 +/* int16_t getAsInt16 (); */
  1.1744 +NS_IMETHODIMP nsVariant::GetAsInt16(int16_t *_retval)
  1.1745 +{
  1.1746 +    return nsVariant::ConvertToInt16(mData, _retval);
  1.1747 +}
  1.1748 +
  1.1749 +/* int32_t getAsInt32 (); */
  1.1750 +NS_IMETHODIMP nsVariant::GetAsInt32(int32_t *_retval)
  1.1751 +{
  1.1752 +    return nsVariant::ConvertToInt32(mData, _retval);
  1.1753 +}
  1.1754 +
  1.1755 +/* int64_t getAsInt64 (); */
  1.1756 +NS_IMETHODIMP nsVariant::GetAsInt64(int64_t *_retval)
  1.1757 +{
  1.1758 +    return nsVariant::ConvertToInt64(mData, _retval);
  1.1759 +}
  1.1760 +
  1.1761 +/* uint8_t getAsUint8 (); */
  1.1762 +NS_IMETHODIMP nsVariant::GetAsUint8(uint8_t *_retval)
  1.1763 +{
  1.1764 +    return nsVariant::ConvertToUint8(mData, _retval);
  1.1765 +}
  1.1766 +
  1.1767 +/* uint16_t getAsUint16 (); */
  1.1768 +NS_IMETHODIMP nsVariant::GetAsUint16(uint16_t *_retval)
  1.1769 +{
  1.1770 +    return nsVariant::ConvertToUint16(mData, _retval);
  1.1771 +}
  1.1772 +
  1.1773 +/* uint32_t getAsUint32 (); */
  1.1774 +NS_IMETHODIMP nsVariant::GetAsUint32(uint32_t *_retval)
  1.1775 +{
  1.1776 +    return nsVariant::ConvertToUint32(mData, _retval);
  1.1777 +}
  1.1778 +
  1.1779 +/* uint64_t getAsUint64 (); */
  1.1780 +NS_IMETHODIMP nsVariant::GetAsUint64(uint64_t *_retval)
  1.1781 +{
  1.1782 +    return nsVariant::ConvertToUint64(mData, _retval);
  1.1783 +}
  1.1784 +
  1.1785 +/* float getAsFloat (); */
  1.1786 +NS_IMETHODIMP nsVariant::GetAsFloat(float *_retval)
  1.1787 +{
  1.1788 +    return nsVariant::ConvertToFloat(mData, _retval);
  1.1789 +}
  1.1790 +
  1.1791 +/* double getAsDouble (); */
  1.1792 +NS_IMETHODIMP nsVariant::GetAsDouble(double *_retval)
  1.1793 +{
  1.1794 +    return nsVariant::ConvertToDouble(mData, _retval);
  1.1795 +}
  1.1796 +
  1.1797 +/* bool getAsBool (); */
  1.1798 +NS_IMETHODIMP nsVariant::GetAsBool(bool *_retval)
  1.1799 +{
  1.1800 +    return nsVariant::ConvertToBool(mData, _retval);
  1.1801 +}
  1.1802 +
  1.1803 +/* char getAsChar (); */
  1.1804 +NS_IMETHODIMP nsVariant::GetAsChar(char *_retval)
  1.1805 +{
  1.1806 +    return nsVariant::ConvertToChar(mData, _retval);
  1.1807 +}
  1.1808 +
  1.1809 +/* wchar getAsWChar (); */
  1.1810 +NS_IMETHODIMP nsVariant::GetAsWChar(char16_t *_retval)
  1.1811 +{
  1.1812 +    return nsVariant::ConvertToWChar(mData, _retval);
  1.1813 +}
  1.1814 +
  1.1815 +/* [notxpcom] nsresult getAsID (out nsID retval); */
  1.1816 +NS_IMETHODIMP_(nsresult) nsVariant::GetAsID(nsID *retval)
  1.1817 +{
  1.1818 +    return nsVariant::ConvertToID(mData, retval);
  1.1819 +}
  1.1820 +
  1.1821 +/* AString getAsAString (); */
  1.1822 +NS_IMETHODIMP nsVariant::GetAsAString(nsAString & _retval)
  1.1823 +{
  1.1824 +    return nsVariant::ConvertToAString(mData, _retval);
  1.1825 +}
  1.1826 +
  1.1827 +/* DOMString getAsDOMString (); */
  1.1828 +NS_IMETHODIMP nsVariant::GetAsDOMString(nsAString & _retval)
  1.1829 +{
  1.1830 +    // A DOMString maps to an AString internally, so we can re-use
  1.1831 +    // ConvertToAString here.
  1.1832 +    return nsVariant::ConvertToAString(mData, _retval);
  1.1833 +}
  1.1834 +
  1.1835 +/* ACString getAsACString (); */
  1.1836 +NS_IMETHODIMP nsVariant::GetAsACString(nsACString & _retval)
  1.1837 +{
  1.1838 +    return nsVariant::ConvertToACString(mData, _retval);
  1.1839 +}
  1.1840 +
  1.1841 +/* AUTF8String getAsAUTF8String (); */
  1.1842 +NS_IMETHODIMP nsVariant::GetAsAUTF8String(nsAUTF8String & _retval)
  1.1843 +{
  1.1844 +    return nsVariant::ConvertToAUTF8String(mData, _retval);
  1.1845 +}
  1.1846 +
  1.1847 +/* string getAsString (); */
  1.1848 +NS_IMETHODIMP nsVariant::GetAsString(char **_retval)
  1.1849 +{
  1.1850 +    return nsVariant::ConvertToString(mData, _retval);
  1.1851 +}
  1.1852 +
  1.1853 +/* wstring getAsWString (); */
  1.1854 +NS_IMETHODIMP nsVariant::GetAsWString(char16_t **_retval)
  1.1855 +{
  1.1856 +    return nsVariant::ConvertToWString(mData, _retval);
  1.1857 +}
  1.1858 +
  1.1859 +/* nsISupports getAsISupports (); */
  1.1860 +NS_IMETHODIMP nsVariant::GetAsISupports(nsISupports **_retval)
  1.1861 +{
  1.1862 +    return nsVariant::ConvertToISupports(mData, _retval);
  1.1863 +}
  1.1864 +
  1.1865 +/* jsval getAsJSVal() */
  1.1866 +NS_IMETHODIMP nsVariant::GetAsJSVal(JS::MutableHandleValue)
  1.1867 +{
  1.1868 +    // Can only get the jsval from an XPCVariant.
  1.1869 +    return NS_ERROR_CANNOT_CONVERT_DATA;
  1.1870 +}
  1.1871 +
  1.1872 +/* void getAsInterface (out nsIIDPtr iid, [iid_is (iid), retval] out nsQIResult iface); */
  1.1873 +NS_IMETHODIMP nsVariant::GetAsInterface(nsIID * *iid, void * *iface)
  1.1874 +{
  1.1875 +    return nsVariant::ConvertToInterface(mData, iid, iface);
  1.1876 +}
  1.1877 +
  1.1878 +/* [notxpcom] nsresult getAsArray (out uint16_t type, out nsIID iid, out uint32_t count, out voidPtr ptr); */
  1.1879 +NS_IMETHODIMP_(nsresult) nsVariant::GetAsArray(uint16_t *type, nsIID *iid, uint32_t *count, void * *ptr)
  1.1880 +{
  1.1881 +    return nsVariant::ConvertToArray(mData, type, iid, count, ptr);
  1.1882 +}
  1.1883 +
  1.1884 +/* void getAsStringWithSize (out uint32_t size, [size_is (size), retval] out string str); */
  1.1885 +NS_IMETHODIMP nsVariant::GetAsStringWithSize(uint32_t *size, char **str)
  1.1886 +{
  1.1887 +    return nsVariant::ConvertToStringWithSize(mData, size, str);
  1.1888 +}
  1.1889 +
  1.1890 +/* void getAsWStringWithSize (out uint32_t size, [size_is (size), retval] out wstring str); */
  1.1891 +NS_IMETHODIMP nsVariant::GetAsWStringWithSize(uint32_t *size, char16_t **str)
  1.1892 +{
  1.1893 +    return nsVariant::ConvertToWStringWithSize(mData, size, str);
  1.1894 +}
  1.1895 +
  1.1896 +/***************************************************************************/
  1.1897 +
  1.1898 +/* attribute bool writable; */
  1.1899 +NS_IMETHODIMP nsVariant::GetWritable(bool *aWritable)
  1.1900 +{
  1.1901 +    *aWritable = mWritable;
  1.1902 +    return NS_OK;
  1.1903 +}
  1.1904 +NS_IMETHODIMP nsVariant::SetWritable(bool aWritable)
  1.1905 +{
  1.1906 +    if(!mWritable && aWritable)
  1.1907 +        return NS_ERROR_FAILURE;
  1.1908 +    mWritable = aWritable;
  1.1909 +    return NS_OK;
  1.1910 +}
  1.1911 +
  1.1912 +/***************************************************************************/
  1.1913 +
  1.1914 +// For all the data setters we just forward to the static (and sharable)
  1.1915 +// 'SetFrom' functions.
  1.1916 +
  1.1917 +/* void setAsInt8 (in uint8_t aValue); */
  1.1918 +NS_IMETHODIMP nsVariant::SetAsInt8(uint8_t aValue)
  1.1919 +{
  1.1920 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.1921 +    return nsVariant::SetFromInt8(&mData, aValue);
  1.1922 +}
  1.1923 +
  1.1924 +/* void setAsInt16 (in int16_t aValue); */
  1.1925 +NS_IMETHODIMP nsVariant::SetAsInt16(int16_t aValue)
  1.1926 +{
  1.1927 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.1928 +    return nsVariant::SetFromInt16(&mData, aValue);
  1.1929 +}
  1.1930 +
  1.1931 +/* void setAsInt32 (in int32_t aValue); */
  1.1932 +NS_IMETHODIMP nsVariant::SetAsInt32(int32_t aValue)
  1.1933 +{
  1.1934 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.1935 +    return nsVariant::SetFromInt32(&mData, aValue);
  1.1936 +}
  1.1937 +
  1.1938 +/* void setAsInt64 (in int64_t aValue); */
  1.1939 +NS_IMETHODIMP nsVariant::SetAsInt64(int64_t aValue)
  1.1940 +{
  1.1941 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.1942 +    return nsVariant::SetFromInt64(&mData, aValue);
  1.1943 +}
  1.1944 +
  1.1945 +/* void setAsUint8 (in uint8_t aValue); */
  1.1946 +NS_IMETHODIMP nsVariant::SetAsUint8(uint8_t aValue)
  1.1947 +{
  1.1948 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.1949 +    return nsVariant::SetFromUint8(&mData, aValue);
  1.1950 +}
  1.1951 +
  1.1952 +/* void setAsUint16 (in uint16_t aValue); */
  1.1953 +NS_IMETHODIMP nsVariant::SetAsUint16(uint16_t aValue)
  1.1954 +{
  1.1955 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.1956 +    return nsVariant::SetFromUint16(&mData, aValue);
  1.1957 +}
  1.1958 +
  1.1959 +/* void setAsUint32 (in uint32_t aValue); */
  1.1960 +NS_IMETHODIMP nsVariant::SetAsUint32(uint32_t aValue)
  1.1961 +{
  1.1962 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.1963 +    return nsVariant::SetFromUint32(&mData, aValue);
  1.1964 +}
  1.1965 +
  1.1966 +/* void setAsUint64 (in uint64_t aValue); */
  1.1967 +NS_IMETHODIMP nsVariant::SetAsUint64(uint64_t aValue)
  1.1968 +{
  1.1969 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.1970 +    return nsVariant::SetFromUint64(&mData, aValue);
  1.1971 +}
  1.1972 +
  1.1973 +/* void setAsFloat (in float aValue); */
  1.1974 +NS_IMETHODIMP nsVariant::SetAsFloat(float aValue)
  1.1975 +{
  1.1976 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.1977 +    return nsVariant::SetFromFloat(&mData, aValue);
  1.1978 +}
  1.1979 +
  1.1980 +/* void setAsDouble (in double aValue); */
  1.1981 +NS_IMETHODIMP nsVariant::SetAsDouble(double aValue)
  1.1982 +{
  1.1983 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.1984 +    return nsVariant::SetFromDouble(&mData, aValue);
  1.1985 +}
  1.1986 +
  1.1987 +/* void setAsBool (in bool aValue); */
  1.1988 +NS_IMETHODIMP nsVariant::SetAsBool(bool aValue)
  1.1989 +{
  1.1990 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.1991 +    return nsVariant::SetFromBool(&mData, aValue);
  1.1992 +}
  1.1993 +
  1.1994 +/* void setAsChar (in char aValue); */
  1.1995 +NS_IMETHODIMP nsVariant::SetAsChar(char aValue)
  1.1996 +{
  1.1997 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.1998 +    return nsVariant::SetFromChar(&mData, aValue);
  1.1999 +}
  1.2000 +
  1.2001 +/* void setAsWChar (in wchar aValue); */
  1.2002 +NS_IMETHODIMP nsVariant::SetAsWChar(char16_t aValue)
  1.2003 +{
  1.2004 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.2005 +    return nsVariant::SetFromWChar(&mData, aValue);
  1.2006 +}
  1.2007 +
  1.2008 +/* void setAsID (in nsIDRef aValue); */
  1.2009 +NS_IMETHODIMP nsVariant::SetAsID(const nsID & aValue)
  1.2010 +{
  1.2011 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.2012 +    return nsVariant::SetFromID(&mData, aValue);
  1.2013 +}
  1.2014 +
  1.2015 +/* void setAsAString (in AString aValue); */
  1.2016 +NS_IMETHODIMP nsVariant::SetAsAString(const nsAString & aValue)
  1.2017 +{
  1.2018 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.2019 +    return nsVariant::SetFromAString(&mData, aValue);
  1.2020 +}
  1.2021 +
  1.2022 +/* void setAsDOMString (in DOMString aValue); */
  1.2023 +NS_IMETHODIMP nsVariant::SetAsDOMString(const nsAString & aValue)
  1.2024 +{
  1.2025 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.2026 +
  1.2027 +    DATA_SETTER_PROLOGUE((&mData));
  1.2028 +    if(!(mData.u.mAStringValue = new nsString(aValue)))
  1.2029 +        return NS_ERROR_OUT_OF_MEMORY;
  1.2030 +    DATA_SETTER_EPILOGUE((&mData), VTYPE_DOMSTRING);
  1.2031 +}
  1.2032 +
  1.2033 +/* void setAsACString (in ACString aValue); */
  1.2034 +NS_IMETHODIMP nsVariant::SetAsACString(const nsACString & aValue)
  1.2035 +{
  1.2036 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.2037 +    return nsVariant::SetFromACString(&mData, aValue);
  1.2038 +}
  1.2039 +
  1.2040 +/* void setAsAUTF8String (in AUTF8String aValue); */
  1.2041 +NS_IMETHODIMP nsVariant::SetAsAUTF8String(const nsAUTF8String & aValue)
  1.2042 +{
  1.2043 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.2044 +    return nsVariant::SetFromAUTF8String(&mData, aValue);
  1.2045 +}
  1.2046 +
  1.2047 +/* void setAsString (in string aValue); */
  1.2048 +NS_IMETHODIMP nsVariant::SetAsString(const char *aValue)
  1.2049 +{
  1.2050 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.2051 +    return nsVariant::SetFromString(&mData, aValue);
  1.2052 +}
  1.2053 +
  1.2054 +/* void setAsWString (in wstring aValue); */
  1.2055 +NS_IMETHODIMP nsVariant::SetAsWString(const char16_t *aValue)
  1.2056 +{
  1.2057 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.2058 +    return nsVariant::SetFromWString(&mData, aValue);
  1.2059 +}
  1.2060 +
  1.2061 +/* void setAsISupports (in nsISupports aValue); */
  1.2062 +NS_IMETHODIMP nsVariant::SetAsISupports(nsISupports *aValue)
  1.2063 +{
  1.2064 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.2065 +    return nsVariant::SetFromISupports(&mData, aValue);
  1.2066 +}
  1.2067 +
  1.2068 +/* void setAsInterface (in nsIIDRef iid, [iid_is (iid)] in nsQIResult iface); */
  1.2069 +NS_IMETHODIMP nsVariant::SetAsInterface(const nsIID & iid, void * iface)
  1.2070 +{
  1.2071 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.2072 +    return nsVariant::SetFromInterface(&mData, iid, (nsISupports*)iface);
  1.2073 +}
  1.2074 +
  1.2075 +/* [noscript] void setAsArray (in uint16_t type, in nsIIDPtr iid, in uint32_t count, in voidPtr ptr); */
  1.2076 +NS_IMETHODIMP nsVariant::SetAsArray(uint16_t type, const nsIID * iid, uint32_t count, void * ptr)
  1.2077 +{
  1.2078 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.2079 +    return nsVariant::SetFromArray(&mData, type, iid, count, ptr);
  1.2080 +}
  1.2081 +
  1.2082 +/* void setAsStringWithSize (in uint32_t size, [size_is (size)] in string str); */
  1.2083 +NS_IMETHODIMP nsVariant::SetAsStringWithSize(uint32_t size, const char *str)
  1.2084 +{
  1.2085 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.2086 +    return nsVariant::SetFromStringWithSize(&mData, size, str);
  1.2087 +}
  1.2088 +
  1.2089 +/* void setAsWStringWithSize (in uint32_t size, [size_is (size)] in wstring str); */
  1.2090 +NS_IMETHODIMP nsVariant::SetAsWStringWithSize(uint32_t size, const char16_t *str)
  1.2091 +{
  1.2092 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.2093 +    return nsVariant::SetFromWStringWithSize(&mData, size, str);
  1.2094 +}
  1.2095 +
  1.2096 +/* void setAsVoid (); */
  1.2097 +NS_IMETHODIMP nsVariant::SetAsVoid()
  1.2098 +{
  1.2099 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.2100 +    return nsVariant::SetToVoid(&mData);
  1.2101 +}
  1.2102 +
  1.2103 +/* void setAsEmpty (); */
  1.2104 +NS_IMETHODIMP nsVariant::SetAsEmpty()
  1.2105 +{
  1.2106 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.2107 +    return nsVariant::SetToEmpty(&mData);
  1.2108 +}
  1.2109 +
  1.2110 +/* void setAsEmptyArray (); */
  1.2111 +NS_IMETHODIMP nsVariant::SetAsEmptyArray()
  1.2112 +{
  1.2113 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.2114 +    return nsVariant::SetToEmptyArray(&mData);
  1.2115 +}
  1.2116 +
  1.2117 +/* void setFromVariant (in nsIVariant aValue); */
  1.2118 +NS_IMETHODIMP nsVariant::SetFromVariant(nsIVariant *aValue)
  1.2119 +{
  1.2120 +    if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1.2121 +    return nsVariant::SetFromVariant(&mData, aValue);
  1.2122 +}

mercurial