xpcom/ds/nsVariant.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  *
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 /* The long avoided variant support for xpcom. */
     9 #include "nsVariant.h"
    10 #include "prprf.h"
    11 #include "prdtoa.h"
    12 #include <math.h>
    13 #include "nsCycleCollectionParticipant.h"
    14 #include "xpt_struct.h"
    15 #include "nsReadableUtils.h"
    16 #include "nsMemory.h"
    17 #include "nsString.h"
    18 #include "nsCRTGlue.h"
    20 /***************************************************************************/
    21 // Helpers for static convert functions...
    23 static nsresult String2Double(const char* aString, double* retval)
    24 {
    25     char* next;
    26     double value = PR_strtod(aString, &next);
    27     if(next == aString)
    28         return NS_ERROR_CANNOT_CONVERT_DATA;
    29     *retval = value;
    30     return NS_OK;
    31 }
    33 static nsresult AString2Double(const nsAString& aString, double* retval)
    34 {
    35     char* pChars = ToNewCString(aString);
    36     if(!pChars)
    37         return NS_ERROR_OUT_OF_MEMORY;
    38     nsresult rv = String2Double(pChars, retval);
    39     nsMemory::Free(pChars);
    40     return rv;
    41 }
    43 static nsresult AUTF8String2Double(const nsAUTF8String& aString, double* retval)
    44 {
    45     return String2Double(PromiseFlatUTF8String(aString).get(), retval);
    46 }
    48 static nsresult ACString2Double(const nsACString& aString, double* retval)
    49 {
    50     return String2Double(PromiseFlatCString(aString).get(), retval);
    51 }
    53 // Fills outVariant with double, uint32_t, or int32_t.
    54 // Returns NS_OK, an error code, or a non-NS_OK success code
    55 static nsresult ToManageableNumber(const nsDiscriminatedUnion& inData,
    56                                    nsDiscriminatedUnion* outData)
    57 {
    58     nsresult rv;
    60     switch(inData.mType)
    61     {
    62     // This group results in a int32_t...
    64 #define CASE__NUMBER_INT32(type_, member_)                                    \
    65     case nsIDataType :: type_ :                                               \
    66         outData->u.mInt32Value = inData.u. member_ ;                          \
    67         outData->mType = nsIDataType::VTYPE_INT32;                            \
    68         return NS_OK;
    70     CASE__NUMBER_INT32(VTYPE_INT8,   mInt8Value)
    71     CASE__NUMBER_INT32(VTYPE_INT16,  mInt16Value)
    72     CASE__NUMBER_INT32(VTYPE_INT32,  mInt32Value)
    73     CASE__NUMBER_INT32(VTYPE_UINT8,  mUint8Value)
    74     CASE__NUMBER_INT32(VTYPE_UINT16, mUint16Value)
    75     CASE__NUMBER_INT32(VTYPE_BOOL,   mBoolValue)
    76     CASE__NUMBER_INT32(VTYPE_CHAR,   mCharValue)
    77     CASE__NUMBER_INT32(VTYPE_WCHAR,  mWCharValue)
    79 #undef CASE__NUMBER_INT32
    81     // This group results in a uint32_t...
    83     case nsIDataType::VTYPE_UINT32:
    84         outData->u.mInt32Value = inData.u.mUint32Value;
    85         outData->mType = nsIDataType::VTYPE_INT32;
    86         return NS_OK;
    88     // This group results in a double...
    90     case nsIDataType::VTYPE_INT64:
    91     case nsIDataType::VTYPE_UINT64:
    92         // XXX Need boundary checking here.
    93         // We may need to return NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA
    94         outData->u.mDoubleValue = double(inData.u.mInt64Value);
    95         outData->mType = nsIDataType::VTYPE_DOUBLE;
    96         return NS_OK;
    97     case nsIDataType::VTYPE_FLOAT:
    98         outData->u.mDoubleValue = inData.u.mFloatValue;
    99         outData->mType = nsIDataType::VTYPE_DOUBLE;
   100         return NS_OK;
   101     case nsIDataType::VTYPE_DOUBLE:
   102         outData->u.mDoubleValue = inData.u.mDoubleValue;
   103         outData->mType = nsIDataType::VTYPE_DOUBLE;
   104         return NS_OK;
   105     case nsIDataType::VTYPE_CHAR_STR:
   106     case nsIDataType::VTYPE_STRING_SIZE_IS:
   107         rv = String2Double(inData.u.str.mStringValue, &outData->u.mDoubleValue);
   108         if(NS_FAILED(rv))
   109             return rv;
   110         outData->mType = nsIDataType::VTYPE_DOUBLE;
   111         return NS_OK;
   112     case nsIDataType::VTYPE_DOMSTRING:
   113     case nsIDataType::VTYPE_ASTRING:
   114         rv = AString2Double(*inData.u.mAStringValue, &outData->u.mDoubleValue);
   115         if(NS_FAILED(rv))
   116             return rv;
   117         outData->mType = nsIDataType::VTYPE_DOUBLE;
   118         return NS_OK;
   119     case nsIDataType::VTYPE_UTF8STRING:
   120         rv = AUTF8String2Double(*inData.u.mUTF8StringValue,
   121                                 &outData->u.mDoubleValue);
   122         if(NS_FAILED(rv))
   123             return rv;
   124         outData->mType = nsIDataType::VTYPE_DOUBLE;
   125         return NS_OK;
   126     case nsIDataType::VTYPE_CSTRING:
   127         rv = ACString2Double(*inData.u.mCStringValue,
   128                              &outData->u.mDoubleValue);
   129         if(NS_FAILED(rv))
   130             return rv;
   131         outData->mType = nsIDataType::VTYPE_DOUBLE;
   132         return NS_OK;
   133     case nsIDataType::VTYPE_WCHAR_STR:
   134     case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   135         rv = AString2Double(nsDependentString(inData.u.wstr.mWStringValue),
   136                             &outData->u.mDoubleValue);
   137         if(NS_FAILED(rv))
   138             return rv;
   139         outData->mType = nsIDataType::VTYPE_DOUBLE;
   140         return NS_OK;
   142     // This group fails...
   144     case nsIDataType::VTYPE_VOID:
   145     case nsIDataType::VTYPE_ID:
   146     case nsIDataType::VTYPE_INTERFACE:
   147     case nsIDataType::VTYPE_INTERFACE_IS:
   148     case nsIDataType::VTYPE_ARRAY:
   149     case nsIDataType::VTYPE_EMPTY_ARRAY:
   150     case nsIDataType::VTYPE_EMPTY:
   151     default:
   152         return NS_ERROR_CANNOT_CONVERT_DATA;
   153     }
   154 }
   156 /***************************************************************************/
   157 // Array helpers...
   159 static void FreeArray(nsDiscriminatedUnion* data)
   160 {
   161     NS_ASSERTION(data->mType == nsIDataType::VTYPE_ARRAY, "bad FreeArray call");
   162     NS_ASSERTION(data->u.array.mArrayValue, "bad array");
   163     NS_ASSERTION(data->u.array.mArrayCount, "bad array count");
   165 #define CASE__FREE_ARRAY_PTR(type_, ctype_)                                   \
   166         case nsIDataType:: type_ :                                            \
   167         {                                                                     \
   168             ctype_ ** p = (ctype_ **) data->u.array.mArrayValue;              \
   169             for(uint32_t i = data->u.array.mArrayCount; i > 0; p++, i--)      \
   170                 if(*p)                                                        \
   171                     nsMemory::Free((char*)*p);                                \
   172             break;                                                            \
   173         }
   175 #define CASE__FREE_ARRAY_IFACE(type_, ctype_)                                 \
   176         case nsIDataType:: type_ :                                            \
   177         {                                                                     \
   178             ctype_ ** p = (ctype_ **) data->u.array.mArrayValue;              \
   179             for(uint32_t i = data->u.array.mArrayCount; i > 0; p++, i--)      \
   180                 if(*p)                                                        \
   181                     (*p)->Release();                                          \
   182             break;                                                            \
   183         }
   185     switch(data->u.array.mArrayType)
   186     {
   187         case nsIDataType::VTYPE_INT8:
   188         case nsIDataType::VTYPE_INT16:
   189         case nsIDataType::VTYPE_INT32:
   190         case nsIDataType::VTYPE_INT64:
   191         case nsIDataType::VTYPE_UINT8:
   192         case nsIDataType::VTYPE_UINT16:
   193         case nsIDataType::VTYPE_UINT32:
   194         case nsIDataType::VTYPE_UINT64:
   195         case nsIDataType::VTYPE_FLOAT:
   196         case nsIDataType::VTYPE_DOUBLE:
   197         case nsIDataType::VTYPE_BOOL:
   198         case nsIDataType::VTYPE_CHAR:
   199         case nsIDataType::VTYPE_WCHAR:
   200             break;
   202         // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
   203         CASE__FREE_ARRAY_PTR(VTYPE_ID, nsID)
   204         CASE__FREE_ARRAY_PTR(VTYPE_CHAR_STR, char)
   205         CASE__FREE_ARRAY_PTR(VTYPE_WCHAR_STR, char16_t)
   206         CASE__FREE_ARRAY_IFACE(VTYPE_INTERFACE, nsISupports)
   207         CASE__FREE_ARRAY_IFACE(VTYPE_INTERFACE_IS, nsISupports)
   209         // The rest are illegal.
   210         case nsIDataType::VTYPE_VOID:
   211         case nsIDataType::VTYPE_ASTRING:
   212         case nsIDataType::VTYPE_DOMSTRING:
   213         case nsIDataType::VTYPE_UTF8STRING:
   214         case nsIDataType::VTYPE_CSTRING:
   215         case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   216         case nsIDataType::VTYPE_STRING_SIZE_IS:
   217         case nsIDataType::VTYPE_ARRAY:
   218         case nsIDataType::VTYPE_EMPTY_ARRAY:
   219         case nsIDataType::VTYPE_EMPTY:
   220         default:
   221             NS_ERROR("bad type in array!");
   222             break;
   223     }
   225     // Free the array memory.
   226     nsMemory::Free((char*)data->u.array.mArrayValue);
   228 #undef CASE__FREE_ARRAY_PTR
   229 #undef CASE__FREE_ARRAY_IFACE
   230 }
   232 static nsresult CloneArray(uint16_t inType, const nsIID* inIID,
   233                            uint32_t inCount, void* inValue,
   234                            uint16_t* outType,
   235                            nsIID* outIID,
   236                            uint32_t* outCount,
   237                            void** outValue)
   238 {
   239     NS_ASSERTION(inCount, "bad param");
   240     NS_ASSERTION(inValue, "bad param");
   241     NS_ASSERTION(outType, "bad param");
   242     NS_ASSERTION(outCount, "bad param");
   243     NS_ASSERTION(outValue, "bad param");
   245     uint32_t allocatedValueCount = 0;
   246     nsresult rv = NS_OK;
   247     uint32_t i;
   249     // First we figure out the size of the elements for the new u.array.
   251     size_t elementSize;
   252     size_t allocSize;
   254     switch(inType)
   255     {
   256         case nsIDataType::VTYPE_INT8:
   257             elementSize = sizeof(int8_t);
   258             break;
   259         case nsIDataType::VTYPE_INT16:
   260             elementSize = sizeof(int16_t);
   261             break;
   262         case nsIDataType::VTYPE_INT32:
   263             elementSize = sizeof(int32_t);
   264             break;
   265         case nsIDataType::VTYPE_INT64:
   266             elementSize = sizeof(int64_t);
   267             break;
   268         case nsIDataType::VTYPE_UINT8:
   269             elementSize = sizeof(uint8_t);
   270             break;
   271         case nsIDataType::VTYPE_UINT16:
   272             elementSize = sizeof(uint16_t);
   273             break;
   274         case nsIDataType::VTYPE_UINT32:
   275             elementSize = sizeof(uint32_t);
   276             break;
   277         case nsIDataType::VTYPE_UINT64:
   278             elementSize = sizeof(uint64_t);
   279             break;
   280         case nsIDataType::VTYPE_FLOAT:
   281             elementSize = sizeof(float);
   282             break;
   283         case nsIDataType::VTYPE_DOUBLE:
   284             elementSize = sizeof(double);
   285             break;
   286         case nsIDataType::VTYPE_BOOL:
   287             elementSize = sizeof(bool);
   288             break;
   289         case nsIDataType::VTYPE_CHAR:
   290             elementSize = sizeof(char);
   291             break;
   292         case nsIDataType::VTYPE_WCHAR:
   293             elementSize = sizeof(char16_t);
   294             break;
   296         // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
   297         case nsIDataType::VTYPE_ID:
   298         case nsIDataType::VTYPE_CHAR_STR:
   299         case nsIDataType::VTYPE_WCHAR_STR:
   300         case nsIDataType::VTYPE_INTERFACE:
   301         case nsIDataType::VTYPE_INTERFACE_IS:
   302             elementSize = sizeof(void*);
   303             break;
   305         // The rest are illegal.
   306         case nsIDataType::VTYPE_ASTRING:
   307         case nsIDataType::VTYPE_DOMSTRING:
   308         case nsIDataType::VTYPE_UTF8STRING:
   309         case nsIDataType::VTYPE_CSTRING:
   310         case nsIDataType::VTYPE_STRING_SIZE_IS:
   311         case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   312         case nsIDataType::VTYPE_VOID:
   313         case nsIDataType::VTYPE_ARRAY:
   314         case nsIDataType::VTYPE_EMPTY_ARRAY:
   315         case nsIDataType::VTYPE_EMPTY:
   316         default:
   317             NS_ERROR("bad type in array!");
   318             return NS_ERROR_CANNOT_CONVERT_DATA;
   319     }
   322     // Alloc the u.array.
   324     allocSize = inCount * elementSize;
   325     *outValue = nsMemory::Alloc(allocSize);
   326     if(!*outValue)
   327         return NS_ERROR_OUT_OF_MEMORY;
   329     // Clone the elements.
   331     switch(inType)
   332     {
   333         case nsIDataType::VTYPE_INT8:
   334         case nsIDataType::VTYPE_INT16:
   335         case nsIDataType::VTYPE_INT32:
   336         case nsIDataType::VTYPE_INT64:
   337         case nsIDataType::VTYPE_UINT8:
   338         case nsIDataType::VTYPE_UINT16:
   339         case nsIDataType::VTYPE_UINT32:
   340         case nsIDataType::VTYPE_UINT64:
   341         case nsIDataType::VTYPE_FLOAT:
   342         case nsIDataType::VTYPE_DOUBLE:
   343         case nsIDataType::VTYPE_BOOL:
   344         case nsIDataType::VTYPE_CHAR:
   345         case nsIDataType::VTYPE_WCHAR:
   346             memcpy(*outValue, inValue, allocSize);
   347             break;
   349         case nsIDataType::VTYPE_INTERFACE_IS:
   350             if(outIID)
   351                 *outIID = *inIID;
   352             // fall through...
   353         case nsIDataType::VTYPE_INTERFACE:
   354         {
   355             memcpy(*outValue, inValue, allocSize);
   357             nsISupports** p = (nsISupports**) *outValue;
   358             for(i = inCount; i > 0; p++, i--)
   359                 if(*p)
   360                     (*p)->AddRef();
   361             break;
   362         }
   364         // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
   365         case nsIDataType::VTYPE_ID:
   366         {
   367             nsID** inp  = (nsID**) inValue;
   368             nsID** outp = (nsID**) *outValue;
   369             for(i = inCount; i > 0; i--)
   370             {
   371                 nsID* idp = *(inp++);
   372                 if(idp)
   373                 {
   374                     if(nullptr == (*(outp++) = (nsID*)
   375                        nsMemory::Clone((char*)idp, sizeof(nsID))))
   376                         goto bad;
   377                 }
   378                 else
   379                     *(outp++) = nullptr;
   380                 allocatedValueCount++;
   381             }
   382             break;
   383         }
   385         case nsIDataType::VTYPE_CHAR_STR:
   386         {
   387             char** inp  = (char**) inValue;
   388             char** outp = (char**) *outValue;
   389             for(i = inCount; i > 0; i--)
   390             {
   391                 char* str = *(inp++);
   392                 if(str)
   393                 {
   394                     if(nullptr == (*(outp++) = (char*)
   395                        nsMemory::Clone(str, (strlen(str)+1)*sizeof(char))))
   396                         goto bad;
   397                 }
   398                 else
   399                     *(outp++) = nullptr;
   400                 allocatedValueCount++;
   401             }
   402             break;
   403         }
   405         case nsIDataType::VTYPE_WCHAR_STR:
   406         {
   407             char16_t** inp  = (char16_t**) inValue;
   408             char16_t** outp = (char16_t**) *outValue;
   409             for(i = inCount; i > 0; i--)
   410             {
   411                 char16_t* str = *(inp++);
   412                 if(str)
   413                 {
   414                     if(nullptr == (*(outp++) = (char16_t*)
   415                        nsMemory::Clone(str,
   416                         (NS_strlen(str) + 1) * sizeof(char16_t))))
   417                         goto bad;
   418                 }
   419                 else
   420                     *(outp++) = nullptr;
   421                 allocatedValueCount++;
   422             }
   423             break;
   424         }
   426         // The rest are illegal.
   427         case nsIDataType::VTYPE_VOID:
   428         case nsIDataType::VTYPE_ARRAY:
   429         case nsIDataType::VTYPE_EMPTY_ARRAY:
   430         case nsIDataType::VTYPE_EMPTY:
   431         case nsIDataType::VTYPE_ASTRING:
   432         case nsIDataType::VTYPE_DOMSTRING:
   433         case nsIDataType::VTYPE_UTF8STRING:
   434         case nsIDataType::VTYPE_CSTRING:
   435         case nsIDataType::VTYPE_STRING_SIZE_IS:
   436         case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   437         default:
   438             NS_ERROR("bad type in array!");
   439             return NS_ERROR_CANNOT_CONVERT_DATA;
   440     }
   442     *outType = inType;
   443     *outCount = inCount;
   444     return NS_OK;
   446 bad:
   447     if(*outValue)
   448     {
   449         char** p = (char**) *outValue;
   450         for(i = allocatedValueCount; i > 0; p++, i--)
   451             if(*p)
   452                 nsMemory::Free(*p);
   453         nsMemory::Free((char*)*outValue);
   454         *outValue = nullptr;
   455     }
   456     return rv;
   457 }
   459 /***************************************************************************/
   461 #define TRIVIAL_DATA_CONVERTER(type_, data_, member_, retval_)                \
   462     if(data_.mType == nsIDataType :: type_) {                                 \
   463         *retval_ = data_.u.member_;                                           \
   464         return NS_OK;                                                         \
   465     }
   467 #define NUMERIC_CONVERSION_METHOD_BEGIN(type_, Ctype_, name_)                 \
   468 /* static */ nsresult                                                         \
   469 nsVariant::ConvertTo##name_ (const nsDiscriminatedUnion& data,                \
   470                              Ctype_ *_retval)                                 \
   471 {                                                                             \
   472     TRIVIAL_DATA_CONVERTER(type_, data, m##name_##Value, _retval)             \
   473     nsDiscriminatedUnion tempData;                                            \
   474     nsVariant::Initialize(&tempData);                                         \
   475     nsresult rv = ToManageableNumber(data, &tempData);                        \
   476     /*                                                                     */ \
   477     /* NOTE: rv may indicate a success code that we want to preserve       */ \
   478     /* For the final return. So all the return cases below should return   */ \
   479     /* this rv when indicating success.                                    */ \
   480     /*                                                                     */ \
   481     if(NS_FAILED(rv))                                                         \
   482         return rv;                                                            \
   483     switch(tempData.mType)                                                    \
   484     {
   486 #define CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(Ctype_)                      \
   487     case nsIDataType::VTYPE_INT32:                                            \
   488         *_retval = ( Ctype_ ) tempData.u.mInt32Value;                         \
   489         return rv;
   491 #define CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(Ctype_, min_, max_)            \
   492     case nsIDataType::VTYPE_INT32:                                            \
   493     {                                                                         \
   494         int32_t value = tempData.u.mInt32Value;                               \
   495         if(value < min_ || value > max_)                                      \
   496             return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;                         \
   497         *_retval = ( Ctype_ ) value;                                          \
   498         return rv;                                                            \
   499     }
   501 #define CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(Ctype_)                     \
   502     case nsIDataType::VTYPE_UINT32:                                           \
   503         *_retval = ( Ctype_ ) tempData.u.mUint32Value;                        \
   504         return rv;
   506 #define CASE__NUMERIC_CONVERSION_UINT32_MAX(Ctype_, max_)                     \
   507     case nsIDataType::VTYPE_UINT32:                                           \
   508     {                                                                         \
   509         uint32_t value = tempData.u.mUint32Value;                             \
   510         if(value > max_)                                                      \
   511             return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;                         \
   512         *_retval = ( Ctype_ ) value;                                          \
   513         return rv;                                                            \
   514     }
   516 #define CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(Ctype_)                     \
   517     case nsIDataType::VTYPE_DOUBLE:                                           \
   518         *_retval = ( Ctype_ ) tempData.u.mDoubleValue;                        \
   519         return rv;
   521 #define CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX(Ctype_, min_, max_)           \
   522     case nsIDataType::VTYPE_DOUBLE:                                           \
   523     {                                                                         \
   524         double value = tempData.u.mDoubleValue;                               \
   525         if(value < min_ || value > max_)                                      \
   526             return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;                         \
   527         *_retval = ( Ctype_ ) value;                                          \
   528         return rv;                                                            \
   529     }
   531 #define CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(Ctype_, min_, max_)       \
   532     case nsIDataType::VTYPE_DOUBLE:                                           \
   533     {                                                                         \
   534         double value = tempData.u.mDoubleValue;                               \
   535         if(value < min_ || value > max_)                                      \
   536             return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;                         \
   537         *_retval = ( Ctype_ ) value;                                          \
   538         return (0.0 == fmod(value,1.0)) ?                                     \
   539             rv : NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA;                       \
   540     }
   542 #define CASES__NUMERIC_CONVERSION_NORMAL(Ctype_, min_, max_)                  \
   543     CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(Ctype_, min_, max_)                \
   544     CASE__NUMERIC_CONVERSION_UINT32_MAX(Ctype_, max_)                         \
   545     CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(Ctype_, min_, max_)
   547 #define NUMERIC_CONVERSION_METHOD_END                                         \
   548     default:                                                                  \
   549         NS_ERROR("bad type returned from ToManageableNumber");                \
   550         return NS_ERROR_CANNOT_CONVERT_DATA;                                  \
   551     }                                                                         \
   552 }
   554 #define NUMERIC_CONVERSION_METHOD_NORMAL(type_, Ctype_, name_, min_, max_)    \
   555     NUMERIC_CONVERSION_METHOD_BEGIN(type_, Ctype_, name_)                     \
   556         CASES__NUMERIC_CONVERSION_NORMAL(Ctype_, min_, max_)                  \
   557     NUMERIC_CONVERSION_METHOD_END
   559 /***************************************************************************/
   560 // These expand into full public methods...
   562 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_INT8, uint8_t, Int8, (-127-1), 127)
   563 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_INT16, int16_t, Int16, (-32767-1), 32767)
   565 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_INT32, int32_t, Int32)
   566     CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(int32_t)
   567     CASE__NUMERIC_CONVERSION_UINT32_MAX(int32_t, 2147483647)
   568     CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(int32_t, (-2147483647-1), 2147483647)
   569 NUMERIC_CONVERSION_METHOD_END
   571 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_UINT8, uint8_t, Uint8, 0, 255)
   572 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_UINT16, uint16_t, Uint16, 0, 65535)
   574 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_UINT32, uint32_t, Uint32)
   575     CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(uint32_t, 0, 2147483647)
   576     CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(uint32_t)
   577     CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(uint32_t, 0, 4294967295U)
   578 NUMERIC_CONVERSION_METHOD_END
   580 // XXX toFloat convertions need to be fixed!
   581 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_FLOAT, float, Float)
   582     CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(float)
   583     CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(float)
   584     CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(float)
   585 NUMERIC_CONVERSION_METHOD_END
   587 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_DOUBLE, double, Double)
   588     CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(double)
   589     CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(double)
   590     CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(double)
   591 NUMERIC_CONVERSION_METHOD_END
   593 // XXX toChar convertions need to be fixed!
   594 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_CHAR, char, Char)
   595     CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(char)
   596     CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(char)
   597     CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(char)
   598 NUMERIC_CONVERSION_METHOD_END
   600 // XXX toWChar convertions need to be fixed!
   601 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_WCHAR, char16_t, WChar)
   602     CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(char16_t)
   603     CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(char16_t)
   604     CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(char16_t)
   605 NUMERIC_CONVERSION_METHOD_END
   607 #undef NUMERIC_CONVERSION_METHOD_BEGIN
   608 #undef CASE__NUMERIC_CONVERSION_INT32_JUST_CAST
   609 #undef CASE__NUMERIC_CONVERSION_INT32_MIN_MAX
   610 #undef CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST
   611 #undef CASE__NUMERIC_CONVERSION_UINT32_MIN_MAX
   612 #undef CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST
   613 #undef CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX
   614 #undef CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT
   615 #undef CASES__NUMERIC_CONVERSION_NORMAL
   616 #undef NUMERIC_CONVERSION_METHOD_END
   617 #undef NUMERIC_CONVERSION_METHOD_NORMAL
   619 /***************************************************************************/
   621 // Just leverage a numeric converter for bool (but restrict the values).
   622 // XXX Is this really what we want to do?
   624 /* static */ nsresult
   625 nsVariant::ConvertToBool(const nsDiscriminatedUnion& data, bool *_retval)
   626 {
   627     TRIVIAL_DATA_CONVERTER(VTYPE_BOOL, data, mBoolValue, _retval)
   629     double val;
   630     nsresult rv = nsVariant::ConvertToDouble(data, &val);
   631     if(NS_FAILED(rv))
   632         return rv;
   633     *_retval = 0.0 != val;
   634     return rv;
   635 }
   637 /***************************************************************************/
   639 /* static */ nsresult
   640 nsVariant::ConvertToInt64(const nsDiscriminatedUnion& data, int64_t *_retval)
   641 {
   642     TRIVIAL_DATA_CONVERTER(VTYPE_INT64, data, mInt64Value, _retval)
   643     TRIVIAL_DATA_CONVERTER(VTYPE_UINT64, data, mUint64Value, _retval)
   645     nsDiscriminatedUnion tempData;
   646     nsVariant::Initialize(&tempData);
   647     nsresult rv = ToManageableNumber(data, &tempData);
   648     if(NS_FAILED(rv))
   649         return rv;
   650     switch(tempData.mType)
   651     {
   652     case nsIDataType::VTYPE_INT32:
   653         *_retval = tempData.u.mInt32Value;
   654         return rv;
   655     case nsIDataType::VTYPE_UINT32:
   656         *_retval = tempData.u.mUint32Value;
   657         return rv;
   658     case nsIDataType::VTYPE_DOUBLE:
   659         // XXX should check for data loss here!
   660         *_retval = tempData.u.mDoubleValue;
   661         return rv;
   662     default:
   663         NS_ERROR("bad type returned from ToManageableNumber");
   664         return NS_ERROR_CANNOT_CONVERT_DATA;
   665     }
   666 }
   668 /* static */ nsresult
   669 nsVariant::ConvertToUint64(const nsDiscriminatedUnion& data, uint64_t *_retval)
   670 {
   671     return nsVariant::ConvertToInt64(data, (int64_t *)_retval);
   672 }
   674 /***************************************************************************/
   676 static bool String2ID(const nsDiscriminatedUnion& data, nsID* pid)
   677 {
   678     nsAutoString tempString;
   679     nsAString* pString;
   681     switch(data.mType)
   682     {
   683         case nsIDataType::VTYPE_CHAR_STR:
   684         case nsIDataType::VTYPE_STRING_SIZE_IS:
   685             return pid->Parse(data.u.str.mStringValue);
   686         case nsIDataType::VTYPE_CSTRING:
   687             return pid->Parse(PromiseFlatCString(*data.u.mCStringValue).get());
   688         case nsIDataType::VTYPE_UTF8STRING:
   689             return pid->Parse(PromiseFlatUTF8String(*data.u.mUTF8StringValue).get());
   690         case nsIDataType::VTYPE_ASTRING:
   691         case nsIDataType::VTYPE_DOMSTRING:
   692             pString = data.u.mAStringValue;
   693             break;
   694         case nsIDataType::VTYPE_WCHAR_STR:
   695         case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   696             tempString.Assign(data.u.wstr.mWStringValue);
   697             pString = &tempString;
   698             break;
   699         default:
   700             NS_ERROR("bad type in call to String2ID");
   701             return false;
   702     }
   704     char* pChars = ToNewCString(*pString);
   705     if(!pChars)
   706         return false;
   707     bool result = pid->Parse(pChars);
   708     nsMemory::Free(pChars);
   709     return result;
   710 }
   712 /* static */ nsresult
   713 nsVariant::ConvertToID(const nsDiscriminatedUnion& data, nsID * _retval)
   714 {
   715     nsID id;
   717     switch(data.mType)
   718     {
   719     case nsIDataType::VTYPE_ID:
   720         *_retval = data.u.mIDValue;
   721         return NS_OK;
   722     case nsIDataType::VTYPE_INTERFACE:
   723         *_retval = NS_GET_IID(nsISupports);
   724         return NS_OK;
   725     case nsIDataType::VTYPE_INTERFACE_IS:
   726         *_retval = data.u.iface.mInterfaceID;
   727         return NS_OK;
   728     case nsIDataType::VTYPE_ASTRING:
   729     case nsIDataType::VTYPE_DOMSTRING:
   730     case nsIDataType::VTYPE_UTF8STRING:
   731     case nsIDataType::VTYPE_CSTRING:
   732     case nsIDataType::VTYPE_CHAR_STR:
   733     case nsIDataType::VTYPE_WCHAR_STR:
   734     case nsIDataType::VTYPE_STRING_SIZE_IS:
   735     case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   736         if(!String2ID(data, &id))
   737             return NS_ERROR_CANNOT_CONVERT_DATA;
   738         *_retval = id;
   739         return NS_OK;
   740     default:
   741         return NS_ERROR_CANNOT_CONVERT_DATA;
   742     }
   743 }
   745 /***************************************************************************/
   747 static nsresult ToString(const nsDiscriminatedUnion& data,
   748                          nsACString & outString)
   749 {
   750     char* ptr;
   752     switch(data.mType)
   753     {
   754     // all the stuff we don't handle...
   755     case nsIDataType::VTYPE_ASTRING:
   756     case nsIDataType::VTYPE_DOMSTRING:
   757     case nsIDataType::VTYPE_UTF8STRING:
   758     case nsIDataType::VTYPE_CSTRING:
   759     case nsIDataType::VTYPE_CHAR_STR:
   760     case nsIDataType::VTYPE_WCHAR_STR:
   761     case nsIDataType::VTYPE_STRING_SIZE_IS:
   762     case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   763     case nsIDataType::VTYPE_WCHAR:
   764         NS_ERROR("ToString being called for a string type - screwy logic!");
   765         // fall through...
   767     // XXX We might want stringified versions of these... ???
   769     case nsIDataType::VTYPE_VOID:
   770     case nsIDataType::VTYPE_EMPTY:
   771         outString.Truncate();
   772         outString.SetIsVoid(true);
   773         return NS_OK;
   775     case nsIDataType::VTYPE_EMPTY_ARRAY:
   776     case nsIDataType::VTYPE_ARRAY:
   777     case nsIDataType::VTYPE_INTERFACE:
   778     case nsIDataType::VTYPE_INTERFACE_IS:
   779     default:
   780         return NS_ERROR_CANNOT_CONVERT_DATA;
   782     // nsID has its own text formatter.
   784     case nsIDataType::VTYPE_ID:
   785         ptr = data.u.mIDValue.ToString();
   786         if(!ptr)
   787             return NS_ERROR_OUT_OF_MEMORY;
   788         outString.Assign(ptr);
   789         nsMemory::Free(ptr);
   790         return NS_OK;
   792     // Can't use PR_smprintf for floats, since it's locale-dependent
   793 #define CASE__APPENDFLOAT_NUMBER(type_, member_)                        \
   794     case nsIDataType :: type_ :                                         \
   795     {                                                                   \
   796         nsAutoCString str;                                              \
   797         str.AppendFloat(data.u. member_);                               \
   798         outString.Assign(str);                                          \
   799         return NS_OK;                                                   \
   800     }
   802     CASE__APPENDFLOAT_NUMBER(VTYPE_FLOAT,  mFloatValue)
   803     CASE__APPENDFLOAT_NUMBER(VTYPE_DOUBLE, mDoubleValue)
   805 #undef CASE__APPENDFLOAT_NUMBER
   807     // the rest can be PR_smprintf'd and use common code.
   809 #define CASE__SMPRINTF_NUMBER(type_, format_, cast_, member_)                 \
   810     case nsIDataType :: type_ :                                               \
   811         ptr = PR_smprintf( format_ , (cast_) data.u. member_ );               \
   812         break;
   814     CASE__SMPRINTF_NUMBER(VTYPE_INT8,   "%d",   int,      mInt8Value)
   815     CASE__SMPRINTF_NUMBER(VTYPE_INT16,  "%d",   int,      mInt16Value)
   816     CASE__SMPRINTF_NUMBER(VTYPE_INT32,  "%d",   int,      mInt32Value)
   817     CASE__SMPRINTF_NUMBER(VTYPE_INT64,  "%lld", int64_t,  mInt64Value)
   819     CASE__SMPRINTF_NUMBER(VTYPE_UINT8,  "%u",   unsigned, mUint8Value)
   820     CASE__SMPRINTF_NUMBER(VTYPE_UINT16, "%u",   unsigned, mUint16Value)
   821     CASE__SMPRINTF_NUMBER(VTYPE_UINT32, "%u",   unsigned, mUint32Value)
   822     CASE__SMPRINTF_NUMBER(VTYPE_UINT64, "%llu", int64_t,  mUint64Value)
   824     // XXX Would we rather print "true" / "false" ?
   825     CASE__SMPRINTF_NUMBER(VTYPE_BOOL,   "%d",   int,      mBoolValue)
   827     CASE__SMPRINTF_NUMBER(VTYPE_CHAR,   "%c",   char,     mCharValue)
   829 #undef CASE__SMPRINTF_NUMBER
   830     }
   832     if(!ptr)
   833         return NS_ERROR_OUT_OF_MEMORY;
   834     outString.Assign(ptr);
   835     PR_smprintf_free(ptr);
   836     return NS_OK;
   837 }
   839 /* static */ nsresult
   840 nsVariant::ConvertToAString(const nsDiscriminatedUnion& data,
   841                             nsAString & _retval)
   842 {
   843     switch(data.mType)
   844     {
   845     case nsIDataType::VTYPE_ASTRING:
   846     case nsIDataType::VTYPE_DOMSTRING:
   847         _retval.Assign(*data.u.mAStringValue);
   848         return NS_OK;
   849     case nsIDataType::VTYPE_CSTRING:
   850         CopyASCIItoUTF16(*data.u.mCStringValue, _retval);
   851         return NS_OK;
   852     case nsIDataType::VTYPE_UTF8STRING:
   853         CopyUTF8toUTF16(*data.u.mUTF8StringValue, _retval);
   854         return NS_OK;
   855     case nsIDataType::VTYPE_CHAR_STR:
   856         CopyASCIItoUTF16(data.u.str.mStringValue, _retval);
   857         return NS_OK;
   858     case nsIDataType::VTYPE_WCHAR_STR:
   859         _retval.Assign(data.u.wstr.mWStringValue);
   860         return NS_OK;
   861     case nsIDataType::VTYPE_STRING_SIZE_IS:
   862         CopyASCIItoUTF16(nsDependentCString(data.u.str.mStringValue,
   863                                            data.u.str.mStringLength),
   864                         _retval);
   865         return NS_OK;
   866     case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   867         _retval.Assign(data.u.wstr.mWStringValue, data.u.wstr.mWStringLength);
   868         return NS_OK;
   869     case nsIDataType::VTYPE_WCHAR:
   870         _retval.Assign(data.u.mWCharValue);
   871         return NS_OK;
   872     default:
   873     {
   874         nsAutoCString tempCString;
   875         nsresult rv = ToString(data, tempCString);
   876         if(NS_FAILED(rv))
   877             return rv;
   878         CopyASCIItoUTF16(tempCString, _retval);
   879         return NS_OK;
   880     }
   881     }
   882 }
   884 /* static */ nsresult
   885 nsVariant::ConvertToACString(const nsDiscriminatedUnion& data,
   886                              nsACString & _retval)
   887 {
   888     switch(data.mType)
   889     {
   890     case nsIDataType::VTYPE_ASTRING:
   891     case nsIDataType::VTYPE_DOMSTRING:
   892         LossyCopyUTF16toASCII(*data.u.mAStringValue, _retval);
   893         return NS_OK;
   894     case nsIDataType::VTYPE_CSTRING:
   895         _retval.Assign(*data.u.mCStringValue);
   896         return NS_OK;
   897     case nsIDataType::VTYPE_UTF8STRING:
   898         // XXX This is an extra copy that should be avoided
   899         // once Jag lands support for UTF8String and associated
   900         // conversion methods.
   901         LossyCopyUTF16toASCII(NS_ConvertUTF8toUTF16(*data.u.mUTF8StringValue),
   902                         _retval);
   903         return NS_OK;
   904     case nsIDataType::VTYPE_CHAR_STR:
   905         _retval.Assign(*data.u.str.mStringValue);
   906         return NS_OK;
   907     case nsIDataType::VTYPE_WCHAR_STR:
   908         LossyCopyUTF16toASCII(nsDependentString(data.u.wstr.mWStringValue),
   909                         _retval);
   910         return NS_OK;
   911     case nsIDataType::VTYPE_STRING_SIZE_IS:
   912         _retval.Assign(data.u.str.mStringValue, data.u.str.mStringLength);
   913         return NS_OK;
   914     case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   915         LossyCopyUTF16toASCII(nsDependentString(data.u.wstr.mWStringValue,
   916                         data.u.wstr.mWStringLength), _retval);
   917         return NS_OK;
   918     case nsIDataType::VTYPE_WCHAR:
   919     {
   920         const char16_t* str = &data.u.mWCharValue;
   921         LossyCopyUTF16toASCII(Substring(str, 1), _retval);
   922         return NS_OK;
   923     }
   924     default:
   925         return ToString(data, _retval);
   926     }
   927 }
   929 /* static */ nsresult
   930 nsVariant::ConvertToAUTF8String(const nsDiscriminatedUnion& data,
   931                                 nsAUTF8String & _retval)
   932 {
   933     switch(data.mType)
   934     {
   935     case nsIDataType::VTYPE_ASTRING:
   936     case nsIDataType::VTYPE_DOMSTRING:
   937         CopyUTF16toUTF8(*data.u.mAStringValue, _retval);
   938         return NS_OK;
   939     case nsIDataType::VTYPE_CSTRING:
   940         // XXX Extra copy, can be removed if we're sure CSTRING can
   941         //     only contain ASCII.
   942         CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(*data.u.mCStringValue),
   943                         _retval);
   944         return NS_OK;
   945     case nsIDataType::VTYPE_UTF8STRING:
   946         _retval.Assign(*data.u.mUTF8StringValue);
   947         return NS_OK;
   948     case nsIDataType::VTYPE_CHAR_STR:
   949         // XXX Extra copy, can be removed if we're sure CHAR_STR can
   950         //     only contain ASCII.
   951         CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(data.u.str.mStringValue),
   952                         _retval);
   953         return NS_OK;
   954     case nsIDataType::VTYPE_WCHAR_STR:
   955         CopyUTF16toUTF8(data.u.wstr.mWStringValue, _retval);
   956         return NS_OK;
   957     case nsIDataType::VTYPE_STRING_SIZE_IS:
   958         // XXX Extra copy, can be removed if we're sure CHAR_STR can
   959         //     only contain ASCII.
   960         CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(
   961             nsDependentCString(data.u.str.mStringValue,
   962                                data.u.str.mStringLength)), _retval);
   963         return NS_OK;
   964     case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   965         CopyUTF16toUTF8(nsDependentString(data.u.wstr.mWStringValue,
   966                                           data.u.wstr.mWStringLength),
   967                         _retval);
   968         return NS_OK;
   969     case nsIDataType::VTYPE_WCHAR:
   970     {
   971         const char16_t* str = &data.u.mWCharValue;
   972         CopyUTF16toUTF8(Substring(str, 1), _retval);
   973         return NS_OK;
   974     }
   975     default:
   976     {
   977         nsAutoCString tempCString;
   978         nsresult rv = ToString(data, tempCString);
   979         if(NS_FAILED(rv))
   980             return rv;
   981         // XXX Extra copy, can be removed if we're sure tempCString can
   982         //     only contain ASCII.
   983         CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(tempCString), _retval);
   984         return NS_OK;
   985     }
   986     }
   987 }
   989 /* static */ nsresult
   990 nsVariant::ConvertToString(const nsDiscriminatedUnion& data, char **_retval)
   991 {
   992     uint32_t ignored;
   993     return nsVariant::ConvertToStringWithSize(data, &ignored, _retval);
   994 }
   996 /* static */ nsresult
   997 nsVariant::ConvertToWString(const nsDiscriminatedUnion& data, char16_t **_retval)
   998 {
   999     uint32_t ignored;
  1000     return nsVariant::ConvertToWStringWithSize(data, &ignored, _retval);
  1003 /* static */ nsresult
  1004 nsVariant::ConvertToStringWithSize(const nsDiscriminatedUnion& data,
  1005                                    uint32_t *size, char **str)
  1007     nsAutoString  tempString;
  1008     nsAutoCString tempCString;
  1009     nsresult rv;
  1011     switch(data.mType)
  1013     case nsIDataType::VTYPE_ASTRING:
  1014     case nsIDataType::VTYPE_DOMSTRING:
  1015         *size = data.u.mAStringValue->Length();
  1016         *str = ToNewCString(*data.u.mAStringValue);
  1017         break;
  1018     case nsIDataType::VTYPE_CSTRING:
  1019         *size = data.u.mCStringValue->Length();
  1020         *str = ToNewCString(*data.u.mCStringValue);
  1021         break;
  1022     case nsIDataType::VTYPE_UTF8STRING:
  1024         // XXX This is doing 1 extra copy.  Need to fix this
  1025         // when Jag lands UTF8String
  1026         // we want:
  1027         // *size = *data.mUTF8StringValue->Length();
  1028         // *str = ToNewCString(*data.mUTF8StringValue);
  1029         // But this will have to do for now.
  1030         NS_ConvertUTF8toUTF16 tempString(*data.u.mUTF8StringValue);
  1031         *size = tempString.Length();
  1032         *str = ToNewCString(tempString);
  1033         break;
  1035     case nsIDataType::VTYPE_CHAR_STR:
  1037         nsDependentCString cString(data.u.str.mStringValue);
  1038         *size = cString.Length();
  1039         *str = ToNewCString(cString);
  1040         break;
  1042     case nsIDataType::VTYPE_WCHAR_STR:
  1044         nsDependentString string(data.u.wstr.mWStringValue);
  1045         *size = string.Length();
  1046         *str = ToNewCString(string);
  1047         break;
  1049     case nsIDataType::VTYPE_STRING_SIZE_IS:
  1051         nsDependentCString cString(data.u.str.mStringValue,
  1052                                    data.u.str.mStringLength);
  1053         *size = cString.Length();
  1054         *str = ToNewCString(cString);
  1055         break;
  1057     case nsIDataType::VTYPE_WSTRING_SIZE_IS:
  1059         nsDependentString string(data.u.wstr.mWStringValue,
  1060                                  data.u.wstr.mWStringLength);
  1061         *size = string.Length();
  1062         *str = ToNewCString(string);
  1063         break;
  1065     case nsIDataType::VTYPE_WCHAR:
  1066         tempString.Assign(data.u.mWCharValue);
  1067         *size = tempString.Length();
  1068         *str = ToNewCString(tempString);
  1069         break;
  1070     default:
  1071         rv = ToString(data, tempCString);
  1072         if(NS_FAILED(rv))
  1073             return rv;
  1074         *size = tempCString.Length();
  1075         *str = ToNewCString(tempCString);
  1076         break;
  1079     return *str ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
  1081 /* static */ nsresult
  1082 nsVariant::ConvertToWStringWithSize(const nsDiscriminatedUnion& data,
  1083                                     uint32_t *size, char16_t **str)
  1085     nsAutoString  tempString;
  1086     nsAutoCString tempCString;
  1087     nsresult rv;
  1089     switch(data.mType)
  1091     case nsIDataType::VTYPE_ASTRING:
  1092     case nsIDataType::VTYPE_DOMSTRING:
  1093         *size = data.u.mAStringValue->Length();
  1094         *str = ToNewUnicode(*data.u.mAStringValue);
  1095         break;
  1096     case nsIDataType::VTYPE_CSTRING:
  1097         *size = data.u.mCStringValue->Length();
  1098         *str = ToNewUnicode(*data.u.mCStringValue);
  1099         break;
  1100     case nsIDataType::VTYPE_UTF8STRING:
  1102         *str = UTF8ToNewUnicode(*data.u.mUTF8StringValue, size);
  1103         break;
  1105     case nsIDataType::VTYPE_CHAR_STR:
  1107         nsDependentCString cString(data.u.str.mStringValue);
  1108         *size = cString.Length();
  1109         *str = ToNewUnicode(cString);
  1110         break;
  1112     case nsIDataType::VTYPE_WCHAR_STR:
  1114         nsDependentString string(data.u.wstr.mWStringValue);
  1115         *size = string.Length();
  1116         *str = ToNewUnicode(string);
  1117         break;
  1119     case nsIDataType::VTYPE_STRING_SIZE_IS:
  1121         nsDependentCString cString(data.u.str.mStringValue,
  1122                                    data.u.str.mStringLength);
  1123         *size = cString.Length();
  1124         *str = ToNewUnicode(cString);
  1125         break;
  1127     case nsIDataType::VTYPE_WSTRING_SIZE_IS:
  1129         nsDependentString string(data.u.wstr.mWStringValue,
  1130                                  data.u.wstr.mWStringLength);
  1131         *size = string.Length();
  1132         *str = ToNewUnicode(string);
  1133         break;
  1135     case nsIDataType::VTYPE_WCHAR:
  1136         tempString.Assign(data.u.mWCharValue);
  1137         *size = tempString.Length();
  1138         *str = ToNewUnicode(tempString);
  1139         break;
  1140     default:
  1141         rv = ToString(data, tempCString);
  1142         if(NS_FAILED(rv))
  1143             return rv;
  1144         *size = tempCString.Length();
  1145         *str = ToNewUnicode(tempCString);
  1146         break;
  1149     return *str ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
  1152 /* static */ nsresult
  1153 nsVariant::ConvertToISupports(const nsDiscriminatedUnion& data,
  1154                               nsISupports **_retval)
  1156     switch(data.mType)
  1158     case nsIDataType::VTYPE_INTERFACE:
  1159     case nsIDataType::VTYPE_INTERFACE_IS:
  1160         if (data.u.iface.mInterfaceValue) {
  1161             return data.u.iface.mInterfaceValue->
  1162                 QueryInterface(NS_GET_IID(nsISupports), (void**)_retval);
  1163         } else {
  1164             *_retval = nullptr;
  1165             return NS_OK;
  1167     default:
  1168         return NS_ERROR_CANNOT_CONVERT_DATA;
  1172 /* static */ nsresult
  1173 nsVariant::ConvertToInterface(const nsDiscriminatedUnion& data, nsIID * *iid,
  1174                               void * *iface)
  1176     const nsIID* piid;
  1178     switch(data.mType)
  1180     case nsIDataType::VTYPE_INTERFACE:
  1181         piid = &NS_GET_IID(nsISupports);
  1182         break;
  1183     case nsIDataType::VTYPE_INTERFACE_IS:
  1184         piid = &data.u.iface.mInterfaceID;
  1185         break;
  1186     default:
  1187         return NS_ERROR_CANNOT_CONVERT_DATA;
  1190     *iid = (nsIID*) nsMemory::Clone(piid, sizeof(nsIID));
  1191     if(!*iid)
  1192         return NS_ERROR_OUT_OF_MEMORY;
  1194     if (data.u.iface.mInterfaceValue) {
  1195         return data.u.iface.mInterfaceValue->QueryInterface(*piid, iface);
  1198     *iface = nullptr;
  1199     return NS_OK;
  1202 /* static */ nsresult
  1203 nsVariant::ConvertToArray(const nsDiscriminatedUnion& data, uint16_t *type,
  1204                           nsIID* iid, uint32_t *count, void * *ptr)
  1206     // XXX perhaps we'd like to add support for converting each of the various
  1207     // types into an array containing one element of that type. We can leverage
  1208     // CloneArray to do this if we want to support this.
  1210     if(data.mType == nsIDataType::VTYPE_ARRAY)
  1211         return CloneArray(data.u.array.mArrayType, &data.u.array.mArrayInterfaceID,
  1212                           data.u.array.mArrayCount, data.u.array.mArrayValue,
  1213                           type, iid, count, ptr);
  1214     return NS_ERROR_CANNOT_CONVERT_DATA;
  1217 /***************************************************************************/
  1218 // static setter functions...
  1220 #define DATA_SETTER_PROLOGUE(data_)                                           \
  1221     nsVariant::Cleanup(data_);
  1223 #define DATA_SETTER_EPILOGUE(data_, type_)                                    \
  1224     data_->mType = nsIDataType :: type_;                                      \
  1225     return NS_OK;
  1227 #define DATA_SETTER(data_, type_, member_, value_)                            \
  1228     DATA_SETTER_PROLOGUE(data_)                                               \
  1229     data_->u.member_ = value_;                                                \
  1230     DATA_SETTER_EPILOGUE(data_, type_)
  1232 #define DATA_SETTER_WITH_CAST(data_, type_, member_, cast_, value_)           \
  1233     DATA_SETTER_PROLOGUE(data_)                                               \
  1234     data_->u.member_ = cast_ value_;                                          \
  1235     DATA_SETTER_EPILOGUE(data_, type_)
  1238 /********************************************/
  1240 #define CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_)                          \
  1241     {                                                                         \
  1243 #define CASE__SET_FROM_VARIANT_VTYPE__GETTER(member_, name_)                  \
  1244         rv = aValue->GetAs##name_ (&(data->u. member_ ));
  1246 #define CASE__SET_FROM_VARIANT_VTYPE__GETTER_CAST(cast_, member_, name_)      \
  1247         rv = aValue->GetAs##name_ ( cast_ &(data->u. member_ ));
  1249 #define CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)                          \
  1250         if(NS_SUCCEEDED(rv))                                                  \
  1251         {                                                                     \
  1252             data->mType  = nsIDataType :: type_ ;                             \
  1253         }                                                                     \
  1254         break;                                                                \
  1257 #define CASE__SET_FROM_VARIANT_TYPE(type_, member_, name_)                    \
  1258     case nsIDataType :: type_ :                                               \
  1259         CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_)                          \
  1260         CASE__SET_FROM_VARIANT_VTYPE__GETTER(member_, name_)                  \
  1261         CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)
  1263 #define CASE__SET_FROM_VARIANT_VTYPE_CAST(type_, cast_, member_, name_)       \
  1264     case nsIDataType :: type_ :                                               \
  1265         CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_)                          \
  1266         CASE__SET_FROM_VARIANT_VTYPE__GETTER_CAST(cast_, member_, name_)      \
  1267         CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)
  1270 /* static */ nsresult
  1271 nsVariant::SetFromVariant(nsDiscriminatedUnion* data, nsIVariant* aValue)
  1273     uint16_t type;
  1274     nsresult rv;
  1276     nsVariant::Cleanup(data);
  1278     rv = aValue->GetDataType(&type);
  1279     if(NS_FAILED(rv))
  1280         return rv;
  1282     switch(type)
  1284         CASE__SET_FROM_VARIANT_VTYPE_CAST(VTYPE_INT8, (uint8_t*), mInt8Value,
  1285                                           Int8)
  1286         CASE__SET_FROM_VARIANT_TYPE(VTYPE_INT16,  mInt16Value,  Int16)
  1287         CASE__SET_FROM_VARIANT_TYPE(VTYPE_INT32,  mInt32Value,  Int32)
  1288         CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT8,  mUint8Value,  Uint8)
  1289         CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT16, mUint16Value, Uint16)
  1290         CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT32, mUint32Value, Uint32)
  1291         CASE__SET_FROM_VARIANT_TYPE(VTYPE_FLOAT,  mFloatValue,  Float)
  1292         CASE__SET_FROM_VARIANT_TYPE(VTYPE_DOUBLE, mDoubleValue, Double)
  1293         CASE__SET_FROM_VARIANT_TYPE(VTYPE_BOOL ,  mBoolValue,   Bool)
  1294         CASE__SET_FROM_VARIANT_TYPE(VTYPE_CHAR,   mCharValue,   Char)
  1295         CASE__SET_FROM_VARIANT_TYPE(VTYPE_WCHAR,  mWCharValue,  WChar)
  1296         CASE__SET_FROM_VARIANT_TYPE(VTYPE_ID,     mIDValue,     ID)
  1298         case nsIDataType::VTYPE_ASTRING:
  1299         case nsIDataType::VTYPE_DOMSTRING:
  1300         case nsIDataType::VTYPE_WCHAR_STR:
  1301         case nsIDataType::VTYPE_WSTRING_SIZE_IS:
  1302             CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_ASTRING);
  1303             data->u.mAStringValue = new nsString();
  1304             if(!data->u.mAStringValue)
  1305                 return NS_ERROR_OUT_OF_MEMORY;
  1306             rv = aValue->GetAsAString(*data->u.mAStringValue);
  1307             if(NS_FAILED(rv))
  1308                 delete data->u.mAStringValue;
  1309             CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_ASTRING)
  1311         case nsIDataType::VTYPE_CSTRING:
  1312             CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_CSTRING);
  1313             data->u.mCStringValue = new nsCString();
  1314             if(!data->u.mCStringValue)
  1315                 return NS_ERROR_OUT_OF_MEMORY;
  1316             rv = aValue->GetAsACString(*data->u.mCStringValue);
  1317             if(NS_FAILED(rv))
  1318                 delete data->u.mCStringValue;
  1319             CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_CSTRING)
  1321         case nsIDataType::VTYPE_UTF8STRING:
  1322             CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_UTF8STRING);
  1323             data->u.mUTF8StringValue = new nsUTF8String();
  1324             if(!data->u.mUTF8StringValue)
  1325                 return NS_ERROR_OUT_OF_MEMORY;
  1326             rv = aValue->GetAsAUTF8String(*data->u.mUTF8StringValue);
  1327             if(NS_FAILED(rv))
  1328                 delete data->u.mUTF8StringValue;
  1329             CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_UTF8STRING)
  1331         case nsIDataType::VTYPE_CHAR_STR:
  1332         case nsIDataType::VTYPE_STRING_SIZE_IS:
  1333             CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_STRING_SIZE_IS);
  1334             rv = aValue->GetAsStringWithSize(&data->u.str.mStringLength,
  1335                                              &data->u.str.mStringValue);
  1336             CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_STRING_SIZE_IS)
  1338         case nsIDataType::VTYPE_INTERFACE:
  1339         case nsIDataType::VTYPE_INTERFACE_IS:
  1340             CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_INTERFACE_IS);
  1341             // XXX This iid handling is ugly!
  1342             nsIID* iid;
  1343             rv = aValue->GetAsInterface(&iid, (void**)&data->u.iface.mInterfaceValue);
  1344             if(NS_SUCCEEDED(rv))
  1346                 data->u.iface.mInterfaceID = *iid;
  1347                 nsMemory::Free((char*)iid);
  1349             CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_INTERFACE_IS)
  1351         case nsIDataType::VTYPE_ARRAY:
  1352             CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_ARRAY);
  1353             rv = aValue->GetAsArray(&data->u.array.mArrayType,
  1354                                     &data->u.array.mArrayInterfaceID,
  1355                                     &data->u.array.mArrayCount,
  1356                                     &data->u.array.mArrayValue);
  1357             CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_ARRAY)
  1359         case nsIDataType::VTYPE_VOID:
  1360             rv = nsVariant::SetToVoid(data);
  1361             break;
  1362         case nsIDataType::VTYPE_EMPTY_ARRAY:
  1363             rv = nsVariant::SetToEmptyArray(data);
  1364             break;
  1365         case nsIDataType::VTYPE_EMPTY:
  1366             rv = nsVariant::SetToEmpty(data);
  1367             break;
  1368         default:
  1369             NS_ERROR("bad type in variant!");
  1370             rv = NS_ERROR_FAILURE;
  1371             break;
  1373     return rv;
  1376 /* static */ nsresult
  1377 nsVariant::SetFromInt8(nsDiscriminatedUnion* data, uint8_t aValue)
  1379     DATA_SETTER_WITH_CAST(data, VTYPE_INT8, mInt8Value, (uint8_t), aValue)
  1381 /* static */ nsresult
  1382 nsVariant::SetFromInt16(nsDiscriminatedUnion* data, int16_t aValue)
  1384     DATA_SETTER(data, VTYPE_INT16, mInt16Value, aValue)
  1386 /* static */ nsresult
  1387 nsVariant::SetFromInt32(nsDiscriminatedUnion* data, int32_t aValue)
  1389     DATA_SETTER(data, VTYPE_INT32, mInt32Value, aValue)
  1391 /* static */ nsresult
  1392 nsVariant::SetFromInt64(nsDiscriminatedUnion* data, int64_t aValue)
  1394     DATA_SETTER(data, VTYPE_INT64, mInt64Value, aValue)
  1396 /* static */ nsresult
  1397 nsVariant::SetFromUint8(nsDiscriminatedUnion* data, uint8_t aValue)
  1399     DATA_SETTER(data, VTYPE_UINT8, mUint8Value, aValue)
  1401 /* static */ nsresult
  1402 nsVariant::SetFromUint16(nsDiscriminatedUnion* data, uint16_t aValue)
  1404     DATA_SETTER(data, VTYPE_UINT16, mUint16Value, aValue)
  1406 /* static */ nsresult
  1407 nsVariant::SetFromUint32(nsDiscriminatedUnion* data, uint32_t aValue)
  1409     DATA_SETTER(data, VTYPE_UINT32, mUint32Value, aValue)
  1411 /* static */ nsresult
  1412 nsVariant::SetFromUint64(nsDiscriminatedUnion* data, uint64_t aValue)
  1414     DATA_SETTER(data, VTYPE_UINT64, mUint64Value, aValue)
  1416 /* static */ nsresult
  1417 nsVariant::SetFromFloat(nsDiscriminatedUnion* data, float aValue)
  1419     DATA_SETTER(data, VTYPE_FLOAT, mFloatValue, aValue)
  1421 /* static */ nsresult
  1422 nsVariant::SetFromDouble(nsDiscriminatedUnion* data, double aValue)
  1424     DATA_SETTER(data, VTYPE_DOUBLE, mDoubleValue, aValue)
  1426 /* static */ nsresult
  1427 nsVariant::SetFromBool(nsDiscriminatedUnion* data, bool aValue)
  1429     DATA_SETTER(data, VTYPE_BOOL, mBoolValue, aValue)
  1431 /* static */ nsresult
  1432 nsVariant::SetFromChar(nsDiscriminatedUnion* data, char aValue)
  1434     DATA_SETTER(data, VTYPE_CHAR, mCharValue, aValue)
  1436 /* static */ nsresult
  1437 nsVariant::SetFromWChar(nsDiscriminatedUnion* data, char16_t aValue)
  1439     DATA_SETTER(data, VTYPE_WCHAR, mWCharValue, aValue)
  1441 /* static */ nsresult
  1442 nsVariant::SetFromID(nsDiscriminatedUnion* data, const nsID & aValue)
  1444     DATA_SETTER(data, VTYPE_ID, mIDValue, aValue)
  1446 /* static */ nsresult
  1447 nsVariant::SetFromAString(nsDiscriminatedUnion* data, const nsAString & aValue)
  1449     DATA_SETTER_PROLOGUE(data);
  1450     if(!(data->u.mAStringValue = new nsString(aValue)))
  1451         return NS_ERROR_OUT_OF_MEMORY;
  1452     DATA_SETTER_EPILOGUE(data, VTYPE_ASTRING);
  1455 /* static */ nsresult
  1456 nsVariant::SetFromACString(nsDiscriminatedUnion* data,
  1457                            const nsACString & aValue)
  1459     DATA_SETTER_PROLOGUE(data);
  1460     if(!(data->u.mCStringValue = new nsCString(aValue)))
  1461         return NS_ERROR_OUT_OF_MEMORY;
  1462     DATA_SETTER_EPILOGUE(data, VTYPE_CSTRING);
  1465 /* static */ nsresult
  1466 nsVariant::SetFromAUTF8String(nsDiscriminatedUnion* data,
  1467                               const nsAUTF8String & aValue)
  1469     DATA_SETTER_PROLOGUE(data);
  1470     if(!(data->u.mUTF8StringValue = new nsUTF8String(aValue)))
  1471         return NS_ERROR_OUT_OF_MEMORY;
  1472     DATA_SETTER_EPILOGUE(data, VTYPE_UTF8STRING);
  1475 /* static */ nsresult
  1476 nsVariant::SetFromString(nsDiscriminatedUnion* data, const char *aValue)
  1478     DATA_SETTER_PROLOGUE(data);
  1479     if(!aValue)
  1480         return NS_ERROR_NULL_POINTER;
  1481     return SetFromStringWithSize(data, strlen(aValue), aValue);
  1483 /* static */ nsresult
  1484 nsVariant::SetFromWString(nsDiscriminatedUnion* data, const char16_t *aValue)
  1486     DATA_SETTER_PROLOGUE(data);
  1487     if(!aValue)
  1488         return NS_ERROR_NULL_POINTER;
  1489     return SetFromWStringWithSize(data, NS_strlen(aValue), aValue);
  1491 /* static */ nsresult
  1492 nsVariant::SetFromISupports(nsDiscriminatedUnion* data, nsISupports *aValue)
  1494     return SetFromInterface(data, NS_GET_IID(nsISupports), aValue);
  1496 /* static */ nsresult
  1497 nsVariant::SetFromInterface(nsDiscriminatedUnion* data, const nsIID& iid,
  1498                             nsISupports *aValue)
  1500     DATA_SETTER_PROLOGUE(data);
  1501     NS_IF_ADDREF(aValue);
  1502     data->u.iface.mInterfaceValue = aValue;
  1503     data->u.iface.mInterfaceID = iid;
  1504     DATA_SETTER_EPILOGUE(data, VTYPE_INTERFACE_IS);
  1506 /* static */ nsresult
  1507 nsVariant::SetFromArray(nsDiscriminatedUnion* data, uint16_t type,
  1508                         const nsIID* iid, uint32_t count, void * aValue)
  1510     DATA_SETTER_PROLOGUE(data);
  1511     if(!aValue || !count)
  1512         return NS_ERROR_NULL_POINTER;
  1514     nsresult rv = CloneArray(type, iid, count, aValue,
  1515                              &data->u.array.mArrayType,
  1516                              &data->u.array.mArrayInterfaceID,
  1517                              &data->u.array.mArrayCount,
  1518                              &data->u.array.mArrayValue);
  1519     if(NS_FAILED(rv))
  1520         return rv;
  1521     DATA_SETTER_EPILOGUE(data, VTYPE_ARRAY);
  1523 /* static */ nsresult
  1524 nsVariant::SetFromStringWithSize(nsDiscriminatedUnion* data, uint32_t size, const char *aValue)
  1526     DATA_SETTER_PROLOGUE(data);
  1527     if(!aValue)
  1528         return NS_ERROR_NULL_POINTER;
  1529     if(!(data->u.str.mStringValue =
  1530          (char*) nsMemory::Clone(aValue, (size+1)*sizeof(char))))
  1531         return NS_ERROR_OUT_OF_MEMORY;
  1532     data->u.str.mStringLength = size;
  1533     DATA_SETTER_EPILOGUE(data, VTYPE_STRING_SIZE_IS);
  1535 /* static */ nsresult
  1536 nsVariant::SetFromWStringWithSize(nsDiscriminatedUnion* data, uint32_t size, const char16_t *aValue)
  1538     DATA_SETTER_PROLOGUE(data);
  1539     if(!aValue)
  1540         return NS_ERROR_NULL_POINTER;
  1541     if(!(data->u.wstr.mWStringValue =
  1542          (char16_t*) nsMemory::Clone(aValue, (size+1)*sizeof(char16_t))))
  1543         return NS_ERROR_OUT_OF_MEMORY;
  1544     data->u.wstr.mWStringLength = size;
  1545     DATA_SETTER_EPILOGUE(data, VTYPE_WSTRING_SIZE_IS);
  1547 /* static */ nsresult
  1548 nsVariant::SetToVoid(nsDiscriminatedUnion* data)
  1550     DATA_SETTER_PROLOGUE(data);
  1551     DATA_SETTER_EPILOGUE(data, VTYPE_VOID);
  1553 /* static */ nsresult
  1554 nsVariant::SetToEmpty(nsDiscriminatedUnion* data)
  1556     DATA_SETTER_PROLOGUE(data);
  1557     DATA_SETTER_EPILOGUE(data, VTYPE_EMPTY);
  1559 /* static */ nsresult
  1560 nsVariant::SetToEmptyArray(nsDiscriminatedUnion* data)
  1562     DATA_SETTER_PROLOGUE(data);
  1563     DATA_SETTER_EPILOGUE(data, VTYPE_EMPTY_ARRAY);
  1566 /***************************************************************************/
  1568 /* static */ nsresult
  1569 nsVariant::Initialize(nsDiscriminatedUnion* data)
  1571     data->mType = nsIDataType::VTYPE_EMPTY;
  1572     return NS_OK;
  1575 /* static */ nsresult
  1576 nsVariant::Cleanup(nsDiscriminatedUnion* data)
  1578     switch(data->mType)
  1580         case nsIDataType::VTYPE_INT8:
  1581         case nsIDataType::VTYPE_INT16:
  1582         case nsIDataType::VTYPE_INT32:
  1583         case nsIDataType::VTYPE_INT64:
  1584         case nsIDataType::VTYPE_UINT8:
  1585         case nsIDataType::VTYPE_UINT16:
  1586         case nsIDataType::VTYPE_UINT32:
  1587         case nsIDataType::VTYPE_UINT64:
  1588         case nsIDataType::VTYPE_FLOAT:
  1589         case nsIDataType::VTYPE_DOUBLE:
  1590         case nsIDataType::VTYPE_BOOL:
  1591         case nsIDataType::VTYPE_CHAR:
  1592         case nsIDataType::VTYPE_WCHAR:
  1593         case nsIDataType::VTYPE_VOID:
  1594         case nsIDataType::VTYPE_ID:
  1595             break;
  1596         case nsIDataType::VTYPE_ASTRING:
  1597         case nsIDataType::VTYPE_DOMSTRING:
  1598             delete data->u.mAStringValue;
  1599             break;
  1600         case nsIDataType::VTYPE_CSTRING:
  1601             delete data->u.mCStringValue;
  1602             break;
  1603         case nsIDataType::VTYPE_UTF8STRING:
  1604             delete data->u.mUTF8StringValue;
  1605             break;
  1606         case nsIDataType::VTYPE_CHAR_STR:
  1607         case nsIDataType::VTYPE_STRING_SIZE_IS:
  1608             nsMemory::Free((char*)data->u.str.mStringValue);
  1609             break;
  1610         case nsIDataType::VTYPE_WCHAR_STR:
  1611         case nsIDataType::VTYPE_WSTRING_SIZE_IS:
  1612             nsMemory::Free((char*)data->u.wstr.mWStringValue);
  1613             break;
  1614         case nsIDataType::VTYPE_INTERFACE:
  1615         case nsIDataType::VTYPE_INTERFACE_IS:
  1616             NS_IF_RELEASE(data->u.iface.mInterfaceValue);
  1617             break;
  1618         case nsIDataType::VTYPE_ARRAY:
  1619             FreeArray(data);
  1620             break;
  1621         case nsIDataType::VTYPE_EMPTY_ARRAY:
  1622         case nsIDataType::VTYPE_EMPTY:
  1623             break;
  1624         default:
  1625             NS_ERROR("bad type in variant!");
  1626             break;
  1629     data->mType = nsIDataType::VTYPE_EMPTY;
  1630     return NS_OK;
  1633 /* static */ void
  1634 nsVariant::Traverse(const nsDiscriminatedUnion& data,
  1635                     nsCycleCollectionTraversalCallback &cb)
  1637     switch(data.mType)
  1639         case nsIDataType::VTYPE_INTERFACE:
  1640         case nsIDataType::VTYPE_INTERFACE_IS:
  1641             NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mData");
  1642             cb.NoteXPCOMChild(data.u.iface.mInterfaceValue);
  1643             break;
  1644         case nsIDataType::VTYPE_ARRAY:
  1645             switch(data.u.array.mArrayType) {
  1646                 case nsIDataType::VTYPE_INTERFACE:
  1647                 case nsIDataType::VTYPE_INTERFACE_IS:
  1649                     nsISupports** p = (nsISupports**) data.u.array.mArrayValue;
  1650                     for(uint32_t i = data.u.array.mArrayCount; i > 0; p++, i--) {
  1651                         NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mData[i]");
  1652                         cb.NoteXPCOMChild(*p);
  1655                 default:
  1656                     break;
  1658         default:
  1659             break;
  1663 /***************************************************************************/
  1664 /***************************************************************************/
  1665 // members...
  1667 NS_IMPL_ISUPPORTS(nsVariant, nsIVariant, nsIWritableVariant)
  1669 nsVariant::nsVariant()
  1670     : mWritable(true)
  1672     nsVariant::Initialize(&mData);
  1674 #ifdef DEBUG
  1676         // Assert that the nsIDataType consts match the values #defined in
  1677         // xpt_struct.h. Bad things happen somewhere if they don't.
  1678         struct THE_TYPES {uint16_t a; uint16_t b;};
  1679         static const THE_TYPES array[] = {
  1680             {nsIDataType::VTYPE_INT8              , TD_INT8             },
  1681             {nsIDataType::VTYPE_INT16             , TD_INT16            },
  1682             {nsIDataType::VTYPE_INT32             , TD_INT32            },
  1683             {nsIDataType::VTYPE_INT64             , TD_INT64            },
  1684             {nsIDataType::VTYPE_UINT8             , TD_UINT8            },
  1685             {nsIDataType::VTYPE_UINT16            , TD_UINT16           },
  1686             {nsIDataType::VTYPE_UINT32            , TD_UINT32           },
  1687             {nsIDataType::VTYPE_UINT64            , TD_UINT64           },
  1688             {nsIDataType::VTYPE_FLOAT             , TD_FLOAT            },
  1689             {nsIDataType::VTYPE_DOUBLE            , TD_DOUBLE           },
  1690             {nsIDataType::VTYPE_BOOL              , TD_BOOL             },
  1691             {nsIDataType::VTYPE_CHAR              , TD_CHAR             },
  1692             {nsIDataType::VTYPE_WCHAR             , TD_WCHAR            },
  1693             {nsIDataType::VTYPE_VOID              , TD_VOID             },
  1694             {nsIDataType::VTYPE_ID                , TD_PNSIID           },
  1695             {nsIDataType::VTYPE_DOMSTRING         , TD_DOMSTRING        },
  1696             {nsIDataType::VTYPE_CHAR_STR          , TD_PSTRING          },
  1697             {nsIDataType::VTYPE_WCHAR_STR         , TD_PWSTRING         },
  1698             {nsIDataType::VTYPE_INTERFACE         , TD_INTERFACE_TYPE   },
  1699             {nsIDataType::VTYPE_INTERFACE_IS      , TD_INTERFACE_IS_TYPE},
  1700             {nsIDataType::VTYPE_ARRAY             , TD_ARRAY            },
  1701             {nsIDataType::VTYPE_STRING_SIZE_IS    , TD_PSTRING_SIZE_IS  },
  1702             {nsIDataType::VTYPE_WSTRING_SIZE_IS   , TD_PWSTRING_SIZE_IS },
  1703             {nsIDataType::VTYPE_UTF8STRING        , TD_UTF8STRING       },
  1704             {nsIDataType::VTYPE_CSTRING           , TD_CSTRING          },
  1705             {nsIDataType::VTYPE_ASTRING           , TD_ASTRING          }
  1706         };
  1707         static const int length = sizeof(array)/sizeof(array[0]);
  1708         static bool inited = false;
  1709         if(!inited)
  1711             for(int i = 0; i < length; i++)
  1712                 NS_ASSERTION(array[i].a == array[i].b, "bad const declaration");
  1713             inited = true;
  1716 #endif
  1719 nsVariant::~nsVariant()
  1721     nsVariant::Cleanup(&mData);
  1724 // For all the data getters we just forward to the static (and sharable)
  1725 // 'ConvertTo' functions.
  1727 /* readonly attribute uint16_t dataType; */
  1728 NS_IMETHODIMP nsVariant::GetDataType(uint16_t *aDataType)
  1730     *aDataType = mData.mType;
  1731     return NS_OK;
  1734 /* uint8_t getAsInt8 (); */
  1735 NS_IMETHODIMP nsVariant::GetAsInt8(uint8_t *_retval)
  1737     return nsVariant::ConvertToInt8(mData, _retval);
  1740 /* int16_t getAsInt16 (); */
  1741 NS_IMETHODIMP nsVariant::GetAsInt16(int16_t *_retval)
  1743     return nsVariant::ConvertToInt16(mData, _retval);
  1746 /* int32_t getAsInt32 (); */
  1747 NS_IMETHODIMP nsVariant::GetAsInt32(int32_t *_retval)
  1749     return nsVariant::ConvertToInt32(mData, _retval);
  1752 /* int64_t getAsInt64 (); */
  1753 NS_IMETHODIMP nsVariant::GetAsInt64(int64_t *_retval)
  1755     return nsVariant::ConvertToInt64(mData, _retval);
  1758 /* uint8_t getAsUint8 (); */
  1759 NS_IMETHODIMP nsVariant::GetAsUint8(uint8_t *_retval)
  1761     return nsVariant::ConvertToUint8(mData, _retval);
  1764 /* uint16_t getAsUint16 (); */
  1765 NS_IMETHODIMP nsVariant::GetAsUint16(uint16_t *_retval)
  1767     return nsVariant::ConvertToUint16(mData, _retval);
  1770 /* uint32_t getAsUint32 (); */
  1771 NS_IMETHODIMP nsVariant::GetAsUint32(uint32_t *_retval)
  1773     return nsVariant::ConvertToUint32(mData, _retval);
  1776 /* uint64_t getAsUint64 (); */
  1777 NS_IMETHODIMP nsVariant::GetAsUint64(uint64_t *_retval)
  1779     return nsVariant::ConvertToUint64(mData, _retval);
  1782 /* float getAsFloat (); */
  1783 NS_IMETHODIMP nsVariant::GetAsFloat(float *_retval)
  1785     return nsVariant::ConvertToFloat(mData, _retval);
  1788 /* double getAsDouble (); */
  1789 NS_IMETHODIMP nsVariant::GetAsDouble(double *_retval)
  1791     return nsVariant::ConvertToDouble(mData, _retval);
  1794 /* bool getAsBool (); */
  1795 NS_IMETHODIMP nsVariant::GetAsBool(bool *_retval)
  1797     return nsVariant::ConvertToBool(mData, _retval);
  1800 /* char getAsChar (); */
  1801 NS_IMETHODIMP nsVariant::GetAsChar(char *_retval)
  1803     return nsVariant::ConvertToChar(mData, _retval);
  1806 /* wchar getAsWChar (); */
  1807 NS_IMETHODIMP nsVariant::GetAsWChar(char16_t *_retval)
  1809     return nsVariant::ConvertToWChar(mData, _retval);
  1812 /* [notxpcom] nsresult getAsID (out nsID retval); */
  1813 NS_IMETHODIMP_(nsresult) nsVariant::GetAsID(nsID *retval)
  1815     return nsVariant::ConvertToID(mData, retval);
  1818 /* AString getAsAString (); */
  1819 NS_IMETHODIMP nsVariant::GetAsAString(nsAString & _retval)
  1821     return nsVariant::ConvertToAString(mData, _retval);
  1824 /* DOMString getAsDOMString (); */
  1825 NS_IMETHODIMP nsVariant::GetAsDOMString(nsAString & _retval)
  1827     // A DOMString maps to an AString internally, so we can re-use
  1828     // ConvertToAString here.
  1829     return nsVariant::ConvertToAString(mData, _retval);
  1832 /* ACString getAsACString (); */
  1833 NS_IMETHODIMP nsVariant::GetAsACString(nsACString & _retval)
  1835     return nsVariant::ConvertToACString(mData, _retval);
  1838 /* AUTF8String getAsAUTF8String (); */
  1839 NS_IMETHODIMP nsVariant::GetAsAUTF8String(nsAUTF8String & _retval)
  1841     return nsVariant::ConvertToAUTF8String(mData, _retval);
  1844 /* string getAsString (); */
  1845 NS_IMETHODIMP nsVariant::GetAsString(char **_retval)
  1847     return nsVariant::ConvertToString(mData, _retval);
  1850 /* wstring getAsWString (); */
  1851 NS_IMETHODIMP nsVariant::GetAsWString(char16_t **_retval)
  1853     return nsVariant::ConvertToWString(mData, _retval);
  1856 /* nsISupports getAsISupports (); */
  1857 NS_IMETHODIMP nsVariant::GetAsISupports(nsISupports **_retval)
  1859     return nsVariant::ConvertToISupports(mData, _retval);
  1862 /* jsval getAsJSVal() */
  1863 NS_IMETHODIMP nsVariant::GetAsJSVal(JS::MutableHandleValue)
  1865     // Can only get the jsval from an XPCVariant.
  1866     return NS_ERROR_CANNOT_CONVERT_DATA;
  1869 /* void getAsInterface (out nsIIDPtr iid, [iid_is (iid), retval] out nsQIResult iface); */
  1870 NS_IMETHODIMP nsVariant::GetAsInterface(nsIID * *iid, void * *iface)
  1872     return nsVariant::ConvertToInterface(mData, iid, iface);
  1875 /* [notxpcom] nsresult getAsArray (out uint16_t type, out nsIID iid, out uint32_t count, out voidPtr ptr); */
  1876 NS_IMETHODIMP_(nsresult) nsVariant::GetAsArray(uint16_t *type, nsIID *iid, uint32_t *count, void * *ptr)
  1878     return nsVariant::ConvertToArray(mData, type, iid, count, ptr);
  1881 /* void getAsStringWithSize (out uint32_t size, [size_is (size), retval] out string str); */
  1882 NS_IMETHODIMP nsVariant::GetAsStringWithSize(uint32_t *size, char **str)
  1884     return nsVariant::ConvertToStringWithSize(mData, size, str);
  1887 /* void getAsWStringWithSize (out uint32_t size, [size_is (size), retval] out wstring str); */
  1888 NS_IMETHODIMP nsVariant::GetAsWStringWithSize(uint32_t *size, char16_t **str)
  1890     return nsVariant::ConvertToWStringWithSize(mData, size, str);
  1893 /***************************************************************************/
  1895 /* attribute bool writable; */
  1896 NS_IMETHODIMP nsVariant::GetWritable(bool *aWritable)
  1898     *aWritable = mWritable;
  1899     return NS_OK;
  1901 NS_IMETHODIMP nsVariant::SetWritable(bool aWritable)
  1903     if(!mWritable && aWritable)
  1904         return NS_ERROR_FAILURE;
  1905     mWritable = aWritable;
  1906     return NS_OK;
  1909 /***************************************************************************/
  1911 // For all the data setters we just forward to the static (and sharable)
  1912 // 'SetFrom' functions.
  1914 /* void setAsInt8 (in uint8_t aValue); */
  1915 NS_IMETHODIMP nsVariant::SetAsInt8(uint8_t aValue)
  1917     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1918     return nsVariant::SetFromInt8(&mData, aValue);
  1921 /* void setAsInt16 (in int16_t aValue); */
  1922 NS_IMETHODIMP nsVariant::SetAsInt16(int16_t aValue)
  1924     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1925     return nsVariant::SetFromInt16(&mData, aValue);
  1928 /* void setAsInt32 (in int32_t aValue); */
  1929 NS_IMETHODIMP nsVariant::SetAsInt32(int32_t aValue)
  1931     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1932     return nsVariant::SetFromInt32(&mData, aValue);
  1935 /* void setAsInt64 (in int64_t aValue); */
  1936 NS_IMETHODIMP nsVariant::SetAsInt64(int64_t aValue)
  1938     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1939     return nsVariant::SetFromInt64(&mData, aValue);
  1942 /* void setAsUint8 (in uint8_t aValue); */
  1943 NS_IMETHODIMP nsVariant::SetAsUint8(uint8_t aValue)
  1945     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1946     return nsVariant::SetFromUint8(&mData, aValue);
  1949 /* void setAsUint16 (in uint16_t aValue); */
  1950 NS_IMETHODIMP nsVariant::SetAsUint16(uint16_t aValue)
  1952     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1953     return nsVariant::SetFromUint16(&mData, aValue);
  1956 /* void setAsUint32 (in uint32_t aValue); */
  1957 NS_IMETHODIMP nsVariant::SetAsUint32(uint32_t aValue)
  1959     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1960     return nsVariant::SetFromUint32(&mData, aValue);
  1963 /* void setAsUint64 (in uint64_t aValue); */
  1964 NS_IMETHODIMP nsVariant::SetAsUint64(uint64_t aValue)
  1966     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1967     return nsVariant::SetFromUint64(&mData, aValue);
  1970 /* void setAsFloat (in float aValue); */
  1971 NS_IMETHODIMP nsVariant::SetAsFloat(float aValue)
  1973     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1974     return nsVariant::SetFromFloat(&mData, aValue);
  1977 /* void setAsDouble (in double aValue); */
  1978 NS_IMETHODIMP nsVariant::SetAsDouble(double aValue)
  1980     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1981     return nsVariant::SetFromDouble(&mData, aValue);
  1984 /* void setAsBool (in bool aValue); */
  1985 NS_IMETHODIMP nsVariant::SetAsBool(bool aValue)
  1987     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1988     return nsVariant::SetFromBool(&mData, aValue);
  1991 /* void setAsChar (in char aValue); */
  1992 NS_IMETHODIMP nsVariant::SetAsChar(char aValue)
  1994     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  1995     return nsVariant::SetFromChar(&mData, aValue);
  1998 /* void setAsWChar (in wchar aValue); */
  1999 NS_IMETHODIMP nsVariant::SetAsWChar(char16_t aValue)
  2001     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  2002     return nsVariant::SetFromWChar(&mData, aValue);
  2005 /* void setAsID (in nsIDRef aValue); */
  2006 NS_IMETHODIMP nsVariant::SetAsID(const nsID & aValue)
  2008     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  2009     return nsVariant::SetFromID(&mData, aValue);
  2012 /* void setAsAString (in AString aValue); */
  2013 NS_IMETHODIMP nsVariant::SetAsAString(const nsAString & aValue)
  2015     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  2016     return nsVariant::SetFromAString(&mData, aValue);
  2019 /* void setAsDOMString (in DOMString aValue); */
  2020 NS_IMETHODIMP nsVariant::SetAsDOMString(const nsAString & aValue)
  2022     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  2024     DATA_SETTER_PROLOGUE((&mData));
  2025     if(!(mData.u.mAStringValue = new nsString(aValue)))
  2026         return NS_ERROR_OUT_OF_MEMORY;
  2027     DATA_SETTER_EPILOGUE((&mData), VTYPE_DOMSTRING);
  2030 /* void setAsACString (in ACString aValue); */
  2031 NS_IMETHODIMP nsVariant::SetAsACString(const nsACString & aValue)
  2033     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  2034     return nsVariant::SetFromACString(&mData, aValue);
  2037 /* void setAsAUTF8String (in AUTF8String aValue); */
  2038 NS_IMETHODIMP nsVariant::SetAsAUTF8String(const nsAUTF8String & aValue)
  2040     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  2041     return nsVariant::SetFromAUTF8String(&mData, aValue);
  2044 /* void setAsString (in string aValue); */
  2045 NS_IMETHODIMP nsVariant::SetAsString(const char *aValue)
  2047     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  2048     return nsVariant::SetFromString(&mData, aValue);
  2051 /* void setAsWString (in wstring aValue); */
  2052 NS_IMETHODIMP nsVariant::SetAsWString(const char16_t *aValue)
  2054     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  2055     return nsVariant::SetFromWString(&mData, aValue);
  2058 /* void setAsISupports (in nsISupports aValue); */
  2059 NS_IMETHODIMP nsVariant::SetAsISupports(nsISupports *aValue)
  2061     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  2062     return nsVariant::SetFromISupports(&mData, aValue);
  2065 /* void setAsInterface (in nsIIDRef iid, [iid_is (iid)] in nsQIResult iface); */
  2066 NS_IMETHODIMP nsVariant::SetAsInterface(const nsIID & iid, void * iface)
  2068     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  2069     return nsVariant::SetFromInterface(&mData, iid, (nsISupports*)iface);
  2072 /* [noscript] void setAsArray (in uint16_t type, in nsIIDPtr iid, in uint32_t count, in voidPtr ptr); */
  2073 NS_IMETHODIMP nsVariant::SetAsArray(uint16_t type, const nsIID * iid, uint32_t count, void * ptr)
  2075     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  2076     return nsVariant::SetFromArray(&mData, type, iid, count, ptr);
  2079 /* void setAsStringWithSize (in uint32_t size, [size_is (size)] in string str); */
  2080 NS_IMETHODIMP nsVariant::SetAsStringWithSize(uint32_t size, const char *str)
  2082     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  2083     return nsVariant::SetFromStringWithSize(&mData, size, str);
  2086 /* void setAsWStringWithSize (in uint32_t size, [size_is (size)] in wstring str); */
  2087 NS_IMETHODIMP nsVariant::SetAsWStringWithSize(uint32_t size, const char16_t *str)
  2089     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  2090     return nsVariant::SetFromWStringWithSize(&mData, size, str);
  2093 /* void setAsVoid (); */
  2094 NS_IMETHODIMP nsVariant::SetAsVoid()
  2096     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  2097     return nsVariant::SetToVoid(&mData);
  2100 /* void setAsEmpty (); */
  2101 NS_IMETHODIMP nsVariant::SetAsEmpty()
  2103     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  2104     return nsVariant::SetToEmpty(&mData);
  2107 /* void setAsEmptyArray (); */
  2108 NS_IMETHODIMP nsVariant::SetAsEmptyArray()
  2110     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  2111     return nsVariant::SetToEmptyArray(&mData);
  2114 /* void setFromVariant (in nsIVariant aValue); */
  2115 NS_IMETHODIMP nsVariant::SetFromVariant(nsIVariant *aValue)
  2117     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
  2118     return nsVariant::SetFromVariant(&mData, aValue);

mercurial