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