Bumping gaia.json for 8 gaia revision(s) a=gaia-bump
[gecko.git] / xpcom / ds / nsVariant.cpp
blobebf6f0381db09743afc435aa9edf4cd08b22cf39
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* The long avoided variant support for xpcom. */
9 #include "nsVariant.h"
10 #include "prprf.h"
11 #include "prdtoa.h"
12 #include <math.h>
13 #include "nsCycleCollectionParticipant.h"
14 #include "xpt_struct.h"
15 #include "nsReadableUtils.h"
16 #include "nsMemory.h"
17 #include "nsString.h"
18 #include "nsCRTGlue.h"
20 /***************************************************************************/
21 // Helpers for static convert functions...
23 static nsresult
24 String2Double(const char* aString, double* aResult)
26 char* next;
27 double value = PR_strtod(aString, &next);
28 if (next == aString) {
29 return NS_ERROR_CANNOT_CONVERT_DATA;
31 *aResult = value;
32 return NS_OK;
35 static nsresult
36 AString2Double(const nsAString& aString, double* aResult)
38 char* pChars = ToNewCString(aString);
39 if (!pChars) {
40 return NS_ERROR_OUT_OF_MEMORY;
42 nsresult rv = String2Double(pChars, aResult);
43 nsMemory::Free(pChars);
44 return rv;
47 static nsresult
48 AUTF8String2Double(const nsAUTF8String& aString, double* aResult)
50 return String2Double(PromiseFlatUTF8String(aString).get(), aResult);
53 static nsresult
54 ACString2Double(const nsACString& aString, double* aResult)
56 return String2Double(PromiseFlatCString(aString).get(), aResult);
59 // Fills outVariant with double, uint32_t, or int32_t.
60 // Returns NS_OK, an error code, or a non-NS_OK success code
61 static nsresult
62 ToManageableNumber(const nsDiscriminatedUnion& aInData,
63 nsDiscriminatedUnion* aOutData)
65 nsresult rv;
67 switch (aInData.mType) {
68 // This group results in a int32_t...
70 #define CASE__NUMBER_INT32(type_, member_) \
71 case nsIDataType :: type_ : \
72 aOutData->u.mInt32Value = aInData.u. member_ ; \
73 aOutData->mType = nsIDataType::VTYPE_INT32; \
74 return NS_OK;
76 CASE__NUMBER_INT32(VTYPE_INT8, mInt8Value)
77 CASE__NUMBER_INT32(VTYPE_INT16, mInt16Value)
78 CASE__NUMBER_INT32(VTYPE_INT32, mInt32Value)
79 CASE__NUMBER_INT32(VTYPE_UINT8, mUint8Value)
80 CASE__NUMBER_INT32(VTYPE_UINT16, mUint16Value)
81 CASE__NUMBER_INT32(VTYPE_BOOL, mBoolValue)
82 CASE__NUMBER_INT32(VTYPE_CHAR, mCharValue)
83 CASE__NUMBER_INT32(VTYPE_WCHAR, mWCharValue)
85 #undef CASE__NUMBER_INT32
87 // This group results in a uint32_t...
89 case nsIDataType::VTYPE_UINT32:
90 aOutData->u.mInt32Value = aInData.u.mUint32Value;
91 aOutData->mType = nsIDataType::VTYPE_INT32;
92 return NS_OK;
94 // This group results in a double...
96 case nsIDataType::VTYPE_INT64:
97 case nsIDataType::VTYPE_UINT64:
98 // XXX Need boundary checking here.
99 // We may need to return NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA
100 aOutData->u.mDoubleValue = double(aInData.u.mInt64Value);
101 aOutData->mType = nsIDataType::VTYPE_DOUBLE;
102 return NS_OK;
103 case nsIDataType::VTYPE_FLOAT:
104 aOutData->u.mDoubleValue = aInData.u.mFloatValue;
105 aOutData->mType = nsIDataType::VTYPE_DOUBLE;
106 return NS_OK;
107 case nsIDataType::VTYPE_DOUBLE:
108 aOutData->u.mDoubleValue = aInData.u.mDoubleValue;
109 aOutData->mType = nsIDataType::VTYPE_DOUBLE;
110 return NS_OK;
111 case nsIDataType::VTYPE_CHAR_STR:
112 case nsIDataType::VTYPE_STRING_SIZE_IS:
113 rv = String2Double(aInData.u.str.mStringValue, &aOutData->u.mDoubleValue);
114 if (NS_FAILED(rv)) {
115 return rv;
117 aOutData->mType = nsIDataType::VTYPE_DOUBLE;
118 return NS_OK;
119 case nsIDataType::VTYPE_DOMSTRING:
120 case nsIDataType::VTYPE_ASTRING:
121 rv = AString2Double(*aInData.u.mAStringValue, &aOutData->u.mDoubleValue);
122 if (NS_FAILED(rv)) {
123 return rv;
125 aOutData->mType = nsIDataType::VTYPE_DOUBLE;
126 return NS_OK;
127 case nsIDataType::VTYPE_UTF8STRING:
128 rv = AUTF8String2Double(*aInData.u.mUTF8StringValue,
129 &aOutData->u.mDoubleValue);
130 if (NS_FAILED(rv)) {
131 return rv;
133 aOutData->mType = nsIDataType::VTYPE_DOUBLE;
134 return NS_OK;
135 case nsIDataType::VTYPE_CSTRING:
136 rv = ACString2Double(*aInData.u.mCStringValue,
137 &aOutData->u.mDoubleValue);
138 if (NS_FAILED(rv)) {
139 return rv;
141 aOutData->mType = nsIDataType::VTYPE_DOUBLE;
142 return NS_OK;
143 case nsIDataType::VTYPE_WCHAR_STR:
144 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
145 rv = AString2Double(nsDependentString(aInData.u.wstr.mWStringValue),
146 &aOutData->u.mDoubleValue);
147 if (NS_FAILED(rv)) {
148 return rv;
150 aOutData->mType = nsIDataType::VTYPE_DOUBLE;
151 return NS_OK;
153 // This group fails...
155 case nsIDataType::VTYPE_VOID:
156 case nsIDataType::VTYPE_ID:
157 case nsIDataType::VTYPE_INTERFACE:
158 case nsIDataType::VTYPE_INTERFACE_IS:
159 case nsIDataType::VTYPE_ARRAY:
160 case nsIDataType::VTYPE_EMPTY_ARRAY:
161 case nsIDataType::VTYPE_EMPTY:
162 default:
163 return NS_ERROR_CANNOT_CONVERT_DATA;
167 /***************************************************************************/
168 // Array helpers...
170 static void
171 FreeArray(nsDiscriminatedUnion* aData)
173 NS_ASSERTION(aData->mType == nsIDataType::VTYPE_ARRAY, "bad FreeArray call");
174 NS_ASSERTION(aData->u.array.mArrayValue, "bad array");
175 NS_ASSERTION(aData->u.array.mArrayCount, "bad array count");
177 #define CASE__FREE_ARRAY_PTR(type_, ctype_) \
178 case nsIDataType:: type_ : \
180 ctype_ ** p = (ctype_ **) aData->u.array.mArrayValue; \
181 for(uint32_t i = aData->u.array.mArrayCount; i > 0; p++, i--) \
182 if(*p) \
183 nsMemory::Free((char*)*p); \
184 break; \
187 #define CASE__FREE_ARRAY_IFACE(type_, ctype_) \
188 case nsIDataType:: type_ : \
190 ctype_ ** p = (ctype_ **) aData->u.array.mArrayValue; \
191 for(uint32_t i = aData->u.array.mArrayCount; i > 0; p++, i--) \
192 if(*p) \
193 (*p)->Release(); \
194 break; \
197 switch (aData->u.array.mArrayType) {
198 case nsIDataType::VTYPE_INT8:
199 case nsIDataType::VTYPE_INT16:
200 case nsIDataType::VTYPE_INT32:
201 case nsIDataType::VTYPE_INT64:
202 case nsIDataType::VTYPE_UINT8:
203 case nsIDataType::VTYPE_UINT16:
204 case nsIDataType::VTYPE_UINT32:
205 case nsIDataType::VTYPE_UINT64:
206 case nsIDataType::VTYPE_FLOAT:
207 case nsIDataType::VTYPE_DOUBLE:
208 case nsIDataType::VTYPE_BOOL:
209 case nsIDataType::VTYPE_CHAR:
210 case nsIDataType::VTYPE_WCHAR:
211 break;
213 // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
214 CASE__FREE_ARRAY_PTR(VTYPE_ID, nsID)
215 CASE__FREE_ARRAY_PTR(VTYPE_CHAR_STR, char)
216 CASE__FREE_ARRAY_PTR(VTYPE_WCHAR_STR, char16_t)
217 CASE__FREE_ARRAY_IFACE(VTYPE_INTERFACE, nsISupports)
218 CASE__FREE_ARRAY_IFACE(VTYPE_INTERFACE_IS, nsISupports)
220 // The rest are illegal.
221 case nsIDataType::VTYPE_VOID:
222 case nsIDataType::VTYPE_ASTRING:
223 case nsIDataType::VTYPE_DOMSTRING:
224 case nsIDataType::VTYPE_UTF8STRING:
225 case nsIDataType::VTYPE_CSTRING:
226 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
227 case nsIDataType::VTYPE_STRING_SIZE_IS:
228 case nsIDataType::VTYPE_ARRAY:
229 case nsIDataType::VTYPE_EMPTY_ARRAY:
230 case nsIDataType::VTYPE_EMPTY:
231 default:
232 NS_ERROR("bad type in array!");
233 break;
236 // Free the array memory.
237 nsMemory::Free((char*)aData->u.array.mArrayValue);
239 #undef CASE__FREE_ARRAY_PTR
240 #undef CASE__FREE_ARRAY_IFACE
243 static nsresult
244 CloneArray(uint16_t aInType, const nsIID* aInIID,
245 uint32_t aInCount, void* aInValue,
246 uint16_t* aOutType, nsIID* aOutIID,
247 uint32_t* aOutCount, void** aOutValue)
249 NS_ASSERTION(aInCount, "bad param");
250 NS_ASSERTION(aInValue, "bad param");
251 NS_ASSERTION(aOutType, "bad param");
252 NS_ASSERTION(aOutCount, "bad param");
253 NS_ASSERTION(aOutValue, "bad param");
255 uint32_t allocatedValueCount = 0;
256 nsresult rv = NS_OK;
257 uint32_t i;
259 // First we figure out the size of the elements for the new u.array.
261 size_t elementSize;
262 size_t allocSize;
264 switch (aInType) {
265 case nsIDataType::VTYPE_INT8:
266 elementSize = sizeof(int8_t);
267 break;
268 case nsIDataType::VTYPE_INT16:
269 elementSize = sizeof(int16_t);
270 break;
271 case nsIDataType::VTYPE_INT32:
272 elementSize = sizeof(int32_t);
273 break;
274 case nsIDataType::VTYPE_INT64:
275 elementSize = sizeof(int64_t);
276 break;
277 case nsIDataType::VTYPE_UINT8:
278 elementSize = sizeof(uint8_t);
279 break;
280 case nsIDataType::VTYPE_UINT16:
281 elementSize = sizeof(uint16_t);
282 break;
283 case nsIDataType::VTYPE_UINT32:
284 elementSize = sizeof(uint32_t);
285 break;
286 case nsIDataType::VTYPE_UINT64:
287 elementSize = sizeof(uint64_t);
288 break;
289 case nsIDataType::VTYPE_FLOAT:
290 elementSize = sizeof(float);
291 break;
292 case nsIDataType::VTYPE_DOUBLE:
293 elementSize = sizeof(double);
294 break;
295 case nsIDataType::VTYPE_BOOL:
296 elementSize = sizeof(bool);
297 break;
298 case nsIDataType::VTYPE_CHAR:
299 elementSize = sizeof(char);
300 break;
301 case nsIDataType::VTYPE_WCHAR:
302 elementSize = sizeof(char16_t);
303 break;
305 // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
306 case nsIDataType::VTYPE_ID:
307 case nsIDataType::VTYPE_CHAR_STR:
308 case nsIDataType::VTYPE_WCHAR_STR:
309 case nsIDataType::VTYPE_INTERFACE:
310 case nsIDataType::VTYPE_INTERFACE_IS:
311 elementSize = sizeof(void*);
312 break;
314 // The rest are illegal.
315 case nsIDataType::VTYPE_ASTRING:
316 case nsIDataType::VTYPE_DOMSTRING:
317 case nsIDataType::VTYPE_UTF8STRING:
318 case nsIDataType::VTYPE_CSTRING:
319 case nsIDataType::VTYPE_STRING_SIZE_IS:
320 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
321 case nsIDataType::VTYPE_VOID:
322 case nsIDataType::VTYPE_ARRAY:
323 case nsIDataType::VTYPE_EMPTY_ARRAY:
324 case nsIDataType::VTYPE_EMPTY:
325 default:
326 NS_ERROR("bad type in array!");
327 return NS_ERROR_CANNOT_CONVERT_DATA;
331 // Alloc the u.array.
333 allocSize = aInCount * elementSize;
334 *aOutValue = nsMemory::Alloc(allocSize);
335 if (!*aOutValue) {
336 return NS_ERROR_OUT_OF_MEMORY;
339 // Clone the elements.
341 switch (aInType) {
342 case nsIDataType::VTYPE_INT8:
343 case nsIDataType::VTYPE_INT16:
344 case nsIDataType::VTYPE_INT32:
345 case nsIDataType::VTYPE_INT64:
346 case nsIDataType::VTYPE_UINT8:
347 case nsIDataType::VTYPE_UINT16:
348 case nsIDataType::VTYPE_UINT32:
349 case nsIDataType::VTYPE_UINT64:
350 case nsIDataType::VTYPE_FLOAT:
351 case nsIDataType::VTYPE_DOUBLE:
352 case nsIDataType::VTYPE_BOOL:
353 case nsIDataType::VTYPE_CHAR:
354 case nsIDataType::VTYPE_WCHAR:
355 memcpy(*aOutValue, aInValue, allocSize);
356 break;
358 case nsIDataType::VTYPE_INTERFACE_IS:
359 if (aOutIID) {
360 *aOutIID = *aInIID;
362 // fall through...
363 case nsIDataType::VTYPE_INTERFACE: {
364 memcpy(*aOutValue, aInValue, allocSize);
366 nsISupports** p = (nsISupports**)*aOutValue;
367 for (i = aInCount; i > 0; ++p, --i)
368 if (*p) {
369 (*p)->AddRef();
371 break;
374 // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
375 case nsIDataType::VTYPE_ID: {
376 nsID** inp = (nsID**)aInValue;
377 nsID** outp = (nsID**)*aOutValue;
378 for (i = aInCount; i > 0; --i) {
379 nsID* idp = *(inp++);
380 if (idp) {
381 if (!(*(outp++) = (nsID*)nsMemory::Clone((char*)idp, sizeof(nsID)))) {
382 goto bad;
384 } else {
385 *(outp++) = nullptr;
387 allocatedValueCount++;
389 break;
392 case nsIDataType::VTYPE_CHAR_STR: {
393 char** inp = (char**)aInValue;
394 char** outp = (char**)*aOutValue;
395 for (i = aInCount; i > 0; i--) {
396 char* str = *(inp++);
397 if (str) {
398 if (!(*(outp++) = (char*)nsMemory::Clone(
399 str, (strlen(str) + 1) * sizeof(char)))) {
400 goto bad;
402 } else {
403 *(outp++) = nullptr;
405 allocatedValueCount++;
407 break;
410 case nsIDataType::VTYPE_WCHAR_STR: {
411 char16_t** inp = (char16_t**)aInValue;
412 char16_t** outp = (char16_t**)*aOutValue;
413 for (i = aInCount; i > 0; i--) {
414 char16_t* str = *(inp++);
415 if (str) {
416 if (!(*(outp++) = (char16_t*)nsMemory::Clone(
417 str, (NS_strlen(str) + 1) * sizeof(char16_t)))) {
418 goto bad;
420 } else {
421 *(outp++) = nullptr;
423 allocatedValueCount++;
425 break;
428 // The rest are illegal.
429 case nsIDataType::VTYPE_VOID:
430 case nsIDataType::VTYPE_ARRAY:
431 case nsIDataType::VTYPE_EMPTY_ARRAY:
432 case nsIDataType::VTYPE_EMPTY:
433 case nsIDataType::VTYPE_ASTRING:
434 case nsIDataType::VTYPE_DOMSTRING:
435 case nsIDataType::VTYPE_UTF8STRING:
436 case nsIDataType::VTYPE_CSTRING:
437 case nsIDataType::VTYPE_STRING_SIZE_IS:
438 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
439 default:
440 NS_ERROR("bad type in array!");
441 return NS_ERROR_CANNOT_CONVERT_DATA;
444 *aOutType = aInType;
445 *aOutCount = aInCount;
446 return NS_OK;
448 bad:
449 if (*aOutValue) {
450 char** p = (char**)*aOutValue;
451 for (i = allocatedValueCount; i > 0; ++p, --i)
452 if (*p) {
453 nsMemory::Free(*p);
455 nsMemory::Free((char*)*aOutValue);
456 *aOutValue = nullptr;
458 return rv;
461 /***************************************************************************/
463 #define TRIVIAL_DATA_CONVERTER(type_, data_, member_, retval_) \
464 if(data_.mType == nsIDataType :: type_) { \
465 *retval_ = data_.u.member_; \
466 return NS_OK; \
469 #define NUMERIC_CONVERSION_METHOD_BEGIN(type_, Ctype_, name_) \
470 /* static */ nsresult \
471 nsVariant::ConvertTo##name_ (const nsDiscriminatedUnion& data, \
472 Ctype_ *_retval) \
474 TRIVIAL_DATA_CONVERTER(type_, data, m##name_##Value, _retval) \
475 nsDiscriminatedUnion tempData; \
476 nsVariant::Initialize(&tempData); \
477 nsresult rv = ToManageableNumber(data, &tempData); \
478 /* */ \
479 /* NOTE: rv may indicate a success code that we want to preserve */ \
480 /* For the final return. So all the return cases below should return */ \
481 /* this rv when indicating success. */ \
482 /* */ \
483 if(NS_FAILED(rv)) \
484 return rv; \
485 switch(tempData.mType) \
488 #define CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(Ctype_) \
489 case nsIDataType::VTYPE_INT32: \
490 *_retval = ( Ctype_ ) tempData.u.mInt32Value; \
491 return rv;
493 #define CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(Ctype_, min_, max_) \
494 case nsIDataType::VTYPE_INT32: \
496 int32_t value = tempData.u.mInt32Value; \
497 if(value < min_ || value > max_) \
498 return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
499 *_retval = ( Ctype_ ) value; \
500 return rv; \
503 #define CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(Ctype_) \
504 case nsIDataType::VTYPE_UINT32: \
505 *_retval = ( Ctype_ ) tempData.u.mUint32Value; \
506 return rv;
508 #define CASE__NUMERIC_CONVERSION_UINT32_MAX(Ctype_, max_) \
509 case nsIDataType::VTYPE_UINT32: \
511 uint32_t value = tempData.u.mUint32Value; \
512 if(value > max_) \
513 return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
514 *_retval = ( Ctype_ ) value; \
515 return rv; \
518 #define CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(Ctype_) \
519 case nsIDataType::VTYPE_DOUBLE: \
520 *_retval = ( Ctype_ ) tempData.u.mDoubleValue; \
521 return rv;
523 #define CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX(Ctype_, min_, max_) \
524 case nsIDataType::VTYPE_DOUBLE: \
526 double value = tempData.u.mDoubleValue; \
527 if(value < min_ || value > max_) \
528 return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
529 *_retval = ( Ctype_ ) value; \
530 return rv; \
533 #define CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(Ctype_, min_, max_) \
534 case nsIDataType::VTYPE_DOUBLE: \
536 double value = tempData.u.mDoubleValue; \
537 if(value < min_ || value > max_) \
538 return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
539 *_retval = ( Ctype_ ) value; \
540 return (0.0 == fmod(value,1.0)) ? \
541 rv : NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA; \
544 #define CASES__NUMERIC_CONVERSION_NORMAL(Ctype_, min_, max_) \
545 CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(Ctype_, min_, max_) \
546 CASE__NUMERIC_CONVERSION_UINT32_MAX(Ctype_, max_) \
547 CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(Ctype_, min_, max_)
549 #define NUMERIC_CONVERSION_METHOD_END \
550 default: \
551 NS_ERROR("bad type returned from ToManageableNumber"); \
552 return NS_ERROR_CANNOT_CONVERT_DATA; \
556 #define NUMERIC_CONVERSION_METHOD_NORMAL(type_, Ctype_, name_, min_, max_) \
557 NUMERIC_CONVERSION_METHOD_BEGIN(type_, Ctype_, name_) \
558 CASES__NUMERIC_CONVERSION_NORMAL(Ctype_, min_, max_) \
559 NUMERIC_CONVERSION_METHOD_END
561 /***************************************************************************/
562 // These expand into full public methods...
564 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_INT8, uint8_t, Int8, (-127 - 1), 127)
565 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_INT16, int16_t, Int16, (-32767 - 1), 32767)
567 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_INT32, int32_t, Int32)
568 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(int32_t)
569 CASE__NUMERIC_CONVERSION_UINT32_MAX(int32_t, 2147483647)
570 CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(int32_t, (-2147483647 - 1), 2147483647)
571 NUMERIC_CONVERSION_METHOD_END
573 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_UINT8, uint8_t, Uint8, 0, 255)
574 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_UINT16, uint16_t, Uint16, 0, 65535)
576 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_UINT32, uint32_t, Uint32)
577 CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(uint32_t, 0, 2147483647)
578 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(uint32_t)
579 CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(uint32_t, 0, 4294967295U)
580 NUMERIC_CONVERSION_METHOD_END
582 // XXX toFloat convertions need to be fixed!
583 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_FLOAT, float, Float)
584 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(float)
585 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(float)
586 CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(float)
587 NUMERIC_CONVERSION_METHOD_END
589 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_DOUBLE, double, Double)
590 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(double)
591 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(double)
592 CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(double)
593 NUMERIC_CONVERSION_METHOD_END
595 // XXX toChar convertions need to be fixed!
596 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_CHAR, char, Char)
597 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(char)
598 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(char)
599 CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(char)
600 NUMERIC_CONVERSION_METHOD_END
602 // XXX toWChar convertions need to be fixed!
603 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_WCHAR, char16_t, WChar)
604 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(char16_t)
605 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(char16_t)
606 CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(char16_t)
607 NUMERIC_CONVERSION_METHOD_END
609 #undef NUMERIC_CONVERSION_METHOD_BEGIN
610 #undef CASE__NUMERIC_CONVERSION_INT32_JUST_CAST
611 #undef CASE__NUMERIC_CONVERSION_INT32_MIN_MAX
612 #undef CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST
613 #undef CASE__NUMERIC_CONVERSION_UINT32_MIN_MAX
614 #undef CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST
615 #undef CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX
616 #undef CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT
617 #undef CASES__NUMERIC_CONVERSION_NORMAL
618 #undef NUMERIC_CONVERSION_METHOD_END
619 #undef NUMERIC_CONVERSION_METHOD_NORMAL
621 /***************************************************************************/
623 // Just leverage a numeric converter for bool (but restrict the values).
624 // XXX Is this really what we want to do?
626 /* static */ nsresult
627 nsVariant::ConvertToBool(const nsDiscriminatedUnion& aData, bool* aResult)
629 TRIVIAL_DATA_CONVERTER(VTYPE_BOOL, aData, mBoolValue, aResult)
631 double val;
632 nsresult rv = nsVariant::ConvertToDouble(aData, &val);
633 if (NS_FAILED(rv)) {
634 return rv;
636 *aResult = 0.0 != val;
637 return rv;
640 /***************************************************************************/
642 /* static */ nsresult
643 nsVariant::ConvertToInt64(const nsDiscriminatedUnion& aData, int64_t* aResult)
645 TRIVIAL_DATA_CONVERTER(VTYPE_INT64, aData, mInt64Value, aResult)
646 TRIVIAL_DATA_CONVERTER(VTYPE_UINT64, aData, mUint64Value, aResult)
648 nsDiscriminatedUnion tempData;
649 nsVariant::Initialize(&tempData);
650 nsresult rv = ToManageableNumber(aData, &tempData);
651 if (NS_FAILED(rv)) {
652 return rv;
654 switch (tempData.mType) {
655 case nsIDataType::VTYPE_INT32:
656 *aResult = tempData.u.mInt32Value;
657 return rv;
658 case nsIDataType::VTYPE_UINT32:
659 *aResult = tempData.u.mUint32Value;
660 return rv;
661 case nsIDataType::VTYPE_DOUBLE:
662 // XXX should check for data loss here!
663 *aResult = tempData.u.mDoubleValue;
664 return rv;
665 default:
666 NS_ERROR("bad type returned from ToManageableNumber");
667 return NS_ERROR_CANNOT_CONVERT_DATA;
671 /* static */ nsresult
672 nsVariant::ConvertToUint64(const nsDiscriminatedUnion& aData,
673 uint64_t* aResult)
675 return nsVariant::ConvertToInt64(aData, (int64_t*)aResult);
678 /***************************************************************************/
680 static bool
681 String2ID(const nsDiscriminatedUnion& aData, nsID* aPid)
683 nsAutoString tempString;
684 nsAString* pString;
686 switch (aData.mType) {
687 case nsIDataType::VTYPE_CHAR_STR:
688 case nsIDataType::VTYPE_STRING_SIZE_IS:
689 return aPid->Parse(aData.u.str.mStringValue);
690 case nsIDataType::VTYPE_CSTRING:
691 return aPid->Parse(PromiseFlatCString(*aData.u.mCStringValue).get());
692 case nsIDataType::VTYPE_UTF8STRING:
693 return aPid->Parse(PromiseFlatUTF8String(*aData.u.mUTF8StringValue).get());
694 case nsIDataType::VTYPE_ASTRING:
695 case nsIDataType::VTYPE_DOMSTRING:
696 pString = aData.u.mAStringValue;
697 break;
698 case nsIDataType::VTYPE_WCHAR_STR:
699 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
700 tempString.Assign(aData.u.wstr.mWStringValue);
701 pString = &tempString;
702 break;
703 default:
704 NS_ERROR("bad type in call to String2ID");
705 return false;
708 char* pChars = ToNewCString(*pString);
709 if (!pChars) {
710 return false;
712 bool result = aPid->Parse(pChars);
713 nsMemory::Free(pChars);
714 return result;
717 /* static */ nsresult
718 nsVariant::ConvertToID(const nsDiscriminatedUnion& aData, nsID* aResult)
720 nsID id;
722 switch (aData.mType) {
723 case nsIDataType::VTYPE_ID:
724 *aResult = aData.u.mIDValue;
725 return NS_OK;
726 case nsIDataType::VTYPE_INTERFACE:
727 *aResult = NS_GET_IID(nsISupports);
728 return NS_OK;
729 case nsIDataType::VTYPE_INTERFACE_IS:
730 *aResult = aData.u.iface.mInterfaceID;
731 return NS_OK;
732 case nsIDataType::VTYPE_ASTRING:
733 case nsIDataType::VTYPE_DOMSTRING:
734 case nsIDataType::VTYPE_UTF8STRING:
735 case nsIDataType::VTYPE_CSTRING:
736 case nsIDataType::VTYPE_CHAR_STR:
737 case nsIDataType::VTYPE_WCHAR_STR:
738 case nsIDataType::VTYPE_STRING_SIZE_IS:
739 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
740 if (!String2ID(aData, &id)) {
741 return NS_ERROR_CANNOT_CONVERT_DATA;
743 *aResult = id;
744 return NS_OK;
745 default:
746 return NS_ERROR_CANNOT_CONVERT_DATA;
750 /***************************************************************************/
752 static nsresult
753 ToString(const nsDiscriminatedUnion& aData, nsACString& aOutString)
755 char* ptr;
757 switch (aData.mType) {
758 // all the stuff we don't handle...
759 case nsIDataType::VTYPE_ASTRING:
760 case nsIDataType::VTYPE_DOMSTRING:
761 case nsIDataType::VTYPE_UTF8STRING:
762 case nsIDataType::VTYPE_CSTRING:
763 case nsIDataType::VTYPE_CHAR_STR:
764 case nsIDataType::VTYPE_WCHAR_STR:
765 case nsIDataType::VTYPE_STRING_SIZE_IS:
766 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
767 case nsIDataType::VTYPE_WCHAR:
768 NS_ERROR("ToString being called for a string type - screwy logic!");
769 // fall through...
771 // XXX We might want stringified versions of these... ???
773 case nsIDataType::VTYPE_VOID:
774 case nsIDataType::VTYPE_EMPTY:
775 aOutString.Truncate();
776 aOutString.SetIsVoid(true);
777 return NS_OK;
779 case nsIDataType::VTYPE_EMPTY_ARRAY:
780 case nsIDataType::VTYPE_ARRAY:
781 case nsIDataType::VTYPE_INTERFACE:
782 case nsIDataType::VTYPE_INTERFACE_IS:
783 default:
784 return NS_ERROR_CANNOT_CONVERT_DATA;
786 // nsID has its own text formatter.
788 case nsIDataType::VTYPE_ID:
789 ptr = aData.u.mIDValue.ToString();
790 if (!ptr) {
791 return NS_ERROR_OUT_OF_MEMORY;
793 aOutString.Assign(ptr);
794 nsMemory::Free(ptr);
795 return NS_OK;
797 // Can't use PR_smprintf for floats, since it's locale-dependent
798 #define CASE__APPENDFLOAT_NUMBER(type_, member_) \
799 case nsIDataType :: type_ : \
801 nsAutoCString str; \
802 str.AppendFloat(aData.u. member_); \
803 aOutString.Assign(str); \
804 return NS_OK; \
807 CASE__APPENDFLOAT_NUMBER(VTYPE_FLOAT, mFloatValue)
808 CASE__APPENDFLOAT_NUMBER(VTYPE_DOUBLE, mDoubleValue)
810 #undef CASE__APPENDFLOAT_NUMBER
812 // the rest can be PR_smprintf'd and use common code.
814 #define CASE__SMPRINTF_NUMBER(type_, format_, cast_, member_) \
815 case nsIDataType :: type_ : \
816 ptr = PR_smprintf( format_ , (cast_) aData.u. member_ ); \
817 break;
819 CASE__SMPRINTF_NUMBER(VTYPE_INT8, "%d", int, mInt8Value)
820 CASE__SMPRINTF_NUMBER(VTYPE_INT16, "%d", int, mInt16Value)
821 CASE__SMPRINTF_NUMBER(VTYPE_INT32, "%d", int, mInt32Value)
822 CASE__SMPRINTF_NUMBER(VTYPE_INT64, "%lld", int64_t, mInt64Value)
824 CASE__SMPRINTF_NUMBER(VTYPE_UINT8, "%u", unsigned, mUint8Value)
825 CASE__SMPRINTF_NUMBER(VTYPE_UINT16, "%u", unsigned, mUint16Value)
826 CASE__SMPRINTF_NUMBER(VTYPE_UINT32, "%u", unsigned, mUint32Value)
827 CASE__SMPRINTF_NUMBER(VTYPE_UINT64, "%llu", int64_t, mUint64Value)
829 // XXX Would we rather print "true" / "false" ?
830 CASE__SMPRINTF_NUMBER(VTYPE_BOOL, "%d", int, mBoolValue)
832 CASE__SMPRINTF_NUMBER(VTYPE_CHAR, "%c", char, mCharValue)
834 #undef CASE__SMPRINTF_NUMBER
837 if (!ptr) {
838 return NS_ERROR_OUT_OF_MEMORY;
840 aOutString.Assign(ptr);
841 PR_smprintf_free(ptr);
842 return NS_OK;
845 /* static */ nsresult
846 nsVariant::ConvertToAString(const nsDiscriminatedUnion& aData,
847 nsAString& aResult)
849 switch (aData.mType) {
850 case nsIDataType::VTYPE_ASTRING:
851 case nsIDataType::VTYPE_DOMSTRING:
852 aResult.Assign(*aData.u.mAStringValue);
853 return NS_OK;
854 case nsIDataType::VTYPE_CSTRING:
855 CopyASCIItoUTF16(*aData.u.mCStringValue, aResult);
856 return NS_OK;
857 case nsIDataType::VTYPE_UTF8STRING:
858 CopyUTF8toUTF16(*aData.u.mUTF8StringValue, aResult);
859 return NS_OK;
860 case nsIDataType::VTYPE_CHAR_STR:
861 CopyASCIItoUTF16(aData.u.str.mStringValue, aResult);
862 return NS_OK;
863 case nsIDataType::VTYPE_WCHAR_STR:
864 aResult.Assign(aData.u.wstr.mWStringValue);
865 return NS_OK;
866 case nsIDataType::VTYPE_STRING_SIZE_IS:
867 CopyASCIItoUTF16(nsDependentCString(aData.u.str.mStringValue,
868 aData.u.str.mStringLength),
869 aResult);
870 return NS_OK;
871 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
872 aResult.Assign(aData.u.wstr.mWStringValue, aData.u.wstr.mWStringLength);
873 return NS_OK;
874 case nsIDataType::VTYPE_WCHAR:
875 aResult.Assign(aData.u.mWCharValue);
876 return NS_OK;
877 default: {
878 nsAutoCString tempCString;
879 nsresult rv = ToString(aData, tempCString);
880 if (NS_FAILED(rv)) {
881 return rv;
883 CopyASCIItoUTF16(tempCString, aResult);
884 return NS_OK;
889 /* static */ nsresult
890 nsVariant::ConvertToACString(const nsDiscriminatedUnion& aData,
891 nsACString& aResult)
893 switch (aData.mType) {
894 case nsIDataType::VTYPE_ASTRING:
895 case nsIDataType::VTYPE_DOMSTRING:
896 LossyCopyUTF16toASCII(*aData.u.mAStringValue, aResult);
897 return NS_OK;
898 case nsIDataType::VTYPE_CSTRING:
899 aResult.Assign(*aData.u.mCStringValue);
900 return NS_OK;
901 case nsIDataType::VTYPE_UTF8STRING:
902 // XXX This is an extra copy that should be avoided
903 // once Jag lands support for UTF8String and associated
904 // conversion methods.
905 LossyCopyUTF16toASCII(NS_ConvertUTF8toUTF16(*aData.u.mUTF8StringValue),
906 aResult);
907 return NS_OK;
908 case nsIDataType::VTYPE_CHAR_STR:
909 aResult.Assign(*aData.u.str.mStringValue);
910 return NS_OK;
911 case nsIDataType::VTYPE_WCHAR_STR:
912 LossyCopyUTF16toASCII(nsDependentString(aData.u.wstr.mWStringValue),
913 aResult);
914 return NS_OK;
915 case nsIDataType::VTYPE_STRING_SIZE_IS:
916 aResult.Assign(aData.u.str.mStringValue, aData.u.str.mStringLength);
917 return NS_OK;
918 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
919 LossyCopyUTF16toASCII(nsDependentString(aData.u.wstr.mWStringValue,
920 aData.u.wstr.mWStringLength),
921 aResult);
922 return NS_OK;
923 case nsIDataType::VTYPE_WCHAR: {
924 const char16_t* str = &aData.u.mWCharValue;
925 LossyCopyUTF16toASCII(Substring(str, 1), aResult);
926 return NS_OK;
928 default:
929 return ToString(aData, aResult);
933 /* static */ nsresult
934 nsVariant::ConvertToAUTF8String(const nsDiscriminatedUnion& aData,
935 nsAUTF8String& aResult)
937 switch (aData.mType) {
938 case nsIDataType::VTYPE_ASTRING:
939 case nsIDataType::VTYPE_DOMSTRING:
940 CopyUTF16toUTF8(*aData.u.mAStringValue, aResult);
941 return NS_OK;
942 case nsIDataType::VTYPE_CSTRING:
943 // XXX Extra copy, can be removed if we're sure CSTRING can
944 // only contain ASCII.
945 CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(*aData.u.mCStringValue),
946 aResult);
947 return NS_OK;
948 case nsIDataType::VTYPE_UTF8STRING:
949 aResult.Assign(*aData.u.mUTF8StringValue);
950 return NS_OK;
951 case nsIDataType::VTYPE_CHAR_STR:
952 // XXX Extra copy, can be removed if we're sure CHAR_STR can
953 // only contain ASCII.
954 CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(aData.u.str.mStringValue),
955 aResult);
956 return NS_OK;
957 case nsIDataType::VTYPE_WCHAR_STR:
958 CopyUTF16toUTF8(aData.u.wstr.mWStringValue, aResult);
959 return NS_OK;
960 case nsIDataType::VTYPE_STRING_SIZE_IS:
961 // XXX Extra copy, can be removed if we're sure CHAR_STR can
962 // only contain ASCII.
963 CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(
964 nsDependentCString(aData.u.str.mStringValue,
965 aData.u.str.mStringLength)), aResult);
966 return NS_OK;
967 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
968 CopyUTF16toUTF8(nsDependentString(aData.u.wstr.mWStringValue,
969 aData.u.wstr.mWStringLength),
970 aResult);
971 return NS_OK;
972 case nsIDataType::VTYPE_WCHAR: {
973 const char16_t* str = &aData.u.mWCharValue;
974 CopyUTF16toUTF8(Substring(str, 1), aResult);
975 return NS_OK;
977 default: {
978 nsAutoCString tempCString;
979 nsresult rv = ToString(aData, tempCString);
980 if (NS_FAILED(rv)) {
981 return rv;
983 // XXX Extra copy, can be removed if we're sure tempCString can
984 // only contain ASCII.
985 CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(tempCString), aResult);
986 return NS_OK;
991 /* static */ nsresult
992 nsVariant::ConvertToString(const nsDiscriminatedUnion& aData, char** aResult)
994 uint32_t ignored;
995 return nsVariant::ConvertToStringWithSize(aData, &ignored, aResult);
998 /* static */ nsresult
999 nsVariant::ConvertToWString(const nsDiscriminatedUnion& aData,
1000 char16_t** aResult)
1002 uint32_t ignored;
1003 return nsVariant::ConvertToWStringWithSize(aData, &ignored, aResult);
1006 /* static */ nsresult
1007 nsVariant::ConvertToStringWithSize(const nsDiscriminatedUnion& aData,
1008 uint32_t* aSize, char** aStr)
1010 nsAutoString tempString;
1011 nsAutoCString tempCString;
1012 nsresult rv;
1014 switch (aData.mType) {
1015 case nsIDataType::VTYPE_ASTRING:
1016 case nsIDataType::VTYPE_DOMSTRING:
1017 *aSize = aData.u.mAStringValue->Length();
1018 *aStr = ToNewCString(*aData.u.mAStringValue);
1019 break;
1020 case nsIDataType::VTYPE_CSTRING:
1021 *aSize = aData.u.mCStringValue->Length();
1022 *aStr = ToNewCString(*aData.u.mCStringValue);
1023 break;
1024 case nsIDataType::VTYPE_UTF8STRING: {
1025 // XXX This is doing 1 extra copy. Need to fix this
1026 // when Jag lands UTF8String
1027 // we want:
1028 // *aSize = *aData.mUTF8StringValue->Length();
1029 // *aStr = ToNewCString(*aData.mUTF8StringValue);
1030 // But this will have to do for now.
1031 NS_ConvertUTF8toUTF16 tempString(*aData.u.mUTF8StringValue);
1032 *aSize = tempString.Length();
1033 *aStr = ToNewCString(tempString);
1034 break;
1036 case nsIDataType::VTYPE_CHAR_STR: {
1037 nsDependentCString cString(aData.u.str.mStringValue);
1038 *aSize = cString.Length();
1039 *aStr = ToNewCString(cString);
1040 break;
1042 case nsIDataType::VTYPE_WCHAR_STR: {
1043 nsDependentString string(aData.u.wstr.mWStringValue);
1044 *aSize = string.Length();
1045 *aStr = ToNewCString(string);
1046 break;
1048 case nsIDataType::VTYPE_STRING_SIZE_IS: {
1049 nsDependentCString cString(aData.u.str.mStringValue,
1050 aData.u.str.mStringLength);
1051 *aSize = cString.Length();
1052 *aStr = ToNewCString(cString);
1053 break;
1055 case nsIDataType::VTYPE_WSTRING_SIZE_IS: {
1056 nsDependentString string(aData.u.wstr.mWStringValue,
1057 aData.u.wstr.mWStringLength);
1058 *aSize = string.Length();
1059 *aStr = ToNewCString(string);
1060 break;
1062 case nsIDataType::VTYPE_WCHAR:
1063 tempString.Assign(aData.u.mWCharValue);
1064 *aSize = tempString.Length();
1065 *aStr = ToNewCString(tempString);
1066 break;
1067 default:
1068 rv = ToString(aData, tempCString);
1069 if (NS_FAILED(rv)) {
1070 return rv;
1072 *aSize = tempCString.Length();
1073 *aStr = ToNewCString(tempCString);
1074 break;
1077 return *aStr ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
1079 /* static */ nsresult
1080 nsVariant::ConvertToWStringWithSize(const nsDiscriminatedUnion& aData,
1081 uint32_t* aSize, char16_t** aStr)
1083 nsAutoString tempString;
1084 nsAutoCString tempCString;
1085 nsresult rv;
1087 switch (aData.mType) {
1088 case nsIDataType::VTYPE_ASTRING:
1089 case nsIDataType::VTYPE_DOMSTRING:
1090 *aSize = aData.u.mAStringValue->Length();
1091 *aStr = ToNewUnicode(*aData.u.mAStringValue);
1092 break;
1093 case nsIDataType::VTYPE_CSTRING:
1094 *aSize = aData.u.mCStringValue->Length();
1095 *aStr = ToNewUnicode(*aData.u.mCStringValue);
1096 break;
1097 case nsIDataType::VTYPE_UTF8STRING: {
1098 *aStr = UTF8ToNewUnicode(*aData.u.mUTF8StringValue, aSize);
1099 break;
1101 case nsIDataType::VTYPE_CHAR_STR: {
1102 nsDependentCString cString(aData.u.str.mStringValue);
1103 *aSize = cString.Length();
1104 *aStr = ToNewUnicode(cString);
1105 break;
1107 case nsIDataType::VTYPE_WCHAR_STR: {
1108 nsDependentString string(aData.u.wstr.mWStringValue);
1109 *aSize = string.Length();
1110 *aStr = ToNewUnicode(string);
1111 break;
1113 case nsIDataType::VTYPE_STRING_SIZE_IS: {
1114 nsDependentCString cString(aData.u.str.mStringValue,
1115 aData.u.str.mStringLength);
1116 *aSize = cString.Length();
1117 *aStr = ToNewUnicode(cString);
1118 break;
1120 case nsIDataType::VTYPE_WSTRING_SIZE_IS: {
1121 nsDependentString string(aData.u.wstr.mWStringValue,
1122 aData.u.wstr.mWStringLength);
1123 *aSize = string.Length();
1124 *aStr = ToNewUnicode(string);
1125 break;
1127 case nsIDataType::VTYPE_WCHAR:
1128 tempString.Assign(aData.u.mWCharValue);
1129 *aSize = tempString.Length();
1130 *aStr = ToNewUnicode(tempString);
1131 break;
1132 default:
1133 rv = ToString(aData, tempCString);
1134 if (NS_FAILED(rv)) {
1135 return rv;
1137 *aSize = tempCString.Length();
1138 *aStr = ToNewUnicode(tempCString);
1139 break;
1142 return *aStr ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
1145 /* static */ nsresult
1146 nsVariant::ConvertToISupports(const nsDiscriminatedUnion& aData,
1147 nsISupports** aResult)
1149 switch (aData.mType) {
1150 case nsIDataType::VTYPE_INTERFACE:
1151 case nsIDataType::VTYPE_INTERFACE_IS:
1152 if (aData.u.iface.mInterfaceValue) {
1153 return aData.u.iface.mInterfaceValue->
1154 QueryInterface(NS_GET_IID(nsISupports), (void**)aResult);
1155 } else {
1156 *aResult = nullptr;
1157 return NS_OK;
1159 default:
1160 return NS_ERROR_CANNOT_CONVERT_DATA;
1164 /* static */ nsresult
1165 nsVariant::ConvertToInterface(const nsDiscriminatedUnion& aData, nsIID** aIID,
1166 void** aInterface)
1168 const nsIID* piid;
1170 switch (aData.mType) {
1171 case nsIDataType::VTYPE_INTERFACE:
1172 piid = &NS_GET_IID(nsISupports);
1173 break;
1174 case nsIDataType::VTYPE_INTERFACE_IS:
1175 piid = &aData.u.iface.mInterfaceID;
1176 break;
1177 default:
1178 return NS_ERROR_CANNOT_CONVERT_DATA;
1181 *aIID = (nsIID*)nsMemory::Clone(piid, sizeof(nsIID));
1182 if (!*aIID) {
1183 return NS_ERROR_OUT_OF_MEMORY;
1186 if (aData.u.iface.mInterfaceValue) {
1187 return aData.u.iface.mInterfaceValue->QueryInterface(*piid,
1188 aInterface);
1191 *aInterface = nullptr;
1192 return NS_OK;
1195 /* static */ nsresult
1196 nsVariant::ConvertToArray(const nsDiscriminatedUnion& aData, uint16_t* aType,
1197 nsIID* aIID, uint32_t* aCount, void** aPtr)
1199 // XXX perhaps we'd like to add support for converting each of the various
1200 // types into an array containing one element of that type. We can leverage
1201 // CloneArray to do this if we want to support this.
1203 if (aData.mType == nsIDataType::VTYPE_ARRAY) {
1204 return CloneArray(aData.u.array.mArrayType, &aData.u.array.mArrayInterfaceID,
1205 aData.u.array.mArrayCount, aData.u.array.mArrayValue,
1206 aType, aIID, aCount, aPtr);
1208 return NS_ERROR_CANNOT_CONVERT_DATA;
1211 /***************************************************************************/
1212 // static setter functions...
1214 #define DATA_SETTER_PROLOGUE(data_) \
1215 nsVariant::Cleanup(data_);
1217 #define DATA_SETTER_EPILOGUE(data_, type_) \
1218 data_->mType = nsIDataType :: type_; \
1219 return NS_OK;
1221 #define DATA_SETTER(data_, type_, member_, value_) \
1222 DATA_SETTER_PROLOGUE(data_) \
1223 data_->u.member_ = value_; \
1224 DATA_SETTER_EPILOGUE(data_, type_)
1226 #define DATA_SETTER_WITH_CAST(data_, type_, member_, cast_, value_) \
1227 DATA_SETTER_PROLOGUE(data_) \
1228 data_->u.member_ = cast_ value_; \
1229 DATA_SETTER_EPILOGUE(data_, type_)
1232 /********************************************/
1234 #define CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_) \
1237 #define CASE__SET_FROM_VARIANT_VTYPE__GETTER(member_, name_) \
1238 rv = aValue->GetAs##name_ (&(aData->u. member_ ));
1240 #define CASE__SET_FROM_VARIANT_VTYPE__GETTER_CAST(cast_, member_, name_) \
1241 rv = aValue->GetAs##name_ ( cast_ &(aData->u. member_ ));
1243 #define CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_) \
1244 if(NS_SUCCEEDED(rv)) \
1246 aData->mType = nsIDataType :: type_ ; \
1248 break; \
1251 #define CASE__SET_FROM_VARIANT_TYPE(type_, member_, name_) \
1252 case nsIDataType :: type_ : \
1253 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_) \
1254 CASE__SET_FROM_VARIANT_VTYPE__GETTER(member_, name_) \
1255 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)
1257 #define CASE__SET_FROM_VARIANT_VTYPE_CAST(type_, cast_, member_, name_) \
1258 case nsIDataType :: type_ : \
1259 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_) \
1260 CASE__SET_FROM_VARIANT_VTYPE__GETTER_CAST(cast_, member_, name_) \
1261 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)
1264 /* static */ nsresult
1265 nsVariant::SetFromVariant(nsDiscriminatedUnion* aData, nsIVariant* aValue)
1267 uint16_t type;
1268 nsresult rv;
1270 nsVariant::Cleanup(aData);
1272 rv = aValue->GetDataType(&type);
1273 if (NS_FAILED(rv)) {
1274 return rv;
1277 switch (type) {
1278 CASE__SET_FROM_VARIANT_VTYPE_CAST(VTYPE_INT8, (uint8_t*), mInt8Value,
1279 Int8)
1280 CASE__SET_FROM_VARIANT_TYPE(VTYPE_INT16, mInt16Value, Int16)
1281 CASE__SET_FROM_VARIANT_TYPE(VTYPE_INT32, mInt32Value, Int32)
1282 CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT8, mUint8Value, Uint8)
1283 CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT16, mUint16Value, Uint16)
1284 CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT32, mUint32Value, Uint32)
1285 CASE__SET_FROM_VARIANT_TYPE(VTYPE_FLOAT, mFloatValue, Float)
1286 CASE__SET_FROM_VARIANT_TYPE(VTYPE_DOUBLE, mDoubleValue, Double)
1287 CASE__SET_FROM_VARIANT_TYPE(VTYPE_BOOL , mBoolValue, Bool)
1288 CASE__SET_FROM_VARIANT_TYPE(VTYPE_CHAR, mCharValue, Char)
1289 CASE__SET_FROM_VARIANT_TYPE(VTYPE_WCHAR, mWCharValue, WChar)
1290 CASE__SET_FROM_VARIANT_TYPE(VTYPE_ID, mIDValue, ID)
1292 case nsIDataType::VTYPE_ASTRING:
1293 case nsIDataType::VTYPE_DOMSTRING:
1294 case nsIDataType::VTYPE_WCHAR_STR:
1295 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
1296 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_ASTRING);
1297 aData->u.mAStringValue = new nsString();
1298 if (!aData->u.mAStringValue) {
1299 return NS_ERROR_OUT_OF_MEMORY;
1301 rv = aValue->GetAsAString(*aData->u.mAStringValue);
1302 if (NS_FAILED(rv)) {
1303 delete aData->u.mAStringValue;
1305 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_ASTRING)
1307 case nsIDataType::VTYPE_CSTRING:
1308 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_CSTRING);
1309 aData->u.mCStringValue = new nsCString();
1310 if (!aData->u.mCStringValue) {
1311 return NS_ERROR_OUT_OF_MEMORY;
1313 rv = aValue->GetAsACString(*aData->u.mCStringValue);
1314 if (NS_FAILED(rv)) {
1315 delete aData->u.mCStringValue;
1317 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_CSTRING)
1319 case nsIDataType::VTYPE_UTF8STRING:
1320 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_UTF8STRING);
1321 aData->u.mUTF8StringValue = new nsUTF8String();
1322 if (!aData->u.mUTF8StringValue) {
1323 return NS_ERROR_OUT_OF_MEMORY;
1325 rv = aValue->GetAsAUTF8String(*aData->u.mUTF8StringValue);
1326 if (NS_FAILED(rv)) {
1327 delete aData->u.mUTF8StringValue;
1329 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_UTF8STRING)
1331 case nsIDataType::VTYPE_CHAR_STR:
1332 case nsIDataType::VTYPE_STRING_SIZE_IS:
1333 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_STRING_SIZE_IS);
1334 rv = aValue->GetAsStringWithSize(&aData->u.str.mStringLength,
1335 &aData->u.str.mStringValue);
1336 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_STRING_SIZE_IS)
1338 case nsIDataType::VTYPE_INTERFACE:
1339 case nsIDataType::VTYPE_INTERFACE_IS:
1340 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_INTERFACE_IS);
1341 // XXX This iid handling is ugly!
1342 nsIID* iid;
1343 rv = aValue->GetAsInterface(&iid, (void**)&aData->u.iface.mInterfaceValue);
1344 if (NS_SUCCEEDED(rv)) {
1345 aData->u.iface.mInterfaceID = *iid;
1346 nsMemory::Free((char*)iid);
1348 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_INTERFACE_IS)
1350 case nsIDataType::VTYPE_ARRAY:
1351 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_ARRAY);
1352 rv = aValue->GetAsArray(&aData->u.array.mArrayType,
1353 &aData->u.array.mArrayInterfaceID,
1354 &aData->u.array.mArrayCount,
1355 &aData->u.array.mArrayValue);
1356 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_ARRAY)
1358 case nsIDataType::VTYPE_VOID:
1359 rv = nsVariant::SetToVoid(aData);
1360 break;
1361 case nsIDataType::VTYPE_EMPTY_ARRAY:
1362 rv = nsVariant::SetToEmptyArray(aData);
1363 break;
1364 case nsIDataType::VTYPE_EMPTY:
1365 rv = nsVariant::SetToEmpty(aData);
1366 break;
1367 default:
1368 NS_ERROR("bad type in variant!");
1369 rv = NS_ERROR_FAILURE;
1370 break;
1372 return rv;
1375 /* static */ nsresult
1376 nsVariant::SetFromInt8(nsDiscriminatedUnion* aData, uint8_t aValue)
1378 DATA_SETTER_WITH_CAST(aData, VTYPE_INT8, mInt8Value, (uint8_t), aValue)
1380 /* static */ nsresult
1381 nsVariant::SetFromInt16(nsDiscriminatedUnion* aData, int16_t aValue)
1383 DATA_SETTER(aData, VTYPE_INT16, mInt16Value, aValue)
1385 /* static */ nsresult
1386 nsVariant::SetFromInt32(nsDiscriminatedUnion* aData, int32_t aValue)
1388 DATA_SETTER(aData, VTYPE_INT32, mInt32Value, aValue)
1390 /* static */ nsresult
1391 nsVariant::SetFromInt64(nsDiscriminatedUnion* aData, int64_t aValue)
1393 DATA_SETTER(aData, VTYPE_INT64, mInt64Value, aValue)
1395 /* static */ nsresult
1396 nsVariant::SetFromUint8(nsDiscriminatedUnion* aData, uint8_t aValue)
1398 DATA_SETTER(aData, VTYPE_UINT8, mUint8Value, aValue)
1400 /* static */ nsresult
1401 nsVariant::SetFromUint16(nsDiscriminatedUnion* aData, uint16_t aValue)
1403 DATA_SETTER(aData, VTYPE_UINT16, mUint16Value, aValue)
1405 /* static */ nsresult
1406 nsVariant::SetFromUint32(nsDiscriminatedUnion* aData, uint32_t aValue)
1408 DATA_SETTER(aData, VTYPE_UINT32, mUint32Value, aValue)
1410 /* static */ nsresult
1411 nsVariant::SetFromUint64(nsDiscriminatedUnion* aData, uint64_t aValue)
1413 DATA_SETTER(aData, VTYPE_UINT64, mUint64Value, aValue)
1415 /* static */ nsresult
1416 nsVariant::SetFromFloat(nsDiscriminatedUnion* aData, float aValue)
1418 DATA_SETTER(aData, VTYPE_FLOAT, mFloatValue, aValue)
1420 /* static */ nsresult
1421 nsVariant::SetFromDouble(nsDiscriminatedUnion* aData, double aValue)
1423 DATA_SETTER(aData, VTYPE_DOUBLE, mDoubleValue, aValue)
1425 /* static */ nsresult
1426 nsVariant::SetFromBool(nsDiscriminatedUnion* aData, bool aValue)
1428 DATA_SETTER(aData, VTYPE_BOOL, mBoolValue, aValue)
1430 /* static */ nsresult
1431 nsVariant::SetFromChar(nsDiscriminatedUnion* aData, char aValue)
1433 DATA_SETTER(aData, VTYPE_CHAR, mCharValue, aValue)
1435 /* static */ nsresult
1436 nsVariant::SetFromWChar(nsDiscriminatedUnion* aData, char16_t aValue)
1438 DATA_SETTER(aData, VTYPE_WCHAR, mWCharValue, aValue)
1440 /* static */ nsresult
1441 nsVariant::SetFromID(nsDiscriminatedUnion* aData, const nsID& aValue)
1443 DATA_SETTER(aData, VTYPE_ID, mIDValue, aValue)
1445 /* static */ nsresult
1446 nsVariant::SetFromAString(nsDiscriminatedUnion* aData, const nsAString& aValue)
1448 DATA_SETTER_PROLOGUE(aData);
1449 if (!(aData->u.mAStringValue = new nsString(aValue))) {
1450 return NS_ERROR_OUT_OF_MEMORY;
1452 DATA_SETTER_EPILOGUE(aData, VTYPE_ASTRING);
1455 /* static */ nsresult
1456 nsVariant::SetFromACString(nsDiscriminatedUnion* aData,
1457 const nsACString& aValue)
1459 DATA_SETTER_PROLOGUE(aData);
1460 if (!(aData->u.mCStringValue = new nsCString(aValue))) {
1461 return NS_ERROR_OUT_OF_MEMORY;
1463 DATA_SETTER_EPILOGUE(aData, VTYPE_CSTRING);
1466 /* static */ nsresult
1467 nsVariant::SetFromAUTF8String(nsDiscriminatedUnion* aData,
1468 const nsAUTF8String& aValue)
1470 DATA_SETTER_PROLOGUE(aData);
1471 if (!(aData->u.mUTF8StringValue = new nsUTF8String(aValue))) {
1472 return NS_ERROR_OUT_OF_MEMORY;
1474 DATA_SETTER_EPILOGUE(aData, VTYPE_UTF8STRING);
1477 /* static */ nsresult
1478 nsVariant::SetFromString(nsDiscriminatedUnion* aData, const char* aValue)
1480 DATA_SETTER_PROLOGUE(aData);
1481 if (!aValue) {
1482 return NS_ERROR_NULL_POINTER;
1484 return SetFromStringWithSize(aData, strlen(aValue), aValue);
1486 /* static */ nsresult
1487 nsVariant::SetFromWString(nsDiscriminatedUnion* aData, const char16_t* aValue)
1489 DATA_SETTER_PROLOGUE(aData);
1490 if (!aValue) {
1491 return NS_ERROR_NULL_POINTER;
1493 return SetFromWStringWithSize(aData, NS_strlen(aValue), aValue);
1495 /* static */ nsresult
1496 nsVariant::SetFromISupports(nsDiscriminatedUnion* aData, nsISupports* aValue)
1498 return SetFromInterface(aData, NS_GET_IID(nsISupports), aValue);
1500 /* static */ nsresult
1501 nsVariant::SetFromInterface(nsDiscriminatedUnion* aData, const nsIID& aIID,
1502 nsISupports* aValue)
1504 DATA_SETTER_PROLOGUE(aData);
1505 NS_IF_ADDREF(aValue);
1506 aData->u.iface.mInterfaceValue = aValue;
1507 aData->u.iface.mInterfaceID = aIID;
1508 DATA_SETTER_EPILOGUE(aData, VTYPE_INTERFACE_IS);
1510 /* static */ nsresult
1511 nsVariant::SetFromArray(nsDiscriminatedUnion* aData, uint16_t aType,
1512 const nsIID* aIID, uint32_t aCount, void* aValue)
1514 DATA_SETTER_PROLOGUE(aData);
1515 if (!aValue || !aCount) {
1516 return NS_ERROR_NULL_POINTER;
1519 nsresult rv = CloneArray(aType, aIID, aCount, aValue,
1520 &aData->u.array.mArrayType,
1521 &aData->u.array.mArrayInterfaceID,
1522 &aData->u.array.mArrayCount,
1523 &aData->u.array.mArrayValue);
1524 if (NS_FAILED(rv)) {
1525 return rv;
1527 DATA_SETTER_EPILOGUE(aData, VTYPE_ARRAY);
1529 /* static */ nsresult
1530 nsVariant::SetFromStringWithSize(nsDiscriminatedUnion* aData, uint32_t aSize,
1531 const char* aValue)
1533 DATA_SETTER_PROLOGUE(aData);
1534 if (!aValue) {
1535 return NS_ERROR_NULL_POINTER;
1537 if (!(aData->u.str.mStringValue =
1538 (char*)nsMemory::Clone(aValue, (aSize + 1) * sizeof(char)))) {
1539 return NS_ERROR_OUT_OF_MEMORY;
1541 aData->u.str.mStringLength = aSize;
1542 DATA_SETTER_EPILOGUE(aData, VTYPE_STRING_SIZE_IS);
1544 /* static */ nsresult
1545 nsVariant::SetFromWStringWithSize(nsDiscriminatedUnion* aData, uint32_t aSize,
1546 const char16_t* aValue)
1548 DATA_SETTER_PROLOGUE(aData);
1549 if (!aValue) {
1550 return NS_ERROR_NULL_POINTER;
1552 if (!(aData->u.wstr.mWStringValue =
1553 (char16_t*)nsMemory::Clone(aValue, (aSize + 1) * sizeof(char16_t)))) {
1554 return NS_ERROR_OUT_OF_MEMORY;
1556 aData->u.wstr.mWStringLength = aSize;
1557 DATA_SETTER_EPILOGUE(aData, VTYPE_WSTRING_SIZE_IS);
1559 /* static */ nsresult
1560 nsVariant::AllocateWStringWithSize(nsDiscriminatedUnion* aData, uint32_t aSize)
1562 DATA_SETTER_PROLOGUE(aData);
1563 if (!(aData->u.wstr.mWStringValue =
1564 (char16_t*)NS_Alloc((aSize + 1) * sizeof(char16_t)))) {
1565 return NS_ERROR_OUT_OF_MEMORY;
1567 aData->u.wstr.mWStringValue[aSize] = '\0';
1568 aData->u.wstr.mWStringLength = aSize;
1569 DATA_SETTER_EPILOGUE(aData, VTYPE_WSTRING_SIZE_IS);
1571 /* static */ nsresult
1572 nsVariant::SetToVoid(nsDiscriminatedUnion* aData)
1574 DATA_SETTER_PROLOGUE(aData);
1575 DATA_SETTER_EPILOGUE(aData, VTYPE_VOID);
1577 /* static */ nsresult
1578 nsVariant::SetToEmpty(nsDiscriminatedUnion* aData)
1580 DATA_SETTER_PROLOGUE(aData);
1581 DATA_SETTER_EPILOGUE(aData, VTYPE_EMPTY);
1583 /* static */ nsresult
1584 nsVariant::SetToEmptyArray(nsDiscriminatedUnion* aData)
1586 DATA_SETTER_PROLOGUE(aData);
1587 DATA_SETTER_EPILOGUE(aData, VTYPE_EMPTY_ARRAY);
1590 /***************************************************************************/
1592 /* static */ nsresult
1593 nsVariant::Initialize(nsDiscriminatedUnion* aData)
1595 aData->mType = nsIDataType::VTYPE_EMPTY;
1596 return NS_OK;
1599 /* static */ nsresult
1600 nsVariant::Cleanup(nsDiscriminatedUnion* aData)
1602 switch (aData->mType) {
1603 case nsIDataType::VTYPE_INT8:
1604 case nsIDataType::VTYPE_INT16:
1605 case nsIDataType::VTYPE_INT32:
1606 case nsIDataType::VTYPE_INT64:
1607 case nsIDataType::VTYPE_UINT8:
1608 case nsIDataType::VTYPE_UINT16:
1609 case nsIDataType::VTYPE_UINT32:
1610 case nsIDataType::VTYPE_UINT64:
1611 case nsIDataType::VTYPE_FLOAT:
1612 case nsIDataType::VTYPE_DOUBLE:
1613 case nsIDataType::VTYPE_BOOL:
1614 case nsIDataType::VTYPE_CHAR:
1615 case nsIDataType::VTYPE_WCHAR:
1616 case nsIDataType::VTYPE_VOID:
1617 case nsIDataType::VTYPE_ID:
1618 break;
1619 case nsIDataType::VTYPE_ASTRING:
1620 case nsIDataType::VTYPE_DOMSTRING:
1621 delete aData->u.mAStringValue;
1622 break;
1623 case nsIDataType::VTYPE_CSTRING:
1624 delete aData->u.mCStringValue;
1625 break;
1626 case nsIDataType::VTYPE_UTF8STRING:
1627 delete aData->u.mUTF8StringValue;
1628 break;
1629 case nsIDataType::VTYPE_CHAR_STR:
1630 case nsIDataType::VTYPE_STRING_SIZE_IS:
1631 nsMemory::Free((char*)aData->u.str.mStringValue);
1632 break;
1633 case nsIDataType::VTYPE_WCHAR_STR:
1634 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
1635 nsMemory::Free((char*)aData->u.wstr.mWStringValue);
1636 break;
1637 case nsIDataType::VTYPE_INTERFACE:
1638 case nsIDataType::VTYPE_INTERFACE_IS:
1639 NS_IF_RELEASE(aData->u.iface.mInterfaceValue);
1640 break;
1641 case nsIDataType::VTYPE_ARRAY:
1642 FreeArray(aData);
1643 break;
1644 case nsIDataType::VTYPE_EMPTY_ARRAY:
1645 case nsIDataType::VTYPE_EMPTY:
1646 break;
1647 default:
1648 NS_ERROR("bad type in variant!");
1649 break;
1652 aData->mType = nsIDataType::VTYPE_EMPTY;
1653 return NS_OK;
1656 /* static */ void
1657 nsVariant::Traverse(const nsDiscriminatedUnion& aData,
1658 nsCycleCollectionTraversalCallback& aCb)
1660 switch (aData.mType) {
1661 case nsIDataType::VTYPE_INTERFACE:
1662 case nsIDataType::VTYPE_INTERFACE_IS:
1663 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mData");
1664 aCb.NoteXPCOMChild(aData.u.iface.mInterfaceValue);
1665 break;
1666 case nsIDataType::VTYPE_ARRAY:
1667 switch (aData.u.array.mArrayType) {
1668 case nsIDataType::VTYPE_INTERFACE:
1669 case nsIDataType::VTYPE_INTERFACE_IS: {
1670 nsISupports** p = (nsISupports**)aData.u.array.mArrayValue;
1671 for (uint32_t i = aData.u.array.mArrayCount; i > 0; ++p, --i) {
1672 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mData[i]");
1673 aCb.NoteXPCOMChild(*p);
1676 default:
1677 break;
1679 default:
1680 break;
1684 /***************************************************************************/
1685 /***************************************************************************/
1686 // members...
1688 NS_IMPL_ISUPPORTS(nsVariant, nsIVariant, nsIWritableVariant)
1690 nsVariant::nsVariant()
1691 : mWritable(true)
1693 nsVariant::Initialize(&mData);
1695 #ifdef DEBUG
1697 // Assert that the nsIDataType consts match the values #defined in
1698 // xpt_struct.h. Bad things happen somewhere if they don't.
1699 struct THE_TYPES
1701 uint16_t a;
1702 uint16_t 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 bool inited = false;
1734 if (!inited) {
1735 for (int i = 0; i < length; ++i) {
1736 NS_ASSERTION(array[i].a == array[i].b, "bad const declaration");
1738 inited = 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 uint16_t dataType; */
1753 NS_IMETHODIMP
1754 nsVariant::GetDataType(uint16_t* aDataType)
1756 *aDataType = mData.mType;
1757 return NS_OK;
1760 /* uint8_t getAsInt8 (); */
1761 NS_IMETHODIMP
1762 nsVariant::GetAsInt8(uint8_t* aResult)
1764 return nsVariant::ConvertToInt8(mData, aResult);
1767 /* int16_t getAsInt16 (); */
1768 NS_IMETHODIMP
1769 nsVariant::GetAsInt16(int16_t* aResult)
1771 return nsVariant::ConvertToInt16(mData, aResult);
1774 /* int32_t getAsInt32 (); */
1775 NS_IMETHODIMP
1776 nsVariant::GetAsInt32(int32_t* aResult)
1778 return nsVariant::ConvertToInt32(mData, aResult);
1781 /* int64_t getAsInt64 (); */
1782 NS_IMETHODIMP
1783 nsVariant::GetAsInt64(int64_t* aResult)
1785 return nsVariant::ConvertToInt64(mData, aResult);
1788 /* uint8_t getAsUint8 (); */
1789 NS_IMETHODIMP
1790 nsVariant::GetAsUint8(uint8_t* aResult)
1792 return nsVariant::ConvertToUint8(mData, aResult);
1795 /* uint16_t getAsUint16 (); */
1796 NS_IMETHODIMP
1797 nsVariant::GetAsUint16(uint16_t* aResult)
1799 return nsVariant::ConvertToUint16(mData, aResult);
1802 /* uint32_t getAsUint32 (); */
1803 NS_IMETHODIMP
1804 nsVariant::GetAsUint32(uint32_t* aResult)
1806 return nsVariant::ConvertToUint32(mData, aResult);
1809 /* uint64_t getAsUint64 (); */
1810 NS_IMETHODIMP
1811 nsVariant::GetAsUint64(uint64_t* aResult)
1813 return nsVariant::ConvertToUint64(mData, aResult);
1816 /* float getAsFloat (); */
1817 NS_IMETHODIMP
1818 nsVariant::GetAsFloat(float* aResult)
1820 return nsVariant::ConvertToFloat(mData, aResult);
1823 /* double getAsDouble (); */
1824 NS_IMETHODIMP
1825 nsVariant::GetAsDouble(double* aResult)
1827 return nsVariant::ConvertToDouble(mData, aResult);
1830 /* bool getAsBool (); */
1831 NS_IMETHODIMP
1832 nsVariant::GetAsBool(bool* aResult)
1834 return nsVariant::ConvertToBool(mData, aResult);
1837 /* char getAsChar (); */
1838 NS_IMETHODIMP
1839 nsVariant::GetAsChar(char* aResult)
1841 return nsVariant::ConvertToChar(mData, aResult);
1844 /* wchar getAsWChar (); */
1845 NS_IMETHODIMP
1846 nsVariant::GetAsWChar(char16_t* aResult)
1848 return nsVariant::ConvertToWChar(mData, aResult);
1851 /* [notxpcom] nsresult getAsID (out nsID retval); */
1852 NS_IMETHODIMP_(nsresult)
1853 nsVariant::GetAsID(nsID* aResult)
1855 return nsVariant::ConvertToID(mData, aResult);
1858 /* AString getAsAString (); */
1859 NS_IMETHODIMP
1860 nsVariant::GetAsAString(nsAString& aResult)
1862 return nsVariant::ConvertToAString(mData, aResult);
1865 /* DOMString getAsDOMString (); */
1866 NS_IMETHODIMP
1867 nsVariant::GetAsDOMString(nsAString& aResult)
1869 // A DOMString maps to an AString internally, so we can re-use
1870 // ConvertToAString here.
1871 return nsVariant::ConvertToAString(mData, aResult);
1874 /* ACString getAsACString (); */
1875 NS_IMETHODIMP
1876 nsVariant::GetAsACString(nsACString& aResult)
1878 return nsVariant::ConvertToACString(mData, aResult);
1881 /* AUTF8String getAsAUTF8String (); */
1882 NS_IMETHODIMP
1883 nsVariant::GetAsAUTF8String(nsAUTF8String& aResult)
1885 return nsVariant::ConvertToAUTF8String(mData, aResult);
1888 /* string getAsString (); */
1889 NS_IMETHODIMP
1890 nsVariant::GetAsString(char** aResult)
1892 return nsVariant::ConvertToString(mData, aResult);
1895 /* wstring getAsWString (); */
1896 NS_IMETHODIMP
1897 nsVariant::GetAsWString(char16_t** aResult)
1899 return nsVariant::ConvertToWString(mData, aResult);
1902 /* nsISupports getAsISupports (); */
1903 NS_IMETHODIMP
1904 nsVariant::GetAsISupports(nsISupports** aResult)
1906 return nsVariant::ConvertToISupports(mData, aResult);
1909 /* jsval getAsJSVal() */
1910 NS_IMETHODIMP
1911 nsVariant::GetAsJSVal(JS::MutableHandleValue)
1913 // Can only get the jsval from an XPCVariant.
1914 return NS_ERROR_CANNOT_CONVERT_DATA;
1917 /* void getAsInterface (out nsIIDPtr iid, [iid_is (iid), retval] out nsQIResult iface); */
1918 NS_IMETHODIMP
1919 nsVariant::GetAsInterface(nsIID** aIID, void** aInterface)
1921 return nsVariant::ConvertToInterface(mData, aIID, aInterface);
1924 /* [notxpcom] nsresult getAsArray (out uint16_t type, out nsIID iid, out uint32_t count, out voidPtr ptr); */
1925 NS_IMETHODIMP_(nsresult)
1926 nsVariant::GetAsArray(uint16_t* aType, nsIID* aIID,
1927 uint32_t* aCount, void** aPtr)
1929 return nsVariant::ConvertToArray(mData, aType, aIID, aCount, aPtr);
1932 /* void getAsStringWithSize (out uint32_t size, [size_is (size), retval] out string str); */
1933 NS_IMETHODIMP
1934 nsVariant::GetAsStringWithSize(uint32_t* aSize, char** aStr)
1936 return nsVariant::ConvertToStringWithSize(mData, aSize, aStr);
1939 /* void getAsWStringWithSize (out uint32_t size, [size_is (size), retval] out wstring str); */
1940 NS_IMETHODIMP
1941 nsVariant::GetAsWStringWithSize(uint32_t* aSize, char16_t** aStr)
1943 return nsVariant::ConvertToWStringWithSize(mData, aSize, aStr);
1946 /***************************************************************************/
1948 /* attribute bool writable; */
1949 NS_IMETHODIMP
1950 nsVariant::GetWritable(bool* aWritable)
1952 *aWritable = mWritable;
1953 return NS_OK;
1955 NS_IMETHODIMP
1956 nsVariant::SetWritable(bool aWritable)
1958 if (!mWritable && aWritable) {
1959 return NS_ERROR_FAILURE;
1961 mWritable = aWritable;
1962 return NS_OK;
1965 /***************************************************************************/
1967 // For all the data setters we just forward to the static (and sharable)
1968 // 'SetFrom' functions.
1970 /* void setAsInt8 (in uint8_t aValue); */
1971 NS_IMETHODIMP
1972 nsVariant::SetAsInt8(uint8_t aValue)
1974 if (!mWritable) {
1975 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1977 return nsVariant::SetFromInt8(&mData, aValue);
1980 /* void setAsInt16 (in int16_t aValue); */
1981 NS_IMETHODIMP
1982 nsVariant::SetAsInt16(int16_t aValue)
1984 if (!mWritable) {
1985 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1987 return nsVariant::SetFromInt16(&mData, aValue);
1990 /* void setAsInt32 (in int32_t aValue); */
1991 NS_IMETHODIMP
1992 nsVariant::SetAsInt32(int32_t aValue)
1994 if (!mWritable) {
1995 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1997 return nsVariant::SetFromInt32(&mData, aValue);
2000 /* void setAsInt64 (in int64_t aValue); */
2001 NS_IMETHODIMP
2002 nsVariant::SetAsInt64(int64_t aValue)
2004 if (!mWritable) {
2005 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2007 return nsVariant::SetFromInt64(&mData, aValue);
2010 /* void setAsUint8 (in uint8_t aValue); */
2011 NS_IMETHODIMP
2012 nsVariant::SetAsUint8(uint8_t aValue)
2014 if (!mWritable) {
2015 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2017 return nsVariant::SetFromUint8(&mData, aValue);
2020 /* void setAsUint16 (in uint16_t aValue); */
2021 NS_IMETHODIMP
2022 nsVariant::SetAsUint16(uint16_t aValue)
2024 if (!mWritable) {
2025 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2027 return nsVariant::SetFromUint16(&mData, aValue);
2030 /* void setAsUint32 (in uint32_t aValue); */
2031 NS_IMETHODIMP
2032 nsVariant::SetAsUint32(uint32_t aValue)
2034 if (!mWritable) {
2035 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2037 return nsVariant::SetFromUint32(&mData, aValue);
2040 /* void setAsUint64 (in uint64_t aValue); */
2041 NS_IMETHODIMP
2042 nsVariant::SetAsUint64(uint64_t aValue)
2044 if (!mWritable) {
2045 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2047 return nsVariant::SetFromUint64(&mData, aValue);
2050 /* void setAsFloat (in float aValue); */
2051 NS_IMETHODIMP
2052 nsVariant::SetAsFloat(float aValue)
2054 if (!mWritable) {
2055 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2057 return nsVariant::SetFromFloat(&mData, aValue);
2060 /* void setAsDouble (in double aValue); */
2061 NS_IMETHODIMP
2062 nsVariant::SetAsDouble(double aValue)
2064 if (!mWritable) {
2065 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2067 return nsVariant::SetFromDouble(&mData, aValue);
2070 /* void setAsBool (in bool aValue); */
2071 NS_IMETHODIMP
2072 nsVariant::SetAsBool(bool aValue)
2074 if (!mWritable) {
2075 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2077 return nsVariant::SetFromBool(&mData, aValue);
2080 /* void setAsChar (in char aValue); */
2081 NS_IMETHODIMP
2082 nsVariant::SetAsChar(char aValue)
2084 if (!mWritable) {
2085 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2087 return nsVariant::SetFromChar(&mData, aValue);
2090 /* void setAsWChar (in wchar aValue); */
2091 NS_IMETHODIMP
2092 nsVariant::SetAsWChar(char16_t aValue)
2094 if (!mWritable) {
2095 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2097 return nsVariant::SetFromWChar(&mData, aValue);
2100 /* void setAsID (in nsIDRef aValue); */
2101 NS_IMETHODIMP
2102 nsVariant::SetAsID(const nsID& aValue)
2104 if (!mWritable) {
2105 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2107 return nsVariant::SetFromID(&mData, aValue);
2110 /* void setAsAString (in AString aValue); */
2111 NS_IMETHODIMP
2112 nsVariant::SetAsAString(const nsAString& aValue)
2114 if (!mWritable) {
2115 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2117 return nsVariant::SetFromAString(&mData, aValue);
2120 /* void setAsDOMString (in DOMString aValue); */
2121 NS_IMETHODIMP
2122 nsVariant::SetAsDOMString(const nsAString& aValue)
2124 if (!mWritable) {
2125 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2128 DATA_SETTER_PROLOGUE((&mData));
2129 if (!(mData.u.mAStringValue = new nsString(aValue))) {
2130 return NS_ERROR_OUT_OF_MEMORY;
2132 DATA_SETTER_EPILOGUE((&mData), VTYPE_DOMSTRING);
2135 /* void setAsACString (in ACString aValue); */
2136 NS_IMETHODIMP
2137 nsVariant::SetAsACString(const nsACString& aValue)
2139 if (!mWritable) {
2140 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2142 return nsVariant::SetFromACString(&mData, aValue);
2145 /* void setAsAUTF8String (in AUTF8String aValue); */
2146 NS_IMETHODIMP
2147 nsVariant::SetAsAUTF8String(const nsAUTF8String& aValue)
2149 if (!mWritable) {
2150 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2152 return nsVariant::SetFromAUTF8String(&mData, aValue);
2155 /* void setAsString (in string aValue); */
2156 NS_IMETHODIMP
2157 nsVariant::SetAsString(const char* aValue)
2159 if (!mWritable) {
2160 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2162 return nsVariant::SetFromString(&mData, aValue);
2165 /* void setAsWString (in wstring aValue); */
2166 NS_IMETHODIMP
2167 nsVariant::SetAsWString(const char16_t* aValue)
2169 if (!mWritable) {
2170 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2172 return nsVariant::SetFromWString(&mData, aValue);
2175 /* void setAsISupports (in nsISupports aValue); */
2176 NS_IMETHODIMP
2177 nsVariant::SetAsISupports(nsISupports* aValue)
2179 if (!mWritable) {
2180 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2182 return nsVariant::SetFromISupports(&mData, aValue);
2185 /* void setAsInterface (in nsIIDRef iid, [iid_is (iid)] in nsQIResult iface); */
2186 NS_IMETHODIMP
2187 nsVariant::SetAsInterface(const nsIID& aIID, void* aInterface)
2189 if (!mWritable) {
2190 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2192 return nsVariant::SetFromInterface(&mData, aIID, (nsISupports*)aInterface);
2195 /* [noscript] void setAsArray (in uint16_t type, in nsIIDPtr iid, in uint32_t count, in voidPtr ptr); */
2196 NS_IMETHODIMP
2197 nsVariant::SetAsArray(uint16_t aType, const nsIID* aIID,
2198 uint32_t aCount, void* aPtr)
2200 if (!mWritable) {
2201 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2203 return nsVariant::SetFromArray(&mData, aType, aIID, aCount, aPtr);
2206 /* void setAsStringWithSize (in uint32_t size, [size_is (size)] in string str); */
2207 NS_IMETHODIMP
2208 nsVariant::SetAsStringWithSize(uint32_t aSize, const char* aStr)
2210 if (!mWritable) {
2211 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2213 return nsVariant::SetFromStringWithSize(&mData, aSize, aStr);
2216 /* void setAsWStringWithSize (in uint32_t size, [size_is (size)] in wstring str); */
2217 NS_IMETHODIMP
2218 nsVariant::SetAsWStringWithSize(uint32_t aSize, const char16_t* aStr)
2220 if (!mWritable) {
2221 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2223 return nsVariant::SetFromWStringWithSize(&mData, aSize, aStr);
2226 /* void setAsVoid (); */
2227 NS_IMETHODIMP
2228 nsVariant::SetAsVoid()
2230 if (!mWritable) {
2231 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2233 return nsVariant::SetToVoid(&mData);
2236 /* void setAsEmpty (); */
2237 NS_IMETHODIMP
2238 nsVariant::SetAsEmpty()
2240 if (!mWritable) {
2241 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2243 return nsVariant::SetToEmpty(&mData);
2246 /* void setAsEmptyArray (); */
2247 NS_IMETHODIMP
2248 nsVariant::SetAsEmptyArray()
2250 if (!mWritable) {
2251 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2253 return nsVariant::SetToEmptyArray(&mData);
2256 /* void setFromVariant (in nsIVariant aValue); */
2257 NS_IMETHODIMP
2258 nsVariant::SetFromVariant(nsIVariant* aValue)
2260 if (!mWritable) {
2261 return NS_ERROR_OBJECT_IS_IMMUTABLE;
2263 return nsVariant::SetFromVariant(&mData, aValue);