CLOSED TREE: TraceMonkey merge head. (a=blockers)
[mozilla-central.git] / xpcom / ds / nsVariant.cpp
blob470f22a7fa337780aee7ac4afe39baf3a204a5a9
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 NS_OUTPARAM,
265 nsIID* outIID NS_OUTPARAM,
266 PRUint32* outCount NS_OUTPARAM,
267 void** outValue)
269 NS_ASSERTION(inCount, "bad param");
270 NS_ASSERTION(inValue, "bad param");
271 NS_ASSERTION(outType, "bad param");
272 NS_ASSERTION(outCount, "bad param");
273 NS_ASSERTION(outValue, "bad param");
275 PRUint32 allocatedValueCount = 0;
276 nsresult rv = NS_OK;
277 PRUint32 i;
279 // First we figure out the size of the elements for the new u.array.
281 size_t elementSize;
282 size_t allocSize;
284 switch(inType)
286 case nsIDataType::VTYPE_INT8:
287 elementSize = sizeof(PRInt8);
288 break;
289 case nsIDataType::VTYPE_INT16:
290 elementSize = sizeof(PRInt16);
291 break;
292 case nsIDataType::VTYPE_INT32:
293 elementSize = sizeof(PRInt32);
294 break;
295 case nsIDataType::VTYPE_INT64:
296 elementSize = sizeof(PRInt64);
297 break;
298 case nsIDataType::VTYPE_UINT8:
299 elementSize = sizeof(PRUint8);
300 break;
301 case nsIDataType::VTYPE_UINT16:
302 elementSize = sizeof(PRUint16);
303 break;
304 case nsIDataType::VTYPE_UINT32:
305 elementSize = sizeof(PRUint32);
306 break;
307 case nsIDataType::VTYPE_UINT64:
308 elementSize = sizeof(PRUint64);
309 break;
310 case nsIDataType::VTYPE_FLOAT:
311 elementSize = sizeof(float);
312 break;
313 case nsIDataType::VTYPE_DOUBLE:
314 elementSize = sizeof(double);
315 break;
316 case nsIDataType::VTYPE_BOOL:
317 elementSize = sizeof(PRBool);
318 break;
319 case nsIDataType::VTYPE_CHAR:
320 elementSize = sizeof(char);
321 break;
322 case nsIDataType::VTYPE_WCHAR:
323 elementSize = sizeof(PRUnichar);
324 break;
326 // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
327 case nsIDataType::VTYPE_ID:
328 case nsIDataType::VTYPE_CHAR_STR:
329 case nsIDataType::VTYPE_WCHAR_STR:
330 case nsIDataType::VTYPE_INTERFACE:
331 case nsIDataType::VTYPE_INTERFACE_IS:
332 elementSize = sizeof(void*);
333 break;
335 // The rest are illegal.
336 case nsIDataType::VTYPE_ASTRING:
337 case nsIDataType::VTYPE_DOMSTRING:
338 case nsIDataType::VTYPE_UTF8STRING:
339 case nsIDataType::VTYPE_CSTRING:
340 case nsIDataType::VTYPE_STRING_SIZE_IS:
341 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
342 case nsIDataType::VTYPE_VOID:
343 case nsIDataType::VTYPE_ARRAY:
344 case nsIDataType::VTYPE_EMPTY_ARRAY:
345 case nsIDataType::VTYPE_EMPTY:
346 default:
347 NS_ERROR("bad type in array!");
348 return NS_ERROR_CANNOT_CONVERT_DATA;
352 // Alloc the u.array.
354 allocSize = inCount * elementSize;
355 *outValue = nsMemory::Alloc(allocSize);
356 if(!*outValue)
357 return NS_ERROR_OUT_OF_MEMORY;
359 // Clone the elements.
361 switch(inType)
363 case nsIDataType::VTYPE_INT8:
364 case nsIDataType::VTYPE_INT16:
365 case nsIDataType::VTYPE_INT32:
366 case nsIDataType::VTYPE_INT64:
367 case nsIDataType::VTYPE_UINT8:
368 case nsIDataType::VTYPE_UINT16:
369 case nsIDataType::VTYPE_UINT32:
370 case nsIDataType::VTYPE_UINT64:
371 case nsIDataType::VTYPE_FLOAT:
372 case nsIDataType::VTYPE_DOUBLE:
373 case nsIDataType::VTYPE_BOOL:
374 case nsIDataType::VTYPE_CHAR:
375 case nsIDataType::VTYPE_WCHAR:
376 memcpy(*outValue, inValue, allocSize);
377 break;
379 case nsIDataType::VTYPE_INTERFACE_IS:
380 if(outIID)
381 *outIID = *inIID;
382 // fall through...
383 case nsIDataType::VTYPE_INTERFACE:
385 memcpy(*outValue, inValue, allocSize);
387 nsISupports** p = (nsISupports**) *outValue;
388 for(i = inCount; i > 0; p++, i--)
389 if(*p)
390 (*p)->AddRef();
391 break;
394 // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
395 case nsIDataType::VTYPE_ID:
397 nsID** inp = (nsID**) inValue;
398 nsID** outp = (nsID**) *outValue;
399 for(i = inCount; i > 0; i--)
401 nsID* idp = *(inp++);
402 if(idp)
404 if(nsnull == (*(outp++) = (nsID*)
405 nsMemory::Clone((char*)idp, sizeof(nsID))))
406 goto bad;
408 else
409 *(outp++) = nsnull;
410 allocatedValueCount++;
412 break;
415 case nsIDataType::VTYPE_CHAR_STR:
417 char** inp = (char**) inValue;
418 char** outp = (char**) *outValue;
419 for(i = inCount; i > 0; i--)
421 char* str = *(inp++);
422 if(str)
424 if(nsnull == (*(outp++) = (char*)
425 nsMemory::Clone(str, (strlen(str)+1)*sizeof(char))))
426 goto bad;
428 else
429 *(outp++) = nsnull;
430 allocatedValueCount++;
432 break;
435 case nsIDataType::VTYPE_WCHAR_STR:
437 PRUnichar** inp = (PRUnichar**) inValue;
438 PRUnichar** outp = (PRUnichar**) *outValue;
439 for(i = inCount; i > 0; i--)
441 PRUnichar* str = *(inp++);
442 if(str)
444 if(nsnull == (*(outp++) = (PRUnichar*)
445 nsMemory::Clone(str,
446 (nsCRT::strlen(str)+1)*sizeof(PRUnichar))))
447 goto bad;
449 else
450 *(outp++) = nsnull;
451 allocatedValueCount++;
453 break;
456 // The rest are illegal.
457 case nsIDataType::VTYPE_VOID:
458 case nsIDataType::VTYPE_ARRAY:
459 case nsIDataType::VTYPE_EMPTY_ARRAY:
460 case nsIDataType::VTYPE_EMPTY:
461 case nsIDataType::VTYPE_ASTRING:
462 case nsIDataType::VTYPE_DOMSTRING:
463 case nsIDataType::VTYPE_UTF8STRING:
464 case nsIDataType::VTYPE_CSTRING:
465 case nsIDataType::VTYPE_STRING_SIZE_IS:
466 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
467 default:
468 NS_ERROR("bad type in array!");
469 return NS_ERROR_CANNOT_CONVERT_DATA;
472 *outType = inType;
473 *outCount = inCount;
474 return NS_OK;
476 bad:
477 if(*outValue)
479 char** p = (char**) *outValue;
480 for(i = allocatedValueCount; i > 0; p++, i--)
481 if(*p)
482 nsMemory::Free(*p);
483 nsMemory::Free((char*)*outValue);
484 *outValue = nsnull;
486 return rv;
489 /***************************************************************************/
491 #define TRIVIAL_DATA_CONVERTER(type_, data_, member_, retval_) \
492 if(data_.mType == nsIDataType :: type_) { \
493 *retval_ = data_.u.member_; \
494 return NS_OK; \
497 #define NUMERIC_CONVERSION_METHOD_BEGIN(type_, Ctype_, name_) \
498 /* static */ nsresult \
499 nsVariant::ConvertTo##name_ (const nsDiscriminatedUnion& data, \
500 Ctype_ *_retval) \
502 TRIVIAL_DATA_CONVERTER(type_, data, m##name_##Value, _retval) \
503 nsDiscriminatedUnion tempData; \
504 nsVariant::Initialize(&tempData); \
505 nsresult rv = ToManageableNumber(data, &tempData); \
506 /* */ \
507 /* NOTE: rv may indicate a success code that we want to preserve */ \
508 /* For the final return. So all the return cases below should return */ \
509 /* this rv when indicating success. */ \
510 /* */ \
511 if(NS_FAILED(rv)) \
512 return rv; \
513 switch(tempData.mType) \
516 #define CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(Ctype_) \
517 case nsIDataType::VTYPE_INT32: \
518 *_retval = ( Ctype_ ) tempData.u.mInt32Value; \
519 return rv;
521 #define CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(Ctype_, min_, max_) \
522 case nsIDataType::VTYPE_INT32: \
524 PRInt32 value = tempData.u.mInt32Value; \
525 if(value < min_ || value > max_) \
526 return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
527 *_retval = ( Ctype_ ) value; \
528 return rv; \
531 #define CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(Ctype_) \
532 case nsIDataType::VTYPE_UINT32: \
533 *_retval = ( Ctype_ ) tempData.u.mUint32Value; \
534 return rv;
536 #define CASE__NUMERIC_CONVERSION_UINT32_MAX(Ctype_, max_) \
537 case nsIDataType::VTYPE_UINT32: \
539 PRUint32 value = tempData.u.mUint32Value; \
540 if(value > max_) \
541 return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
542 *_retval = ( Ctype_ ) value; \
543 return rv; \
546 #define CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(Ctype_) \
547 case nsIDataType::VTYPE_DOUBLE: \
548 *_retval = ( Ctype_ ) tempData.u.mDoubleValue; \
549 return rv;
551 #define CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX(Ctype_, min_, max_) \
552 case nsIDataType::VTYPE_DOUBLE: \
554 double value = tempData.u.mDoubleValue; \
555 if(value < min_ || value > max_) \
556 return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
557 *_retval = ( Ctype_ ) value; \
558 return rv; \
561 #define CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(Ctype_, min_, max_) \
562 case nsIDataType::VTYPE_DOUBLE: \
564 double value = tempData.u.mDoubleValue; \
565 if(value < min_ || value > max_) \
566 return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
567 *_retval = ( Ctype_ ) value; \
568 return (0.0 == fmod(value,1.0)) ? \
569 rv : NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA; \
572 #define CASES__NUMERIC_CONVERSION_NORMAL(Ctype_, min_, max_) \
573 CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(Ctype_, min_, max_) \
574 CASE__NUMERIC_CONVERSION_UINT32_MAX(Ctype_, max_) \
575 CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(Ctype_, min_, max_)
577 #define NUMERIC_CONVERSION_METHOD_END \
578 default: \
579 NS_ERROR("bad type returned from ToManageableNumber"); \
580 return NS_ERROR_CANNOT_CONVERT_DATA; \
584 #define NUMERIC_CONVERSION_METHOD_NORMAL(type_, Ctype_, name_, min_, max_) \
585 NUMERIC_CONVERSION_METHOD_BEGIN(type_, Ctype_, name_) \
586 CASES__NUMERIC_CONVERSION_NORMAL(Ctype_, min_, max_) \
587 NUMERIC_CONVERSION_METHOD_END
589 /***************************************************************************/
590 // These expand into full public methods...
592 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_INT8, PRUint8, Int8, (-127-1), 127)
593 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_INT16, PRInt16, Int16, (-32767-1), 32767)
595 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_INT32, PRInt32, Int32)
596 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(PRInt32)
597 CASE__NUMERIC_CONVERSION_UINT32_MAX(PRInt32, 2147483647)
598 CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(PRInt32, (-2147483647-1), 2147483647)
599 NUMERIC_CONVERSION_METHOD_END
601 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_UINT8, PRUint8, Uint8, 0, 255)
602 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_UINT16, PRUint16, Uint16, 0, 65535)
604 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_UINT32, PRUint32, Uint32)
605 CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(PRUint32, 0, 2147483647)
606 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(PRUint32)
607 CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(PRUint32, 0, 4294967295U)
608 NUMERIC_CONVERSION_METHOD_END
610 // XXX toFloat convertions need to be fixed!
611 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_FLOAT, float, Float)
612 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(float)
613 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(float)
614 CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(float)
615 NUMERIC_CONVERSION_METHOD_END
617 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_DOUBLE, double, Double)
618 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(double)
619 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(double)
620 CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(double)
621 NUMERIC_CONVERSION_METHOD_END
623 // XXX toChar convertions need to be fixed!
624 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_CHAR, char, Char)
625 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(char)
626 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(char)
627 CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(char)
628 NUMERIC_CONVERSION_METHOD_END
630 // XXX toWChar convertions need to be fixed!
631 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_WCHAR, PRUnichar, WChar)
632 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(PRUnichar)
633 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(PRUnichar)
634 CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(PRUnichar)
635 NUMERIC_CONVERSION_METHOD_END
637 #undef NUMERIC_CONVERSION_METHOD_BEGIN
638 #undef CASE__NUMERIC_CONVERSION_INT32_JUST_CAST
639 #undef CASE__NUMERIC_CONVERSION_INT32_MIN_MAX
640 #undef CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST
641 #undef CASE__NUMERIC_CONVERSION_UINT32_MIN_MAX
642 #undef CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST
643 #undef CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX
644 #undef CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT
645 #undef CASES__NUMERIC_CONVERSION_NORMAL
646 #undef NUMERIC_CONVERSION_METHOD_END
647 #undef NUMERIC_CONVERSION_METHOD_NORMAL
649 /***************************************************************************/
651 // Just leverage a numeric converter for bool (but restrict the values).
652 // XXX Is this really what we want to do?
654 /* static */ nsresult
655 nsVariant::ConvertToBool(const nsDiscriminatedUnion& data, PRBool *_retval)
657 TRIVIAL_DATA_CONVERTER(VTYPE_BOOL, data, mBoolValue, _retval)
659 double val;
660 nsresult rv = nsVariant::ConvertToDouble(data, &val);
661 if(NS_FAILED(rv))
662 return rv;
663 *_retval = 0.0 != val;
664 return rv;
667 /***************************************************************************/
669 /* static */ nsresult
670 nsVariant::ConvertToInt64(const nsDiscriminatedUnion& data, PRInt64 *_retval)
672 TRIVIAL_DATA_CONVERTER(VTYPE_INT64, data, mInt64Value, _retval)
673 TRIVIAL_DATA_CONVERTER(VTYPE_UINT64, data, mUint64Value, _retval)
675 nsDiscriminatedUnion tempData;
676 nsVariant::Initialize(&tempData);
677 nsresult rv = ToManageableNumber(data, &tempData);
678 if(NS_FAILED(rv))
679 return rv;
680 switch(tempData.mType)
682 case nsIDataType::VTYPE_INT32:
683 LL_I2L(*_retval, tempData.u.mInt32Value);
684 return rv;
685 case nsIDataType::VTYPE_UINT32:
686 LL_UI2L(*_retval, tempData.u.mUint32Value);
687 return rv;
688 case nsIDataType::VTYPE_DOUBLE:
689 // XXX should check for data loss here!
690 LL_D2L(*_retval, tempData.u.mDoubleValue);
691 return rv;
692 default:
693 NS_ERROR("bad type returned from ToManageableNumber");
694 return NS_ERROR_CANNOT_CONVERT_DATA;
698 /* static */ nsresult
699 nsVariant::ConvertToUint64(const nsDiscriminatedUnion& data, PRUint64 *_retval)
701 return nsVariant::ConvertToInt64(data, (PRInt64 *)_retval);
704 /***************************************************************************/
706 static PRBool String2ID(const nsDiscriminatedUnion& data, nsID* pid)
708 nsAutoString tempString;
709 nsAString* pString;
711 switch(data.mType)
713 case nsIDataType::VTYPE_CHAR_STR:
714 case nsIDataType::VTYPE_STRING_SIZE_IS:
715 return pid->Parse(data.u.str.mStringValue);
716 case nsIDataType::VTYPE_CSTRING:
717 return pid->Parse(PromiseFlatCString(*data.u.mCStringValue).get());
718 case nsIDataType::VTYPE_UTF8STRING:
719 return pid->Parse(PromiseFlatUTF8String(*data.u.mUTF8StringValue).get());
720 case nsIDataType::VTYPE_ASTRING:
721 case nsIDataType::VTYPE_DOMSTRING:
722 pString = data.u.mAStringValue;
723 break;
724 case nsIDataType::VTYPE_WCHAR_STR:
725 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
726 tempString.Assign(data.u.wstr.mWStringValue);
727 pString = &tempString;
728 break;
729 default:
730 NS_ERROR("bad type in call to String2ID");
731 return PR_FALSE;
734 char* pChars = ToNewCString(*pString);
735 if(!pChars)
736 return PR_FALSE;
737 PRBool result = pid->Parse(pChars);
738 nsMemory::Free(pChars);
739 return result;
742 /* static */ nsresult
743 nsVariant::ConvertToID(const nsDiscriminatedUnion& data, nsID * _retval)
745 nsID id;
747 switch(data.mType)
749 case nsIDataType::VTYPE_ID:
750 *_retval = data.u.mIDValue;
751 return NS_OK;
752 case nsIDataType::VTYPE_INTERFACE:
753 *_retval = NS_GET_IID(nsISupports);
754 return NS_OK;
755 case nsIDataType::VTYPE_INTERFACE_IS:
756 *_retval = data.u.iface.mInterfaceID;
757 return NS_OK;
758 case nsIDataType::VTYPE_ASTRING:
759 case nsIDataType::VTYPE_DOMSTRING:
760 case nsIDataType::VTYPE_UTF8STRING:
761 case nsIDataType::VTYPE_CSTRING:
762 case nsIDataType::VTYPE_CHAR_STR:
763 case nsIDataType::VTYPE_WCHAR_STR:
764 case nsIDataType::VTYPE_STRING_SIZE_IS:
765 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
766 if(!String2ID(data, &id))
767 return NS_ERROR_CANNOT_CONVERT_DATA;
768 *_retval = id;
769 return NS_OK;
770 default:
771 return NS_ERROR_CANNOT_CONVERT_DATA;
775 /***************************************************************************/
777 static nsresult ToString(const nsDiscriminatedUnion& data,
778 nsACString & outString)
780 char* ptr;
782 switch(data.mType)
784 // all the stuff we don't handle...
785 case nsIDataType::VTYPE_ASTRING:
786 case nsIDataType::VTYPE_DOMSTRING:
787 case nsIDataType::VTYPE_UTF8STRING:
788 case nsIDataType::VTYPE_CSTRING:
789 case nsIDataType::VTYPE_CHAR_STR:
790 case nsIDataType::VTYPE_WCHAR_STR:
791 case nsIDataType::VTYPE_STRING_SIZE_IS:
792 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
793 case nsIDataType::VTYPE_WCHAR:
794 NS_ERROR("ToString being called for a string type - screwy logic!");
795 // fall through...
797 // XXX We might want stringified versions of these... ???
799 case nsIDataType::VTYPE_VOID:
800 case nsIDataType::VTYPE_EMPTY:
801 outString.Truncate();
802 outString.SetIsVoid(true);
803 return NS_OK;
805 case nsIDataType::VTYPE_EMPTY_ARRAY:
806 case nsIDataType::VTYPE_ARRAY:
807 case nsIDataType::VTYPE_INTERFACE:
808 case nsIDataType::VTYPE_INTERFACE_IS:
809 default:
810 return NS_ERROR_CANNOT_CONVERT_DATA;
812 // nsID has its own text formatter.
814 case nsIDataType::VTYPE_ID:
815 ptr = data.u.mIDValue.ToString();
816 if(!ptr)
817 return NS_ERROR_OUT_OF_MEMORY;
818 outString.Assign(ptr);
819 nsMemory::Free(ptr);
820 return NS_OK;
822 // Can't use PR_smprintf for floats, since it's locale-dependent
823 #define CASE__APPENDFLOAT_NUMBER(type_, member_) \
824 case nsIDataType :: type_ : \
826 nsCAutoString str; \
827 str.AppendFloat(data.u. member_); \
828 outString.Assign(str); \
829 return NS_OK; \
832 CASE__APPENDFLOAT_NUMBER(VTYPE_FLOAT, mFloatValue)
833 CASE__APPENDFLOAT_NUMBER(VTYPE_DOUBLE, mDoubleValue)
835 #undef CASE__APPENDFLOAT_NUMBER
837 // the rest can be PR_smprintf'd and use common code.
839 #define CASE__SMPRINTF_NUMBER(type_, format_, cast_, member_) \
840 case nsIDataType :: type_ : \
841 ptr = PR_smprintf( format_ , (cast_) data.u. member_ ); \
842 break;
844 CASE__SMPRINTF_NUMBER(VTYPE_INT8, "%d", int, mInt8Value)
845 CASE__SMPRINTF_NUMBER(VTYPE_INT16, "%d", int, mInt16Value)
846 CASE__SMPRINTF_NUMBER(VTYPE_INT32, "%d", int, mInt32Value)
847 CASE__SMPRINTF_NUMBER(VTYPE_INT64, "%lld", PRInt64, mInt64Value)
849 CASE__SMPRINTF_NUMBER(VTYPE_UINT8, "%u", unsigned, mUint8Value)
850 CASE__SMPRINTF_NUMBER(VTYPE_UINT16, "%u", unsigned, mUint16Value)
851 CASE__SMPRINTF_NUMBER(VTYPE_UINT32, "%u", unsigned, mUint32Value)
852 CASE__SMPRINTF_NUMBER(VTYPE_UINT64, "%llu", PRInt64, mUint64Value)
854 // XXX Would we rather print "true" / "false" ?
855 CASE__SMPRINTF_NUMBER(VTYPE_BOOL, "%d", int, mBoolValue)
857 CASE__SMPRINTF_NUMBER(VTYPE_CHAR, "%c", char, mCharValue)
859 #undef CASE__SMPRINTF_NUMBER
862 if(!ptr)
863 return NS_ERROR_OUT_OF_MEMORY;
864 outString.Assign(ptr);
865 PR_smprintf_free(ptr);
866 return NS_OK;
869 /* static */ nsresult
870 nsVariant::ConvertToAString(const nsDiscriminatedUnion& data,
871 nsAString & _retval)
873 switch(data.mType)
875 case nsIDataType::VTYPE_ASTRING:
876 case nsIDataType::VTYPE_DOMSTRING:
877 _retval.Assign(*data.u.mAStringValue);
878 return NS_OK;
879 case nsIDataType::VTYPE_CSTRING:
880 CopyASCIItoUTF16(*data.u.mCStringValue, _retval);
881 return NS_OK;
882 case nsIDataType::VTYPE_UTF8STRING:
883 CopyUTF8toUTF16(*data.u.mUTF8StringValue, _retval);
884 return NS_OK;
885 case nsIDataType::VTYPE_CHAR_STR:
886 CopyASCIItoUTF16(data.u.str.mStringValue, _retval);
887 return NS_OK;
888 case nsIDataType::VTYPE_WCHAR_STR:
889 _retval.Assign(data.u.wstr.mWStringValue);
890 return NS_OK;
891 case nsIDataType::VTYPE_STRING_SIZE_IS:
892 CopyASCIItoUTF16(nsDependentCString(data.u.str.mStringValue,
893 data.u.str.mStringLength),
894 _retval);
895 return NS_OK;
896 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
897 _retval.Assign(data.u.wstr.mWStringValue, data.u.wstr.mWStringLength);
898 return NS_OK;
899 case nsIDataType::VTYPE_WCHAR:
900 _retval.Assign(data.u.mWCharValue);
901 return NS_OK;
902 default:
904 nsCAutoString tempCString;
905 nsresult rv = ToString(data, tempCString);
906 if(NS_FAILED(rv))
907 return rv;
908 CopyASCIItoUTF16(tempCString, _retval);
909 return NS_OK;
914 /* static */ nsresult
915 nsVariant::ConvertToACString(const nsDiscriminatedUnion& data,
916 nsACString & _retval)
918 switch(data.mType)
920 case nsIDataType::VTYPE_ASTRING:
921 case nsIDataType::VTYPE_DOMSTRING:
922 LossyCopyUTF16toASCII(*data.u.mAStringValue, _retval);
923 return NS_OK;
924 case nsIDataType::VTYPE_CSTRING:
925 _retval.Assign(*data.u.mCStringValue);
926 return NS_OK;
927 case nsIDataType::VTYPE_UTF8STRING:
928 // XXX This is an extra copy that should be avoided
929 // once Jag lands support for UTF8String and associated
930 // conversion methods.
931 LossyCopyUTF16toASCII(NS_ConvertUTF8toUTF16(*data.u.mUTF8StringValue),
932 _retval);
933 return NS_OK;
934 case nsIDataType::VTYPE_CHAR_STR:
935 _retval.Assign(*data.u.str.mStringValue);
936 return NS_OK;
937 case nsIDataType::VTYPE_WCHAR_STR:
938 LossyCopyUTF16toASCII(nsDependentString(data.u.wstr.mWStringValue),
939 _retval);
940 return NS_OK;
941 case nsIDataType::VTYPE_STRING_SIZE_IS:
942 _retval.Assign(data.u.str.mStringValue, data.u.str.mStringLength);
943 return NS_OK;
944 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
945 LossyCopyUTF16toASCII(nsDependentString(data.u.wstr.mWStringValue,
946 data.u.wstr.mWStringLength), _retval);
947 return NS_OK;
948 case nsIDataType::VTYPE_WCHAR:
950 const PRUnichar* str = &data.u.mWCharValue;
951 LossyCopyUTF16toASCII(Substring(str, str + 1), _retval);
952 return NS_OK;
954 default:
955 return ToString(data, _retval);
959 /* static */ nsresult
960 nsVariant::ConvertToAUTF8String(const nsDiscriminatedUnion& data,
961 nsAUTF8String & _retval)
963 switch(data.mType)
965 case nsIDataType::VTYPE_ASTRING:
966 case nsIDataType::VTYPE_DOMSTRING:
967 CopyUTF16toUTF8(*data.u.mAStringValue, _retval);
968 return NS_OK;
969 case nsIDataType::VTYPE_CSTRING:
970 // XXX Extra copy, can be removed if we're sure CSTRING can
971 // only contain ASCII.
972 CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(*data.u.mCStringValue),
973 _retval);
974 return NS_OK;
975 case nsIDataType::VTYPE_UTF8STRING:
976 _retval.Assign(*data.u.mUTF8StringValue);
977 return NS_OK;
978 case nsIDataType::VTYPE_CHAR_STR:
979 // XXX Extra copy, can be removed if we're sure CHAR_STR can
980 // only contain ASCII.
981 CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(data.u.str.mStringValue),
982 _retval);
983 return NS_OK;
984 case nsIDataType::VTYPE_WCHAR_STR:
985 CopyUTF16toUTF8(data.u.wstr.mWStringValue, _retval);
986 return NS_OK;
987 case nsIDataType::VTYPE_STRING_SIZE_IS:
988 // XXX Extra copy, can be removed if we're sure CHAR_STR can
989 // only contain ASCII.
990 CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(
991 nsDependentCString(data.u.str.mStringValue,
992 data.u.str.mStringLength)), _retval);
993 return NS_OK;
994 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
995 CopyUTF16toUTF8(nsDependentString(data.u.wstr.mWStringValue,
996 data.u.wstr.mWStringLength),
997 _retval);
998 return NS_OK;
999 case nsIDataType::VTYPE_WCHAR:
1001 const PRUnichar* str = &data.u.mWCharValue;
1002 CopyUTF16toUTF8(Substring(str, str + 1), _retval);
1003 return NS_OK;
1005 default:
1007 nsCAutoString tempCString;
1008 nsresult rv = ToString(data, tempCString);
1009 if(NS_FAILED(rv))
1010 return rv;
1011 // XXX Extra copy, can be removed if we're sure tempCString can
1012 // only contain ASCII.
1013 CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(tempCString), _retval);
1014 return NS_OK;
1019 /* static */ nsresult
1020 nsVariant::ConvertToString(const nsDiscriminatedUnion& data, char **_retval)
1022 PRUint32 ignored;
1023 return nsVariant::ConvertToStringWithSize(data, &ignored, _retval);
1026 /* static */ nsresult
1027 nsVariant::ConvertToWString(const nsDiscriminatedUnion& data, PRUnichar **_retval)
1029 PRUint32 ignored;
1030 return nsVariant::ConvertToWStringWithSize(data, &ignored, _retval);
1033 /* static */ nsresult
1034 nsVariant::ConvertToStringWithSize(const nsDiscriminatedUnion& data,
1035 PRUint32 *size, char **str)
1037 nsAutoString tempString;
1038 nsCAutoString tempCString;
1039 nsresult rv;
1041 switch(data.mType)
1043 case nsIDataType::VTYPE_ASTRING:
1044 case nsIDataType::VTYPE_DOMSTRING:
1045 *size = data.u.mAStringValue->Length();
1046 *str = ToNewCString(*data.u.mAStringValue);
1047 break;
1048 case nsIDataType::VTYPE_CSTRING:
1049 *size = data.u.mCStringValue->Length();
1050 *str = ToNewCString(*data.u.mCStringValue);
1051 break;
1052 case nsIDataType::VTYPE_UTF8STRING:
1054 // XXX This is doing 1 extra copy. Need to fix this
1055 // when Jag lands UTF8String
1056 // we want:
1057 // *size = *data.mUTF8StringValue->Length();
1058 // *str = ToNewCString(*data.mUTF8StringValue);
1059 // But this will have to do for now.
1060 NS_ConvertUTF8toUTF16 tempString(*data.u.mUTF8StringValue);
1061 *size = tempString.Length();
1062 *str = ToNewCString(tempString);
1063 break;
1065 case nsIDataType::VTYPE_CHAR_STR:
1067 nsDependentCString cString(data.u.str.mStringValue);
1068 *size = cString.Length();
1069 *str = ToNewCString(cString);
1070 break;
1072 case nsIDataType::VTYPE_WCHAR_STR:
1074 nsDependentString string(data.u.wstr.mWStringValue);
1075 *size = string.Length();
1076 *str = ToNewCString(string);
1077 break;
1079 case nsIDataType::VTYPE_STRING_SIZE_IS:
1081 nsDependentCString cString(data.u.str.mStringValue,
1082 data.u.str.mStringLength);
1083 *size = cString.Length();
1084 *str = ToNewCString(cString);
1085 break;
1087 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
1089 nsDependentString string(data.u.wstr.mWStringValue,
1090 data.u.wstr.mWStringLength);
1091 *size = string.Length();
1092 *str = ToNewCString(string);
1093 break;
1095 case nsIDataType::VTYPE_WCHAR:
1096 tempString.Assign(data.u.mWCharValue);
1097 *size = tempString.Length();
1098 *str = ToNewCString(tempString);
1099 break;
1100 default:
1101 rv = ToString(data, tempCString);
1102 if(NS_FAILED(rv))
1103 return rv;
1104 *size = tempCString.Length();
1105 *str = ToNewCString(tempCString);
1106 break;
1109 return *str ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
1111 /* static */ nsresult
1112 nsVariant::ConvertToWStringWithSize(const nsDiscriminatedUnion& data,
1113 PRUint32 *size, PRUnichar **str)
1115 nsAutoString tempString;
1116 nsCAutoString tempCString;
1117 nsresult rv;
1119 switch(data.mType)
1121 case nsIDataType::VTYPE_ASTRING:
1122 case nsIDataType::VTYPE_DOMSTRING:
1123 *size = data.u.mAStringValue->Length();
1124 *str = ToNewUnicode(*data.u.mAStringValue);
1125 break;
1126 case nsIDataType::VTYPE_CSTRING:
1127 *size = data.u.mCStringValue->Length();
1128 *str = ToNewUnicode(*data.u.mCStringValue);
1129 break;
1130 case nsIDataType::VTYPE_UTF8STRING:
1132 *str = UTF8ToNewUnicode(*data.u.mUTF8StringValue, size);
1133 break;
1135 case nsIDataType::VTYPE_CHAR_STR:
1137 nsDependentCString cString(data.u.str.mStringValue);
1138 *size = cString.Length();
1139 *str = ToNewUnicode(cString);
1140 break;
1142 case nsIDataType::VTYPE_WCHAR_STR:
1144 nsDependentString string(data.u.wstr.mWStringValue);
1145 *size = string.Length();
1146 *str = ToNewUnicode(string);
1147 break;
1149 case nsIDataType::VTYPE_STRING_SIZE_IS:
1151 nsDependentCString cString(data.u.str.mStringValue,
1152 data.u.str.mStringLength);
1153 *size = cString.Length();
1154 *str = ToNewUnicode(cString);
1155 break;
1157 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
1159 nsDependentString string(data.u.wstr.mWStringValue,
1160 data.u.wstr.mWStringLength);
1161 *size = string.Length();
1162 *str = ToNewUnicode(string);
1163 break;
1165 case nsIDataType::VTYPE_WCHAR:
1166 tempString.Assign(data.u.mWCharValue);
1167 *size = tempString.Length();
1168 *str = ToNewUnicode(tempString);
1169 break;
1170 default:
1171 rv = ToString(data, tempCString);
1172 if(NS_FAILED(rv))
1173 return rv;
1174 *size = tempCString.Length();
1175 *str = ToNewUnicode(tempCString);
1176 break;
1179 return *str ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
1182 /* static */ nsresult
1183 nsVariant::ConvertToISupports(const nsDiscriminatedUnion& data,
1184 nsISupports **_retval)
1186 switch(data.mType)
1188 case nsIDataType::VTYPE_INTERFACE:
1189 case nsIDataType::VTYPE_INTERFACE_IS:
1190 if (data.u.iface.mInterfaceValue) {
1191 return data.u.iface.mInterfaceValue->
1192 QueryInterface(NS_GET_IID(nsISupports), (void**)_retval);
1193 } else {
1194 *_retval = nsnull;
1195 return NS_OK;
1197 default:
1198 return NS_ERROR_CANNOT_CONVERT_DATA;
1202 /* static */ nsresult
1203 nsVariant::ConvertToInterface(const nsDiscriminatedUnion& data, nsIID * *iid,
1204 void * *iface)
1206 const nsIID* piid;
1208 switch(data.mType)
1210 case nsIDataType::VTYPE_INTERFACE:
1211 piid = &NS_GET_IID(nsISupports);
1212 break;
1213 case nsIDataType::VTYPE_INTERFACE_IS:
1214 piid = &data.u.iface.mInterfaceID;
1215 break;
1216 default:
1217 return NS_ERROR_CANNOT_CONVERT_DATA;
1220 *iid = (nsIID*) nsMemory::Clone(piid, sizeof(nsIID));
1221 if(!*iid)
1222 return NS_ERROR_OUT_OF_MEMORY;
1224 if (data.u.iface.mInterfaceValue) {
1225 return data.u.iface.mInterfaceValue->QueryInterface(*piid, iface);
1228 *iface = nsnull;
1229 return NS_OK;
1232 /* static */ nsresult
1233 nsVariant::ConvertToArray(const nsDiscriminatedUnion& data, PRUint16 *type,
1234 nsIID* iid, PRUint32 *count, void * *ptr)
1236 // XXX perhaps we'd like to add support for converting each of the various
1237 // types into an array containing one element of that type. We can leverage
1238 // CloneArray to do this if we want to support this.
1240 if(data.mType == nsIDataType::VTYPE_ARRAY)
1241 return CloneArray(data.u.array.mArrayType, &data.u.array.mArrayInterfaceID,
1242 data.u.array.mArrayCount, data.u.array.mArrayValue,
1243 type, iid, count, ptr);
1244 return NS_ERROR_CANNOT_CONVERT_DATA;
1247 /***************************************************************************/
1248 // static setter functions...
1250 #define DATA_SETTER_PROLOGUE(data_) \
1251 nsVariant::Cleanup(data_);
1253 #define DATA_SETTER_EPILOGUE(data_, type_) \
1254 data_->mType = nsIDataType :: type_; \
1255 return NS_OK;
1257 #define DATA_SETTER(data_, type_, member_, value_) \
1258 DATA_SETTER_PROLOGUE(data_) \
1259 data_->u.member_ = value_; \
1260 DATA_SETTER_EPILOGUE(data_, type_)
1262 #define DATA_SETTER_WITH_CAST(data_, type_, member_, cast_, value_) \
1263 DATA_SETTER_PROLOGUE(data_) \
1264 data_->u.member_ = cast_ value_; \
1265 DATA_SETTER_EPILOGUE(data_, type_)
1268 /********************************************/
1270 #define CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_) \
1273 #define CASE__SET_FROM_VARIANT_VTYPE__GETTER(member_, name_) \
1274 rv = aValue->GetAs##name_ (&(data->u. member_ ));
1276 #define CASE__SET_FROM_VARIANT_VTYPE__GETTER_CAST(cast_, member_, name_) \
1277 rv = aValue->GetAs##name_ ( cast_ &(data->u. member_ ));
1279 #define CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_) \
1280 if(NS_SUCCEEDED(rv)) \
1282 data->mType = nsIDataType :: type_ ; \
1284 break; \
1287 #define CASE__SET_FROM_VARIANT_TYPE(type_, member_, name_) \
1288 case nsIDataType :: type_ : \
1289 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_) \
1290 CASE__SET_FROM_VARIANT_VTYPE__GETTER(member_, name_) \
1291 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)
1293 #define CASE__SET_FROM_VARIANT_VTYPE_CAST(type_, cast_, member_, name_) \
1294 case nsIDataType :: type_ : \
1295 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_) \
1296 CASE__SET_FROM_VARIANT_VTYPE__GETTER_CAST(cast_, member_, name_) \
1297 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)
1300 /* static */ nsresult
1301 nsVariant::SetFromVariant(nsDiscriminatedUnion* data, nsIVariant* aValue)
1303 PRUint16 type;
1304 nsresult rv;
1306 nsVariant::Cleanup(data);
1308 rv = aValue->GetDataType(&type);
1309 if(NS_FAILED(rv))
1310 return rv;
1312 switch(type)
1314 CASE__SET_FROM_VARIANT_VTYPE_CAST(VTYPE_INT8, (PRUint8*), mInt8Value,
1315 Int8)
1316 CASE__SET_FROM_VARIANT_TYPE(VTYPE_INT16, mInt16Value, Int16)
1317 CASE__SET_FROM_VARIANT_TYPE(VTYPE_INT32, mInt32Value, Int32)
1318 CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT8, mUint8Value, Uint8)
1319 CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT16, mUint16Value, Uint16)
1320 CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT32, mUint32Value, Uint32)
1321 CASE__SET_FROM_VARIANT_TYPE(VTYPE_FLOAT, mFloatValue, Float)
1322 CASE__SET_FROM_VARIANT_TYPE(VTYPE_DOUBLE, mDoubleValue, Double)
1323 CASE__SET_FROM_VARIANT_TYPE(VTYPE_BOOL , mBoolValue, Bool)
1324 CASE__SET_FROM_VARIANT_TYPE(VTYPE_CHAR, mCharValue, Char)
1325 CASE__SET_FROM_VARIANT_TYPE(VTYPE_WCHAR, mWCharValue, WChar)
1326 CASE__SET_FROM_VARIANT_TYPE(VTYPE_ID, mIDValue, ID)
1328 case nsIDataType::VTYPE_ASTRING:
1329 case nsIDataType::VTYPE_DOMSTRING:
1330 case nsIDataType::VTYPE_WCHAR_STR:
1331 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
1332 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_ASTRING);
1333 data->u.mAStringValue = new nsString();
1334 if(!data->u.mAStringValue)
1335 return NS_ERROR_OUT_OF_MEMORY;
1336 rv = aValue->GetAsAString(*data->u.mAStringValue);
1337 if(NS_FAILED(rv))
1338 delete data->u.mAStringValue;
1339 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_ASTRING)
1341 case nsIDataType::VTYPE_CSTRING:
1342 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_CSTRING);
1343 data->u.mCStringValue = new nsCString();
1344 if(!data->u.mCStringValue)
1345 return NS_ERROR_OUT_OF_MEMORY;
1346 rv = aValue->GetAsACString(*data->u.mCStringValue);
1347 if(NS_FAILED(rv))
1348 delete data->u.mCStringValue;
1349 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_CSTRING)
1351 case nsIDataType::VTYPE_UTF8STRING:
1352 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_UTF8STRING);
1353 data->u.mUTF8StringValue = new nsUTF8String();
1354 if(!data->u.mUTF8StringValue)
1355 return NS_ERROR_OUT_OF_MEMORY;
1356 rv = aValue->GetAsAUTF8String(*data->u.mUTF8StringValue);
1357 if(NS_FAILED(rv))
1358 delete data->u.mUTF8StringValue;
1359 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_UTF8STRING)
1361 case nsIDataType::VTYPE_CHAR_STR:
1362 case nsIDataType::VTYPE_STRING_SIZE_IS:
1363 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_STRING_SIZE_IS);
1364 rv = aValue->GetAsStringWithSize(&data->u.str.mStringLength,
1365 &data->u.str.mStringValue);
1366 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_STRING_SIZE_IS)
1368 case nsIDataType::VTYPE_INTERFACE:
1369 case nsIDataType::VTYPE_INTERFACE_IS:
1370 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_INTERFACE_IS);
1371 // XXX This iid handling is ugly!
1372 nsIID* iid;
1373 rv = aValue->GetAsInterface(&iid, (void**)&data->u.iface.mInterfaceValue);
1374 if(NS_SUCCEEDED(rv))
1376 data->u.iface.mInterfaceID = *iid;
1377 nsMemory::Free((char*)iid);
1379 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_INTERFACE_IS)
1381 case nsIDataType::VTYPE_ARRAY:
1382 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_ARRAY);
1383 rv = aValue->GetAsArray(&data->u.array.mArrayType,
1384 &data->u.array.mArrayInterfaceID,
1385 &data->u.array.mArrayCount,
1386 &data->u.array.mArrayValue);
1387 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_ARRAY)
1389 case nsIDataType::VTYPE_VOID:
1390 rv = nsVariant::SetToVoid(data);
1391 break;
1392 case nsIDataType::VTYPE_EMPTY_ARRAY:
1393 rv = nsVariant::SetToEmptyArray(data);
1394 break;
1395 case nsIDataType::VTYPE_EMPTY:
1396 rv = nsVariant::SetToEmpty(data);
1397 break;
1398 default:
1399 NS_ERROR("bad type in variant!");
1400 rv = NS_ERROR_FAILURE;
1401 break;
1403 return rv;
1406 /* static */ nsresult
1407 nsVariant::SetFromInt8(nsDiscriminatedUnion* data, PRUint8 aValue)
1409 DATA_SETTER_WITH_CAST(data, VTYPE_INT8, mInt8Value, (PRUint8), aValue)
1411 /* static */ nsresult
1412 nsVariant::SetFromInt16(nsDiscriminatedUnion* data, PRInt16 aValue)
1414 DATA_SETTER(data, VTYPE_INT16, mInt16Value, aValue)
1416 /* static */ nsresult
1417 nsVariant::SetFromInt32(nsDiscriminatedUnion* data, PRInt32 aValue)
1419 DATA_SETTER(data, VTYPE_INT32, mInt32Value, aValue)
1421 /* static */ nsresult
1422 nsVariant::SetFromInt64(nsDiscriminatedUnion* data, PRInt64 aValue)
1424 DATA_SETTER(data, VTYPE_INT64, mInt64Value, aValue)
1426 /* static */ nsresult
1427 nsVariant::SetFromUint8(nsDiscriminatedUnion* data, PRUint8 aValue)
1429 DATA_SETTER(data, VTYPE_UINT8, mUint8Value, aValue)
1431 /* static */ nsresult
1432 nsVariant::SetFromUint16(nsDiscriminatedUnion* data, PRUint16 aValue)
1434 DATA_SETTER(data, VTYPE_UINT16, mUint16Value, aValue)
1436 /* static */ nsresult
1437 nsVariant::SetFromUint32(nsDiscriminatedUnion* data, PRUint32 aValue)
1439 DATA_SETTER(data, VTYPE_UINT32, mUint32Value, aValue)
1441 /* static */ nsresult
1442 nsVariant::SetFromUint64(nsDiscriminatedUnion* data, PRUint64 aValue)
1444 DATA_SETTER(data, VTYPE_UINT64, mUint64Value, aValue)
1446 /* static */ nsresult
1447 nsVariant::SetFromFloat(nsDiscriminatedUnion* data, float aValue)
1449 DATA_SETTER(data, VTYPE_FLOAT, mFloatValue, aValue)
1451 /* static */ nsresult
1452 nsVariant::SetFromDouble(nsDiscriminatedUnion* data, double aValue)
1454 DATA_SETTER(data, VTYPE_DOUBLE, mDoubleValue, aValue)
1456 /* static */ nsresult
1457 nsVariant::SetFromBool(nsDiscriminatedUnion* data, PRBool aValue)
1459 DATA_SETTER(data, VTYPE_BOOL, mBoolValue, aValue)
1461 /* static */ nsresult
1462 nsVariant::SetFromChar(nsDiscriminatedUnion* data, char aValue)
1464 DATA_SETTER(data, VTYPE_CHAR, mCharValue, aValue)
1466 /* static */ nsresult
1467 nsVariant::SetFromWChar(nsDiscriminatedUnion* data, PRUnichar aValue)
1469 DATA_SETTER(data, VTYPE_WCHAR, mWCharValue, aValue)
1471 /* static */ nsresult
1472 nsVariant::SetFromID(nsDiscriminatedUnion* data, const nsID & aValue)
1474 DATA_SETTER(data, VTYPE_ID, mIDValue, aValue)
1476 /* static */ nsresult
1477 nsVariant::SetFromAString(nsDiscriminatedUnion* data, const nsAString & aValue)
1479 DATA_SETTER_PROLOGUE(data);
1480 if(!(data->u.mAStringValue = new nsString(aValue)))
1481 return NS_ERROR_OUT_OF_MEMORY;
1482 DATA_SETTER_EPILOGUE(data, VTYPE_ASTRING);
1485 /* static */ nsresult
1486 nsVariant::SetFromACString(nsDiscriminatedUnion* data,
1487 const nsACString & aValue)
1489 DATA_SETTER_PROLOGUE(data);
1490 if(!(data->u.mCStringValue = new nsCString(aValue)))
1491 return NS_ERROR_OUT_OF_MEMORY;
1492 DATA_SETTER_EPILOGUE(data, VTYPE_CSTRING);
1495 /* static */ nsresult
1496 nsVariant::SetFromAUTF8String(nsDiscriminatedUnion* data,
1497 const nsAUTF8String & aValue)
1499 DATA_SETTER_PROLOGUE(data);
1500 if(!(data->u.mUTF8StringValue = new nsUTF8String(aValue)))
1501 return NS_ERROR_OUT_OF_MEMORY;
1502 DATA_SETTER_EPILOGUE(data, VTYPE_UTF8STRING);
1505 /* static */ nsresult
1506 nsVariant::SetFromString(nsDiscriminatedUnion* data, const char *aValue)
1508 DATA_SETTER_PROLOGUE(data);
1509 if(!aValue)
1510 return NS_ERROR_NULL_POINTER;
1511 return SetFromStringWithSize(data, strlen(aValue), aValue);
1513 /* static */ nsresult
1514 nsVariant::SetFromWString(nsDiscriminatedUnion* data, const PRUnichar *aValue)
1516 DATA_SETTER_PROLOGUE(data);
1517 if(!aValue)
1518 return NS_ERROR_NULL_POINTER;
1519 return SetFromWStringWithSize(data, nsCRT::strlen(aValue), aValue);
1521 /* static */ nsresult
1522 nsVariant::SetFromISupports(nsDiscriminatedUnion* data, nsISupports *aValue)
1524 return SetFromInterface(data, NS_GET_IID(nsISupports), aValue);
1526 /* static */ nsresult
1527 nsVariant::SetFromInterface(nsDiscriminatedUnion* data, const nsIID& iid,
1528 nsISupports *aValue)
1530 DATA_SETTER_PROLOGUE(data);
1531 NS_IF_ADDREF(aValue);
1532 data->u.iface.mInterfaceValue = aValue;
1533 data->u.iface.mInterfaceID = iid;
1534 DATA_SETTER_EPILOGUE(data, VTYPE_INTERFACE_IS);
1536 /* static */ nsresult
1537 nsVariant::SetFromArray(nsDiscriminatedUnion* data, PRUint16 type,
1538 const nsIID* iid, PRUint32 count, void * aValue)
1540 DATA_SETTER_PROLOGUE(data);
1541 if(!aValue || !count)
1542 return NS_ERROR_NULL_POINTER;
1544 nsresult rv = CloneArray(type, iid, count, aValue,
1545 &data->u.array.mArrayType,
1546 &data->u.array.mArrayInterfaceID,
1547 &data->u.array.mArrayCount,
1548 &data->u.array.mArrayValue);
1549 if(NS_FAILED(rv))
1550 return rv;
1551 DATA_SETTER_EPILOGUE(data, VTYPE_ARRAY);
1553 /* static */ nsresult
1554 nsVariant::SetFromStringWithSize(nsDiscriminatedUnion* data, PRUint32 size, const char *aValue)
1556 DATA_SETTER_PROLOGUE(data);
1557 if(!aValue)
1558 return NS_ERROR_NULL_POINTER;
1559 if(!(data->u.str.mStringValue =
1560 (char*) nsMemory::Clone(aValue, (size+1)*sizeof(char))))
1561 return NS_ERROR_OUT_OF_MEMORY;
1562 data->u.str.mStringLength = size;
1563 DATA_SETTER_EPILOGUE(data, VTYPE_STRING_SIZE_IS);
1565 /* static */ nsresult
1566 nsVariant::SetFromWStringWithSize(nsDiscriminatedUnion* data, PRUint32 size, const PRUnichar *aValue)
1568 DATA_SETTER_PROLOGUE(data);
1569 if(!aValue)
1570 return NS_ERROR_NULL_POINTER;
1571 if(!(data->u.wstr.mWStringValue =
1572 (PRUnichar*) nsMemory::Clone(aValue, (size+1)*sizeof(PRUnichar))))
1573 return NS_ERROR_OUT_OF_MEMORY;
1574 data->u.wstr.mWStringLength = size;
1575 DATA_SETTER_EPILOGUE(data, VTYPE_WSTRING_SIZE_IS);
1577 /* static */ nsresult
1578 nsVariant::SetToVoid(nsDiscriminatedUnion* data)
1580 DATA_SETTER_PROLOGUE(data);
1581 DATA_SETTER_EPILOGUE(data, VTYPE_VOID);
1583 /* static */ nsresult
1584 nsVariant::SetToEmpty(nsDiscriminatedUnion* data)
1586 DATA_SETTER_PROLOGUE(data);
1587 DATA_SETTER_EPILOGUE(data, VTYPE_EMPTY);
1589 /* static */ nsresult
1590 nsVariant::SetToEmptyArray(nsDiscriminatedUnion* data)
1592 DATA_SETTER_PROLOGUE(data);
1593 DATA_SETTER_EPILOGUE(data, VTYPE_EMPTY_ARRAY);
1596 /***************************************************************************/
1598 /* static */ nsresult
1599 nsVariant::Initialize(nsDiscriminatedUnion* data)
1601 data->mType = nsIDataType::VTYPE_EMPTY;
1602 return NS_OK;
1605 /* static */ nsresult
1606 nsVariant::Cleanup(nsDiscriminatedUnion* data)
1608 switch(data->mType)
1610 case nsIDataType::VTYPE_INT8:
1611 case nsIDataType::VTYPE_INT16:
1612 case nsIDataType::VTYPE_INT32:
1613 case nsIDataType::VTYPE_INT64:
1614 case nsIDataType::VTYPE_UINT8:
1615 case nsIDataType::VTYPE_UINT16:
1616 case nsIDataType::VTYPE_UINT32:
1617 case nsIDataType::VTYPE_UINT64:
1618 case nsIDataType::VTYPE_FLOAT:
1619 case nsIDataType::VTYPE_DOUBLE:
1620 case nsIDataType::VTYPE_BOOL:
1621 case nsIDataType::VTYPE_CHAR:
1622 case nsIDataType::VTYPE_WCHAR:
1623 case nsIDataType::VTYPE_VOID:
1624 case nsIDataType::VTYPE_ID:
1625 break;
1626 case nsIDataType::VTYPE_ASTRING:
1627 case nsIDataType::VTYPE_DOMSTRING:
1628 delete data->u.mAStringValue;
1629 break;
1630 case nsIDataType::VTYPE_CSTRING:
1631 delete data->u.mCStringValue;
1632 break;
1633 case nsIDataType::VTYPE_UTF8STRING:
1634 delete data->u.mUTF8StringValue;
1635 break;
1636 case nsIDataType::VTYPE_CHAR_STR:
1637 case nsIDataType::VTYPE_STRING_SIZE_IS:
1638 nsMemory::Free((char*)data->u.str.mStringValue);
1639 break;
1640 case nsIDataType::VTYPE_WCHAR_STR:
1641 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
1642 nsMemory::Free((char*)data->u.wstr.mWStringValue);
1643 break;
1644 case nsIDataType::VTYPE_INTERFACE:
1645 case nsIDataType::VTYPE_INTERFACE_IS:
1646 NS_IF_RELEASE(data->u.iface.mInterfaceValue);
1647 break;
1648 case nsIDataType::VTYPE_ARRAY:
1649 FreeArray(data);
1650 break;
1651 case nsIDataType::VTYPE_EMPTY_ARRAY:
1652 case nsIDataType::VTYPE_EMPTY:
1653 break;
1654 default:
1655 NS_ERROR("bad type in variant!");
1656 break;
1659 data->mType = nsIDataType::VTYPE_EMPTY;
1660 return NS_OK;
1663 /* static */ void
1664 nsVariant::Traverse(const nsDiscriminatedUnion& data,
1665 nsCycleCollectionTraversalCallback &cb)
1667 switch(data.mType)
1669 case nsIDataType::VTYPE_INTERFACE:
1670 case nsIDataType::VTYPE_INTERFACE_IS:
1671 cb.NoteXPCOMChild(data.u.iface.mInterfaceValue);
1672 break;
1673 case nsIDataType::VTYPE_ARRAY:
1674 switch(data.u.array.mArrayType) {
1675 case nsIDataType::VTYPE_INTERFACE:
1676 case nsIDataType::VTYPE_INTERFACE_IS:
1678 nsISupports** p = (nsISupports**) data.u.array.mArrayValue;
1679 for(PRUint32 i = data.u.array.mArrayCount; i > 0; p++, i--)
1680 cb.NoteXPCOMChild(*p);
1682 default:
1683 break;
1685 default:
1686 break;
1690 /***************************************************************************/
1691 /***************************************************************************/
1692 // members...
1694 NS_IMPL_ISUPPORTS2(nsVariant, nsIVariant, nsIWritableVariant)
1696 nsVariant::nsVariant()
1697 : mWritable(PR_TRUE)
1699 nsVariant::Initialize(&mData);
1701 #ifdef DEBUG
1703 // Assert that the nsIDataType consts match the values #defined in
1704 // xpt_struct.h. Bad things happen somewhere if they don't.
1705 struct THE_TYPES {PRUint16 a; PRUint16 b;};
1706 static const THE_TYPES array[] = {
1707 {nsIDataType::VTYPE_INT8 , TD_INT8 },
1708 {nsIDataType::VTYPE_INT16 , TD_INT16 },
1709 {nsIDataType::VTYPE_INT32 , TD_INT32 },
1710 {nsIDataType::VTYPE_INT64 , TD_INT64 },
1711 {nsIDataType::VTYPE_UINT8 , TD_UINT8 },
1712 {nsIDataType::VTYPE_UINT16 , TD_UINT16 },
1713 {nsIDataType::VTYPE_UINT32 , TD_UINT32 },
1714 {nsIDataType::VTYPE_UINT64 , TD_UINT64 },
1715 {nsIDataType::VTYPE_FLOAT , TD_FLOAT },
1716 {nsIDataType::VTYPE_DOUBLE , TD_DOUBLE },
1717 {nsIDataType::VTYPE_BOOL , TD_BOOL },
1718 {nsIDataType::VTYPE_CHAR , TD_CHAR },
1719 {nsIDataType::VTYPE_WCHAR , TD_WCHAR },
1720 {nsIDataType::VTYPE_VOID , TD_VOID },
1721 {nsIDataType::VTYPE_ID , TD_PNSIID },
1722 {nsIDataType::VTYPE_DOMSTRING , TD_DOMSTRING },
1723 {nsIDataType::VTYPE_CHAR_STR , TD_PSTRING },
1724 {nsIDataType::VTYPE_WCHAR_STR , TD_PWSTRING },
1725 {nsIDataType::VTYPE_INTERFACE , TD_INTERFACE_TYPE },
1726 {nsIDataType::VTYPE_INTERFACE_IS , TD_INTERFACE_IS_TYPE},
1727 {nsIDataType::VTYPE_ARRAY , TD_ARRAY },
1728 {nsIDataType::VTYPE_STRING_SIZE_IS , TD_PSTRING_SIZE_IS },
1729 {nsIDataType::VTYPE_WSTRING_SIZE_IS , TD_PWSTRING_SIZE_IS },
1730 {nsIDataType::VTYPE_UTF8STRING , TD_UTF8STRING },
1731 {nsIDataType::VTYPE_CSTRING , TD_CSTRING },
1732 {nsIDataType::VTYPE_ASTRING , TD_ASTRING }
1734 static const int length = sizeof(array)/sizeof(array[0]);
1735 static PRBool inited = PR_FALSE;
1736 if(!inited)
1738 for(int i = 0; i < length; i++)
1739 NS_ASSERTION(array[i].a == array[i].b, "bad const declaration");
1740 inited = PR_TRUE;
1743 #endif
1746 nsVariant::~nsVariant()
1748 nsVariant::Cleanup(&mData);
1751 // For all the data getters we just forward to the static (and sharable)
1752 // 'ConvertTo' functions.
1754 /* readonly attribute PRUint16 dataType; */
1755 NS_IMETHODIMP nsVariant::GetDataType(PRUint16 *aDataType)
1757 *aDataType = mData.mType;
1758 return NS_OK;
1761 /* PRUint8 getAsInt8 (); */
1762 NS_IMETHODIMP nsVariant::GetAsInt8(PRUint8 *_retval)
1764 return nsVariant::ConvertToInt8(mData, _retval);
1767 /* PRInt16 getAsInt16 (); */
1768 NS_IMETHODIMP nsVariant::GetAsInt16(PRInt16 *_retval)
1770 return nsVariant::ConvertToInt16(mData, _retval);
1773 /* PRInt32 getAsInt32 (); */
1774 NS_IMETHODIMP nsVariant::GetAsInt32(PRInt32 *_retval)
1776 return nsVariant::ConvertToInt32(mData, _retval);
1779 /* PRInt64 getAsInt64 (); */
1780 NS_IMETHODIMP nsVariant::GetAsInt64(PRInt64 *_retval)
1782 return nsVariant::ConvertToInt64(mData, _retval);
1785 /* PRUint8 getAsUint8 (); */
1786 NS_IMETHODIMP nsVariant::GetAsUint8(PRUint8 *_retval)
1788 return nsVariant::ConvertToUint8(mData, _retval);
1791 /* PRUint16 getAsUint16 (); */
1792 NS_IMETHODIMP nsVariant::GetAsUint16(PRUint16 *_retval)
1794 return nsVariant::ConvertToUint16(mData, _retval);
1797 /* PRUint32 getAsUint32 (); */
1798 NS_IMETHODIMP nsVariant::GetAsUint32(PRUint32 *_retval)
1800 return nsVariant::ConvertToUint32(mData, _retval);
1803 /* PRUint64 getAsUint64 (); */
1804 NS_IMETHODIMP nsVariant::GetAsUint64(PRUint64 *_retval)
1806 return nsVariant::ConvertToUint64(mData, _retval);
1809 /* float getAsFloat (); */
1810 NS_IMETHODIMP nsVariant::GetAsFloat(float *_retval)
1812 return nsVariant::ConvertToFloat(mData, _retval);
1815 /* double getAsDouble (); */
1816 NS_IMETHODIMP nsVariant::GetAsDouble(double *_retval)
1818 return nsVariant::ConvertToDouble(mData, _retval);
1821 /* PRBool getAsBool (); */
1822 NS_IMETHODIMP nsVariant::GetAsBool(PRBool *_retval)
1824 return nsVariant::ConvertToBool(mData, _retval);
1827 /* char getAsChar (); */
1828 NS_IMETHODIMP nsVariant::GetAsChar(char *_retval)
1830 return nsVariant::ConvertToChar(mData, _retval);
1833 /* wchar getAsWChar (); */
1834 NS_IMETHODIMP nsVariant::GetAsWChar(PRUnichar *_retval)
1836 return nsVariant::ConvertToWChar(mData, _retval);
1839 /* [notxpcom] nsresult getAsID (out nsID retval); */
1840 NS_IMETHODIMP_(nsresult) nsVariant::GetAsID(nsID *retval)
1842 return nsVariant::ConvertToID(mData, retval);
1845 /* AString getAsAString (); */
1846 NS_IMETHODIMP nsVariant::GetAsAString(nsAString & _retval)
1848 return nsVariant::ConvertToAString(mData, _retval);
1851 /* DOMString getAsDOMString (); */
1852 NS_IMETHODIMP nsVariant::GetAsDOMString(nsAString & _retval)
1854 // A DOMString maps to an AString internally, so we can re-use
1855 // ConvertToAString here.
1856 return nsVariant::ConvertToAString(mData, _retval);
1859 /* ACString getAsACString (); */
1860 NS_IMETHODIMP nsVariant::GetAsACString(nsACString & _retval)
1862 return nsVariant::ConvertToACString(mData, _retval);
1865 /* AUTF8String getAsAUTF8String (); */
1866 NS_IMETHODIMP nsVariant::GetAsAUTF8String(nsAUTF8String & _retval)
1868 return nsVariant::ConvertToAUTF8String(mData, _retval);
1871 /* string getAsString (); */
1872 NS_IMETHODIMP nsVariant::GetAsString(char **_retval)
1874 return nsVariant::ConvertToString(mData, _retval);
1877 /* wstring getAsWString (); */
1878 NS_IMETHODIMP nsVariant::GetAsWString(PRUnichar **_retval)
1880 return nsVariant::ConvertToWString(mData, _retval);
1883 /* nsISupports getAsISupports (); */
1884 NS_IMETHODIMP nsVariant::GetAsISupports(nsISupports **_retval)
1886 return nsVariant::ConvertToISupports(mData, _retval);
1889 /* jsval getAsJSVal() */
1890 NS_IMETHODIMP nsVariant::GetAsJSVal(jsval *_retval)
1892 // Can only get the jsval from an XPCVariant.
1893 return NS_ERROR_CANNOT_CONVERT_DATA;
1896 /* void getAsInterface (out nsIIDPtr iid, [iid_is (iid), retval] out nsQIResult iface); */
1897 NS_IMETHODIMP nsVariant::GetAsInterface(nsIID * *iid, void * *iface)
1899 return nsVariant::ConvertToInterface(mData, iid, iface);
1902 /* [notxpcom] nsresult getAsArray (out PRUint16 type, out nsIID iid, out PRUint32 count, out voidPtr ptr); */
1903 NS_IMETHODIMP_(nsresult) nsVariant::GetAsArray(PRUint16 *type, nsIID *iid, PRUint32 *count, void * *ptr)
1905 return nsVariant::ConvertToArray(mData, type, iid, count, ptr);
1908 /* void getAsStringWithSize (out PRUint32 size, [size_is (size), retval] out string str); */
1909 NS_IMETHODIMP nsVariant::GetAsStringWithSize(PRUint32 *size, char **str)
1911 return nsVariant::ConvertToStringWithSize(mData, size, str);
1914 /* void getAsWStringWithSize (out PRUint32 size, [size_is (size), retval] out wstring str); */
1915 NS_IMETHODIMP nsVariant::GetAsWStringWithSize(PRUint32 *size, PRUnichar **str)
1917 return nsVariant::ConvertToWStringWithSize(mData, size, str);
1920 /***************************************************************************/
1922 /* attribute PRBool writable; */
1923 NS_IMETHODIMP nsVariant::GetWritable(PRBool *aWritable)
1925 *aWritable = mWritable;
1926 return NS_OK;
1928 NS_IMETHODIMP nsVariant::SetWritable(PRBool aWritable)
1930 if(!mWritable && aWritable)
1931 return NS_ERROR_FAILURE;
1932 mWritable = aWritable;
1933 return NS_OK;
1936 /***************************************************************************/
1938 // For all the data setters we just forward to the static (and sharable)
1939 // 'SetFrom' functions.
1941 /* void setAsInt8 (in PRUint8 aValue); */
1942 NS_IMETHODIMP nsVariant::SetAsInt8(PRUint8 aValue)
1944 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
1945 return nsVariant::SetFromInt8(&mData, aValue);
1948 /* void setAsInt16 (in PRInt16 aValue); */
1949 NS_IMETHODIMP nsVariant::SetAsInt16(PRInt16 aValue)
1951 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
1952 return nsVariant::SetFromInt16(&mData, aValue);
1955 /* void setAsInt32 (in PRInt32 aValue); */
1956 NS_IMETHODIMP nsVariant::SetAsInt32(PRInt32 aValue)
1958 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
1959 return nsVariant::SetFromInt32(&mData, aValue);
1962 /* void setAsInt64 (in PRInt64 aValue); */
1963 NS_IMETHODIMP nsVariant::SetAsInt64(PRInt64 aValue)
1965 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
1966 return nsVariant::SetFromInt64(&mData, aValue);
1969 /* void setAsUint8 (in PRUint8 aValue); */
1970 NS_IMETHODIMP nsVariant::SetAsUint8(PRUint8 aValue)
1972 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
1973 return nsVariant::SetFromUint8(&mData, aValue);
1976 /* void setAsUint16 (in PRUint16 aValue); */
1977 NS_IMETHODIMP nsVariant::SetAsUint16(PRUint16 aValue)
1979 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
1980 return nsVariant::SetFromUint16(&mData, aValue);
1983 /* void setAsUint32 (in PRUint32 aValue); */
1984 NS_IMETHODIMP nsVariant::SetAsUint32(PRUint32 aValue)
1986 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
1987 return nsVariant::SetFromUint32(&mData, aValue);
1990 /* void setAsUint64 (in PRUint64 aValue); */
1991 NS_IMETHODIMP nsVariant::SetAsUint64(PRUint64 aValue)
1993 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
1994 return nsVariant::SetFromUint64(&mData, aValue);
1997 /* void setAsFloat (in float aValue); */
1998 NS_IMETHODIMP nsVariant::SetAsFloat(float aValue)
2000 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2001 return nsVariant::SetFromFloat(&mData, aValue);
2004 /* void setAsDouble (in double aValue); */
2005 NS_IMETHODIMP nsVariant::SetAsDouble(double aValue)
2007 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2008 return nsVariant::SetFromDouble(&mData, aValue);
2011 /* void setAsBool (in PRBool aValue); */
2012 NS_IMETHODIMP nsVariant::SetAsBool(PRBool aValue)
2014 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2015 return nsVariant::SetFromBool(&mData, aValue);
2018 /* void setAsChar (in char aValue); */
2019 NS_IMETHODIMP nsVariant::SetAsChar(char aValue)
2021 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2022 return nsVariant::SetFromChar(&mData, aValue);
2025 /* void setAsWChar (in wchar aValue); */
2026 NS_IMETHODIMP nsVariant::SetAsWChar(PRUnichar aValue)
2028 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2029 return nsVariant::SetFromWChar(&mData, aValue);
2032 /* void setAsID (in nsIDRef aValue); */
2033 NS_IMETHODIMP nsVariant::SetAsID(const nsID & aValue)
2035 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2036 return nsVariant::SetFromID(&mData, aValue);
2039 /* void setAsAString (in AString aValue); */
2040 NS_IMETHODIMP nsVariant::SetAsAString(const nsAString & aValue)
2042 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2043 return nsVariant::SetFromAString(&mData, aValue);
2046 /* void setAsDOMString (in DOMString aValue); */
2047 NS_IMETHODIMP nsVariant::SetAsDOMString(const nsAString & aValue)
2049 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2051 DATA_SETTER_PROLOGUE((&mData));
2052 if(!(mData.u.mAStringValue = new nsString(aValue)))
2053 return NS_ERROR_OUT_OF_MEMORY;
2054 DATA_SETTER_EPILOGUE((&mData), VTYPE_DOMSTRING);
2057 /* void setAsACString (in ACString aValue); */
2058 NS_IMETHODIMP nsVariant::SetAsACString(const nsACString & aValue)
2060 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2061 return nsVariant::SetFromACString(&mData, aValue);
2064 /* void setAsAUTF8String (in AUTF8String aValue); */
2065 NS_IMETHODIMP nsVariant::SetAsAUTF8String(const nsAUTF8String & aValue)
2067 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2068 return nsVariant::SetFromAUTF8String(&mData, aValue);
2071 /* void setAsString (in string aValue); */
2072 NS_IMETHODIMP nsVariant::SetAsString(const char *aValue)
2074 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2075 return nsVariant::SetFromString(&mData, aValue);
2078 /* void setAsWString (in wstring aValue); */
2079 NS_IMETHODIMP nsVariant::SetAsWString(const PRUnichar *aValue)
2081 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2082 return nsVariant::SetFromWString(&mData, aValue);
2085 /* void setAsISupports (in nsISupports aValue); */
2086 NS_IMETHODIMP nsVariant::SetAsISupports(nsISupports *aValue)
2088 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2089 return nsVariant::SetFromISupports(&mData, aValue);
2092 /* void setAsInterface (in nsIIDRef iid, [iid_is (iid)] in nsQIResult iface); */
2093 NS_IMETHODIMP nsVariant::SetAsInterface(const nsIID & iid, void * iface)
2095 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2096 return nsVariant::SetFromInterface(&mData, iid, (nsISupports*)iface);
2099 /* [noscript] void setAsArray (in PRUint16 type, in nsIIDPtr iid, in PRUint32 count, in voidPtr ptr); */
2100 NS_IMETHODIMP nsVariant::SetAsArray(PRUint16 type, const nsIID * iid, PRUint32 count, void * ptr)
2102 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2103 return nsVariant::SetFromArray(&mData, type, iid, count, ptr);
2106 /* void setAsStringWithSize (in PRUint32 size, [size_is (size)] in string str); */
2107 NS_IMETHODIMP nsVariant::SetAsStringWithSize(PRUint32 size, const char *str)
2109 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2110 return nsVariant::SetFromStringWithSize(&mData, size, str);
2113 /* void setAsWStringWithSize (in PRUint32 size, [size_is (size)] in wstring str); */
2114 NS_IMETHODIMP nsVariant::SetAsWStringWithSize(PRUint32 size, const PRUnichar *str)
2116 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2117 return nsVariant::SetFromWStringWithSize(&mData, size, str);
2120 /* void setAsVoid (); */
2121 NS_IMETHODIMP nsVariant::SetAsVoid()
2123 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2124 return nsVariant::SetToVoid(&mData);
2127 /* void setAsEmpty (); */
2128 NS_IMETHODIMP nsVariant::SetAsEmpty()
2130 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2131 return nsVariant::SetToEmpty(&mData);
2134 /* void setAsEmptyArray (); */
2135 NS_IMETHODIMP nsVariant::SetAsEmptyArray()
2137 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2138 return nsVariant::SetToEmptyArray(&mData);
2141 /* void setFromVariant (in nsIVariant aValue); */
2142 NS_IMETHODIMP nsVariant::SetFromVariant(nsIVariant *aValue)
2144 if(!mWritable) return NS_ERROR_OBJECT_IS_IMMUTABLE;
2145 return nsVariant::SetFromVariant(&mData, aValue);