Back to index

lightning-sunbird  0.9+nobinonly
nsVariant.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is mozilla.org code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   John Bandhauer <jband@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 /* The long avoided variant support for xpcom. */
00041 
00042 #include "nsVariant.h"
00043 #include "nsString.h"
00044 #include "prprf.h"
00045 #include "prdtoa.h"
00046 #include <math.h>
00047 #include "nsCRT.h"
00048 
00049 /***************************************************************************/
00050 // Helpers for static convert functions...
00051 
00052 static nsresult String2Double(const char* aString, double* retval)
00053 {
00054     char* next;
00055     double value = PR_strtod(aString, &next);
00056     if(next == aString)
00057         return NS_ERROR_CANNOT_CONVERT_DATA;
00058     *retval = value;
00059     return NS_OK;
00060 }
00061 
00062 static nsresult AString2Double(const nsAString& aString, double* retval)
00063 {
00064     char* pChars = ToNewCString(aString);
00065     if(!pChars)
00066         return NS_ERROR_OUT_OF_MEMORY;
00067     nsresult rv = String2Double(pChars, retval);
00068     nsMemory::Free(pChars);
00069     return rv;
00070 }
00071 
00072 static nsresult AUTF8String2Double(const nsAUTF8String& aString, double* retval)
00073 {
00074     return String2Double(PromiseFlatUTF8String(aString).get(), retval);
00075 }
00076 
00077 static nsresult ACString2Double(const nsACString& aString, double* retval)
00078 {
00079     return String2Double(PromiseFlatCString(aString).get(), retval);
00080 }
00081 
00082 // Fills outVariant with double, PRUint32, or PRInt32.
00083 // Returns NS_OK, an error code, or a non-NS_OK success code
00084 static nsresult ToManageableNumber(const nsDiscriminatedUnion& inData,
00085                                    nsDiscriminatedUnion* outData)
00086 {
00087     nsresult rv;
00088 
00089     switch(inData.mType)
00090     {
00091     // This group results in a PRInt32...
00092 
00093 #define CASE__NUMBER_INT32(type_, member_)                                    \
00094     case nsIDataType :: type_ :                                               \
00095         outData->u.mInt32Value = inData.u. member_ ;                          \
00096         outData->mType = nsIDataType::VTYPE_INT32;                            \
00097         return NS_OK;
00098 
00099     CASE__NUMBER_INT32(VTYPE_INT8,   mInt8Value)
00100     CASE__NUMBER_INT32(VTYPE_INT16,  mInt16Value)
00101     CASE__NUMBER_INT32(VTYPE_INT32,  mInt32Value)
00102     CASE__NUMBER_INT32(VTYPE_UINT8,  mUint8Value)
00103     CASE__NUMBER_INT32(VTYPE_UINT16, mUint16Value)
00104     CASE__NUMBER_INT32(VTYPE_BOOL,   mBoolValue)
00105     CASE__NUMBER_INT32(VTYPE_CHAR,   mCharValue)
00106     CASE__NUMBER_INT32(VTYPE_WCHAR,  mWCharValue)
00107 
00108 #undef CASE__NUMBER_INT32
00109 
00110     // This group results in a PRUint32...
00111 
00112     case nsIDataType::VTYPE_UINT32:
00113         outData->u.mInt32Value = inData.u.mUint32Value;
00114         outData->mType = nsIDataType::VTYPE_INT32;
00115         return NS_OK;
00116 
00117     // This group results in a double...
00118 
00119     case nsIDataType::VTYPE_INT64:
00120     case nsIDataType::VTYPE_UINT64:
00121         // XXX Need boundary checking here.
00122         // We may need to return NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA
00123         LL_L2D(outData->u.mDoubleValue, inData.u.mInt64Value);
00124         outData->mType = nsIDataType::VTYPE_DOUBLE;
00125         return NS_OK;
00126     case nsIDataType::VTYPE_FLOAT:
00127         outData->u.mDoubleValue = inData.u.mFloatValue;
00128         outData->mType = nsIDataType::VTYPE_DOUBLE;
00129         return NS_OK;
00130     case nsIDataType::VTYPE_DOUBLE:
00131         outData->u.mDoubleValue = inData.u.mDoubleValue;
00132         outData->mType = nsIDataType::VTYPE_DOUBLE;
00133         return NS_OK;
00134     case nsIDataType::VTYPE_CHAR_STR:
00135     case nsIDataType::VTYPE_STRING_SIZE_IS:
00136         rv = String2Double(inData.u.str.mStringValue, &outData->u.mDoubleValue);
00137         if(NS_FAILED(rv))
00138             return rv;
00139         outData->mType = nsIDataType::VTYPE_DOUBLE;
00140         return NS_OK;
00141     case nsIDataType::VTYPE_DOMSTRING:
00142     case nsIDataType::VTYPE_ASTRING:
00143         rv = AString2Double(*inData.u.mAStringValue, &outData->u.mDoubleValue);
00144         if(NS_FAILED(rv))
00145             return rv;
00146         outData->mType = nsIDataType::VTYPE_DOUBLE;
00147         return NS_OK;
00148     case nsIDataType::VTYPE_UTF8STRING:
00149         rv = AUTF8String2Double(*inData.u.mUTF8StringValue,
00150                                 &outData->u.mDoubleValue);
00151         if(NS_FAILED(rv))
00152             return rv;
00153         outData->mType = nsIDataType::VTYPE_DOUBLE;
00154         return NS_OK;
00155     case nsIDataType::VTYPE_CSTRING:
00156         rv = ACString2Double(*inData.u.mCStringValue,
00157                              &outData->u.mDoubleValue);
00158         if(NS_FAILED(rv))
00159             return rv;
00160         outData->mType = nsIDataType::VTYPE_DOUBLE;
00161         return NS_OK;
00162     case nsIDataType::VTYPE_WCHAR_STR:
00163     case nsIDataType::VTYPE_WSTRING_SIZE_IS:
00164         rv = AString2Double(nsDependentString(inData.u.wstr.mWStringValue),
00165                             &outData->u.mDoubleValue);
00166         if(NS_FAILED(rv))
00167             return rv;
00168         outData->mType = nsIDataType::VTYPE_DOUBLE;
00169         return NS_OK;
00170 
00171     // This group fails...
00172 
00173     case nsIDataType::VTYPE_VOID:
00174     case nsIDataType::VTYPE_ID:
00175     case nsIDataType::VTYPE_INTERFACE:
00176     case nsIDataType::VTYPE_INTERFACE_IS:
00177     case nsIDataType::VTYPE_ARRAY:
00178     case nsIDataType::VTYPE_EMPTY_ARRAY:
00179     case nsIDataType::VTYPE_EMPTY:
00180     default:
00181         return NS_ERROR_CANNOT_CONVERT_DATA;
00182     }
00183 }
00184 
00185 /***************************************************************************/
00186 // Array helpers...
00187 
00188 static void FreeArray(nsDiscriminatedUnion* data)
00189 {
00190     NS_ASSERTION(data->mType == nsIDataType::VTYPE_ARRAY, "bad FreeArray call");
00191     NS_ASSERTION(data->u.array.mArrayValue, "bad array");
00192     NS_ASSERTION(data->u.array.mArrayCount, "bad array count");
00193 
00194 #define CASE__FREE_ARRAY_PTR(type_, ctype_)                                   \
00195         case nsIDataType:: type_ :                                            \
00196         {                                                                     \
00197             ctype_ ** p = (ctype_ **) data->u.array.mArrayValue;              \
00198             for(PRUint32 i = data->u.array.mArrayCount; i > 0; p++, i--)      \
00199                 if(*p)                                                        \
00200                     nsMemory::Free((char*)*p);                                \
00201             break;                                                            \
00202         }
00203 
00204 #define CASE__FREE_ARRAY_IFACE(type_, ctype_)                                 \
00205         case nsIDataType:: type_ :                                            \
00206         {                                                                     \
00207             ctype_ ** p = (ctype_ **) data->u.array.mArrayValue;              \
00208             for(PRUint32 i = data->u.array.mArrayCount; i > 0; p++, i--)      \
00209                 if(*p)                                                        \
00210                     (*p)->Release();                                          \
00211             break;                                                            \
00212         }
00213 
00214     switch(data->u.array.mArrayType)
00215     {
00216         case nsIDataType::VTYPE_INT8:
00217         case nsIDataType::VTYPE_INT16:
00218         case nsIDataType::VTYPE_INT32:
00219         case nsIDataType::VTYPE_INT64:
00220         case nsIDataType::VTYPE_UINT8:
00221         case nsIDataType::VTYPE_UINT16:
00222         case nsIDataType::VTYPE_UINT32:
00223         case nsIDataType::VTYPE_UINT64:
00224         case nsIDataType::VTYPE_FLOAT:
00225         case nsIDataType::VTYPE_DOUBLE:
00226         case nsIDataType::VTYPE_BOOL:
00227         case nsIDataType::VTYPE_CHAR:
00228         case nsIDataType::VTYPE_WCHAR:
00229             break;
00230 
00231         // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
00232         CASE__FREE_ARRAY_PTR(VTYPE_ID, nsID)
00233         CASE__FREE_ARRAY_PTR(VTYPE_CHAR_STR, char)
00234         CASE__FREE_ARRAY_PTR(VTYPE_WCHAR_STR, PRUnichar)
00235         CASE__FREE_ARRAY_IFACE(VTYPE_INTERFACE, nsISupports)
00236         CASE__FREE_ARRAY_IFACE(VTYPE_INTERFACE_IS, nsISupports)
00237 
00238         // The rest are illegal.
00239         case nsIDataType::VTYPE_VOID:
00240         case nsIDataType::VTYPE_ASTRING:
00241         case nsIDataType::VTYPE_DOMSTRING:
00242         case nsIDataType::VTYPE_UTF8STRING:
00243         case nsIDataType::VTYPE_CSTRING:
00244         case nsIDataType::VTYPE_WSTRING_SIZE_IS:
00245         case nsIDataType::VTYPE_STRING_SIZE_IS:
00246         case nsIDataType::VTYPE_ARRAY:
00247         case nsIDataType::VTYPE_EMPTY_ARRAY:
00248         case nsIDataType::VTYPE_EMPTY:
00249         default:
00250             NS_ERROR("bad type in array!");
00251             break;
00252     }
00253 
00254     // Free the array memory.
00255     nsMemory::Free((char*)data->u.array.mArrayValue);
00256 
00257 #undef CASE__FREE_ARRAY_PTR
00258 #undef CASE__FREE_ARRAY_IFACE
00259 }
00260 
00261 static nsresult CloneArray(PRUint16 inType, const nsIID* inIID,
00262                            PRUint32 inCount, void* inValue,
00263                            PRUint16* outType, nsIID* outIID,
00264                            PRUint32* outCount, void** outValue)
00265 {
00266     NS_ASSERTION(inCount, "bad param");
00267     NS_ASSERTION(inValue, "bad param");
00268     NS_ASSERTION(outType, "bad param");
00269     NS_ASSERTION(outCount, "bad param");
00270     NS_ASSERTION(outValue, "bad param");
00271 
00272     PRUint32 allocatedValueCount = 0;
00273     nsresult rv = NS_OK;
00274     PRUint32 i;
00275 
00276     // First we figure out the size of the elements for the new u.array.
00277 
00278     size_t elementSize;
00279     size_t allocSize;
00280 
00281     switch(inType)
00282     {
00283         case nsIDataType::VTYPE_INT8:
00284             elementSize = sizeof(PRInt8);
00285             break;
00286         case nsIDataType::VTYPE_INT16:
00287             elementSize = sizeof(PRInt16);
00288             break;
00289         case nsIDataType::VTYPE_INT32:
00290             elementSize = sizeof(PRInt32);
00291             break;
00292         case nsIDataType::VTYPE_INT64:
00293             elementSize = sizeof(PRInt64);
00294             break;
00295         case nsIDataType::VTYPE_UINT8:
00296             elementSize = sizeof(PRUint8);
00297             break;
00298         case nsIDataType::VTYPE_UINT16:
00299             elementSize = sizeof(PRUint16);
00300             break;
00301         case nsIDataType::VTYPE_UINT32:
00302             elementSize = sizeof(PRUint32);
00303             break;
00304         case nsIDataType::VTYPE_UINT64:
00305             elementSize = sizeof(PRUint64);
00306             break;
00307         case nsIDataType::VTYPE_FLOAT:
00308             elementSize = sizeof(float);
00309             break;
00310         case nsIDataType::VTYPE_DOUBLE:
00311             elementSize = sizeof(double);
00312             break;
00313         case nsIDataType::VTYPE_BOOL:
00314             elementSize = sizeof(PRBool);
00315             break;
00316         case nsIDataType::VTYPE_CHAR:
00317             elementSize = sizeof(char);
00318             break;
00319         case nsIDataType::VTYPE_WCHAR:
00320             elementSize = sizeof(PRUnichar);
00321             break;
00322 
00323         // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
00324         case nsIDataType::VTYPE_ID:
00325         case nsIDataType::VTYPE_CHAR_STR:
00326         case nsIDataType::VTYPE_WCHAR_STR:
00327         case nsIDataType::VTYPE_INTERFACE:
00328         case nsIDataType::VTYPE_INTERFACE_IS:
00329             elementSize = sizeof(void*);
00330             break;
00331 
00332         // The rest are illegal.
00333         case nsIDataType::VTYPE_ASTRING:
00334         case nsIDataType::VTYPE_DOMSTRING:
00335         case nsIDataType::VTYPE_UTF8STRING:
00336         case nsIDataType::VTYPE_CSTRING:
00337         case nsIDataType::VTYPE_STRING_SIZE_IS:
00338         case nsIDataType::VTYPE_WSTRING_SIZE_IS:
00339         case nsIDataType::VTYPE_VOID:
00340         case nsIDataType::VTYPE_ARRAY:
00341         case nsIDataType::VTYPE_EMPTY_ARRAY:
00342         case nsIDataType::VTYPE_EMPTY:
00343         default:
00344             NS_ERROR("bad type in array!");
00345             return NS_ERROR_CANNOT_CONVERT_DATA;
00346     }
00347 
00348 
00349     // Alloc the u.array.
00350 
00351     allocSize = inCount * elementSize;
00352     *outValue = nsMemory::Alloc(allocSize);
00353     if(!*outValue)
00354         return NS_ERROR_OUT_OF_MEMORY;
00355 
00356     // Clone the elements.
00357 
00358     switch(inType)
00359     {
00360         case nsIDataType::VTYPE_INT8:
00361         case nsIDataType::VTYPE_INT16:
00362         case nsIDataType::VTYPE_INT32:
00363         case nsIDataType::VTYPE_INT64:
00364         case nsIDataType::VTYPE_UINT8:
00365         case nsIDataType::VTYPE_UINT16:
00366         case nsIDataType::VTYPE_UINT32:
00367         case nsIDataType::VTYPE_UINT64:
00368         case nsIDataType::VTYPE_FLOAT:
00369         case nsIDataType::VTYPE_DOUBLE:
00370         case nsIDataType::VTYPE_BOOL:
00371         case nsIDataType::VTYPE_CHAR:
00372         case nsIDataType::VTYPE_WCHAR:
00373             memcpy(*outValue, inValue, allocSize);
00374             break;
00375 
00376         case nsIDataType::VTYPE_INTERFACE_IS:
00377             if(outIID)
00378                 *outIID = *inIID;
00379             // fall through...
00380         case nsIDataType::VTYPE_INTERFACE:
00381         {
00382             memcpy(*outValue, inValue, allocSize);
00383 
00384             nsISupports** p = (nsISupports**) *outValue;
00385             for(i = inCount; i > 0; p++, i--)
00386                 if(*p)
00387                     (*p)->AddRef();
00388             break;
00389         }
00390 
00391         // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
00392         case nsIDataType::VTYPE_ID:
00393         {
00394             nsID** inp  = (nsID**) inValue;
00395             nsID** outp = (nsID**) *outValue;
00396             for(i = inCount; i > 0; i--)
00397             {
00398                 nsID* idp = *(inp++);
00399                 if(idp)
00400                 {
00401                     if(nsnull == (*(outp++) = (nsID*)
00402                        nsMemory::Clone((char*)idp, sizeof(nsID))))
00403                         goto bad;
00404                 }
00405                 else
00406                     *(outp++) = nsnull;
00407                 allocatedValueCount++;
00408             }
00409             break;
00410         }
00411 
00412         case nsIDataType::VTYPE_CHAR_STR:
00413         {
00414             char** inp  = (char**) inValue;
00415             char** outp = (char**) *outValue;
00416             for(i = inCount; i > 0; i--)
00417             {
00418                 char* str = *(inp++);
00419                 if(str)
00420                 {
00421                     if(nsnull == (*(outp++) = (char*)
00422                        nsMemory::Clone(str, (strlen(str)+1)*sizeof(char))))
00423                         goto bad;
00424                 }
00425                 else
00426                     *(outp++) = nsnull;
00427                 allocatedValueCount++;
00428             }
00429             break;
00430         }
00431 
00432         case nsIDataType::VTYPE_WCHAR_STR:
00433         {
00434             PRUnichar** inp  = (PRUnichar**) inValue;
00435             PRUnichar** outp = (PRUnichar**) *outValue;
00436             for(i = inCount; i > 0; i--)
00437             {
00438                 PRUnichar* str = *(inp++);
00439                 if(str)
00440                 {
00441                     if(nsnull == (*(outp++) = (PRUnichar*)
00442                        nsMemory::Clone(str,
00443                         (nsCRT::strlen(str)+1)*sizeof(PRUnichar))))
00444                         goto bad;
00445                 }
00446                 else
00447                     *(outp++) = nsnull;
00448                 allocatedValueCount++;
00449             }
00450             break;
00451         }
00452 
00453         // The rest are illegal.
00454         case nsIDataType::VTYPE_VOID:
00455         case nsIDataType::VTYPE_ARRAY:
00456         case nsIDataType::VTYPE_EMPTY_ARRAY:
00457         case nsIDataType::VTYPE_EMPTY:
00458         case nsIDataType::VTYPE_ASTRING:
00459         case nsIDataType::VTYPE_DOMSTRING:
00460         case nsIDataType::VTYPE_UTF8STRING:
00461         case nsIDataType::VTYPE_CSTRING:
00462         case nsIDataType::VTYPE_STRING_SIZE_IS:
00463         case nsIDataType::VTYPE_WSTRING_SIZE_IS:
00464         default:
00465             NS_ERROR("bad type in array!");
00466             return NS_ERROR_CANNOT_CONVERT_DATA;
00467     }
00468 
00469     *outType = inType;
00470     *outCount = inCount;
00471     return NS_OK;
00472 
00473 bad:
00474     if(*outValue)
00475     {
00476         char** p = (char**) *outValue;
00477         for(i = allocatedValueCount; i > 0; p++, i--)
00478             if(*p)
00479                 nsMemory::Free(*p);
00480         nsMemory::Free((char*)*outValue);
00481         *outValue = nsnull;
00482     }
00483     return rv;
00484 }
00485 
00486 /***************************************************************************/
00487 
00488 #define TRIVIAL_DATA_CONVERTER(type_, data_, member_, retval_)                \
00489     if(data_.mType == nsIDataType :: type_) {                                 \
00490         *retval_ = data_.u.member_;                                           \
00491         return NS_OK;                                                         \
00492     }
00493 
00494 #define NUMERIC_CONVERSION_METHOD_BEGIN(type_, Ctype_, name_)                 \
00495 /* static */ nsresult                                                         \
00496 nsVariant::ConvertTo##name_ (const nsDiscriminatedUnion& data,                \
00497                              Ctype_ *_retval)                                 \
00498 {                                                                             \
00499     TRIVIAL_DATA_CONVERTER(type_, data, m##name_##Value, _retval)             \
00500     nsDiscriminatedUnion tempData;                                            \
00501     nsVariant::Initialize(&tempData);                                         \
00502     nsresult rv = ToManageableNumber(data, &tempData);                        \
00503     /*                                                                     */ \
00504     /* NOTE: rv may indicate a success code that we want to preserve       */ \
00505     /* For the final return. So all the return cases below should return   */ \
00506     /* this rv when indicating success.                                    */ \
00507     /*                                                                     */ \
00508     if(NS_FAILED(rv))                                                         \
00509         return rv;                                                            \
00510     switch(tempData.mType)                                                    \
00511     {
00512 
00513 #define CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(Ctype_)                      \
00514     case nsIDataType::VTYPE_INT32:                                            \
00515         *_retval = ( Ctype_ ) tempData.u.mInt32Value;                         \
00516         return rv;
00517 
00518 #define CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(Ctype_, min_, max_)            \
00519     case nsIDataType::VTYPE_INT32:                                            \
00520     {                                                                         \
00521         PRInt32 value = tempData.u.mInt32Value;                               \
00522         if(value < min_ || value > max_)                                      \
00523             return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;                         \
00524         *_retval = ( Ctype_ ) value;                                          \
00525         return rv;                                                            \
00526     }
00527 
00528 #define CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(Ctype_)                     \
00529     case nsIDataType::VTYPE_UINT32:                                           \
00530         *_retval = ( Ctype_ ) tempData.u.mUint32Value;                        \
00531         return rv;
00532 
00533 #define CASE__NUMERIC_CONVERSION_UINT32_MAX(Ctype_, max_)                     \
00534     case nsIDataType::VTYPE_UINT32:                                           \
00535     {                                                                         \
00536         PRUint32 value = tempData.u.mUint32Value;                             \
00537         if(value > max_)                                                      \
00538             return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;                         \
00539         *_retval = ( Ctype_ ) value;                                          \
00540         return rv;                                                            \
00541     }
00542 
00543 #define CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(Ctype_)                     \
00544     case nsIDataType::VTYPE_DOUBLE:                                           \
00545         *_retval = ( Ctype_ ) tempData.u.mDoubleValue;                        \
00546         return rv;
00547 
00548 #define CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX(Ctype_, min_, max_)           \
00549     case nsIDataType::VTYPE_DOUBLE:                                           \
00550     {                                                                         \
00551         double value = tempData.u.mDoubleValue;                               \
00552         if(value < min_ || value > max_)                                      \
00553             return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;                         \
00554         *_retval = ( Ctype_ ) value;                                          \
00555         return rv;                                                            \
00556     }
00557 
00558 #define CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(Ctype_, min_, max_)       \
00559     case nsIDataType::VTYPE_DOUBLE:                                           \
00560     {                                                                         \
00561         double value = tempData.u.mDoubleValue;                               \
00562         if(value < min_ || value > max_)                                      \
00563             return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;                         \
00564         *_retval = ( Ctype_ ) value;                                          \
00565         return (0.0 == fmod(value,1.0)) ?                                     \
00566             rv : NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA;                       \
00567     }
00568 
00569 #define CASES__NUMERIC_CONVERSION_NORMAL(Ctype_, min_, max_)                  \
00570     CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(Ctype_, min_, max_)                \
00571     CASE__NUMERIC_CONVERSION_UINT32_MAX(Ctype_, max_)                         \
00572     CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(Ctype_, min_, max_)
00573 
00574 #define NUMERIC_CONVERSION_METHOD_END                                         \
00575     default:                                                                  \
00576         NS_ERROR("bad type returned from ToManageableNumber");                \
00577         return NS_ERROR_CANNOT_CONVERT_DATA;                                  \
00578     }                                                                         \
00579 }
00580 
00581 #define NUMERIC_CONVERSION_METHOD_NORMAL(type_, Ctype_, name_, min_, max_)    \
00582     NUMERIC_CONVERSION_METHOD_BEGIN(type_, Ctype_, name_)                     \
00583         CASES__NUMERIC_CONVERSION_NORMAL(Ctype_, min_, max_)                  \
00584     NUMERIC_CONVERSION_METHOD_END
00585 
00586 /***************************************************************************/
00587 // These expand into full public methods...
00588 
00589 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_INT8, PRUint8, Int8, (-127-1), 127)
00590 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_INT16, PRInt16, Int16, (-32767-1), 32767)
00591 
00592 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_INT32, PRInt32, Int32)
00593     CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(PRInt32)
00594     CASE__NUMERIC_CONVERSION_UINT32_MAX(PRInt32, 2147483647)
00595     CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(PRInt32, (-2147483647-1), 2147483647)
00596 NUMERIC_CONVERSION_METHOD_END
00597 
00598 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_UINT8, PRUint8, Uint8, 0, 255)
00599 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_UINT16, PRUint16, Uint16, 0, 65535)
00600 
00601 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_UINT32, PRUint32, Uint32)
00602     CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(PRUint32, 0, 2147483647)
00603     CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(PRUint32)
00604     CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(PRUint32, 0, 4294967295U)
00605 NUMERIC_CONVERSION_METHOD_END
00606 
00607 // XXX toFloat convertions need to be fixed!
00608 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_FLOAT, float, Float)
00609     CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(float)
00610     CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(float)
00611     CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(float)
00612 NUMERIC_CONVERSION_METHOD_END
00613 
00614 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_DOUBLE, double, Double)
00615     CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(double)
00616     CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(double)
00617     CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(double)
00618 NUMERIC_CONVERSION_METHOD_END
00619 
00620 // XXX toChar convertions need to be fixed!
00621 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_CHAR, char, Char)
00622     CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(char)
00623     CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(char)
00624     CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(char)
00625 NUMERIC_CONVERSION_METHOD_END
00626 
00627 // XXX toWChar convertions need to be fixed!
00628 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_WCHAR, PRUnichar, WChar)
00629     CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(PRUnichar)
00630     CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(PRUnichar)
00631     CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(PRUnichar)
00632 NUMERIC_CONVERSION_METHOD_END
00633 
00634 #undef NUMERIC_CONVERSION_METHOD_BEGIN
00635 #undef CASE__NUMERIC_CONVERSION_INT32_JUST_CAST
00636 #undef CASE__NUMERIC_CONVERSION_INT32_MIN_MAX
00637 #undef CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST
00638 #undef CASE__NUMERIC_CONVERSION_UINT32_MIN_MAX
00639 #undef CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST
00640 #undef CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX
00641 #undef CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT
00642 #undef CASES__NUMERIC_CONVERSION_NORMAL
00643 #undef NUMERIC_CONVERSION_METHOD_END
00644 #undef NUMERIC_CONVERSION_METHOD_NORMAL
00645 
00646 /***************************************************************************/
00647 
00648 // Just leverage a numeric converter for bool (but restrict the values).
00649 // XXX Is this really what we want to do?
00650 
00651 /* static */ nsresult
00652 nsVariant::ConvertToBool(const nsDiscriminatedUnion& data, PRBool *_retval)
00653 {
00654     TRIVIAL_DATA_CONVERTER(VTYPE_BOOL, data, mBoolValue, _retval)
00655 
00656     double val;
00657     nsresult rv = nsVariant::ConvertToDouble(data, &val);
00658     if(NS_FAILED(rv))
00659         return rv;
00660     *_retval = 0.0 != val;
00661     return rv;
00662 }
00663 
00664 /***************************************************************************/
00665 
00666 /* static */ nsresult
00667 nsVariant::ConvertToInt64(const nsDiscriminatedUnion& data, PRInt64 *_retval)
00668 {
00669     TRIVIAL_DATA_CONVERTER(VTYPE_INT64, data, mInt64Value, _retval)
00670     TRIVIAL_DATA_CONVERTER(VTYPE_UINT64, data, mUint64Value, _retval)
00671 
00672     nsDiscriminatedUnion tempData;
00673     nsVariant::Initialize(&tempData);
00674     nsresult rv = ToManageableNumber(data, &tempData);
00675     if(NS_FAILED(rv))
00676         return rv;
00677     switch(tempData.mType)
00678     {
00679     case nsIDataType::VTYPE_INT32:
00680         LL_I2L(*_retval, tempData.u.mInt32Value);
00681         return rv;
00682     case nsIDataType::VTYPE_UINT32:
00683         LL_UI2L(*_retval, tempData.u.mUint32Value);
00684         return rv;
00685     case nsIDataType::VTYPE_DOUBLE:
00686         // XXX should check for data loss here!
00687         LL_D2L(*_retval, tempData.u.mDoubleValue);
00688         return rv;
00689     default:
00690         NS_ERROR("bad type returned from ToManageableNumber");
00691         return NS_ERROR_CANNOT_CONVERT_DATA;
00692     }
00693 }
00694 
00695 /* static */ nsresult
00696 nsVariant::ConvertToUint64(const nsDiscriminatedUnion& data, PRUint64 *_retval)
00697 {
00698     return nsVariant::ConvertToInt64(data, (PRInt64 *)_retval);
00699 }
00700 
00701 /***************************************************************************/
00702 
00703 static PRBool String2ID(const nsDiscriminatedUnion& data, nsID* pid)
00704 {
00705     nsAutoString tempString;
00706     nsAString* pString;
00707 
00708     switch(data.mType)
00709     {
00710         case nsIDataType::VTYPE_CHAR_STR:
00711         case nsIDataType::VTYPE_STRING_SIZE_IS:
00712             return pid->Parse(data.u.str.mStringValue);
00713         case nsIDataType::VTYPE_CSTRING:
00714             return pid->Parse(PromiseFlatCString(*data.u.mCStringValue).get());
00715         case nsIDataType::VTYPE_UTF8STRING:
00716             return pid->Parse(PromiseFlatUTF8String(*data.u.mUTF8StringValue).get());
00717         case nsIDataType::VTYPE_ASTRING:
00718         case nsIDataType::VTYPE_DOMSTRING:
00719             pString = data.u.mAStringValue;
00720             break;
00721         case nsIDataType::VTYPE_WCHAR_STR:
00722         case nsIDataType::VTYPE_WSTRING_SIZE_IS:
00723             tempString.Assign(data.u.wstr.mWStringValue);
00724             pString = &tempString;
00725             break;
00726         default:
00727             NS_ERROR("bad type in call to String2ID");
00728             return PR_FALSE;
00729     }
00730 
00731     char* pChars = ToNewCString(*pString);
00732     if(!pChars)
00733         return PR_FALSE;
00734     PRBool result = pid->Parse(pChars);
00735     nsMemory::Free(pChars);
00736     return result;
00737 }
00738 
00739 /* static */ nsresult
00740 nsVariant::ConvertToID(const nsDiscriminatedUnion& data, nsID * _retval)
00741 {
00742     nsID id;
00743 
00744     switch(data.mType)
00745     {
00746     case nsIDataType::VTYPE_ID:
00747         *_retval = data.u.mIDValue;
00748         return NS_OK;
00749     case nsIDataType::VTYPE_INTERFACE:
00750         *_retval = NS_GET_IID(nsISupports);
00751         return NS_OK;
00752     case nsIDataType::VTYPE_INTERFACE_IS:
00753         *_retval = data.u.iface.mInterfaceID;
00754         return NS_OK;
00755     case nsIDataType::VTYPE_ASTRING:
00756     case nsIDataType::VTYPE_DOMSTRING:
00757     case nsIDataType::VTYPE_UTF8STRING:
00758     case nsIDataType::VTYPE_CSTRING:
00759     case nsIDataType::VTYPE_CHAR_STR:
00760     case nsIDataType::VTYPE_WCHAR_STR:
00761     case nsIDataType::VTYPE_STRING_SIZE_IS:
00762     case nsIDataType::VTYPE_WSTRING_SIZE_IS:
00763         if(!String2ID(data, &id))
00764             return NS_ERROR_CANNOT_CONVERT_DATA;
00765         *_retval = id;
00766         return NS_OK;
00767     default:
00768         return NS_ERROR_CANNOT_CONVERT_DATA;
00769     }
00770 }
00771 
00772 /***************************************************************************/
00773 
00774 static nsresult ToString(const nsDiscriminatedUnion& data,
00775                          nsACString & outString)
00776 {
00777     char* ptr;
00778 
00779     switch(data.mType)
00780     {
00781     // all the stuff we don't handle...
00782     case nsIDataType::VTYPE_ASTRING:
00783     case nsIDataType::VTYPE_DOMSTRING:
00784     case nsIDataType::VTYPE_UTF8STRING:
00785     case nsIDataType::VTYPE_CSTRING:
00786     case nsIDataType::VTYPE_CHAR_STR:
00787     case nsIDataType::VTYPE_WCHAR_STR:
00788     case nsIDataType::VTYPE_STRING_SIZE_IS:
00789     case nsIDataType::VTYPE_WSTRING_SIZE_IS:
00790     case nsIDataType::VTYPE_WCHAR:
00791         NS_ERROR("ToString being called for a string type - screwy logic!");
00792         // fall through...
00793 
00794     // XXX We might want stringified versions of these... ???
00795 
00796     case nsIDataType::VTYPE_VOID:
00797     case nsIDataType::VTYPE_EMPTY:
00798         outString.Truncate();
00799         outString.SetIsVoid(true);
00800         return NS_OK;
00801 
00802     case nsIDataType::VTYPE_EMPTY_ARRAY:
00803     case nsIDataType::VTYPE_ARRAY:
00804     case nsIDataType::VTYPE_INTERFACE:
00805     case nsIDataType::VTYPE_INTERFACE_IS:
00806     default:
00807         return NS_ERROR_CANNOT_CONVERT_DATA;
00808 
00809     // nsID has its own text formater.
00810 
00811     case nsIDataType::VTYPE_ID:
00812         ptr = data.u.mIDValue.ToString();
00813         if(!ptr)
00814             return NS_ERROR_OUT_OF_MEMORY;
00815         outString.Assign(ptr);
00816         nsMemory::Free(ptr);
00817         return NS_OK;
00818 
00819     // Can't use PR_smprintf for floats, since it's locale-dependent
00820 #define CASE__APPENDFLOAT_NUMBER(type_, member_)                        \
00821     case nsIDataType :: type_ :                                         \
00822     {                                                                   \
00823         nsCAutoString str;                                              \
00824         str.AppendFloat(data.u. member_);                               \
00825         outString.Assign(str);                                          \
00826         return NS_OK;                                                   \
00827     }
00828 
00829     CASE__APPENDFLOAT_NUMBER(VTYPE_FLOAT,  mFloatValue)
00830     CASE__APPENDFLOAT_NUMBER(VTYPE_DOUBLE, mDoubleValue)
00831 
00832 #undef CASE__APPENDFLOAT_NUMBER
00833 
00834     // the rest can be PR_smprintf'd and use common code.
00835 
00836 #define CASE__SMPRINTF_NUMBER(type_, format_, cast_, member_)                 \
00837     case nsIDataType :: type_ :                                               \
00838         ptr = PR_smprintf( format_ , (cast_) data.u. member_ );               \
00839         break;
00840 
00841     CASE__SMPRINTF_NUMBER(VTYPE_INT8,   "%d",   int,      mInt8Value)
00842     CASE__SMPRINTF_NUMBER(VTYPE_INT16,  "%d",   int,      mInt16Value)
00843     CASE__SMPRINTF_NUMBER(VTYPE_INT32,  "%d",   int,      mInt32Value)
00844     CASE__SMPRINTF_NUMBER(VTYPE_INT64,  "%lld", PRInt64,  mInt64Value)
00845 
00846     CASE__SMPRINTF_NUMBER(VTYPE_UINT8,  "%u",   unsigned, mUint8Value)
00847     CASE__SMPRINTF_NUMBER(VTYPE_UINT16, "%u",   unsigned, mUint16Value)
00848     CASE__SMPRINTF_NUMBER(VTYPE_UINT32, "%u",   unsigned, mUint32Value)
00849     CASE__SMPRINTF_NUMBER(VTYPE_UINT64, "%llu", PRInt64,  mUint64Value)
00850 
00851     // XXX Would we rather print "true" / "false" ?
00852     CASE__SMPRINTF_NUMBER(VTYPE_BOOL,   "%d",   int,      mBoolValue)
00853 
00854     CASE__SMPRINTF_NUMBER(VTYPE_CHAR,   "%c",   char,     mCharValue)
00855 
00856 #undef CASE__SMPRINTF_NUMBER
00857     }
00858 
00859     if(!ptr)
00860         return NS_ERROR_OUT_OF_MEMORY;
00861     outString.Assign(ptr);
00862     PR_smprintf_free(ptr);
00863     return NS_OK;
00864 }
00865 
00866 /* static */ nsresult
00867 nsVariant::ConvertToAString(const nsDiscriminatedUnion& data,
00868                             nsAString & _retval)
00869 {
00870     switch(data.mType)
00871     {
00872     case nsIDataType::VTYPE_ASTRING:
00873     case nsIDataType::VTYPE_DOMSTRING:
00874         _retval.Assign(*data.u.mAStringValue);
00875         return NS_OK;
00876     case nsIDataType::VTYPE_CSTRING:
00877         CopyASCIItoUCS2(*data.u.mCStringValue, _retval);
00878         return NS_OK;
00879     case nsIDataType::VTYPE_UTF8STRING:
00880         CopyUTF8toUTF16(*data.u.mUTF8StringValue, _retval);
00881         return NS_OK;
00882     case nsIDataType::VTYPE_CHAR_STR:
00883         CopyASCIItoUTF16(data.u.str.mStringValue, _retval);
00884         return NS_OK;
00885     case nsIDataType::VTYPE_WCHAR_STR:
00886         _retval.Assign(data.u.wstr.mWStringValue);
00887         return NS_OK;
00888     case nsIDataType::VTYPE_STRING_SIZE_IS:
00889         CopyASCIItoUCS2(nsDependentCString(data.u.str.mStringValue,
00890                                            data.u.str.mStringLength),
00891                         _retval);
00892         return NS_OK;
00893     case nsIDataType::VTYPE_WSTRING_SIZE_IS:
00894         _retval.Assign(data.u.wstr.mWStringValue, data.u.wstr.mWStringLength);
00895         return NS_OK;
00896     case nsIDataType::VTYPE_WCHAR:
00897         _retval.Assign(data.u.mWCharValue);
00898         return NS_OK;
00899     default:
00900     {
00901         nsCAutoString tempCString;
00902         nsresult rv = ToString(data, tempCString);
00903         if(NS_FAILED(rv))
00904             return rv;
00905         CopyASCIItoUTF16(tempCString, _retval);
00906         return NS_OK;
00907     }
00908     }
00909 }
00910 
00911 /* static */ nsresult
00912 nsVariant::ConvertToACString(const nsDiscriminatedUnion& data,
00913                              nsACString & _retval)
00914 {
00915     switch(data.mType)
00916     {
00917     case nsIDataType::VTYPE_ASTRING:
00918     case nsIDataType::VTYPE_DOMSTRING:
00919         CopyUCS2toASCII(*data.u.mAStringValue, _retval);
00920         return NS_OK;
00921     case nsIDataType::VTYPE_CSTRING:
00922         _retval.Assign(*data.u.mCStringValue);
00923         return NS_OK;
00924     case nsIDataType::VTYPE_UTF8STRING:
00925         // XXX This is an extra copy that should be avoided
00926         // once Jag lands support for UTF8String and associated
00927         // conversion methods.
00928         CopyUCS2toASCII(NS_ConvertUTF8toUCS2(*data.u.mUTF8StringValue),
00929                         _retval);
00930         return NS_OK;
00931     case nsIDataType::VTYPE_CHAR_STR:
00932         _retval.Assign(*data.u.str.mStringValue);
00933         return NS_OK;
00934     case nsIDataType::VTYPE_WCHAR_STR:
00935         CopyUCS2toASCII(nsDependentString(data.u.wstr.mWStringValue),
00936                         _retval);
00937         return NS_OK;
00938     case nsIDataType::VTYPE_STRING_SIZE_IS:
00939         _retval.Assign(data.u.str.mStringValue, data.u.str.mStringLength);
00940         return NS_OK;
00941     case nsIDataType::VTYPE_WSTRING_SIZE_IS:
00942         CopyUCS2toASCII(nsDependentString(data.u.wstr.mWStringValue,
00943                         data.u.wstr.mWStringLength), _retval);
00944         return NS_OK;
00945     case nsIDataType::VTYPE_WCHAR:
00946     {
00947         const PRUnichar* str = &data.u.mWCharValue;
00948         CopyUCS2toASCII(Substring(str, str + 1), _retval);
00949         return NS_OK;
00950     }
00951     default:
00952         return ToString(data, _retval);
00953     }
00954 }
00955 
00956 /* static */ nsresult
00957 nsVariant::ConvertToAUTF8String(const nsDiscriminatedUnion& data,
00958                                 nsAUTF8String & _retval)
00959 {
00960     switch(data.mType)
00961     {
00962     case nsIDataType::VTYPE_ASTRING:
00963     case nsIDataType::VTYPE_DOMSTRING:
00964         CopyUTF16toUTF8(*data.u.mAStringValue, _retval);
00965         return NS_OK;
00966     case nsIDataType::VTYPE_CSTRING:
00967         // XXX Extra copy, can be removed if we're sure CSTRING can
00968         //     only contain ASCII.
00969         CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(*data.u.mCStringValue),
00970                         _retval);
00971         return NS_OK;
00972     case nsIDataType::VTYPE_UTF8STRING:
00973         _retval.Assign(*data.u.mUTF8StringValue);
00974         return NS_OK;
00975     case nsIDataType::VTYPE_CHAR_STR:
00976         // XXX Extra copy, can be removed if we're sure CHAR_STR can
00977         //     only contain ASCII.
00978         CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(data.u.str.mStringValue),
00979                         _retval);
00980         return NS_OK;
00981     case nsIDataType::VTYPE_WCHAR_STR:
00982         CopyUTF16toUTF8(data.u.wstr.mWStringValue, _retval);
00983         return NS_OK;
00984     case nsIDataType::VTYPE_STRING_SIZE_IS:
00985         // XXX Extra copy, can be removed if we're sure CHAR_STR can
00986         //     only contain ASCII.
00987         CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(
00988             nsDependentCString(data.u.str.mStringValue,
00989                                data.u.str.mStringLength)), _retval);
00990         return NS_OK;
00991     case nsIDataType::VTYPE_WSTRING_SIZE_IS:
00992         CopyUTF16toUTF8(nsDependentString(data.u.wstr.mWStringValue,
00993                                           data.u.wstr.mWStringLength),
00994                         _retval);
00995         return NS_OK;
00996     case nsIDataType::VTYPE_WCHAR:
00997     {
00998         const PRUnichar* str = &data.u.mWCharValue;
00999         CopyUTF16toUTF8(Substring(str, str + 1), _retval);
01000         return NS_OK;
01001     }
01002     default:
01003     {
01004         nsCAutoString tempCString;
01005         nsresult rv = ToString(data, tempCString);
01006         if(NS_FAILED(rv))
01007             return rv;
01008         // XXX Extra copy, can be removed if we're sure tempCString can
01009         //     only contain ASCII.
01010         CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(tempCString), _retval);
01011         return NS_OK;
01012     }
01013     }
01014 }
01015 
01016 /* static */ nsresult
01017 nsVariant::ConvertToString(const nsDiscriminatedUnion& data, char **_retval)
01018 {
01019     PRUint32 ignored;
01020     return nsVariant::ConvertToStringWithSize(data, &ignored, _retval);
01021 }
01022 
01023 /* static */ nsresult
01024 nsVariant::ConvertToWString(const nsDiscriminatedUnion& data, PRUnichar **_retval)
01025 {
01026     PRUint32 ignored;
01027     return nsVariant::ConvertToWStringWithSize(data, &ignored, _retval);
01028 }
01029 
01030 /* static */ nsresult
01031 nsVariant::ConvertToStringWithSize(const nsDiscriminatedUnion& data,
01032                                    PRUint32 *size, char **str)
01033 {
01034     nsAutoString  tempString;
01035     nsCAutoString tempCString;
01036     nsresult rv;
01037 
01038     switch(data.mType)
01039     {
01040     case nsIDataType::VTYPE_ASTRING:
01041     case nsIDataType::VTYPE_DOMSTRING:
01042         *size = data.u.mAStringValue->Length();
01043         *str = ToNewCString(*data.u.mAStringValue);
01044         break;
01045     case nsIDataType::VTYPE_CSTRING:
01046         *size = data.u.mCStringValue->Length();
01047         *str = ToNewCString(*data.u.mCStringValue);
01048         break;
01049     case nsIDataType::VTYPE_UTF8STRING:
01050     {
01051         // XXX This is doing 1 extra copy.  Need to fix this
01052         // when Jag lands UTF8String
01053         // we want:
01054         // *size = *data.mUTF8StringValue->Length();
01055         // *str = ToNewCString(*data.mUTF8StringValue);
01056         // But this will have to do for now.
01057         NS_ConvertUTF8toUCS2 tempString(*data.u.mUTF8StringValue);
01058         *size = tempString.Length();
01059         *str = ToNewCString(tempString);
01060         break;
01061     }
01062     case nsIDataType::VTYPE_CHAR_STR:
01063     {
01064         nsDependentCString cString(data.u.str.mStringValue);
01065         *size = cString.Length();
01066         *str = ToNewCString(cString);
01067         break;
01068     }
01069     case nsIDataType::VTYPE_WCHAR_STR:
01070     {
01071         nsDependentString string(data.u.wstr.mWStringValue);
01072         *size = string.Length();
01073         *str = ToNewCString(string);
01074         break;
01075     }
01076     case nsIDataType::VTYPE_STRING_SIZE_IS:
01077     {
01078         nsDependentCString cString(data.u.str.mStringValue,
01079                                    data.u.str.mStringLength);
01080         *size = cString.Length();
01081         *str = ToNewCString(cString);
01082         break;
01083     }
01084     case nsIDataType::VTYPE_WSTRING_SIZE_IS:
01085     {
01086         nsDependentString string(data.u.wstr.mWStringValue,
01087                                  data.u.wstr.mWStringLength);
01088         *size = string.Length();
01089         *str = ToNewCString(string);
01090         break;
01091     }
01092     case nsIDataType::VTYPE_WCHAR:
01093         tempString.Assign(data.u.mWCharValue);
01094         *size = tempString.Length();
01095         *str = ToNewCString(tempString);
01096         break;
01097     default:
01098         rv = ToString(data, tempCString);
01099         if(NS_FAILED(rv))
01100             return rv;
01101         *size = tempCString.Length();
01102         *str = ToNewCString(tempCString);
01103         break;
01104     }
01105 
01106     return *str ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
01107 }
01108 /* static */ nsresult
01109 nsVariant::ConvertToWStringWithSize(const nsDiscriminatedUnion& data,
01110                                     PRUint32 *size, PRUnichar **str)
01111 {
01112     nsAutoString  tempString;
01113     nsCAutoString tempCString;
01114     nsresult rv;
01115 
01116     switch(data.mType)
01117     {
01118     case nsIDataType::VTYPE_ASTRING:
01119     case nsIDataType::VTYPE_DOMSTRING:
01120         *size = data.u.mAStringValue->Length();
01121         *str = ToNewUnicode(*data.u.mAStringValue);
01122         break;
01123     case nsIDataType::VTYPE_CSTRING:
01124         *size = data.u.mCStringValue->Length();
01125         *str = ToNewUnicode(*data.u.mCStringValue);
01126         break;
01127     case nsIDataType::VTYPE_UTF8STRING:
01128     {
01129         *str = UTF8ToNewUnicode(*data.u.mUTF8StringValue, size);
01130         break;
01131     }
01132     case nsIDataType::VTYPE_CHAR_STR:
01133     {
01134         nsDependentCString cString(data.u.str.mStringValue);
01135         *size = cString.Length();
01136         *str = ToNewUnicode(cString);
01137         break;
01138     }
01139     case nsIDataType::VTYPE_WCHAR_STR:
01140     {
01141         nsDependentString string(data.u.wstr.mWStringValue);
01142         *size = string.Length();
01143         *str = ToNewUnicode(string);
01144         break;
01145     }
01146     case nsIDataType::VTYPE_STRING_SIZE_IS:
01147     {
01148         nsDependentCString cString(data.u.str.mStringValue,
01149                                    data.u.str.mStringLength);
01150         *size = cString.Length();
01151         *str = ToNewUnicode(cString);
01152         break;
01153     }
01154     case nsIDataType::VTYPE_WSTRING_SIZE_IS:
01155     {
01156         nsDependentString string(data.u.wstr.mWStringValue,
01157                                  data.u.wstr.mWStringLength);
01158         *size = string.Length();
01159         *str = ToNewUnicode(string);
01160         break;
01161     }
01162     case nsIDataType::VTYPE_WCHAR:
01163         tempString.Assign(data.u.mWCharValue);
01164         *size = tempString.Length();
01165         *str = ToNewUnicode(tempString);
01166         break;
01167     default:
01168         rv = ToString(data, tempCString);
01169         if(NS_FAILED(rv))
01170             return rv;
01171         *size = tempCString.Length();
01172         *str = ToNewUnicode(tempCString);
01173         break;
01174     }
01175 
01176     return *str ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
01177 }
01178 
01179 /* static */ nsresult
01180 nsVariant::ConvertToISupports(const nsDiscriminatedUnion& data,
01181                               nsISupports **_retval)
01182 {
01183     switch(data.mType)
01184     {
01185     case nsIDataType::VTYPE_INTERFACE:
01186     case nsIDataType::VTYPE_INTERFACE_IS:
01187         if (data.u.iface.mInterfaceValue) {
01188             return data.u.iface.mInterfaceValue->
01189                 QueryInterface(NS_GET_IID(nsISupports), (void**)_retval);
01190         } else {
01191             *_retval = nsnull;
01192             return NS_OK;
01193         }
01194     default:
01195         return NS_ERROR_CANNOT_CONVERT_DATA;
01196     }
01197 }
01198 
01199 /* static */ nsresult
01200 nsVariant::ConvertToInterface(const nsDiscriminatedUnion& data, nsIID * *iid,
01201                               void * *iface)
01202 {
01203     const nsIID* piid;
01204 
01205     switch(data.mType)
01206     {
01207     case nsIDataType::VTYPE_INTERFACE:
01208         piid = &NS_GET_IID(nsISupports);
01209         break;
01210     case nsIDataType::VTYPE_INTERFACE_IS:
01211         piid = &data.u.iface.mInterfaceID;
01212         break;
01213     default:
01214         return NS_ERROR_CANNOT_CONVERT_DATA;
01215     }
01216 
01217     *iid = (nsIID*) nsMemory::Clone(piid, sizeof(nsIID));
01218     if(!*iid)
01219         return NS_ERROR_OUT_OF_MEMORY;
01220 
01221     if (data.u.iface.mInterfaceValue) {
01222         return data.u.iface.mInterfaceValue->QueryInterface(*piid, iface);
01223     }
01224 
01225     *iface = nsnull;
01226     return NS_OK;
01227 }
01228 
01229 /* static */ nsresult
01230 nsVariant::ConvertToArray(const nsDiscriminatedUnion& data, PRUint16 *type,
01231                           nsIID* iid, PRUint32 *count, void * *ptr)
01232 {
01233     // XXX perhaps we'd like to add support for converting each of the various
01234     // types into an array containing one element of that type. We can leverage
01235     // CloneArray to do this if we want to support this.
01236 
01237     if(data.mType == nsIDataType::VTYPE_ARRAY)
01238         return CloneArray(data.u.array.mArrayType, &data.u.array.mArrayInterfaceID,
01239                           data.u.array.mArrayCount, data.u.array.mArrayValue,
01240                           type, iid, count, ptr);
01241     return NS_ERROR_CANNOT_CONVERT_DATA;
01242 }
01243 
01244 /***************************************************************************/
01245 // static setter functions...
01246 
01247 #define DATA_SETTER_PROLOGUE(data_)                                           \
01248     nsVariant::Cleanup(data_);
01249 
01250 #define DATA_SETTER_EPILOGUE(data_, type_)                                    \
01251     data_->mType = nsIDataType :: type_;                                      \
01252     return NS_OK;
01253 
01254 #define DATA_SETTER(data_, type_, member_, value_)                            \
01255     DATA_SETTER_PROLOGUE(data_)                                               \
01256     data_->u.member_ = value_;                                                \
01257     DATA_SETTER_EPILOGUE(data_, type_)
01258 
01259 #define DATA_SETTER_WITH_CAST(data_, type_, member_, cast_, value_)           \
01260     DATA_SETTER_PROLOGUE(data_)                                               \
01261     data_->u.member_ = cast_ value_;                                          \
01262     DATA_SETTER_EPILOGUE(data_, type_)
01263 
01264 
01265 /********************************************/
01266 
01267 #define CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_)                          \
01268     {                                                                         \
01269 
01270 #define CASE__SET_FROM_VARIANT_VTYPE__GETTER(member_, name_)                  \
01271         rv = aValue->GetAs##name_ (&(data->u. member_ ));
01272 
01273 #define CASE__SET_FROM_VARIANT_VTYPE__GETTER_CAST(cast_, member_, name_)      \
01274         rv = aValue->GetAs##name_ ( cast_ &(data->u. member_ ));
01275 
01276 #define CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)                          \
01277         if(NS_SUCCEEDED(rv))                                                  \
01278         {                                                                     \
01279             data->mType  = nsIDataType :: type_ ;                             \
01280         }                                                                     \
01281         break;                                                                \
01282     }
01283 
01284 #define CASE__SET_FROM_VARIANT_TYPE(type_, member_, name_)                    \
01285     case nsIDataType :: type_ :                                               \
01286         CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_)                          \
01287         CASE__SET_FROM_VARIANT_VTYPE__GETTER(member_, name_)                  \
01288         CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)
01289 
01290 #define CASE__SET_FROM_VARIANT_VTYPE_CAST(type_, cast_, member_, name_)       \
01291     case nsIDataType :: type_ :                                               \
01292         CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_)                          \
01293         CASE__SET_FROM_VARIANT_VTYPE__GETTER_CAST(cast_, member_, name_)      \
01294         CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)
01295 
01296 
01297 /* static */ nsresult
01298 nsVariant::SetFromVariant(nsDiscriminatedUnion* data, nsIVariant* aValue)
01299 {
01300     PRUint16 type;
01301     nsresult rv;
01302 
01303     nsVariant::Cleanup(data);
01304 
01305     rv = aValue->GetDataType(&type);
01306     if(NS_FAILED(rv))
01307         return rv;
01308 
01309     switch(type)
01310     {
01311         CASE__SET_FROM_VARIANT_VTYPE_CAST(VTYPE_INT8, (PRUint8*), mInt8Value,
01312                                           Int8)
01313         CASE__SET_FROM_VARIANT_TYPE(VTYPE_INT16,  mInt16Value,  Int16)
01314         CASE__SET_FROM_VARIANT_TYPE(VTYPE_INT32,  mInt32Value,  Int32)
01315         CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT8,  mUint8Value,  Uint8)
01316         CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT16, mUint16Value, Uint16)
01317         CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT32, mUint32Value, Uint32)
01318         CASE__SET_FROM_VARIANT_TYPE(VTYPE_FLOAT,  mFloatValue,  Float)
01319         CASE__SET_FROM_VARIANT_TYPE(VTYPE_DOUBLE, mDoubleValue, Double)
01320         CASE__SET_FROM_VARIANT_TYPE(VTYPE_BOOL ,  mBoolValue,   Bool)
01321         CASE__SET_FROM_VARIANT_TYPE(VTYPE_CHAR,   mCharValue,   Char)
01322         CASE__SET_FROM_VARIANT_TYPE(VTYPE_WCHAR,  mWCharValue,  WChar)
01323         CASE__SET_FROM_VARIANT_TYPE(VTYPE_ID,     mIDValue,     ID)
01324 
01325         case nsIDataType::VTYPE_ASTRING:
01326         case nsIDataType::VTYPE_DOMSTRING:
01327         case nsIDataType::VTYPE_WCHAR_STR:
01328         case nsIDataType::VTYPE_WSTRING_SIZE_IS:
01329             CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_ASTRING);
01330             data->u.mAStringValue = new nsString();
01331             if(!data->u.mAStringValue)
01332                 return NS_ERROR_OUT_OF_MEMORY;
01333             rv = aValue->GetAsAString(*data->u.mAStringValue);
01334             if(NS_FAILED(rv))
01335                 delete data->u.mAStringValue;
01336             CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_ASTRING)
01337 
01338         case nsIDataType::VTYPE_CSTRING:
01339             CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_CSTRING);
01340             data->u.mCStringValue = new nsCString();
01341             if(!data->u.mCStringValue)
01342                 return NS_ERROR_OUT_OF_MEMORY;
01343             rv = aValue->GetAsACString(*data->u.mCStringValue);
01344             if(NS_FAILED(rv))
01345                 delete data->u.mCStringValue;
01346             CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_CSTRING)
01347 
01348         case nsIDataType::VTYPE_UTF8STRING:
01349             CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_UTF8STRING);
01350             data->u.mUTF8StringValue = new nsUTF8String();
01351             if(!data->u.mUTF8StringValue)
01352                 return NS_ERROR_OUT_OF_MEMORY;
01353             rv = aValue->GetAsAUTF8String(*data->u.mUTF8StringValue);
01354             if(NS_FAILED(rv))
01355                 delete data->u.mUTF8StringValue;
01356             CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_UTF8STRING)
01357 
01358         case nsIDataType::VTYPE_CHAR_STR:
01359         case nsIDataType::VTYPE_STRING_SIZE_IS:
01360             CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_STRING_SIZE_IS);
01361             rv = aValue->GetAsStringWithSize(&data->u.str.mStringLength,
01362                                              &data->u.str.mStringValue);
01363             CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_STRING_SIZE_IS)
01364 
01365         case nsIDataType::VTYPE_INTERFACE:
01366         case nsIDataType::VTYPE_INTERFACE_IS:
01367             CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_INTERFACE_IS);
01368             // XXX This iid handling is ugly!
01369             nsIID* iid;
01370             rv = aValue->GetAsInterface(&iid, (void**)&data->u.iface.mInterfaceValue);
01371             if(NS_SUCCEEDED(rv))
01372             {
01373                 data->u.iface.mInterfaceID = *iid;
01374                 nsMemory::Free((char*)iid);
01375             }
01376             CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_INTERFACE_IS)
01377 
01378         case nsIDataType::VTYPE_ARRAY:
01379             CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_ARRAY);
01380             rv = aValue->GetAsArray(&data->u.array.mArrayType,
01381                                     &data->u.array.mArrayInterfaceID,
01382                                     &data->u.array.mArrayCount,
01383                                     &data->u.array.mArrayValue);
01384             CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_ARRAY)
01385 
01386         case nsIDataType::VTYPE_VOID:
01387             rv = nsVariant::SetToVoid(data);
01388             break;
01389         case nsIDataType::VTYPE_EMPTY_ARRAY:
01390             rv = nsVariant::SetToEmptyArray(data);
01391             break;
01392         case nsIDataType::VTYPE_EMPTY:
01393             rv = nsVariant::SetToEmpty(data);
01394             break;
01395         default:
01396             NS_ERROR("bad type in variant!");
01397             rv = NS_ERROR_FAILURE;
01398             break;
01399     }
01400     return rv;
01401 }
01402 
01403 /* static */ nsresult
01404 nsVariant::SetFromInt8(nsDiscriminatedUnion* data, PRUint8 aValue)
01405 {
01406     DATA_SETTER_WITH_CAST(data, VTYPE_INT8, mInt8Value, (PRUint8), aValue)
01407 }
01408 /* static */ nsresult
01409 nsVariant::SetFromInt16(nsDiscriminatedUnion* data, PRInt16 aValue)
01410 {
01411     DATA_SETTER(data, VTYPE_INT16, mInt16Value, aValue)
01412 }
01413 /* static */ nsresult
01414 nsVariant::SetFromInt32(nsDiscriminatedUnion* data, PRInt32 aValue)
01415 {
01416     DATA_SETTER(data, VTYPE_INT32, mInt32Value, aValue)
01417 }
01418 /* static */ nsresult
01419 nsVariant::SetFromInt64(nsDiscriminatedUnion* data, PRInt64 aValue)
01420 {
01421     DATA_SETTER(data, VTYPE_INT64, mInt64Value, aValue)
01422 }
01423 /* static */ nsresult
01424 nsVariant::SetFromUint8(nsDiscriminatedUnion* data, PRUint8 aValue)
01425 {
01426     DATA_SETTER(data, VTYPE_UINT8, mUint8Value, aValue)
01427 }
01428 /* static */ nsresult
01429 nsVariant::SetFromUint16(nsDiscriminatedUnion* data, PRUint16 aValue)
01430 {
01431     DATA_SETTER(data, VTYPE_UINT16, mUint16Value, aValue)
01432 }
01433 /* static */ nsresult
01434 nsVariant::SetFromUint32(nsDiscriminatedUnion* data, PRUint32 aValue)
01435 {
01436     DATA_SETTER(data, VTYPE_UINT32, mUint32Value, aValue)
01437 }
01438 /* static */ nsresult
01439 nsVariant::SetFromUint64(nsDiscriminatedUnion* data, PRUint64 aValue)
01440 {
01441     DATA_SETTER(data, VTYPE_UINT64, mUint64Value, aValue)
01442 }
01443 /* static */ nsresult
01444 nsVariant::SetFromFloat(nsDiscriminatedUnion* data, float aValue)
01445 {
01446     DATA_SETTER(data, VTYPE_FLOAT, mFloatValue, aValue)
01447 }
01448 /* static */ nsresult
01449 nsVariant::SetFromDouble(nsDiscriminatedUnion* data, double aValue)
01450 {
01451     DATA_SETTER(data, VTYPE_DOUBLE, mDoubleValue, aValue)
01452 }
01453 /* static */ nsresult
01454 nsVariant::SetFromBool(nsDiscriminatedUnion* data, PRBool aValue)
01455 {
01456     DATA_SETTER(data, VTYPE_BOOL, mBoolValue, aValue)
01457 }
01458 /* static */ nsresult
01459 nsVariant::SetFromChar(nsDiscriminatedUnion* data, char aValue)
01460 {
01461     DATA_SETTER(data, VTYPE_CHAR, mCharValue, aValue)
01462 }
01463 /* static */ nsresult
01464 nsVariant::SetFromWChar(nsDiscriminatedUnion* data, PRUnichar aValue)
01465 {
01466     DATA_SETTER(data, VTYPE_WCHAR, mWCharValue, aValue)
01467 }
01468 /* static */ nsresult
01469 nsVariant::SetFromID(nsDiscriminatedUnion* data, const nsID & aValue)
01470 {
01471     DATA_SETTER(data, VTYPE_ID, mIDValue, aValue)
01472 }
01473 /* static */ nsresult
01474 nsVariant::SetFromAString(nsDiscriminatedUnion* data, const nsAString & aValue)
01475 {
01476     DATA_SETTER_PROLOGUE(data);
01477     if(!(data->u.mAStringValue = new nsString(aValue)))
01478         return NS_ERROR_OUT_OF_MEMORY;
01479     DATA_SETTER_EPILOGUE(data, VTYPE_ASTRING);
01480 }
01481 
01482 /* static */ nsresult
01483 nsVariant::SetFromACString(nsDiscriminatedUnion* data,
01484                            const nsACString & aValue)
01485 {
01486     DATA_SETTER_PROLOGUE(data);
01487     if(!(data->u.mCStringValue = new nsCString(aValue)))
01488         return NS_ERROR_OUT_OF_MEMORY;
01489     DATA_SETTER_EPILOGUE(data, VTYPE_CSTRING);
01490 }
01491 
01492 /* static */ nsresult
01493 nsVariant::SetFromAUTF8String(nsDiscriminatedUnion* data,
01494                               const nsAUTF8String & aValue)
01495 {
01496     DATA_SETTER_PROLOGUE(data);
01497     if(!(data->u.mUTF8StringValue = new nsUTF8String(aValue)))
01498         return NS_ERROR_OUT_OF_MEMORY;
01499     DATA_SETTER_EPILOGUE(data, VTYPE_UTF8STRING);
01500 }
01501 
01502 /* static */ nsresult
01503 nsVariant::SetFromString(nsDiscriminatedUnion* data, const char *aValue)
01504 {
01505     DATA_SETTER_PROLOGUE(data);
01506     if(!aValue)
01507         return NS_ERROR_NULL_POINTER;
01508     return SetFromStringWithSize(data, strlen(aValue), aValue);
01509 }
01510 /* static */ nsresult
01511 nsVariant::SetFromWString(nsDiscriminatedUnion* data, const PRUnichar *aValue)
01512 {
01513     DATA_SETTER_PROLOGUE(data);
01514     if(!aValue)
01515         return NS_ERROR_NULL_POINTER;
01516     return SetFromWStringWithSize(data, nsCRT::strlen(aValue), aValue);
01517 }
01518 /* static */ nsresult
01519 nsVariant::SetFromISupports(nsDiscriminatedUnion* data, nsISupports *aValue)
01520 {
01521     return SetFromInterface(data, NS_GET_IID(nsISupports), aValue);
01522 }
01523 /* static */ nsresult
01524 nsVariant::SetFromInterface(nsDiscriminatedUnion* data, const nsIID& iid,
01525                             nsISupports *aValue)
01526 {
01527     DATA_SETTER_PROLOGUE(data);
01528     NS_IF_ADDREF(aValue);
01529     data->u.iface.mInterfaceValue = aValue;
01530     data->u.iface.mInterfaceID = iid;
01531     DATA_SETTER_EPILOGUE(data, VTYPE_INTERFACE_IS);
01532 }
01533 /* static */ nsresult
01534 nsVariant::SetFromArray(nsDiscriminatedUnion* data, PRUint16 type,
01535                         const nsIID* iid, PRUint32 count, void * aValue)
01536 {
01537     DATA_SETTER_PROLOGUE(data);
01538     if(!aValue || !count)
01539         return NS_ERROR_NULL_POINTER;
01540 
01541     nsresult rv = CloneArray(type, iid, count, aValue,
01542                              &data->u.array.mArrayType,
01543                              &data->u.array.mArrayInterfaceID,
01544                              &data->u.array.mArrayCount,
01545                              &data->u.array.mArrayValue);
01546     if(NS_FAILED(rv))
01547         return rv;
01548     DATA_SETTER_EPILOGUE(data, VTYPE_ARRAY);
01549 }
01550 /* static */ nsresult
01551 nsVariant::SetFromStringWithSize(nsDiscriminatedUnion* data, PRUint32 size, const char *aValue)
01552 {
01553     DATA_SETTER_PROLOGUE(data);
01554     if(!aValue)
01555         return NS_ERROR_NULL_POINTER;
01556     if(!(data->u.str.mStringValue =
01557          (char*) nsMemory::Clone(aValue, (size+1)*sizeof(char))))
01558         return NS_ERROR_OUT_OF_MEMORY;
01559     data->u.str.mStringLength = size;
01560     DATA_SETTER_EPILOGUE(data, VTYPE_STRING_SIZE_IS);
01561 }
01562 /* static */ nsresult
01563 nsVariant::SetFromWStringWithSize(nsDiscriminatedUnion* data, PRUint32 size, const PRUnichar *aValue)
01564 {
01565     DATA_SETTER_PROLOGUE(data);
01566     if(!aValue)
01567         return NS_ERROR_NULL_POINTER;
01568     if(!(data->u.wstr.mWStringValue =
01569          (PRUnichar*) nsMemory::Clone(aValue, (size+1)*sizeof(PRUnichar))))
01570         return NS_ERROR_OUT_OF_MEMORY;
01571     data->u.wstr.mWStringLength = size;
01572     DATA_SETTER_EPILOGUE(data, VTYPE_WSTRING_SIZE_IS);
01573 }
01574 /* static */ nsresult
01575 nsVariant::SetToVoid(nsDiscriminatedUnion* data)
01576 {
01577     DATA_SETTER_PROLOGUE(data);
01578     DATA_SETTER_EPILOGUE(data, VTYPE_VOID);
01579 }
01580 /* static */ nsresult
01581 nsVariant::SetToEmpty(nsDiscriminatedUnion* data)
01582 {
01583     DATA_SETTER_PROLOGUE(data);
01584     DATA_SETTER_EPILOGUE(data, VTYPE_EMPTY);
01585 }
01586 /* static */ nsresult
01587 nsVariant::SetToEmptyArray(nsDiscriminatedUnion* data)
01588 {
01589     DATA_SETTER_PROLOGUE(data);
01590     DATA_SETTER_EPILOGUE(data, VTYPE_EMPTY_ARRAY);
01591 }
01592 
01593 /***************************************************************************/
01594 
01595 /* static */ nsresult
01596 nsVariant::Initialize(nsDiscriminatedUnion* data)
01597 {
01598     data->mType = nsIDataType::VTYPE_EMPTY;
01599     return NS_OK;
01600 }
01601 
01602 /* static */ nsresult
01603 nsVariant::Cleanup(nsDiscriminatedUnion* data)
01604 {
01605     switch(data->mType)
01606     {
01607         case nsIDataType::VTYPE_INT8:
01608         case nsIDataType::VTYPE_INT16:
01609         case nsIDataType::VTYPE_INT32:
01610         case nsIDataType::VTYPE_INT64:
01611         case nsIDataType::VTYPE_UINT8:
01612         case nsIDataType::VTYPE_UINT16:
01613         case nsIDataType::VTYPE_UINT32:
01614         case nsIDataType::VTYPE_UINT64:
01615         case nsIDataType::VTYPE_FLOAT:
01616         case nsIDataType::VTYPE_DOUBLE:
01617         case nsIDataType::VTYPE_BOOL:
01618         case nsIDataType::VTYPE_CHAR:
01619         case nsIDataType::VTYPE_WCHAR:
01620         case nsIDataType::VTYPE_VOID:
01621         case nsIDataType::VTYPE_ID:
01622             break;
01623         case nsIDataType::VTYPE_ASTRING:
01624         case nsIDataType::VTYPE_DOMSTRING:
01625             delete data->u.mAStringValue;
01626             break;
01627         case nsIDataType::VTYPE_CSTRING:
01628             delete data->u.mCStringValue;
01629             break;
01630         case nsIDataType::VTYPE_UTF8STRING:
01631             delete data->u.mUTF8StringValue;
01632             break;
01633         case nsIDataType::VTYPE_CHAR_STR:
01634         case nsIDataType::VTYPE_STRING_SIZE_IS:
01635             nsMemory::Free((char*)data->u.str.mStringValue);
01636             break;
01637         case nsIDataType::VTYPE_WCHAR_STR:
01638         case nsIDataType::VTYPE_WSTRING_SIZE_IS:
01639             nsMemory::Free((char*)data->u.wstr.mWStringValue);
01640             break;
01641         case nsIDataType::VTYPE_INTERFACE:
01642         case nsIDataType::VTYPE_INTERFACE_IS:
01643             NS_IF_RELEASE(data->u.iface.mInterfaceValue);
01644             break;
01645         case nsIDataType::VTYPE_ARRAY:
01646             FreeArray(data);
01647             break;
01648         case nsIDataType::VTYPE_EMPTY_ARRAY:
01649         case nsIDataType::VTYPE_EMPTY:
01650             break;
01651         default:
01652             NS_ERROR("bad type in variant!");
01653             break;
01654     }
01655 
01656     data->mType = nsIDataType::VTYPE_EMPTY;
01657     return NS_OK;
01658 }
01659 
01660 /***************************************************************************/
01661 /***************************************************************************/
01662 // members...
01663 
01664 NS_IMPL_ISUPPORTS2(nsVariant, nsIVariant, nsIWritableVariant)
01665 
01666 nsVariant::nsVariant()
01667     : mWritable(PR_TRUE)
01668 {
01669     nsVariant::Initialize(&mData);
01670 
01671 #ifdef DEBUG
01672     {
01673         // Assert that the nsIDataType consts match the values #defined in
01674         // xpt_struct.h. Bad things happen somewhere if they don't.
01675         struct THE_TYPES {PRUint16 a; PRUint16 b;};
01676         static const THE_TYPES array[] = {
01677             {nsIDataType::VTYPE_INT8              , TD_INT8             },
01678             {nsIDataType::VTYPE_INT16             , TD_INT16            },
01679             {nsIDataType::VTYPE_INT32             , TD_INT32            },
01680             {nsIDataType::VTYPE_INT64             , TD_INT64            },
01681             {nsIDataType::VTYPE_UINT8             , TD_UINT8            },
01682             {nsIDataType::VTYPE_UINT16            , TD_UINT16           },
01683             {nsIDataType::VTYPE_UINT32            , TD_UINT32           },
01684             {nsIDataType::VTYPE_UINT64            , TD_UINT64           },
01685             {nsIDataType::VTYPE_FLOAT             , TD_FLOAT            },
01686             {nsIDataType::VTYPE_DOUBLE            , TD_DOUBLE           },
01687             {nsIDataType::VTYPE_BOOL              , TD_BOOL             },
01688             {nsIDataType::VTYPE_CHAR              , TD_CHAR             },
01689             {nsIDataType::VTYPE_WCHAR             , TD_WCHAR            },
01690             {nsIDataType::VTYPE_VOID              , TD_VOID             },
01691             {nsIDataType::VTYPE_ID                , TD_PNSIID           },
01692             {nsIDataType::VTYPE_DOMSTRING         , TD_DOMSTRING        },
01693             {nsIDataType::VTYPE_CHAR_STR          , TD_PSTRING          },
01694             {nsIDataType::VTYPE_WCHAR_STR         , TD_PWSTRING         },
01695             {nsIDataType::VTYPE_INTERFACE         , TD_INTERFACE_TYPE   },
01696             {nsIDataType::VTYPE_INTERFACE_IS      , TD_INTERFACE_IS_TYPE},
01697             {nsIDataType::VTYPE_ARRAY             , TD_ARRAY            },
01698             {nsIDataType::VTYPE_STRING_SIZE_IS    , TD_PSTRING_SIZE_IS  },
01699             {nsIDataType::VTYPE_WSTRING_SIZE_IS   , TD_PWSTRING_SIZE_IS },
01700             {nsIDataType::VTYPE_UTF8STRING        , TD_UTF8STRING       },
01701             {nsIDataType::VTYPE_CSTRING           , TD_CSTRING          },
01702             {nsIDataType::VTYPE_ASTRING           , TD_ASTRING          }
01703         };
01704         static const int length = sizeof(array)/sizeof(array[0]);
01705         static PRBool inited = PR_FALSE;
01706         if(!inited)
01707         {
01708             for(int i = 0; i < length; i++)
01709                 NS_ASSERTION(array[i].a == array[i].b, "bad const declaration");
01710             inited = PR_TRUE;
01711         }
01712     }
01713 #endif
01714 }
01715 
01716 nsVariant::~nsVariant()
01717 {
01718     nsVariant::Cleanup(&mData);
01719 }
01720 
01721 // For all the data getters we just forward to the static (and sharable)
01722 // 'ConvertTo' functions.
01723 
01724 /* readonly attribute PRUint16 dataType; */
01725 NS_IMETHODIMP nsVariant::GetDataType(PRUint16 *aDataType)
01726 {
01727     *aDataType = mData.mType;
01728     return NS_OK;
01729 }
01730 
01731 /* PRUint8 getAsInt8 (); */
01732 NS_IMETHODIMP nsVariant::GetAsInt8(PRUint8 *_retval)
01733 {
01734     return nsVariant::ConvertToInt8(mData, _retval);
01735 }
01736 
01737 /* PRInt16 getAsInt16 (); */
01738 NS_IMETHODIMP nsVariant::GetAsInt16(PRInt16 *_retval)
01739 {
01740     return nsVariant::ConvertToInt16(mData, _retval);
01741 }
01742 
01743 /* PRInt32 getAsInt32 (); */
01744 NS_IMETHODIMP nsVariant::GetAsInt32(PRInt32 *_retval)
01745 {
01746     return nsVariant::ConvertToInt32(mData, _retval);
01747 }
01748 
01749 /* PRInt64 getAsInt64 (); */
01750 NS_IMETHODIMP nsVariant::GetAsInt64(PRInt64 *_retval)
01751 {
01752     return nsVariant::ConvertToInt64(mData, _retval);
01753 }
01754 
01755 /* PRUint8 getAsUint8 (); */
01756 NS_IMETHODIMP nsVariant::GetAsUint8(PRUint8 *_retval)
01757 {
01758     return nsVariant::ConvertToUint8(mData, _retval);
01759 }
01760 
01761 /* PRUint16 getAsUint16 (); */
01762 NS_IMETHODIMP nsVariant::GetAsUint16(PRUint16 *_retval)
01763 {
01764     return nsVariant::ConvertToUint16(mData, _retval);
01765 }
01766 
01767 /* PRUint32 getAsUint32 (); */
01768 NS_IMETHODIMP nsVariant::GetAsUint32(PRUint32 *_retval)
01769 {
01770     return nsVariant::ConvertToUint32(mData, _retval);
01771 }
01772 
01773 /* PRUint64 getAsUint64 (); */
01774 NS_IMETHODIMP nsVariant::GetAsUint64(PRUint64 *_retval)
01775 {
01776     return nsVariant::ConvertToUint64(mData, _retval);
01777 }
01778 
01779 /* float getAsFloat (); */
01780 NS_IMETHODIMP nsVariant::GetAsFloat(float *_retval)
01781 {
01782     return nsVariant::ConvertToFloat(mData, _retval);
01783 }
01784 
01785 /* double getAsDouble (); */
01786 NS_IMETHODIMP nsVariant::GetAsDouble(double *_retval)
01787 {
01788     return nsVariant::ConvertToDouble(mData, _retval);
01789 }
01790 
01791 /* PRBool getAsBool (); */
01792 NS_IMETHODIMP nsVariant::GetAsBool(PRBool *_retval)
01793 {
01794     return nsVariant::ConvertToBool(mData, _retval);
01795 }
01796 
01797 /* char getAsChar (); */
01798 NS_IMETHODIMP nsVariant::GetAsChar(char *_retval)
01799 {
01800     return nsVariant::ConvertToChar(mData, _retval);
01801 }
01802 
01803 /* wchar getAsWChar (); */
01804 NS_IMETHODIMP nsVariant::GetAsWChar(PRUnichar *_retval)
01805 {
01806     return nsVariant::ConvertToWChar(mData, _retval);
01807 }
01808 
01809 /* [notxpcom] nsresult getAsID (out nsID retval); */
01810 NS_IMETHODIMP_(nsresult) nsVariant::GetAsID(nsID *retval)
01811 {
01812     return nsVariant::ConvertToID(mData, retval);
01813 }
01814 
01815 /* AString getAsAString (); */
01816 NS_IMETHODIMP nsVariant::GetAsAString(nsAString & _retval)
01817 {
01818     return nsVariant::ConvertToAString(mData, _retval);
01819 }
01820 
01821 /* DOMString getAsDOMString (); */
01822 NS_IMETHODIMP nsVariant::GetAsDOMString(nsAString & _retval)
01823 {
01824     // A DOMString maps to an AString internally, so we can re-use
01825     // ConvertToAString here.
01826     return nsVariant::ConvertToAString(mData, _retval);
01827 }
01828 
01829 /* ACString getAsACString (); */
01830 NS_IMETHODIMP nsVariant::GetAsACString(nsACString & _retval)
01831 {
01832     return nsVariant::ConvertToACString(mData, _retval);
01833 }
01834 
01835 /* AUTF8String getAsAUTF8String (); */
01836 NS_IMETHODIMP nsVariant::GetAsAUTF8String(nsAUTF8String & _retval)
01837 {
01838     return nsVariant::ConvertToAUTF8String(mData, _retval);
01839 }
01840 
01841 /* string getAsString (); */
01842 NS_IMETHODIMP nsVariant::GetAsString(char **_retval)
01843 {
01844     return nsVariant::ConvertToString(mData, _retval);
01845 }
01846 
01847 /* wstring getAsWString (); */
01848 NS_IMETHODIMP nsVariant::GetAsWString(PRUnichar **_retval)
01849 {
01850     return nsVariant::ConvertToWString(mData, _retval);
01851 }
01852 
01853 /* nsISupports getAsISupports (); */
01854 NS_IMETHODIMP nsVariant::GetAsISupports(nsISupports **_retval)
01855 {
01856     return nsVariant::ConvertToISupports(mData, _retval);
01857 }
01858 
01859 /* void getAsInterface (out nsIIDPtr iid, [iid_is (iid), retval] out nsQIResult iface); */
01860 NS_IMETHODIMP nsVariant::GetAsInterface(nsIID * *iid, void * *iface)
01861 {
01862     return nsVariant::ConvertToInterface(mData, iid, iface);
01863 }
01864 
01865 /* [notxpcom] nsresult getAsArray (out PRUint16 type, out nsIID iid, out PRUint32 count, out voidPtr ptr); */
01866 NS_IMETHODIMP_(nsresult) nsVariant::GetAsArray(PRUint16 *type, nsIID *iid, PRUint32 *count, void * *ptr)
01867 {
01868     return nsVariant::ConvertToArray(mData, type, iid, count, ptr);
01869 }
01870 
01871 /* void getAsStringWithSize (out PRUint32 size, [size_is (size), retval] out string str); */
01872 NS_IMETHODIMP nsVariant::GetAsStringWithSize(PRUint32 *size, char **str)
01873 {
01874     return nsVariant::ConvertToStringWithSize(mData, size, str);
01875 }
01876 
01877 /* void getAsWStringWithSize (out PRUint32 size, [size_is (size), retval] out wstring str); */
01878 NS_IMETHODIMP nsVariant::GetAsWStringWithSize(PRUint32 *size, PRUnichar **str)
01879 {
01880     return nsVariant::ConvertToWStringWithSize(mData, size, str);
01881 }
01882 
01883 /***************************************************************************/
01884 
01885 /* attribute PRBool writable; */
01886 NS_IMETHODIMP nsVariant::GetWritable(PRBool *aWritable)
01887 {
01888     *aWritable = mWritable;
01889     return NS_OK;
01890 }
01891 NS_IMETHODIMP nsVariant::SetWritable(PRBool aWritable)
01892 {
01893     if(!mWritable && aWritable)
01894         return NS_ERROR_FAILURE;
01895     mWritable = aWritable;
01896     return NS_OK;
01897 }
01898 
01899 /***************************************************************************/
01900 
01901 // For all the data setters we just forward to the static (and sharable)
01902 // 'SetFrom' functions.
01903 
01904 /* void setAsInt8 (in PRUint8 aValue); */
01905 NS_IMETHODIMP nsVariant::SetAsInt8(PRUint8 aValue)
01906 {
01907     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
01908     return nsVariant::SetFromInt8(&mData, aValue);
01909 }
01910 
01911 /* void setAsInt16 (in PRInt16 aValue); */
01912 NS_IMETHODIMP nsVariant::SetAsInt16(PRInt16 aValue)
01913 {
01914     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
01915     return nsVariant::SetFromInt16(&mData, aValue);
01916 }
01917 
01918 /* void setAsInt32 (in PRInt32 aValue); */
01919 NS_IMETHODIMP nsVariant::SetAsInt32(PRInt32 aValue)
01920 {
01921     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
01922     return nsVariant::SetFromInt32(&mData, aValue);
01923 }
01924 
01925 /* void setAsInt64 (in PRInt64 aValue); */
01926 NS_IMETHODIMP nsVariant::SetAsInt64(PRInt64 aValue)
01927 {
01928     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
01929     return nsVariant::SetFromInt64(&mData, aValue);
01930 }
01931 
01932 /* void setAsUint8 (in PRUint8 aValue); */
01933 NS_IMETHODIMP nsVariant::SetAsUint8(PRUint8 aValue)
01934 {
01935     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
01936     return nsVariant::SetFromUint8(&mData, aValue);
01937 }
01938 
01939 /* void setAsUint16 (in PRUint16 aValue); */
01940 NS_IMETHODIMP nsVariant::SetAsUint16(PRUint16 aValue)
01941 {
01942     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
01943     return nsVariant::SetFromUint16(&mData, aValue);
01944 }
01945 
01946 /* void setAsUint32 (in PRUint32 aValue); */
01947 NS_IMETHODIMP nsVariant::SetAsUint32(PRUint32 aValue)
01948 {
01949     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
01950     return nsVariant::SetFromUint32(&mData, aValue);
01951 }
01952 
01953 /* void setAsUint64 (in PRUint64 aValue); */
01954 NS_IMETHODIMP nsVariant::SetAsUint64(PRUint64 aValue)
01955 {
01956     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
01957     return nsVariant::SetFromUint64(&mData, aValue);
01958 }
01959 
01960 /* void setAsFloat (in float aValue); */
01961 NS_IMETHODIMP nsVariant::SetAsFloat(float aValue)
01962 {
01963     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
01964     return nsVariant::SetFromFloat(&mData, aValue);
01965 }
01966 
01967 /* void setAsDouble (in double aValue); */
01968 NS_IMETHODIMP nsVariant::SetAsDouble(double aValue)
01969 {
01970     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
01971     return nsVariant::SetFromDouble(&mData, aValue);
01972 }
01973 
01974 /* void setAsBool (in PRBool aValue); */
01975 NS_IMETHODIMP nsVariant::SetAsBool(PRBool aValue)
01976 {
01977     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
01978     return nsVariant::SetFromBool(&mData, aValue);
01979 }
01980 
01981 /* void setAsChar (in char aValue); */
01982 NS_IMETHODIMP nsVariant::SetAsChar(char aValue)
01983 {
01984     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
01985     return nsVariant::SetFromChar(&mData, aValue);
01986 }
01987 
01988 /* void setAsWChar (in wchar aValue); */
01989 NS_IMETHODIMP nsVariant::SetAsWChar(PRUnichar aValue)
01990 {
01991     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
01992     return nsVariant::SetFromWChar(&mData, aValue);
01993 }
01994 
01995 /* void setAsID (in nsIDRef aValue); */
01996 NS_IMETHODIMP nsVariant::SetAsID(const nsID & aValue)
01997 {
01998     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
01999     return nsVariant::SetFromID(&mData, aValue);
02000 }
02001 
02002 /* void setAsAString (in AString aValue); */
02003 NS_IMETHODIMP nsVariant::SetAsAString(const nsAString & aValue)
02004 {
02005     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
02006     return nsVariant::SetFromAString(&mData, aValue);
02007 }
02008 
02009 /* void setAsDOMString (in DOMString aValue); */
02010 NS_IMETHODIMP nsVariant::SetAsDOMString(const nsAString & aValue)
02011 {
02012     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
02013 
02014     // A DOMString maps to an AString internally, so we can re-use
02015     // SetFromAString here.
02016     return nsVariant::SetFromAString(&mData, aValue);
02017 }
02018 
02019 /* void setAsACString (in ACString aValue); */
02020 NS_IMETHODIMP nsVariant::SetAsACString(const nsACString & aValue)
02021 {
02022     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
02023     return nsVariant::SetFromACString(&mData, aValue);
02024 }
02025 
02026 /* void setAsAUTF8String (in AUTF8String aValue); */
02027 NS_IMETHODIMP nsVariant::SetAsAUTF8String(const nsAUTF8String & aValue)
02028 {
02029     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
02030     return nsVariant::SetFromAUTF8String(&mData, aValue);
02031 }
02032 
02033 /* void setAsString (in string aValue); */
02034 NS_IMETHODIMP nsVariant::SetAsString(const char *aValue)
02035 {
02036     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
02037     return nsVariant::SetFromString(&mData, aValue);
02038 }
02039 
02040 /* void setAsWString (in wstring aValue); */
02041 NS_IMETHODIMP nsVariant::SetAsWString(const PRUnichar *aValue)
02042 {
02043     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
02044     return nsVariant::SetFromWString(&mData, aValue);
02045 }
02046 
02047 /* void setAsISupports (in nsISupports aValue); */
02048 NS_IMETHODIMP nsVariant::SetAsISupports(nsISupports *aValue)
02049 {
02050     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
02051     return nsVariant::SetFromISupports(&mData, aValue);
02052 }
02053 
02054 /* void setAsInterface (in nsIIDRef iid, [iid_is (iid)] in nsQIResult iface); */
02055 NS_IMETHODIMP nsVariant::SetAsInterface(const nsIID & iid, void * iface)
02056 {
02057     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
02058     return nsVariant::SetFromInterface(&mData, iid, (nsISupports*)iface);
02059 }
02060 
02061 /* [noscript] void setAsArray (in PRUint16 type, in nsIIDPtr iid, in PRUint32 count, in voidPtr ptr); */
02062 NS_IMETHODIMP nsVariant::SetAsArray(PRUint16 type, const nsIID * iid, PRUint32 count, void * ptr)
02063 {
02064     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
02065     return nsVariant::SetFromArray(&mData, type, iid, count, ptr);
02066 }
02067 
02068 /* void setAsStringWithSize (in PRUint32 size, [size_is (size)] in string str); */
02069 NS_IMETHODIMP nsVariant::SetAsStringWithSize(PRUint32 size, const char *str)
02070 {
02071     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
02072     return nsVariant::SetFromStringWithSize(&mData, size, str);
02073 }
02074 
02075 /* void setAsWStringWithSize (in PRUint32 size, [size_is (size)] in wstring str); */
02076 NS_IMETHODIMP nsVariant::SetAsWStringWithSize(PRUint32 size, const PRUnichar *str)
02077 {
02078     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
02079     return nsVariant::SetFromWStringWithSize(&mData, size, str);
02080 }
02081 
02082 /* void setAsVoid (); */
02083 NS_IMETHODIMP nsVariant::SetAsVoid()
02084 {
02085     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
02086     return nsVariant::SetToVoid(&mData);
02087 }
02088 
02089 /* void setAsEmpty (); */
02090 NS_IMETHODIMP nsVariant::SetAsEmpty()
02091 {
02092     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
02093     return nsVariant::SetToEmpty(&mData);
02094 }
02095 
02096 /* void setAsEmptyArray (); */
02097 NS_IMETHODIMP nsVariant::SetAsEmptyArray()
02098 {
02099     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
02100     return nsVariant::SetToEmptyArray(&mData);
02101 }
02102 
02103 /* void setFromVariant (in nsIVariant aValue); */
02104 NS_IMETHODIMP nsVariant::SetFromVariant(nsIVariant *aValue)
02105 {
02106     if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
02107     return nsVariant::SetFromVariant(&mData, aValue);
02108 }