On x86 compilers without fastcall, simulate it when invoking traces and un-simulate...
[wine-gecko.git] / xpcom / ds / nsVariant.cpp
blobc33621b977b08231556a52a6e4a2c71bcae754a1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is mozilla.org code.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 1998
21 * the Initial Developer. All Rights Reserved.
23 * Contributor(s):
24 * John Bandhauer <jband@netscape.com>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 /* The long avoided variant support for xpcom. */
42 #include "nsVariant.h"
43 #include "nsString.h"
44 #include "prprf.h"
45 #include "prdtoa.h"
46 #include <math.h>
47 #include "nsCRT.h"
48 #include "nsCycleCollectionParticipant.h"
50 /***************************************************************************/
51 // Helpers for static convert functions...
53 static nsresult String2Double(const char* aString, double* retval)
55 char* next;
56 double value = PR_strtod(aString, &next);
57 if(next == aString)
58 return NS_ERROR_CANNOT_CONVERT_DATA;
59 *retval = value;
60 return NS_OK;
63 static nsresult AString2Double(const nsAString& aString, double* retval)
65 char* pChars = ToNewCString(aString);
66 if(!pChars)
67 return NS_ERROR_OUT_OF_MEMORY;
68 nsresult rv = String2Double(pChars, retval);
69 nsMemory::Free(pChars);
70 return rv;
73 static nsresult AUTF8String2Double(const nsAUTF8String& aString, double* retval)
75 return String2Double(PromiseFlatUTF8String(aString).get(), retval);
78 static nsresult ACString2Double(const nsACString& aString, double* retval)
80 return String2Double(PromiseFlatCString(aString).get(), retval);
83 // Fills outVariant with double, PRUint32, or PRInt32.
84 // Returns NS_OK, an error code, or a non-NS_OK success code
85 static nsresult ToManageableNumber(const nsDiscriminatedUnion& inData,
86 nsDiscriminatedUnion* outData)
88 nsresult rv;
90 switch(inData.mType)
92 // This group results in a PRInt32...
94 #define CASE__NUMBER_INT32(type_, member_) \
95 case nsIDataType :: type_ : \
96 outData->u.mInt32Value = inData.u. member_ ; \
97 outData->mType = nsIDataType::VTYPE_INT32; \
98 return NS_OK;
100 CASE__NUMBER_INT32(VTYPE_INT8, mInt8Value)
101 CASE__NUMBER_INT32(VTYPE_INT16, mInt16Value)
102 CASE__NUMBER_INT32(VTYPE_INT32, mInt32Value)
103 CASE__NUMBER_INT32(VTYPE_UINT8, mUint8Value)
104 CASE__NUMBER_INT32(VTYPE_UINT16, mUint16Value)
105 CASE__NUMBER_INT32(VTYPE_BOOL, mBoolValue)
106 CASE__NUMBER_INT32(VTYPE_CHAR, mCharValue)
107 CASE__NUMBER_INT32(VTYPE_WCHAR, mWCharValue)
109 #undef CASE__NUMBER_INT32
111 // This group results in a PRUint32...
113 case nsIDataType::VTYPE_UINT32:
114 outData->u.mInt32Value = inData.u.mUint32Value;
115 outData->mType = nsIDataType::VTYPE_INT32;
116 return NS_OK;
118 // This group results in a double...
120 case nsIDataType::VTYPE_INT64:
121 case nsIDataType::VTYPE_UINT64:
122 // XXX Need boundary checking here.
123 // We may need to return NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA
124 LL_L2D(outData->u.mDoubleValue, inData.u.mInt64Value);
125 outData->mType = nsIDataType::VTYPE_DOUBLE;
126 return NS_OK;
127 case nsIDataType::VTYPE_FLOAT:
128 outData->u.mDoubleValue = inData.u.mFloatValue;
129 outData->mType = nsIDataType::VTYPE_DOUBLE;
130 return NS_OK;
131 case nsIDataType::VTYPE_DOUBLE:
132 outData->u.mDoubleValue = inData.u.mDoubleValue;
133 outData->mType = nsIDataType::VTYPE_DOUBLE;
134 return NS_OK;
135 case nsIDataType::VTYPE_CHAR_STR:
136 case nsIDataType::VTYPE_STRING_SIZE_IS:
137 rv = String2Double(inData.u.str.mStringValue, &outData->u.mDoubleValue);
138 if(NS_FAILED(rv))
139 return rv;
140 outData->mType = nsIDataType::VTYPE_DOUBLE;
141 return NS_OK;
142 case nsIDataType::VTYPE_DOMSTRING:
143 case nsIDataType::VTYPE_ASTRING:
144 rv = AString2Double(*inData.u.mAStringValue, &outData->u.mDoubleValue);
145 if(NS_FAILED(rv))
146 return rv;
147 outData->mType = nsIDataType::VTYPE_DOUBLE;
148 return NS_OK;
149 case nsIDataType::VTYPE_UTF8STRING:
150 rv = AUTF8String2Double(*inData.u.mUTF8StringValue,
151 &outData->u.mDoubleValue);
152 if(NS_FAILED(rv))
153 return rv;
154 outData->mType = nsIDataType::VTYPE_DOUBLE;
155 return NS_OK;
156 case nsIDataType::VTYPE_CSTRING:
157 rv = ACString2Double(*inData.u.mCStringValue,
158 &outData->u.mDoubleValue);
159 if(NS_FAILED(rv))
160 return rv;
161 outData->mType = nsIDataType::VTYPE_DOUBLE;
162 return NS_OK;
163 case nsIDataType::VTYPE_WCHAR_STR:
164 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
165 rv = AString2Double(nsDependentString(inData.u.wstr.mWStringValue),
166 &outData->u.mDoubleValue);
167 if(NS_FAILED(rv))
168 return rv;
169 outData->mType = nsIDataType::VTYPE_DOUBLE;
170 return NS_OK;
172 // This group fails...
174 case nsIDataType::VTYPE_VOID:
175 case nsIDataType::VTYPE_ID:
176 case nsIDataType::VTYPE_INTERFACE:
177 case nsIDataType::VTYPE_INTERFACE_IS:
178 case nsIDataType::VTYPE_ARRAY:
179 case nsIDataType::VTYPE_EMPTY_ARRAY:
180 case nsIDataType::VTYPE_EMPTY:
181 default:
182 return NS_ERROR_CANNOT_CONVERT_DATA;
186 /***************************************************************************/
187 // Array helpers...
189 static void FreeArray(nsDiscriminatedUnion* data)
191 NS_ASSERTION(data->mType == nsIDataType::VTYPE_ARRAY, "bad FreeArray call");
192 NS_ASSERTION(data->u.array.mArrayValue, "bad array");
193 NS_ASSERTION(data->u.array.mArrayCount, "bad array count");
195 #define CASE__FREE_ARRAY_PTR(type_, ctype_) \
196 case nsIDataType:: type_ : \
198 ctype_ ** p = (ctype_ **) data->u.array.mArrayValue; \
199 for(PRUint32 i = data->u.array.mArrayCount; i > 0; p++, i--) \
200 if(*p) \
201 nsMemory::Free((char*)*p); \
202 break; \
205 #define CASE__FREE_ARRAY_IFACE(type_, ctype_) \
206 case nsIDataType:: type_ : \
208 ctype_ ** p = (ctype_ **) data->u.array.mArrayValue; \
209 for(PRUint32 i = data->u.array.mArrayCount; i > 0; p++, i--) \
210 if(*p) \
211 (*p)->Release(); \
212 break; \
215 switch(data->u.array.mArrayType)
217 case nsIDataType::VTYPE_INT8:
218 case nsIDataType::VTYPE_INT16:
219 case nsIDataType::VTYPE_INT32:
220 case nsIDataType::VTYPE_INT64:
221 case nsIDataType::VTYPE_UINT8:
222 case nsIDataType::VTYPE_UINT16:
223 case nsIDataType::VTYPE_UINT32:
224 case nsIDataType::VTYPE_UINT64:
225 case nsIDataType::VTYPE_FLOAT:
226 case nsIDataType::VTYPE_DOUBLE:
227 case nsIDataType::VTYPE_BOOL:
228 case nsIDataType::VTYPE_CHAR:
229 case nsIDataType::VTYPE_WCHAR:
230 break;
232 // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
233 CASE__FREE_ARRAY_PTR(VTYPE_ID, nsID)
234 CASE__FREE_ARRAY_PTR(VTYPE_CHAR_STR, char)
235 CASE__FREE_ARRAY_PTR(VTYPE_WCHAR_STR, PRUnichar)
236 CASE__FREE_ARRAY_IFACE(VTYPE_INTERFACE, nsISupports)
237 CASE__FREE_ARRAY_IFACE(VTYPE_INTERFACE_IS, nsISupports)
239 // The rest are illegal.
240 case nsIDataType::VTYPE_VOID:
241 case nsIDataType::VTYPE_ASTRING:
242 case nsIDataType::VTYPE_DOMSTRING:
243 case nsIDataType::VTYPE_UTF8STRING:
244 case nsIDataType::VTYPE_CSTRING:
245 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
246 case nsIDataType::VTYPE_STRING_SIZE_IS:
247 case nsIDataType::VTYPE_ARRAY:
248 case nsIDataType::VTYPE_EMPTY_ARRAY:
249 case nsIDataType::VTYPE_EMPTY:
250 default:
251 NS_ERROR("bad type in array!");
252 break;
255 // Free the array memory.
256 nsMemory::Free((char*)data->u.array.mArrayValue);
258 #undef CASE__FREE_ARRAY_PTR
259 #undef CASE__FREE_ARRAY_IFACE
262 static nsresult CloneArray(PRUint16 inType, const nsIID* inIID,
263 PRUint32 inCount, void* inValue,
264 PRUint16* outType, nsIID* outIID,
265 PRUint32* outCount, void** outValue)
267 NS_ASSERTION(inCount, "bad param");
268 NS_ASSERTION(inValue, "bad param");
269 NS_ASSERTION(outType, "bad param");
270 NS_ASSERTION(outCount, "bad param");
271 NS_ASSERTION(outValue, "bad param");
273 PRUint32 allocatedValueCount = 0;
274 nsresult rv = NS_OK;
275 PRUint32 i;
277 // First we figure out the size of the elements for the new u.array.
279 size_t elementSize;
280 size_t allocSize;
282 switch(inType)
284 case nsIDataType::VTYPE_INT8:
285 elementSize = sizeof(PRInt8);
286 break;
287 case nsIDataType::VTYPE_INT16:
288 elementSize = sizeof(PRInt16);
289 break;
290 case nsIDataType::VTYPE_INT32:
291 elementSize = sizeof(PRInt32);
292 break;
293 case nsIDataType::VTYPE_INT64:
294 elementSize = sizeof(PRInt64);
295 break;
296 case nsIDataType::VTYPE_UINT8:
297 elementSize = sizeof(PRUint8);
298 break;
299 case nsIDataType::VTYPE_UINT16:
300 elementSize = sizeof(PRUint16);
301 break;
302 case nsIDataType::VTYPE_UINT32:
303 elementSize = sizeof(PRUint32);
304 break;
305 case nsIDataType::VTYPE_UINT64:
306 elementSize = sizeof(PRUint64);
307 break;
308 case nsIDataType::VTYPE_FLOAT:
309 elementSize = sizeof(float);
310 break;
311 case nsIDataType::VTYPE_DOUBLE:
312 elementSize = sizeof(double);
313 break;
314 case nsIDataType::VTYPE_BOOL:
315 elementSize = sizeof(PRBool);
316 break;
317 case nsIDataType::VTYPE_CHAR:
318 elementSize = sizeof(char);
319 break;
320 case nsIDataType::VTYPE_WCHAR:
321 elementSize = sizeof(PRUnichar);
322 break;
324 // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
325 case nsIDataType::VTYPE_ID:
326 case nsIDataType::VTYPE_CHAR_STR:
327 case nsIDataType::VTYPE_WCHAR_STR:
328 case nsIDataType::VTYPE_INTERFACE:
329 case nsIDataType::VTYPE_INTERFACE_IS:
330 elementSize = sizeof(void*);
331 break;
333 // The rest are illegal.
334 case nsIDataType::VTYPE_ASTRING:
335 case nsIDataType::VTYPE_DOMSTRING:
336 case nsIDataType::VTYPE_UTF8STRING:
337 case nsIDataType::VTYPE_CSTRING:
338 case nsIDataType::VTYPE_STRING_SIZE_IS:
339 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
340 case nsIDataType::VTYPE_VOID:
341 case nsIDataType::VTYPE_ARRAY:
342 case nsIDataType::VTYPE_EMPTY_ARRAY:
343 case nsIDataType::VTYPE_EMPTY:
344 default:
345 NS_ERROR("bad type in array!");
346 return NS_ERROR_CANNOT_CONVERT_DATA;
350 // Alloc the u.array.
352 allocSize = inCount * elementSize;
353 *outValue = nsMemory::Alloc(allocSize);
354 if(!*outValue)
355 return NS_ERROR_OUT_OF_MEMORY;
357 // Clone the elements.
359 switch(inType)
361 case nsIDataType::VTYPE_INT8:
362 case nsIDataType::VTYPE_INT16:
363 case nsIDataType::VTYPE_INT32:
364 case nsIDataType::VTYPE_INT64:
365 case nsIDataType::VTYPE_UINT8:
366 case nsIDataType::VTYPE_UINT16:
367 case nsIDataType::VTYPE_UINT32:
368 case nsIDataType::VTYPE_UINT64:
369 case nsIDataType::VTYPE_FLOAT:
370 case nsIDataType::VTYPE_DOUBLE:
371 case nsIDataType::VTYPE_BOOL:
372 case nsIDataType::VTYPE_CHAR:
373 case nsIDataType::VTYPE_WCHAR:
374 memcpy(*outValue, inValue, allocSize);
375 break;
377 case nsIDataType::VTYPE_INTERFACE_IS:
378 if(outIID)
379 *outIID = *inIID;
380 // fall through...
381 case nsIDataType::VTYPE_INTERFACE:
383 memcpy(*outValue, inValue, allocSize);
385 nsISupports** p = (nsISupports**) *outValue;
386 for(i = inCount; i > 0; p++, i--)
387 if(*p)
388 (*p)->AddRef();
389 break;
392 // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
393 case nsIDataType::VTYPE_ID:
395 nsID** inp = (nsID**) inValue;
396 nsID** outp = (nsID**) *outValue;
397 for(i = inCount; i > 0; i--)
399 nsID* idp = *(inp++);
400 if(idp)
402 if(nsnull == (*(outp++) = (nsID*)
403 nsMemory::Clone((char*)idp, sizeof(nsID))))
404 goto bad;
406 else
407 *(outp++) = nsnull;
408 allocatedValueCount++;
410 break;
413 case nsIDataType::VTYPE_CHAR_STR:
415 char** inp = (char**) inValue;
416 char** outp = (char**) *outValue;
417 for(i = inCount; i > 0; i--)
419 char* str = *(inp++);
420 if(str)
422 if(nsnull == (*(outp++) = (char*)
423 nsMemory::Clone(str, (strlen(str)+1)*sizeof(char))))
424 goto bad;
426 else
427 *(outp++) = nsnull;
428 allocatedValueCount++;
430 break;
433 case nsIDataType::VTYPE_WCHAR_STR:
435 PRUnichar** inp = (PRUnichar**) inValue;
436 PRUnichar** outp = (PRUnichar**) *outValue;
437 for(i = inCount; i > 0; i--)
439 PRUnichar* str = *(inp++);
440 if(str)
442 if(nsnull == (*(outp++) = (PRUnichar*)
443 nsMemory::Clone(str,
444 (nsCRT::strlen(str)+1)*sizeof(PRUnichar))))
445 goto bad;
447 else
448 *(outp++) = nsnull;
449 allocatedValueCount++;
451 break;
454 // The rest are illegal.
455 case nsIDataType::VTYPE_VOID:
456 case nsIDataType::VTYPE_ARRAY:
457 case nsIDataType::VTYPE_EMPTY_ARRAY:
458 case nsIDataType::VTYPE_EMPTY:
459 case nsIDataType::VTYPE_ASTRING:
460 case nsIDataType::VTYPE_DOMSTRING:
461 case nsIDataType::VTYPE_UTF8STRING:
462 case nsIDataType::VTYPE_CSTRING:
463 case nsIDataType::VTYPE_STRING_SIZE_IS:
464 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
465 default:
466 NS_ERROR("bad type in array!");
467 return NS_ERROR_CANNOT_CONVERT_DATA;
470 *outType = inType;
471 *outCount = inCount;
472 return NS_OK;
474 bad:
475 if(*outValue)
477 char** p = (char**) *outValue;
478 for(i = allocatedValueCount; i > 0; p++, i--)
479 if(*p)
480 nsMemory::Free(*p);
481 nsMemory::Free((char*)*outValue);
482 *outValue = nsnull;
484 return rv;
487 /***************************************************************************/
489 #define TRIVIAL_DATA_CONVERTER(type_, data_, member_, retval_) \
490 if(data_.mType == nsIDataType :: type_) { \
491 *retval_ = data_.u.member_; \
492 return NS_OK; \
495 #define NUMERIC_CONVERSION_METHOD_BEGIN(type_, Ctype_, name_) \
496 /* static */ nsresult \
497 nsVariant::ConvertTo##name_ (const nsDiscriminatedUnion& data, \
498 Ctype_ *_retval) \
500 TRIVIAL_DATA_CONVERTER(type_, data, m##name_##Value, _retval) \
501 nsDiscriminatedUnion tempData; \
502 nsVariant::Initialize(&tempData); \
503 nsresult rv = ToManageableNumber(data, &tempData); \
504 /* */ \
505 /* NOTE: rv may indicate a success code that we want to preserve */ \
506 /* For the final return. So all the return cases below should return */ \
507 /* this rv when indicating success. */ \
508 /* */ \
509 if(NS_FAILED(rv)) \
510 return rv; \
511 switch(tempData.mType) \
514 #define CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(Ctype_) \
515 case nsIDataType::VTYPE_INT32: \
516 *_retval = ( Ctype_ ) tempData.u.mInt32Value; \
517 return rv;
519 #define CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(Ctype_, min_, max_) \
520 case nsIDataType::VTYPE_INT32: \
522 PRInt32 value = tempData.u.mInt32Value; \
523 if(value < min_ || value > max_) \
524 return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
525 *_retval = ( Ctype_ ) value; \
526 return rv; \
529 #define CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(Ctype_) \
530 case nsIDataType::VTYPE_UINT32: \
531 *_retval = ( Ctype_ ) tempData.u.mUint32Value; \
532 return rv;
534 #define CASE__NUMERIC_CONVERSION_UINT32_MAX(Ctype_, max_) \
535 case nsIDataType::VTYPE_UINT32: \
537 PRUint32 value = tempData.u.mUint32Value; \
538 if(value > max_) \
539 return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
540 *_retval = ( Ctype_ ) value; \
541 return rv; \
544 #define CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(Ctype_) \
545 case nsIDataType::VTYPE_DOUBLE: \
546 *_retval = ( Ctype_ ) tempData.u.mDoubleValue; \
547 return rv;
549 #define CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX(Ctype_, min_, max_) \
550 case nsIDataType::VTYPE_DOUBLE: \
552 double value = tempData.u.mDoubleValue; \
553 if(value < min_ || value > max_) \
554 return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
555 *_retval = ( Ctype_ ) value; \
556 return rv; \
559 #define CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(Ctype_, min_, max_) \
560 case nsIDataType::VTYPE_DOUBLE: \
562 double value = tempData.u.mDoubleValue; \
563 if(value < min_ || value > max_) \
564 return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
565 *_retval = ( Ctype_ ) value; \
566 return (0.0 == fmod(value,1.0)) ? \
567 rv : NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA; \
570 #define CASES__NUMERIC_CONVERSION_NORMAL(Ctype_, min_, max_) \
571 CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(Ctype_, min_, max_) \
572 CASE__NUMERIC_CONVERSION_UINT32_MAX(Ctype_, max_) \
573 CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(Ctype_, min_, max_)
575 #define NUMERIC_CONVERSION_METHOD_END \
576 default: \
577 NS_ERROR("bad type returned from ToManageableNumber"); \
578 return NS_ERROR_CANNOT_CONVERT_DATA; \
582 #define NUMERIC_CONVERSION_METHOD_NORMAL(type_, Ctype_, name_, min_, max_) \
583 NUMERIC_CONVERSION_METHOD_BEGIN(type_, Ctype_, name_) \
584 CASES__NUMERIC_CONVERSION_NORMAL(Ctype_, min_, max_) \
585 NUMERIC_CONVERSION_METHOD_END
587 /***************************************************************************/
588 // These expand into full public methods...
590 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_INT8, PRUint8, Int8, (-127-1), 127)
591 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_INT16, PRInt16, Int16, (-32767-1), 32767)
593 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_INT32, PRInt32, Int32)
594 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(PRInt32)
595 CASE__NUMERIC_CONVERSION_UINT32_MAX(PRInt32, 2147483647)
596 CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(PRInt32, (-2147483647-1), 2147483647)
597 NUMERIC_CONVERSION_METHOD_END
599 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_UINT8, PRUint8, Uint8, 0, 255)
600 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_UINT16, PRUint16, Uint16, 0, 65535)
602 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_UINT32, PRUint32, Uint32)
603 CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(PRUint32, 0, 2147483647)
604 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(PRUint32)
605 CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(PRUint32, 0, 4294967295U)
606 NUMERIC_CONVERSION_METHOD_END
608 // XXX toFloat convertions need to be fixed!
609 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_FLOAT, float, Float)
610 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(float)
611 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(float)
612 CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(float)
613 NUMERIC_CONVERSION_METHOD_END
615 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_DOUBLE, double, Double)
616 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(double)
617 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(double)
618 CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(double)
619 NUMERIC_CONVERSION_METHOD_END
621 // XXX toChar convertions need to be fixed!
622 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_CHAR, char, Char)
623 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(char)
624 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(char)
625 CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(char)
626 NUMERIC_CONVERSION_METHOD_END
628 // XXX toWChar convertions need to be fixed!
629 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_WCHAR, PRUnichar, WChar)
630 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(PRUnichar)
631 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(PRUnichar)
632 CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(PRUnichar)
633 NUMERIC_CONVERSION_METHOD_END
635 #undef NUMERIC_CONVERSION_METHOD_BEGIN
636 #undef CASE__NUMERIC_CONVERSION_INT32_JUST_CAST
637 #undef CASE__NUMERIC_CONVERSION_INT32_MIN_MAX
638 #undef CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST
639 #undef CASE__NUMERIC_CONVERSION_UINT32_MIN_MAX
640 #undef CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST
641 #undef CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX
642 #undef CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT
643 #undef CASES__NUMERIC_CONVERSION_NORMAL
644 #undef NUMERIC_CONVERSION_METHOD_END
645 #undef NUMERIC_CONVERSION_METHOD_NORMAL
647 /***************************************************************************/
649 // Just leverage a numeric converter for bool (but restrict the values).
650 // XXX Is this really what we want to do?
652 /* static */ nsresult
653 nsVariant::ConvertToBool(const nsDiscriminatedUnion& data, PRBool *_retval)
655 TRIVIAL_DATA_CONVERTER(VTYPE_BOOL, data, mBoolValue, _retval)
657 double val;
658 nsresult rv = nsVariant::ConvertToDouble(data, &val);
659 if(NS_FAILED(rv))
660 return rv;
661 *_retval = 0.0 != val;
662 return rv;
665 /***************************************************************************/
667 /* static */ nsresult
668 nsVariant::ConvertToInt64(const nsDiscriminatedUnion& data, PRInt64 *_retval)
670 TRIVIAL_DATA_CONVERTER(VTYPE_INT64, data, mInt64Value, _retval)
671 TRIVIAL_DATA_CONVERTER(VTYPE_UINT64, data, mUint64Value, _retval)
673 nsDiscriminatedUnion tempData;
674 nsVariant::Initialize(&tempData);
675 nsresult rv = ToManageableNumber(data, &tempData);
676 if(NS_FAILED(rv))
677 return rv;
678 switch(tempData.mType)
680 case nsIDataType::VTYPE_INT32:
681 LL_I2L(*_retval, tempData.u.mInt32Value);
682 return rv;
683 case nsIDataType::VTYPE_UINT32:
684 LL_UI2L(*_retval, tempData.u.mUint32Value);
685 return rv;
686 case nsIDataType::VTYPE_DOUBLE:
687 // XXX should check for data loss here!
688 LL_D2L(*_retval, tempData.u.mDoubleValue);
689 return rv;
690 default:
691 NS_ERROR("bad type returned from ToManageableNumber");
692 return NS_ERROR_CANNOT_CONVERT_DATA;
696 /* static */ nsresult
697 nsVariant::ConvertToUint64(const nsDiscriminatedUnion& data, PRUint64 *_retval)
699 return nsVariant::ConvertToInt64(data, (PRInt64 *)_retval);
702 /***************************************************************************/
704 static PRBool String2ID(const nsDiscriminatedUnion& data, nsID* pid)
706 nsAutoString tempString;
707 nsAString* pString;
709 switch(data.mType)
711 case nsIDataType::VTYPE_CHAR_STR:
712 case nsIDataType::VTYPE_STRING_SIZE_IS:
713 return pid->Parse(data.u.str.mStringValue);
714 case nsIDataType::VTYPE_CSTRING:
715 return pid->Parse(PromiseFlatCString(*data.u.mCStringValue).get());
716 case nsIDataType::VTYPE_UTF8STRING:
717 return pid->Parse(PromiseFlatUTF8String(*data.u.mUTF8StringValue).get());
718 case nsIDataType::VTYPE_ASTRING:
719 case nsIDataType::VTYPE_DOMSTRING:
720 pString = data.u.mAStringValue;
721 break;
722 case nsIDataType::VTYPE_WCHAR_STR:
723 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
724 tempString.Assign(data.u.wstr.mWStringValue);
725 pString = &tempString;
726 break;
727 default:
728 NS_ERROR("bad type in call to String2ID");
729 return PR_FALSE;
732 char* pChars = ToNewCString(*pString);
733 if(!pChars)
734 return PR_FALSE;
735 PRBool result = pid->Parse(pChars);
736 nsMemory::Free(pChars);
737 return result;
740 /* static */ nsresult
741 nsVariant::ConvertToID(const nsDiscriminatedUnion& data, nsID * _retval)
743 nsID id;
745 switch(data.mType)
747 case nsIDataType::VTYPE_ID:
748 *_retval = data.u.mIDValue;
749 return NS_OK;
750 case nsIDataType::VTYPE_INTERFACE:
751 *_retval = NS_GET_IID(nsISupports);
752 return NS_OK;
753 case nsIDataType::VTYPE_INTERFACE_IS:
754 *_retval = data.u.iface.mInterfaceID;
755 return NS_OK;
756 case nsIDataType::VTYPE_ASTRING:
757 case nsIDataType::VTYPE_DOMSTRING:
758 case nsIDataType::VTYPE_UTF8STRING:
759 case nsIDataType::VTYPE_CSTRING:
760 case nsIDataType::VTYPE_CHAR_STR:
761 case nsIDataType::VTYPE_WCHAR_STR:
762 case nsIDataType::VTYPE_STRING_SIZE_IS:
763 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
764 if(!String2ID(data, &id))
765 return NS_ERROR_CANNOT_CONVERT_DATA;
766 *_retval = id;
767 return NS_OK;
768 default:
769 return NS_ERROR_CANNOT_CONVERT_DATA;
773 /***************************************************************************/
775 static nsresult ToString(const nsDiscriminatedUnion& data,
776 nsACString & outString)
778 char* ptr;
780 switch(data.mType)
782 // all the stuff we don't handle...
783 case nsIDataType::VTYPE_ASTRING:
784 case nsIDataType::VTYPE_DOMSTRING:
785 case nsIDataType::VTYPE_UTF8STRING:
786 case nsIDataType::VTYPE_CSTRING:
787 case nsIDataType::VTYPE_CHAR_STR:
788 case nsIDataType::VTYPE_WCHAR_STR:
789 case nsIDataType::VTYPE_STRING_SIZE_IS:
790 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
791 case nsIDataType::VTYPE_WCHAR:
792 NS_ERROR("ToString being called for a string type - screwy logic!");
793 // fall through...
795 // XXX We might want stringified versions of these... ???
797 case nsIDataType::VTYPE_VOID:
798 case nsIDataType::VTYPE_EMPTY:
799 outString.Truncate();
800 outString.SetIsVoid(true);
801 return NS_OK;
803 case nsIDataType::VTYPE_EMPTY_ARRAY:
804 case nsIDataType::VTYPE_ARRAY:
805 case nsIDataType::VTYPE_INTERFACE:
806 case nsIDataType::VTYPE_INTERFACE_IS:
807 default:
808 return NS_ERROR_CANNOT_CONVERT_DATA;
810 // nsID has its own text formater.
812 case nsIDataType::VTYPE_ID:
813 ptr = data.u.mIDValue.ToString();
814 if(!ptr)
815 return NS_ERROR_OUT_OF_MEMORY;
816 outString.Assign(ptr);
817 nsMemory::Free(ptr);
818 return NS_OK;
820 // Can't use PR_smprintf for floats, since it's locale-dependent
821 #define CASE__APPENDFLOAT_NUMBER(type_, member_) \
822 case nsIDataType :: type_ : \
824 nsCAutoString str; \
825 str.AppendFloat(data.u. member_); \
826 outString.Assign(str); \
827 return NS_OK; \
830 CASE__APPENDFLOAT_NUMBER(VTYPE_FLOAT, mFloatValue)
831 CASE__APPENDFLOAT_NUMBER(VTYPE_DOUBLE, mDoubleValue)
833 #undef CASE__APPENDFLOAT_NUMBER
835 // the rest can be PR_smprintf'd and use common code.
837 #define CASE__SMPRINTF_NUMBER(type_, format_, cast_, member_) \
838 case nsIDataType :: type_ : \
839 ptr = PR_smprintf( format_ , (cast_) data.u. member_ ); \
840 break;
842 CASE__SMPRINTF_NUMBER(VTYPE_INT8, "%d", int, mInt8Value)
843 CASE__SMPRINTF_NUMBER(VTYPE_INT16, "%d", int, mInt16Value)
844 CASE__SMPRINTF_NUMBER(VTYPE_INT32, "%d", int, mInt32Value)
845 CASE__SMPRINTF_NUMBER(VTYPE_INT64, "%lld", PRInt64, mInt64Value)
847 CASE__SMPRINTF_NUMBER(VTYPE_UINT8, "%u", unsigned, mUint8Value)
848 CASE__SMPRINTF_NUMBER(VTYPE_UINT16, "%u", unsigned, mUint16Value)
849 CASE__SMPRINTF_NUMBER(VTYPE_UINT32, "%u", unsigned, mUint32Value)
850 CASE__SMPRINTF_NUMBER(VTYPE_UINT64, "%llu", PRInt64, mUint64Value)
852 // XXX Would we rather print "true" / "false" ?
853 CASE__SMPRINTF_NUMBER(VTYPE_BOOL, "%d", int, mBoolValue)
855 CASE__SMPRINTF_NUMBER(VTYPE_CHAR, "%c", char, mCharValue)
857 #undef CASE__SMPRINTF_NUMBER
860 if(!ptr)
861 return NS_ERROR_OUT_OF_MEMORY;
862 outString.Assign(ptr);
863 PR_smprintf_free(ptr);
864 return NS_OK;
867 /* static */ nsresult
868 nsVariant::ConvertToAString(const nsDiscriminatedUnion& data,
869 nsAString & _retval)
871 switch(data.mType)
873 case nsIDataType::VTYPE_ASTRING:
874 case nsIDataType::VTYPE_DOMSTRING:
875 _retval.Assign(*data.u.mAStringValue);
876 return NS_OK;
877 case nsIDataType::VTYPE_CSTRING:
878 CopyASCIItoUTF16(*data.u.mCStringValue, _retval);
879 return NS_OK;
880 case nsIDataType::VTYPE_UTF8STRING:
881 CopyUTF8toUTF16(*data.u.mUTF8StringValue, _retval);
882 return NS_OK;
883 case nsIDataType::VTYPE_CHAR_STR:
884 CopyASCIItoUTF16(data.u.str.mStringValue, _retval);
885 return NS_OK;
886 case nsIDataType::VTYPE_WCHAR_STR:
887 _retval.Assign(data.u.wstr.mWStringValue);
888 return NS_OK;
889 case nsIDataType::VTYPE_STRING_SIZE_IS:
890 CopyASCIItoUTF16(nsDependentCString(data.u.str.mStringValue,
891 data.u.str.mStringLength),
892 _retval);
893 return NS_OK;
894 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
895 _retval.Assign(data.u.wstr.mWStringValue, data.u.wstr.mWStringLength);
896 return NS_OK;
897 case nsIDataType::VTYPE_WCHAR:
898 _retval.Assign(data.u.mWCharValue);
899 return NS_OK;
900 default:
902 nsCAutoString tempCString;
903 nsresult rv = ToString(data, tempCString);
904 if(NS_FAILED(rv))
905 return rv;
906 CopyASCIItoUTF16(tempCString, _retval);
907 return NS_OK;
912 /* static */ nsresult
913 nsVariant::ConvertToACString(const nsDiscriminatedUnion& data,
914 nsACString & _retval)
916 switch(data.mType)
918 case nsIDataType::VTYPE_ASTRING:
919 case nsIDataType::VTYPE_DOMSTRING:
920 LossyCopyUTF16toASCII(*data.u.mAStringValue, _retval);
921 return NS_OK;
922 case nsIDataType::VTYPE_CSTRING:
923 _retval.Assign(*data.u.mCStringValue);
924 return NS_OK;
925 case nsIDataType::VTYPE_UTF8STRING:
926 // XXX This is an extra copy that should be avoided
927 // once Jag lands support for UTF8String and associated
928 // conversion methods.
929 LossyCopyUTF16toASCII(NS_ConvertUTF8toUTF16(*data.u.mUTF8StringValue),
930 _retval);
931 return NS_OK;
932 case nsIDataType::VTYPE_CHAR_STR:
933 _retval.Assign(*data.u.str.mStringValue);
934 return NS_OK;
935 case nsIDataType::VTYPE_WCHAR_STR:
936 LossyCopyUTF16toASCII(nsDependentString(data.u.wstr.mWStringValue),
937 _retval);
938 return NS_OK;
939 case nsIDataType::VTYPE_STRING_SIZE_IS:
940 _retval.Assign(data.u.str.mStringValue, data.u.str.mStringLength);
941 return NS_OK;
942 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
943 LossyCopyUTF16toASCII(nsDependentString(data.u.wstr.mWStringValue,
944 data.u.wstr.mWStringLength), _retval);
945 return NS_OK;
946 case nsIDataType::VTYPE_WCHAR:
948 const PRUnichar* str = &data.u.mWCharValue;
949 LossyCopyUTF16toASCII(Substring(str, str + 1), _retval);
950 return NS_OK;
952 default:
953 return ToString(data, _retval);
957 /* static */ nsresult
958 nsVariant::ConvertToAUTF8String(const nsDiscriminatedUnion& data,
959 nsAUTF8String & _retval)
961 switch(data.mType)
963 case nsIDataType::VTYPE_ASTRING:
964 case nsIDataType::VTYPE_DOMSTRING:
965 CopyUTF16toUTF8(*data.u.mAStringValue, _retval);
966 return NS_OK;
967 case nsIDataType::VTYPE_CSTRING:
968 // XXX Extra copy, can be removed if we're sure CSTRING can
969 // only contain ASCII.
970 CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(*data.u.mCStringValue),
971 _retval);
972 return NS_OK;
973 case nsIDataType::VTYPE_UTF8STRING:
974 _retval.Assign(*data.u.mUTF8StringValue);
975 return NS_OK;
976 case nsIDataType::VTYPE_CHAR_STR:
977 // XXX Extra copy, can be removed if we're sure CHAR_STR can
978 // only contain ASCII.
979 CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(data.u.str.mStringValue),
980 _retval);
981 return NS_OK;
982 case nsIDataType::VTYPE_WCHAR_STR:
983 CopyUTF16toUTF8(data.u.wstr.mWStringValue, _retval);
984 return NS_OK;
985 case nsIDataType::VTYPE_STRING_SIZE_IS:
986 // XXX Extra copy, can be removed if we're sure CHAR_STR can
987 // only contain ASCII.
988 CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(
989 nsDependentCString(data.u.str.mStringValue,
990 data.u.str.mStringLength)), _retval);
991 return NS_OK;
992 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
993 CopyUTF16toUTF8(nsDependentString(data.u.wstr.mWStringValue,
994 data.u.wstr.mWStringLength),
995 _retval);
996 return NS_OK;
997 case nsIDataType::VTYPE_WCHAR:
999 const PRUnichar* str = &data.u.mWCharValue;
1000 CopyUTF16toUTF8(Substring(str, str + 1), _retval);
1001 return NS_OK;
1003 default:
1005 nsCAutoString tempCString;
1006 nsresult rv = ToString(data, tempCString);
1007 if(NS_FAILED(rv))
1008 return rv;
1009 // XXX Extra copy, can be removed if we're sure tempCString can
1010 // only contain ASCII.
1011 CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(tempCString), _retval);
1012 return NS_OK;
1017 /* static */ nsresult
1018 nsVariant::ConvertToString(const nsDiscriminatedUnion& data, char **_retval)
1020 PRUint32 ignored;
1021 return nsVariant::ConvertToStringWithSize(data, &ignored, _retval);
1024 /* static */ nsresult
1025 nsVariant::ConvertToWString(const nsDiscriminatedUnion& data, PRUnichar **_retval)
1027 PRUint32 ignored;
1028 return nsVariant::ConvertToWStringWithSize(data, &ignored, _retval);
1031 /* static */ nsresult
1032 nsVariant::ConvertToStringWithSize(const nsDiscriminatedUnion& data,
1033 PRUint32 *size, char **str)
1035 nsAutoString tempString;
1036 nsCAutoString tempCString;
1037 nsresult rv;
1039 switch(data.mType)
1041 case nsIDataType::VTYPE_ASTRING:
1042 case nsIDataType::VTYPE_DOMSTRING:
1043 *size = data.u.mAStringValue->Length();
1044 *str = ToNewCString(*data.u.mAStringValue);
1045 break;
1046 case nsIDataType::VTYPE_CSTRING:
1047 *size = data.u.mCStringValue->Length();
1048 *str = ToNewCString(*data.u.mCStringValue);
1049 break;
1050 case nsIDataType::VTYPE_UTF8STRING:
1052 // XXX This is doing 1 extra copy. Need to fix this
1053 // when Jag lands UTF8String
1054 // we want:
1055 // *size = *data.mUTF8StringValue->Length();
1056 // *str = ToNewCString(*data.mUTF8StringValue);
1057 // But this will have to do for now.
1058 NS_ConvertUTF8toUTF16 tempString(*data.u.mUTF8StringValue);
1059 *size = tempString.Length();
1060 *str = ToNewCString(tempString);
1061 break;
1063 case nsIDataType::VTYPE_CHAR_STR:
1065 nsDependentCString cString(data.u.str.mStringValue);
1066 *size = cString.Length();
1067 *str = ToNewCString(cString);
1068 break;
1070 case nsIDataType::VTYPE_WCHAR_STR:
1072 nsDependentString string(data.u.wstr.mWStringValue);
1073 *size = string.Length();
1074 *str = ToNewCString(string);
1075 break;
1077 case nsIDataType::VTYPE_STRING_SIZE_IS:
1079 nsDependentCString cString(data.u.str.mStringValue,
1080 data.u.str.mStringLength);
1081 *size = cString.Length();
1082 *str = ToNewCString(cString);
1083 break;
1085 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
1087 nsDependentString string(data.u.wstr.mWStringValue,
1088 data.u.wstr.mWStringLength);
1089 *size = string.Length();
1090 *str = ToNewCString(string);
1091 break;
1093 case nsIDataType::VTYPE_WCHAR:
1094 tempString.Assign(data.u.mWCharValue);
1095 *size = tempString.Length();
1096 *str = ToNewCString(tempString);
1097 break;
1098 default:
1099 rv = ToString(data, tempCString);
1100 if(NS_FAILED(rv))
1101 return rv;
1102 *size = tempCString.Length();
1103 *str = ToNewCString(tempCString);
1104 break;
1107 return *str ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
1109 /* static */ nsresult
1110 nsVariant::ConvertToWStringWithSize(const nsDiscriminatedUnion& data,
1111 PRUint32 *size, PRUnichar **str)
1113 nsAutoString tempString;
1114 nsCAutoString tempCString;
1115 nsresult rv;
1117 switch(data.mType)
1119 case nsIDataType::VTYPE_ASTRING:
1120 case nsIDataType::VTYPE_DOMSTRING:
1121 *size = data.u.mAStringValue->Length();
1122 *str = ToNewUnicode(*data.u.mAStringValue);
1123 break;
1124 case nsIDataType::VTYPE_CSTRING:
1125 *size = data.u.mCStringValue->Length();
1126 *str = ToNewUnicode(*data.u.mCStringValue);
1127 break;
1128 case nsIDataType::VTYPE_UTF8STRING:
1130 *str = UTF8ToNewUnicode(*data.u.mUTF8StringValue, size);
1131 break;
1133 case nsIDataType::VTYPE_CHAR_STR:
1135 nsDependentCString cString(data.u.str.mStringValue);
1136 *size = cString.Length();
1137 *str = ToNewUnicode(cString);
1138 break;
1140 case nsIDataType::VTYPE_WCHAR_STR:
1142 nsDependentString string(data.u.wstr.mWStringValue);
1143 *size = string.Length();
1144 *str = ToNewUnicode(string);
1145 break;
1147 case nsIDataType::VTYPE_STRING_SIZE_IS:
1149 nsDependentCString cString(data.u.str.mStringValue,
1150 data.u.str.mStringLength);
1151 *size = cString.Length();
1152 *str = ToNewUnicode(cString);
1153 break;
1155 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
1157 nsDependentString string(data.u.wstr.mWStringValue,
1158 data.u.wstr.mWStringLength);
1159 *size = string.Length();
1160 *str = ToNewUnicode(string);
1161 break;
1163 case nsIDataType::VTYPE_WCHAR:
1164 tempString.Assign(data.u.mWCharValue);
1165 *size = tempString.Length();
1166 *str = ToNewUnicode(tempString);
1167 break;
1168 default:
1169 rv = ToString(data, tempCString);
1170 if(NS_FAILED(rv))
1171 return rv;
1172 *size = tempCString.Length();
1173 *str = ToNewUnicode(tempCString);
1174 break;
1177 return *str ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
1180 /* static */ nsresult
1181 nsVariant::ConvertToISupports(const nsDiscriminatedUnion& data,
1182 nsISupports **_retval)
1184 switch(data.mType)
1186 case nsIDataType::VTYPE_INTERFACE:
1187 case nsIDataType::VTYPE_INTERFACE_IS:
1188 if (data.u.iface.mInterfaceValue) {
1189 return data.u.iface.mInterfaceValue->
1190 QueryInterface(NS_GET_IID(nsISupports), (void**)_retval);
1191 } else {
1192 *_retval = nsnull;
1193 return NS_OK;
1195 default:
1196 return NS_ERROR_CANNOT_CONVERT_DATA;
1200 /* static */ nsresult
1201 nsVariant::ConvertToInterface(const nsDiscriminatedUnion& data, nsIID * *iid,
1202 void * *iface)
1204 const nsIID* piid;
1206 switch(data.mType)
1208 case nsIDataType::VTYPE_INTERFACE:
1209 piid = &NS_GET_IID(nsISupports);
1210 break;
1211 case nsIDataType::VTYPE_INTERFACE_IS:
1212 piid = &data.u.iface.mInterfaceID;
1213 break;
1214 default:
1215 return NS_ERROR_CANNOT_CONVERT_DATA;
1218 *iid = (nsIID*) nsMemory::Clone(piid, sizeof(nsIID));
1219 if(!*iid)
1220 return NS_ERROR_OUT_OF_MEMORY;
1222 if (data.u.iface.mInterfaceValue) {
1223 return data.u.iface.mInterfaceValue->QueryInterface(*piid, iface);
1226 *iface = nsnull;
1227 return NS_OK;
1230 /* static */ nsresult
1231 nsVariant::ConvertToArray(const nsDiscriminatedUnion& data, PRUint16 *type,
1232 nsIID* iid, PRUint32 *count, void * *ptr)
1234 // XXX perhaps we'd like to add support for converting each of the various
1235 // types into an array containing one element of that type. We can leverage
1236 // CloneArray to do this if we want to support this.
1238 if(data.mType == nsIDataType::VTYPE_ARRAY)
1239 return CloneArray(data.u.array.mArrayType, &data.u.array.mArrayInterfaceID,
1240 data.u.array.mArrayCount, data.u.array.mArrayValue,
1241 type, iid, count, ptr);
1242 return NS_ERROR_CANNOT_CONVERT_DATA;
1245 /***************************************************************************/
1246 // static setter functions...
1248 #define DATA_SETTER_PROLOGUE(data_) \
1249 nsVariant::Cleanup(data_);
1251 #define DATA_SETTER_EPILOGUE(data_, type_) \
1252 data_->mType = nsIDataType :: type_; \
1253 return NS_OK;
1255 #define DATA_SETTER(data_, type_, member_, value_) \
1256 DATA_SETTER_PROLOGUE(data_) \
1257 data_->u.member_ = value_; \
1258 DATA_SETTER_EPILOGUE(data_, type_)
1260 #define DATA_SETTER_WITH_CAST(data_, type_, member_, cast_, value_) \
1261 DATA_SETTER_PROLOGUE(data_) \
1262 data_->u.member_ = cast_ value_; \
1263 DATA_SETTER_EPILOGUE(data_, type_)
1266 /********************************************/
1268 #define CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_) \
1271 #define CASE__SET_FROM_VARIANT_VTYPE__GETTER(member_, name_) \
1272 rv = aValue->GetAs##name_ (&(data->u. member_ ));
1274 #define CASE__SET_FROM_VARIANT_VTYPE__GETTER_CAST(cast_, member_, name_) \
1275 rv = aValue->GetAs##name_ ( cast_ &(data->u. member_ ));
1277 #define CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_) \
1278 if(NS_SUCCEEDED(rv)) \
1280 data->mType = nsIDataType :: type_ ; \
1282 break; \
1285 #define CASE__SET_FROM_VARIANT_TYPE(type_, member_, name_) \
1286 case nsIDataType :: type_ : \
1287 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_) \
1288 CASE__SET_FROM_VARIANT_VTYPE__GETTER(member_, name_) \
1289 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)
1291 #define CASE__SET_FROM_VARIANT_VTYPE_CAST(type_, cast_, member_, name_) \
1292 case nsIDataType :: type_ : \
1293 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_) \
1294 CASE__SET_FROM_VARIANT_VTYPE__GETTER_CAST(cast_, member_, name_) \
1295 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)
1298 /* static */ nsresult
1299 nsVariant::SetFromVariant(nsDiscriminatedUnion* data, nsIVariant* aValue)
1301 PRUint16 type;
1302 nsresult rv;
1304 nsVariant::Cleanup(data);
1306 rv = aValue->GetDataType(&type);
1307 if(NS_FAILED(rv))
1308 return rv;
1310 switch(type)
1312 CASE__SET_FROM_VARIANT_VTYPE_CAST(VTYPE_INT8, (PRUint8*), mInt8Value,
1313 Int8)
1314 CASE__SET_FROM_VARIANT_TYPE(VTYPE_INT16, mInt16Value, Int16)
1315 CASE__SET_FROM_VARIANT_TYPE(VTYPE_INT32, mInt32Value, Int32)
1316 CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT8, mUint8Value, Uint8)
1317 CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT16, mUint16Value, Uint16)
1318 CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT32, mUint32Value, Uint32)
1319 CASE__SET_FROM_VARIANT_TYPE(VTYPE_FLOAT, mFloatValue, Float)
1320 CASE__SET_FROM_VARIANT_TYPE(VTYPE_DOUBLE, mDoubleValue, Double)
1321 CASE__SET_FROM_VARIANT_TYPE(VTYPE_BOOL , mBoolValue, Bool)
1322 CASE__SET_FROM_VARIANT_TYPE(VTYPE_CHAR, mCharValue, Char)
1323 CASE__SET_FROM_VARIANT_TYPE(VTYPE_WCHAR, mWCharValue, WChar)
1324 CASE__SET_FROM_VARIANT_TYPE(VTYPE_ID, mIDValue, ID)
1326 case nsIDataType::VTYPE_ASTRING:
1327 case nsIDataType::VTYPE_DOMSTRING:
1328 case nsIDataType::VTYPE_WCHAR_STR:
1329 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
1330 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_ASTRING);
1331 data->u.mAStringValue = new nsString();
1332 if(!data->u.mAStringValue)
1333 return NS_ERROR_OUT_OF_MEMORY;
1334 rv = aValue->GetAsAString(*data->u.mAStringValue);
1335 if(NS_FAILED(rv))
1336 delete data->u.mAStringValue;
1337 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_ASTRING)
1339 case nsIDataType::VTYPE_CSTRING:
1340 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_CSTRING);
1341 data->u.mCStringValue = new nsCString();
1342 if(!data->u.mCStringValue)
1343 return NS_ERROR_OUT_OF_MEMORY;
1344 rv = aValue->GetAsACString(*data->u.mCStringValue);
1345 if(NS_FAILED(rv))
1346 delete data->u.mCStringValue;
1347 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_CSTRING)
1349 case nsIDataType::VTYPE_UTF8STRING:
1350 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_UTF8STRING);
1351 data->u.mUTF8StringValue = new nsUTF8String();
1352 if(!data->u.mUTF8StringValue)
1353 return NS_ERROR_OUT_OF_MEMORY;
1354 rv = aValue->GetAsAUTF8String(*data->u.mUTF8StringValue);
1355 if(NS_FAILED(rv))
1356 delete data->u.mUTF8StringValue;
1357 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_UTF8STRING)
1359 case nsIDataType::VTYPE_CHAR_STR:
1360 case nsIDataType::VTYPE_STRING_SIZE_IS:
1361 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_STRING_SIZE_IS);
1362 rv = aValue->GetAsStringWithSize(&data->u.str.mStringLength,
1363 &data->u.str.mStringValue);
1364 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_STRING_SIZE_IS)
1366 case nsIDataType::VTYPE_INTERFACE:
1367 case nsIDataType::VTYPE_INTERFACE_IS:
1368 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_INTERFACE_IS);
1369 // XXX This iid handling is ugly!
1370 nsIID* iid;
1371 rv = aValue->GetAsInterface(&iid, (void**)&data->u.iface.mInterfaceValue);
1372 if(NS_SUCCEEDED(rv))
1374 data->u.iface.mInterfaceID = *iid;
1375 nsMemory::Free((char*)iid);
1377 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_INTERFACE_IS)
1379 case nsIDataType::VTYPE_ARRAY:
1380 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_ARRAY);
1381 rv = aValue->GetAsArray(&data->u.array.mArrayType,
1382 &data->u.array.mArrayInterfaceID,
1383 &data->u.array.mArrayCount,
1384 &data->u.array.mArrayValue);
1385 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_ARRAY)
1387 case nsIDataType::VTYPE_VOID:
1388 rv = nsVariant::SetToVoid(data);
1389 break;
1390 case nsIDataType::VTYPE_EMPTY_ARRAY:
1391 rv = nsVariant::SetToEmptyArray(data);
1392 break;
1393 case nsIDataType::VTYPE_EMPTY:
1394 rv = nsVariant::SetToEmpty(data);
1395 break;
1396 default:
1397 NS_ERROR("bad type in variant!");
1398 rv = NS_ERROR_FAILURE;
1399 break;
1401 return rv;
1404 /* static */ nsresult
1405 nsVariant::SetFromInt8(nsDiscriminatedUnion* data, PRUint8 aValue)
1407 DATA_SETTER_WITH_CAST(data, VTYPE_INT8, mInt8Value, (PRUint8), aValue)
1409 /* static */ nsresult
1410 nsVariant::SetFromInt16(nsDiscriminatedUnion* data, PRInt16 aValue)
1412 DATA_SETTER(data, VTYPE_INT16, mInt16Value, aValue)
1414 /* static */ nsresult
1415 nsVariant::SetFromInt32(nsDiscriminatedUnion* data, PRInt32 aValue)
1417 DATA_SETTER(data, VTYPE_INT32, mInt32Value, aValue)
1419 /* static */ nsresult
1420 nsVariant::SetFromInt64(nsDiscriminatedUnion* data, PRInt64 aValue)
1422 DATA_SETTER(data, VTYPE_INT64, mInt64Value, aValue)
1424 /* static */ nsresult
1425 nsVariant::SetFromUint8(nsDiscriminatedUnion* data, PRUint8 aValue)
1427 DATA_SETTER(data, VTYPE_UINT8, mUint8Value, aValue)
1429 /* static */ nsresult
1430 nsVariant::SetFromUint16(nsDiscriminatedUnion* data, PRUint16 aValue)
1432 DATA_SETTER(data, VTYPE_UINT16, mUint16Value, aValue)
1434 /* static */ nsresult
1435 nsVariant::SetFromUint32(nsDiscriminatedUnion* data, PRUint32 aValue)
1437 DATA_SETTER(data, VTYPE_UINT32, mUint32Value, aValue)
1439 /* static */ nsresult
1440 nsVariant::SetFromUint64(nsDiscriminatedUnion* data, PRUint64 aValue)
1442 DATA_SETTER(data, VTYPE_UINT64, mUint64Value, aValue)
1444 /* static */ nsresult
1445 nsVariant::SetFromFloat(nsDiscriminatedUnion* data, float aValue)
1447 DATA_SETTER(data, VTYPE_FLOAT, mFloatValue, aValue)
1449 /* static */ nsresult
1450 nsVariant::SetFromDouble(nsDiscriminatedUnion* data, double aValue)
1452 DATA_SETTER(data, VTYPE_DOUBLE, mDoubleValue, aValue)
1454 /* static */ nsresult
1455 nsVariant::SetFromBool(nsDiscriminatedUnion* data, PRBool aValue)
1457 DATA_SETTER(data, VTYPE_BOOL, mBoolValue, aValue)
1459 /* static */ nsresult
1460 nsVariant::SetFromChar(nsDiscriminatedUnion* data, char aValue)
1462 DATA_SETTER(data, VTYPE_CHAR, mCharValue, aValue)
1464 /* static */ nsresult
1465 nsVariant::SetFromWChar(nsDiscriminatedUnion* data, PRUnichar aValue)
1467 DATA_SETTER(data, VTYPE_WCHAR, mWCharValue, aValue)
1469 /* static */ nsresult
1470 nsVariant::SetFromID(nsDiscriminatedUnion* data, const nsID & aValue)
1472 DATA_SETTER(data, VTYPE_ID, mIDValue, aValue)
1474 /* static */ nsresult
1475 nsVariant::SetFromAString(nsDiscriminatedUnion* data, const nsAString & aValue)
1477 DATA_SETTER_PROLOGUE(data);
1478 if(!(data->u.mAStringValue = new nsString(aValue)))
1479 return NS_ERROR_OUT_OF_MEMORY;
1480 DATA_SETTER_EPILOGUE(data, VTYPE_ASTRING);
1483 /* static */ nsresult
1484 nsVariant::SetFromACString(nsDiscriminatedUnion* data,
1485 const nsACString & aValue)
1487 DATA_SETTER_PROLOGUE(data);
1488 if(!(data->u.mCStringValue = new nsCString(aValue)))
1489 return NS_ERROR_OUT_OF_MEMORY;
1490 DATA_SETTER_EPILOGUE(data, VTYPE_CSTRING);
1493 /* static */ nsresult
1494 nsVariant::SetFromAUTF8String(nsDiscriminatedUnion* data,
1495 const nsAUTF8String & aValue)
1497 DATA_SETTER_PROLOGUE(data);
1498 if(!(data->u.mUTF8StringValue = new nsUTF8String(aValue)))
1499 return NS_ERROR_OUT_OF_MEMORY;
1500 DATA_SETTER_EPILOGUE(data, VTYPE_UTF8STRING);
1503 /* static */ nsresult
1504 nsVariant::SetFromString(nsDiscriminatedUnion* data, const char *aValue)
1506 DATA_SETTER_PROLOGUE(data);
1507 if(!aValue)
1508 return NS_ERROR_NULL_POINTER;
1509 return SetFromStringWithSize(data, strlen(aValue), aValue);
1511 /* static */ nsresult
1512 nsVariant::SetFromWString(nsDiscriminatedUnion* data, const PRUnichar *aValue)
1514 DATA_SETTER_PROLOGUE(data);
1515 if(!aValue)
1516 return NS_ERROR_NULL_POINTER;
1517 return SetFromWStringWithSize(data, nsCRT::strlen(aValue), aValue);
1519 /* static */ nsresult
1520 nsVariant::SetFromISupports(nsDiscriminatedUnion* data, nsISupports *aValue)
1522 return SetFromInterface(data, NS_GET_IID(nsISupports), aValue);
1524 /* static */ nsresult
1525 nsVariant::SetFromInterface(nsDiscriminatedUnion* data, const nsIID& iid,
1526 nsISupports *aValue)
1528 DATA_SETTER_PROLOGUE(data);
1529 NS_IF_ADDREF(aValue);
1530 data->u.iface.mInterfaceValue = aValue;
1531 data->u.iface.mInterfaceID = iid;
1532 DATA_SETTER_EPILOGUE(data, VTYPE_INTERFACE_IS);
1534 /* static */ nsresult
1535 nsVariant::SetFromArray(nsDiscriminatedUnion* data, PRUint16 type,
1536 const nsIID* iid, PRUint32 count, void * aValue)
1538 DATA_SETTER_PROLOGUE(data);
1539 if(!aValue || !count)
1540 return NS_ERROR_NULL_POINTER;
1542 nsresult rv = CloneArray(type, iid, count, aValue,
1543 &data->u.array.mArrayType,
1544 &data->u.array.mArrayInterfaceID,
1545 &data->u.array.mArrayCount,
1546 &data->u.array.mArrayValue);
1547 if(NS_FAILED(rv))
1548 return rv;
1549 DATA_SETTER_EPILOGUE(data, VTYPE_ARRAY);
1551 /* static */ nsresult
1552 nsVariant::SetFromStringWithSize(nsDiscriminatedUnion* data, PRUint32 size, const char *aValue)
1554 DATA_SETTER_PROLOGUE(data);
1555 if(!aValue)
1556 return NS_ERROR_NULL_POINTER;
1557 if(!(data->u.str.mStringValue =
1558 (char*) nsMemory::Clone(aValue, (size+1)*sizeof(char))))
1559 return NS_ERROR_OUT_OF_MEMORY;
1560 data->u.str.mStringLength = size;
1561 DATA_SETTER_EPILOGUE(data, VTYPE_STRING_SIZE_IS);
1563 /* static */ nsresult
1564 nsVariant::SetFromWStringWithSize(nsDiscriminatedUnion* data, PRUint32 size, const PRUnichar *aValue)
1566 DATA_SETTER_PROLOGUE(data);
1567 if(!aValue)
1568 return NS_ERROR_NULL_POINTER;
1569 if(!(data->u.wstr.mWStringValue =
1570 (PRUnichar*) nsMemory::Clone(aValue, (size+1)*sizeof(PRUnichar))))
1571 return NS_ERROR_OUT_OF_MEMORY;
1572 data->u.wstr.mWStringLength = size;
1573 DATA_SETTER_EPILOGUE(data, VTYPE_WSTRING_SIZE_IS);
1575 /* static */ nsresult
1576 nsVariant::SetToVoid(nsDiscriminatedUnion* data)
1578 DATA_SETTER_PROLOGUE(data);
1579 DATA_SETTER_EPILOGUE(data, VTYPE_VOID);
1581 /* static */ nsresult
1582 nsVariant::SetToEmpty(nsDiscriminatedUnion* data)
1584 DATA_SETTER_PROLOGUE(data);
1585 DATA_SETTER_EPILOGUE(data, VTYPE_EMPTY);
1587 /* static */ nsresult
1588 nsVariant::SetToEmptyArray(nsDiscriminatedUnion* data)
1590 DATA_SETTER_PROLOGUE(data);
1591 DATA_SETTER_EPILOGUE(data, VTYPE_EMPTY_ARRAY);
1594 /***************************************************************************/
1596 /* static */ nsresult
1597 nsVariant::Initialize(nsDiscriminatedUnion* data)
1599 data->mType = nsIDataType::VTYPE_EMPTY;
1600 return NS_OK;
1603 /* static */ nsresult
1604 nsVariant::Cleanup(nsDiscriminatedUnion* data)
1606 switch(data->mType)
1608 case nsIDataType::VTYPE_INT8:
1609 case nsIDataType::VTYPE_INT16:
1610 case nsIDataType::VTYPE_INT32:
1611 case nsIDataType::VTYPE_INT64:
1612 case nsIDataType::VTYPE_UINT8:
1613 case nsIDataType::VTYPE_UINT16:
1614 case nsIDataType::VTYPE_UINT32:
1615 case nsIDataType::VTYPE_UINT64:
1616 case nsIDataType::VTYPE_FLOAT:
1617 case nsIDataType::VTYPE_DOUBLE:
1618 case nsIDataType::VTYPE_BOOL:
1619 case nsIDataType::VTYPE_CHAR:
1620 case nsIDataType::VTYPE_WCHAR:
1621 case nsIDataType::VTYPE_VOID:
1622 case nsIDataType::VTYPE_ID:
1623 break;
1624 case nsIDataType::VTYPE_ASTRING:
1625 case nsIDataType::VTYPE_DOMSTRING:
1626 delete data->u.mAStringValue;
1627 break;
1628 case nsIDataType::VTYPE_CSTRING:
1629 delete data->u.mCStringValue;
1630 break;
1631 case nsIDataType::VTYPE_UTF8STRING:
1632 delete data->u.mUTF8StringValue;
1633 break;
1634 case nsIDataType::VTYPE_CHAR_STR:
1635 case nsIDataType::VTYPE_STRING_SIZE_IS:
1636 nsMemory::Free((char*)data->u.str.mStringValue);
1637 break;
1638 case nsIDataType::VTYPE_WCHAR_STR:
1639 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
1640 nsMemory::Free((char*)data->u.wstr.mWStringValue);
1641 break;
1642 case nsIDataType::VTYPE_INTERFACE:
1643 case nsIDataType::VTYPE_INTERFACE_IS:
1644 NS_IF_RELEASE(data->u.iface.mInterfaceValue);
1645 break;
1646 case nsIDataType::VTYPE_ARRAY:
1647 FreeArray(data);
1648 break;
1649 case nsIDataType::VTYPE_EMPTY_ARRAY:
1650 case nsIDataType::VTYPE_EMPTY:
1651 break;
1652 default:
1653 NS_ERROR("bad type in variant!");
1654 break;
1657 data->mType = nsIDataType::VTYPE_EMPTY;
1658 return NS_OK;
1661 /* static */ void
1662 nsVariant::Traverse(const nsDiscriminatedUnion& data,
1663 nsCycleCollectionTraversalCallback &cb)
1665 switch(data.mType)
1667 case nsIDataType::VTYPE_INTERFACE:
1668 case nsIDataType::VTYPE_INTERFACE_IS:
1669 cb.NoteXPCOMChild(data.u.iface.mInterfaceValue);
1670 break;
1671 case nsIDataType::VTYPE_ARRAY:
1672 switch(data.u.array.mArrayType) {
1673 case nsIDataType::VTYPE_INTERFACE:
1674 case nsIDataType::VTYPE_INTERFACE_IS:
1676 nsISupports** p = (nsISupports**) data.u.array.mArrayValue;
1677 for(PRUint32 i = data.u.array.mArrayCount; i > 0; p++, i--)
1678 cb.NoteXPCOMChild(*p);
1680 default:
1681 break;
1683 default:
1684 break;
1688 /***************************************************************************/
1689 /***************************************************************************/
1690 // members...
1692 NS_IMPL_ISUPPORTS2(nsVariant, nsIVariant, nsIWritableVariant)
1694 nsVariant::nsVariant()
1695 : mWritable(PR_TRUE)
1697 nsVariant::Initialize(&mData);
1699 #ifdef DEBUG
1701 // Assert that the nsIDataType consts match the values #defined in
1702 // xpt_struct.h. Bad things happen somewhere if they don't.
1703 struct THE_TYPES {PRUint16 a; PRUint16 b;};
1704 static const THE_TYPES array[] = {
1705 {nsIDataType::VTYPE_INT8 , TD_INT8 },
1706 {nsIDataType::VTYPE_INT16 , TD_INT16 },
1707 {nsIDataType::VTYPE_INT32 , TD_INT32 },
1708 {nsIDataType::VTYPE_INT64 , TD_INT64 },
1709 {nsIDataType::VTYPE_UINT8 , TD_UINT8 },
1710 {nsIDataType::VTYPE_UINT16 , TD_UINT16 },
1711 {nsIDataType::VTYPE_UINT32 , TD_UINT32 },
1712 {nsIDataType::VTYPE_UINT64 , TD_UINT64 },
1713 {nsIDataType::VTYPE_FLOAT , TD_FLOAT },
1714 {nsIDataType::VTYPE_DOUBLE , TD_DOUBLE },
1715 {nsIDataType::VTYPE_BOOL , TD_BOOL },
1716 {nsIDataType::VTYPE_CHAR , TD_CHAR },
1717 {nsIDataType::VTYPE_WCHAR , TD_WCHAR },
1718 {nsIDataType::VTYPE_VOID , TD_VOID },
1719 {nsIDataType::VTYPE_ID , TD_PNSIID },
1720 {nsIDataType::VTYPE_DOMSTRING , TD_DOMSTRING },
1721 {nsIDataType::VTYPE_CHAR_STR , TD_PSTRING },
1722 {nsIDataType::VTYPE_WCHAR_STR , TD_PWSTRING },
1723 {nsIDataType::VTYPE_INTERFACE , TD_INTERFACE_TYPE },
1724 {nsIDataType::VTYPE_INTERFACE_IS , TD_INTERFACE_IS_TYPE},
1725 {nsIDataType::VTYPE_ARRAY , TD_ARRAY },
1726 {nsIDataType::VTYPE_STRING_SIZE_IS , TD_PSTRING_SIZE_IS },
1727 {nsIDataType::VTYPE_WSTRING_SIZE_IS , TD_PWSTRING_SIZE_IS },
1728 {nsIDataType::VTYPE_UTF8STRING , TD_UTF8STRING },
1729 {nsIDataType::VTYPE_CSTRING , TD_CSTRING },
1730 {nsIDataType::VTYPE_ASTRING , TD_ASTRING }
1732 static const int length = sizeof(array)/sizeof(array[0]);
1733 static PRBool inited = PR_FALSE;
1734 if(!inited)
1736 for(int i = 0; i < length; i++)
1737 NS_ASSERTION(array[i].a == array[i].b, "bad const declaration");
1738 inited = PR_TRUE;
1741 #endif
1744 nsVariant::~nsVariant()
1746 nsVariant::Cleanup(&mData);
1749 // For all the data getters we just forward to the static (and sharable)
1750 // 'ConvertTo' functions.
1752 /* readonly attribute PRUint16 dataType; */
1753 NS_IMETHODIMP nsVariant::GetDataType(PRUint16 *aDataType)
1755 *aDataType = mData.mType;
1756 return NS_OK;
1759 /* PRUint8 getAsInt8 (); */
1760 NS_IMETHODIMP nsVariant::GetAsInt8(PRUint8 *_retval)
1762 return nsVariant::ConvertToInt8(mData, _retval);
1765 /* PRInt16 getAsInt16 (); */
1766 NS_IMETHODIMP nsVariant::GetAsInt16(PRInt16 *_retval)
1768 return nsVariant::ConvertToInt16(mData, _retval);
1771 /* PRInt32 getAsInt32 (); */
1772 NS_IMETHODIMP nsVariant::GetAsInt32(PRInt32 *_retval)
1774 return nsVariant::ConvertToInt32(mData, _retval);
1777 /* PRInt64 getAsInt64 (); */
1778 NS_IMETHODIMP nsVariant::GetAsInt64(PRInt64 *_retval)
1780 return nsVariant::ConvertToInt64(mData, _retval);
1783 /* PRUint8 getAsUint8 (); */
1784 NS_IMETHODIMP nsVariant::GetAsUint8(PRUint8 *_retval)
1786 return nsVariant::ConvertToUint8(mData, _retval);
1789 /* PRUint16 getAsUint16 (); */
1790 NS_IMETHODIMP nsVariant::GetAsUint16(PRUint16 *_retval)
1792 return nsVariant::ConvertToUint16(mData, _retval);
1795 /* PRUint32 getAsUint32 (); */
1796 NS_IMETHODIMP nsVariant::GetAsUint32(PRUint32 *_retval)
1798 return nsVariant::ConvertToUint32(mData, _retval);
1801 /* PRUint64 getAsUint64 (); */
1802 NS_IMETHODIMP nsVariant::GetAsUint64(PRUint64 *_retval)
1804 return nsVariant::ConvertToUint64(mData, _retval);
1807 /* float getAsFloat (); */
1808 NS_IMETHODIMP nsVariant::GetAsFloat(float *_retval)
1810 return nsVariant::ConvertToFloat(mData, _retval);
1813 /* double getAsDouble (); */
1814 NS_IMETHODIMP nsVariant::GetAsDouble(double *_retval)
1816 return nsVariant::ConvertToDouble(mData, _retval);
1819 /* PRBool getAsBool (); */
1820 NS_IMETHODIMP nsVariant::GetAsBool(PRBool *_retval)
1822 return nsVariant::ConvertToBool(mData, _retval);
1825 /* char getAsChar (); */
1826 NS_IMETHODIMP nsVariant::GetAsChar(char *_retval)
1828 return nsVariant::ConvertToChar(mData, _retval);
1831 /* wchar getAsWChar (); */
1832 NS_IMETHODIMP nsVariant::GetAsWChar(PRUnichar *_retval)
1834 return nsVariant::ConvertToWChar(mData, _retval);
1837 /* [notxpcom] nsresult getAsID (out nsID retval); */
1838 NS_IMETHODIMP_(nsresult) nsVariant::GetAsID(nsID *retval)
1840 return nsVariant::ConvertToID(mData, retval);
1843 /* AString getAsAString (); */
1844 NS_IMETHODIMP nsVariant::GetAsAString(nsAString & _retval)
1846 return nsVariant::ConvertToAString(mData, _retval);
1849 /* DOMString getAsDOMString (); */
1850 NS_IMETHODIMP nsVariant::GetAsDOMString(nsAString & _retval)
1852 // A DOMString maps to an AString internally, so we can re-use
1853 // ConvertToAString here.
1854 return nsVariant::ConvertToAString(mData, _retval);
1857 /* ACString getAsACString (); */
1858 NS_IMETHODIMP nsVariant::GetAsACString(nsACString & _retval)
1860 return nsVariant::ConvertToACString(mData, _retval);
1863 /* AUTF8String getAsAUTF8String (); */
1864 NS_IMETHODIMP nsVariant::GetAsAUTF8String(nsAUTF8String & _retval)
1866 return nsVariant::ConvertToAUTF8String(mData, _retval);
1869 /* string getAsString (); */
1870 NS_IMETHODIMP nsVariant::GetAsString(char **_retval)
1872 return nsVariant::ConvertToString(mData, _retval);
1875 /* wstring getAsWString (); */
1876 NS_IMETHODIMP nsVariant::GetAsWString(PRUnichar **_retval)
1878 return nsVariant::ConvertToWString(mData, _retval);
1881 /* nsISupports getAsISupports (); */
1882 NS_IMETHODIMP nsVariant::GetAsISupports(nsISupports **_retval)
1884 return nsVariant::ConvertToISupports(mData, _retval);
1887 /* void getAsInterface (out nsIIDPtr iid, [iid_is (iid), retval] out nsQIResult iface); */
1888 NS_IMETHODIMP nsVariant::GetAsInterface(nsIID * *iid, void * *iface)
1890 return nsVariant::ConvertToInterface(mData, iid, iface);
1893 /* [notxpcom] nsresult getAsArray (out PRUint16 type, out nsIID iid, out PRUint32 count, out voidPtr ptr); */
1894 NS_IMETHODIMP_(nsresult) nsVariant::GetAsArray(PRUint16 *type, nsIID *iid, PRUint32 *count, void * *ptr)
1896 return nsVariant::ConvertToArray(mData, type, iid, count, ptr);
1899 /* void getAsStringWithSize (out PRUint32 size, [size_is (size), retval] out string str); */
1900 NS_IMETHODIMP nsVariant::GetAsStringWithSize(PRUint32 *size, char **str)
1902 return nsVariant::ConvertToStringWithSize(mData, size, str);
1905 /* void getAsWStringWithSize (out PRUint32 size, [size_is (size), retval] out wstring str); */
1906 NS_IMETHODIMP nsVariant::GetAsWStringWithSize(PRUint32 *size, PRUnichar **str)
1908 return nsVariant::ConvertToWStringWithSize(mData, size, str);
1911 /***************************************************************************/
1913 /* attribute PRBool writable; */
1914 NS_IMETHODIMP nsVariant::GetWritable(PRBool *aWritable)
1916 *aWritable = mWritable;
1917 return NS_OK;
1919 NS_IMETHODIMP nsVariant::SetWritable(PRBool aWritable)
1921 if(!mWritable && aWritable)
1922 return NS_ERROR_FAILURE;
1923 mWritable = aWritable;
1924 return NS_OK;
1927 /***************************************************************************/
1929 // For all the data setters we just forward to the static (and sharable)
1930 // 'SetFrom' functions.
1932 /* void setAsInt8 (in PRUint8 aValue); */
1933 NS_IMETHODIMP nsVariant::SetAsInt8(PRUint8 aValue)
1935 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
1936 return nsVariant::SetFromInt8(&mData, aValue);
1939 /* void setAsInt16 (in PRInt16 aValue); */
1940 NS_IMETHODIMP nsVariant::SetAsInt16(PRInt16 aValue)
1942 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
1943 return nsVariant::SetFromInt16(&mData, aValue);
1946 /* void setAsInt32 (in PRInt32 aValue); */
1947 NS_IMETHODIMP nsVariant::SetAsInt32(PRInt32 aValue)
1949 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
1950 return nsVariant::SetFromInt32(&mData, aValue);
1953 /* void setAsInt64 (in PRInt64 aValue); */
1954 NS_IMETHODIMP nsVariant::SetAsInt64(PRInt64 aValue)
1956 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
1957 return nsVariant::SetFromInt64(&mData, aValue);
1960 /* void setAsUint8 (in PRUint8 aValue); */
1961 NS_IMETHODIMP nsVariant::SetAsUint8(PRUint8 aValue)
1963 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
1964 return nsVariant::SetFromUint8(&mData, aValue);
1967 /* void setAsUint16 (in PRUint16 aValue); */
1968 NS_IMETHODIMP nsVariant::SetAsUint16(PRUint16 aValue)
1970 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
1971 return nsVariant::SetFromUint16(&mData, aValue);
1974 /* void setAsUint32 (in PRUint32 aValue); */
1975 NS_IMETHODIMP nsVariant::SetAsUint32(PRUint32 aValue)
1977 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
1978 return nsVariant::SetFromUint32(&mData, aValue);
1981 /* void setAsUint64 (in PRUint64 aValue); */
1982 NS_IMETHODIMP nsVariant::SetAsUint64(PRUint64 aValue)
1984 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
1985 return nsVariant::SetFromUint64(&mData, aValue);
1988 /* void setAsFloat (in float aValue); */
1989 NS_IMETHODIMP nsVariant::SetAsFloat(float aValue)
1991 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
1992 return nsVariant::SetFromFloat(&mData, aValue);
1995 /* void setAsDouble (in double aValue); */
1996 NS_IMETHODIMP nsVariant::SetAsDouble(double aValue)
1998 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
1999 return nsVariant::SetFromDouble(&mData, aValue);
2002 /* void setAsBool (in PRBool aValue); */
2003 NS_IMETHODIMP nsVariant::SetAsBool(PRBool aValue)
2005 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2006 return nsVariant::SetFromBool(&mData, aValue);
2009 /* void setAsChar (in char aValue); */
2010 NS_IMETHODIMP nsVariant::SetAsChar(char aValue)
2012 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2013 return nsVariant::SetFromChar(&mData, aValue);
2016 /* void setAsWChar (in wchar aValue); */
2017 NS_IMETHODIMP nsVariant::SetAsWChar(PRUnichar aValue)
2019 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2020 return nsVariant::SetFromWChar(&mData, aValue);
2023 /* void setAsID (in nsIDRef aValue); */
2024 NS_IMETHODIMP nsVariant::SetAsID(const nsID & aValue)
2026 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2027 return nsVariant::SetFromID(&mData, aValue);
2030 /* void setAsAString (in AString aValue); */
2031 NS_IMETHODIMP nsVariant::SetAsAString(const nsAString & aValue)
2033 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2034 return nsVariant::SetFromAString(&mData, aValue);
2037 /* void setAsDOMString (in DOMString aValue); */
2038 NS_IMETHODIMP nsVariant::SetAsDOMString(const nsAString & aValue)
2040 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2042 DATA_SETTER_PROLOGUE((&mData));
2043 if(!(mData.u.mAStringValue = new nsString(aValue)))
2044 return NS_ERROR_OUT_OF_MEMORY;
2045 DATA_SETTER_EPILOGUE((&mData), VTYPE_DOMSTRING);
2048 /* void setAsACString (in ACString aValue); */
2049 NS_IMETHODIMP nsVariant::SetAsACString(const nsACString & aValue)
2051 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2052 return nsVariant::SetFromACString(&mData, aValue);
2055 /* void setAsAUTF8String (in AUTF8String aValue); */
2056 NS_IMETHODIMP nsVariant::SetAsAUTF8String(const nsAUTF8String & aValue)
2058 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2059 return nsVariant::SetFromAUTF8String(&mData, aValue);
2062 /* void setAsString (in string aValue); */
2063 NS_IMETHODIMP nsVariant::SetAsString(const char *aValue)
2065 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2066 return nsVariant::SetFromString(&mData, aValue);
2069 /* void setAsWString (in wstring aValue); */
2070 NS_IMETHODIMP nsVariant::SetAsWString(const PRUnichar *aValue)
2072 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2073 return nsVariant::SetFromWString(&mData, aValue);
2076 /* void setAsISupports (in nsISupports aValue); */
2077 NS_IMETHODIMP nsVariant::SetAsISupports(nsISupports *aValue)
2079 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2080 return nsVariant::SetFromISupports(&mData, aValue);
2083 /* void setAsInterface (in nsIIDRef iid, [iid_is (iid)] in nsQIResult iface); */
2084 NS_IMETHODIMP nsVariant::SetAsInterface(const nsIID & iid, void * iface)
2086 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2087 return nsVariant::SetFromInterface(&mData, iid, (nsISupports*)iface);
2090 /* [noscript] void setAsArray (in PRUint16 type, in nsIIDPtr iid, in PRUint32 count, in voidPtr ptr); */
2091 NS_IMETHODIMP nsVariant::SetAsArray(PRUint16 type, const nsIID * iid, PRUint32 count, void * ptr)
2093 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2094 return nsVariant::SetFromArray(&mData, type, iid, count, ptr);
2097 /* void setAsStringWithSize (in PRUint32 size, [size_is (size)] in string str); */
2098 NS_IMETHODIMP nsVariant::SetAsStringWithSize(PRUint32 size, const char *str)
2100 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2101 return nsVariant::SetFromStringWithSize(&mData, size, str);
2104 /* void setAsWStringWithSize (in PRUint32 size, [size_is (size)] in wstring str); */
2105 NS_IMETHODIMP nsVariant::SetAsWStringWithSize(PRUint32 size, const PRUnichar *str)
2107 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2108 return nsVariant::SetFromWStringWithSize(&mData, size, str);
2111 /* void setAsVoid (); */
2112 NS_IMETHODIMP nsVariant::SetAsVoid()
2114 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2115 return nsVariant::SetToVoid(&mData);
2118 /* void setAsEmpty (); */
2119 NS_IMETHODIMP nsVariant::SetAsEmpty()
2121 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2122 return nsVariant::SetToEmpty(&mData);
2125 /* void setAsEmptyArray (); */
2126 NS_IMETHODIMP nsVariant::SetAsEmptyArray()
2128 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2129 return nsVariant::SetToEmptyArray(&mData);
2132 /* void setFromVariant (in nsIVariant aValue); */
2133 NS_IMETHODIMP nsVariant::SetFromVariant(nsIVariant *aValue)
2135 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2136 return nsVariant::SetFromVariant(&mData, aValue);