1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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/. */
6
7 #include "nsVariant.h"
8 #include "prprf.h"
9 #include "prdtoa.h"
10 #include <math.h>
11 #include "nsCycleCollectionParticipant.h"
12 #include "xptinfo.h"
13 #include "nsReadableUtils.h"
14 #include "nsMemory.h"
15 #include "nsString.h"
16 #include "nsCRTGlue.h"
17 #include "mozilla/IntegerPrintfMacros.h"
18 #include "mozilla/Printf.h"
19
20 /***************************************************************************/
21 // Helpers for static convert functions...
22
String2Double(const char * aString,double * aResult)23 static nsresult String2Double(const char* aString, double* aResult) {
24 char* next;
25 double value = PR_strtod(aString, &next);
26 if (next == aString) {
27 return NS_ERROR_CANNOT_CONVERT_DATA;
28 }
29 *aResult = value;
30 return NS_OK;
31 }
32
AString2Double(const nsAString & aString,double * aResult)33 static nsresult AString2Double(const nsAString& aString, double* aResult) {
34 char* pChars = ToNewCString(aString, mozilla::fallible);
35 if (!pChars) {
36 return NS_ERROR_OUT_OF_MEMORY;
37 }
38 nsresult rv = String2Double(pChars, aResult);
39 free(pChars);
40 return rv;
41 }
42
AUTF8String2Double(const nsAUTF8String & aString,double * aResult)43 static nsresult AUTF8String2Double(const nsAUTF8String& aString,
44 double* aResult) {
45 return String2Double(PromiseFlatUTF8String(aString).get(), aResult);
46 }
47
ACString2Double(const nsACString & aString,double * aResult)48 static nsresult ACString2Double(const nsACString& aString, double* aResult) {
49 return String2Double(PromiseFlatCString(aString).get(), aResult);
50 }
51
52 // Fills aOutData with double, uint32_t, or int32_t.
53 // Returns NS_OK, an error code, or a non-NS_OK success code
ToManageableNumber(nsDiscriminatedUnion * aOutData) const54 nsresult nsDiscriminatedUnion::ToManageableNumber(
55 nsDiscriminatedUnion* aOutData) const {
56 nsresult rv;
57
58 switch (mType) {
59 // This group results in a int32_t...
60
61 #define CASE__NUMBER_INT32(type_, member_) \
62 case nsIDataType::type_: \
63 aOutData->u.mInt32Value = u.member_; \
64 aOutData->mType = nsIDataType::VTYPE_INT32; \
65 return NS_OK;
66
67 CASE__NUMBER_INT32(VTYPE_INT8, mInt8Value)
68 CASE__NUMBER_INT32(VTYPE_INT16, mInt16Value)
69 CASE__NUMBER_INT32(VTYPE_INT32, mInt32Value)
70 CASE__NUMBER_INT32(VTYPE_UINT8, mUint8Value)
71 CASE__NUMBER_INT32(VTYPE_UINT16, mUint16Value)
72 CASE__NUMBER_INT32(VTYPE_BOOL, mBoolValue)
73 CASE__NUMBER_INT32(VTYPE_CHAR, mCharValue)
74 CASE__NUMBER_INT32(VTYPE_WCHAR, mWCharValue)
75
76 #undef CASE__NUMBER_INT32
77
78 // This group results in a uint32_t...
79
80 case nsIDataType::VTYPE_UINT32:
81 aOutData->u.mUint32Value = u.mUint32Value;
82 aOutData->mType = nsIDataType::VTYPE_UINT32;
83 return NS_OK;
84
85 // This group results in a double...
86
87 case nsIDataType::VTYPE_INT64:
88 case nsIDataType::VTYPE_UINT64:
89 // XXX Need boundary checking here.
90 // We may need to return NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA
91 aOutData->u.mDoubleValue = double(u.mInt64Value);
92 aOutData->mType = nsIDataType::VTYPE_DOUBLE;
93 return NS_OK;
94 case nsIDataType::VTYPE_FLOAT:
95 aOutData->u.mDoubleValue = u.mFloatValue;
96 aOutData->mType = nsIDataType::VTYPE_DOUBLE;
97 return NS_OK;
98 case nsIDataType::VTYPE_DOUBLE:
99 aOutData->u.mDoubleValue = u.mDoubleValue;
100 aOutData->mType = nsIDataType::VTYPE_DOUBLE;
101 return NS_OK;
102 case nsIDataType::VTYPE_CHAR_STR:
103 case nsIDataType::VTYPE_STRING_SIZE_IS:
104 rv = String2Double(u.str.mStringValue, &aOutData->u.mDoubleValue);
105 if (NS_FAILED(rv)) {
106 return rv;
107 }
108 aOutData->mType = nsIDataType::VTYPE_DOUBLE;
109 return NS_OK;
110 case nsIDataType::VTYPE_ASTRING:
111 rv = AString2Double(*u.mAStringValue, &aOutData->u.mDoubleValue);
112 if (NS_FAILED(rv)) {
113 return rv;
114 }
115 aOutData->mType = nsIDataType::VTYPE_DOUBLE;
116 return NS_OK;
117 case nsIDataType::VTYPE_UTF8STRING:
118 rv = AUTF8String2Double(*u.mUTF8StringValue, &aOutData->u.mDoubleValue);
119 if (NS_FAILED(rv)) {
120 return rv;
121 }
122 aOutData->mType = nsIDataType::VTYPE_DOUBLE;
123 return NS_OK;
124 case nsIDataType::VTYPE_CSTRING:
125 rv = ACString2Double(*u.mCStringValue, &aOutData->u.mDoubleValue);
126 if (NS_FAILED(rv)) {
127 return rv;
128 }
129 aOutData->mType = nsIDataType::VTYPE_DOUBLE;
130 return NS_OK;
131 case nsIDataType::VTYPE_WCHAR_STR:
132 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
133 rv = AString2Double(nsDependentString(u.wstr.mWStringValue),
134 &aOutData->u.mDoubleValue);
135 if (NS_FAILED(rv)) {
136 return rv;
137 }
138 aOutData->mType = nsIDataType::VTYPE_DOUBLE;
139 return NS_OK;
140
141 // This group fails...
142
143 case nsIDataType::VTYPE_VOID:
144 case nsIDataType::VTYPE_ID:
145 case nsIDataType::VTYPE_INTERFACE:
146 case nsIDataType::VTYPE_INTERFACE_IS:
147 case nsIDataType::VTYPE_ARRAY:
148 case nsIDataType::VTYPE_EMPTY_ARRAY:
149 case nsIDataType::VTYPE_EMPTY:
150 default:
151 return NS_ERROR_CANNOT_CONVERT_DATA;
152 }
153 }
154
155 /***************************************************************************/
156 // Array helpers...
157
FreeArray()158 void nsDiscriminatedUnion::FreeArray() {
159 NS_ASSERTION(mType == nsIDataType::VTYPE_ARRAY, "bad FreeArray call");
160 NS_ASSERTION(u.array.mArrayValue, "bad array");
161 NS_ASSERTION(u.array.mArrayCount, "bad array count");
162
163 #define CASE__FREE_ARRAY_PTR(type_, ctype_) \
164 case nsIDataType::type_: { \
165 ctype_** p = (ctype_**)u.array.mArrayValue; \
166 for (uint32_t i = u.array.mArrayCount; i > 0; p++, i--) \
167 if (*p) free((char*)*p); \
168 break; \
169 }
170
171 #define CASE__FREE_ARRAY_IFACE(type_, ctype_) \
172 case nsIDataType::type_: { \
173 ctype_** p = (ctype_**)u.array.mArrayValue; \
174 for (uint32_t i = u.array.mArrayCount; i > 0; p++, i--) \
175 if (*p) (*p)->Release(); \
176 break; \
177 }
178
179 switch (u.array.mArrayType) {
180 case nsIDataType::VTYPE_INT8:
181 case nsIDataType::VTYPE_INT16:
182 case nsIDataType::VTYPE_INT32:
183 case nsIDataType::VTYPE_INT64:
184 case nsIDataType::VTYPE_UINT8:
185 case nsIDataType::VTYPE_UINT16:
186 case nsIDataType::VTYPE_UINT32:
187 case nsIDataType::VTYPE_UINT64:
188 case nsIDataType::VTYPE_FLOAT:
189 case nsIDataType::VTYPE_DOUBLE:
190 case nsIDataType::VTYPE_BOOL:
191 case nsIDataType::VTYPE_CHAR:
192 case nsIDataType::VTYPE_WCHAR:
193 break;
194
195 // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
196 CASE__FREE_ARRAY_PTR(VTYPE_ID, nsID)
197 CASE__FREE_ARRAY_PTR(VTYPE_CHAR_STR, char)
198 CASE__FREE_ARRAY_PTR(VTYPE_WCHAR_STR, char16_t)
199 CASE__FREE_ARRAY_IFACE(VTYPE_INTERFACE, nsISupports)
200 CASE__FREE_ARRAY_IFACE(VTYPE_INTERFACE_IS, nsISupports)
201
202 // The rest are illegal.
203 case nsIDataType::VTYPE_VOID:
204 case nsIDataType::VTYPE_ASTRING:
205 case nsIDataType::VTYPE_UTF8STRING:
206 case nsIDataType::VTYPE_CSTRING:
207 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
208 case nsIDataType::VTYPE_STRING_SIZE_IS:
209 case nsIDataType::VTYPE_ARRAY:
210 case nsIDataType::VTYPE_EMPTY_ARRAY:
211 case nsIDataType::VTYPE_EMPTY:
212 default:
213 NS_ERROR("bad type in array!");
214 break;
215 }
216
217 // Free the array memory.
218 free((char*)u.array.mArrayValue);
219
220 #undef CASE__FREE_ARRAY_PTR
221 #undef CASE__FREE_ARRAY_IFACE
222 }
223
CloneArray(uint16_t aInType,const nsIID * aInIID,uint32_t aInCount,void * aInValue,uint16_t * aOutType,nsIID * aOutIID,uint32_t * aOutCount,void ** aOutValue)224 static nsresult CloneArray(uint16_t aInType, const nsIID* aInIID,
225 uint32_t aInCount, void* aInValue,
226 uint16_t* aOutType, nsIID* aOutIID,
227 uint32_t* aOutCount, void** aOutValue) {
228 NS_ASSERTION(aInCount, "bad param");
229 NS_ASSERTION(aInValue, "bad param");
230 NS_ASSERTION(aOutType, "bad param");
231 NS_ASSERTION(aOutCount, "bad param");
232 NS_ASSERTION(aOutValue, "bad param");
233
234 uint32_t i;
235
236 // First we figure out the size of the elements for the new u.array.
237
238 size_t elementSize;
239 size_t allocSize;
240
241 switch (aInType) {
242 case nsIDataType::VTYPE_INT8:
243 elementSize = sizeof(int8_t);
244 break;
245 case nsIDataType::VTYPE_INT16:
246 elementSize = sizeof(int16_t);
247 break;
248 case nsIDataType::VTYPE_INT32:
249 elementSize = sizeof(int32_t);
250 break;
251 case nsIDataType::VTYPE_INT64:
252 elementSize = sizeof(int64_t);
253 break;
254 case nsIDataType::VTYPE_UINT8:
255 elementSize = sizeof(uint8_t);
256 break;
257 case nsIDataType::VTYPE_UINT16:
258 elementSize = sizeof(uint16_t);
259 break;
260 case nsIDataType::VTYPE_UINT32:
261 elementSize = sizeof(uint32_t);
262 break;
263 case nsIDataType::VTYPE_UINT64:
264 elementSize = sizeof(uint64_t);
265 break;
266 case nsIDataType::VTYPE_FLOAT:
267 elementSize = sizeof(float);
268 break;
269 case nsIDataType::VTYPE_DOUBLE:
270 elementSize = sizeof(double);
271 break;
272 case nsIDataType::VTYPE_BOOL:
273 elementSize = sizeof(bool);
274 break;
275 case nsIDataType::VTYPE_CHAR:
276 elementSize = sizeof(char);
277 break;
278 case nsIDataType::VTYPE_WCHAR:
279 elementSize = sizeof(char16_t);
280 break;
281
282 // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
283 case nsIDataType::VTYPE_ID:
284 case nsIDataType::VTYPE_CHAR_STR:
285 case nsIDataType::VTYPE_WCHAR_STR:
286 case nsIDataType::VTYPE_INTERFACE:
287 case nsIDataType::VTYPE_INTERFACE_IS:
288 elementSize = sizeof(void*);
289 break;
290
291 // The rest are illegal.
292 case nsIDataType::VTYPE_ASTRING:
293 case nsIDataType::VTYPE_UTF8STRING:
294 case nsIDataType::VTYPE_CSTRING:
295 case nsIDataType::VTYPE_STRING_SIZE_IS:
296 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
297 case nsIDataType::VTYPE_VOID:
298 case nsIDataType::VTYPE_ARRAY:
299 case nsIDataType::VTYPE_EMPTY_ARRAY:
300 case nsIDataType::VTYPE_EMPTY:
301 default:
302 NS_ERROR("bad type in array!");
303 return NS_ERROR_CANNOT_CONVERT_DATA;
304 }
305
306 // Alloc the u.array.
307
308 allocSize = aInCount * elementSize;
309 *aOutValue = moz_xmalloc(allocSize);
310
311 // Clone the elements.
312
313 switch (aInType) {
314 case nsIDataType::VTYPE_INT8:
315 case nsIDataType::VTYPE_INT16:
316 case nsIDataType::VTYPE_INT32:
317 case nsIDataType::VTYPE_INT64:
318 case nsIDataType::VTYPE_UINT8:
319 case nsIDataType::VTYPE_UINT16:
320 case nsIDataType::VTYPE_UINT32:
321 case nsIDataType::VTYPE_UINT64:
322 case nsIDataType::VTYPE_FLOAT:
323 case nsIDataType::VTYPE_DOUBLE:
324 case nsIDataType::VTYPE_BOOL:
325 case nsIDataType::VTYPE_CHAR:
326 case nsIDataType::VTYPE_WCHAR:
327 memcpy(*aOutValue, aInValue, allocSize);
328 break;
329
330 case nsIDataType::VTYPE_INTERFACE_IS:
331 if (aOutIID) {
332 *aOutIID = *aInIID;
333 }
334 [[fallthrough]];
335
336 case nsIDataType::VTYPE_INTERFACE: {
337 memcpy(*aOutValue, aInValue, allocSize);
338
339 nsISupports** p = (nsISupports**)*aOutValue;
340 for (i = aInCount; i > 0; ++p, --i)
341 if (*p) {
342 (*p)->AddRef();
343 }
344 break;
345 }
346
347 // XXX We ASSUME that "array of nsID" means "array of pointers to nsID".
348 case nsIDataType::VTYPE_ID: {
349 nsID** inp = (nsID**)aInValue;
350 nsID** outp = (nsID**)*aOutValue;
351 for (i = aInCount; i > 0; --i) {
352 nsID* idp = *(inp++);
353 if (idp) {
354 *(outp++) = idp->Clone();
355 } else {
356 *(outp++) = nullptr;
357 }
358 }
359 break;
360 }
361
362 case nsIDataType::VTYPE_CHAR_STR: {
363 char** inp = (char**)aInValue;
364 char** outp = (char**)*aOutValue;
365 for (i = aInCount; i > 0; i--) {
366 char* str = *(inp++);
367 if (str) {
368 *(outp++) = moz_xstrdup(str);
369 } else {
370 *(outp++) = nullptr;
371 }
372 }
373 break;
374 }
375
376 case nsIDataType::VTYPE_WCHAR_STR: {
377 char16_t** inp = (char16_t**)aInValue;
378 char16_t** outp = (char16_t**)*aOutValue;
379 for (i = aInCount; i > 0; i--) {
380 char16_t* str = *(inp++);
381 if (str) {
382 *(outp++) = NS_xstrdup(str);
383 } else {
384 *(outp++) = nullptr;
385 }
386 }
387 break;
388 }
389
390 // The rest are illegal.
391 case nsIDataType::VTYPE_VOID:
392 case nsIDataType::VTYPE_ARRAY:
393 case nsIDataType::VTYPE_EMPTY_ARRAY:
394 case nsIDataType::VTYPE_EMPTY:
395 case nsIDataType::VTYPE_ASTRING:
396 case nsIDataType::VTYPE_UTF8STRING:
397 case nsIDataType::VTYPE_CSTRING:
398 case nsIDataType::VTYPE_STRING_SIZE_IS:
399 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
400 default:
401 NS_ERROR("bad type in array!");
402 return NS_ERROR_CANNOT_CONVERT_DATA;
403 }
404
405 *aOutType = aInType;
406 *aOutCount = aInCount;
407 return NS_OK;
408 }
409
410 /***************************************************************************/
411
412 #define TRIVIAL_DATA_CONVERTER(type_, member_, retval_) \
413 if (mType == nsIDataType::type_) { \
414 *retval_ = u.member_; \
415 return NS_OK; \
416 }
417
418 #define NUMERIC_CONVERSION_METHOD_BEGIN(type_, Ctype_, name_) \
419 nsresult nsDiscriminatedUnion::ConvertTo##name_(Ctype_* aResult) const { \
420 TRIVIAL_DATA_CONVERTER(type_, m##name_##Value, aResult) \
421 nsDiscriminatedUnion tempData; \
422 nsresult rv = ToManageableNumber(&tempData); \
423 /* */ \
424 /* NOTE: rv may indicate a success code that we want to preserve */ \
425 /* For the final return. So all the return cases below should return */ \
426 /* this rv when indicating success. */ \
427 /* */ \
428 if (NS_FAILED(rv)) return rv; \
429 switch (tempData.mType) {
430 #define CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(Ctype_) \
431 case nsIDataType::VTYPE_INT32: \
432 *aResult = (Ctype_)tempData.u.mInt32Value; \
433 return rv;
434
435 #define CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(Ctype_, min_, max_) \
436 case nsIDataType::VTYPE_INT32: { \
437 int32_t value = tempData.u.mInt32Value; \
438 if (value < min_ || value > max_) \
439 return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
440 *aResult = (Ctype_)value; \
441 return rv; \
442 }
443
444 #define CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(Ctype_) \
445 case nsIDataType::VTYPE_UINT32: \
446 *aResult = (Ctype_)tempData.u.mUint32Value; \
447 return rv;
448
449 #define CASE__NUMERIC_CONVERSION_UINT32_MAX(Ctype_, max_) \
450 case nsIDataType::VTYPE_UINT32: { \
451 uint32_t value = tempData.u.mUint32Value; \
452 if (value > max_) return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
453 *aResult = (Ctype_)value; \
454 return rv; \
455 }
456
457 #define CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(Ctype_) \
458 case nsIDataType::VTYPE_DOUBLE: \
459 *aResult = (Ctype_)tempData.u.mDoubleValue; \
460 return rv;
461
462 #define CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX(Ctype_, min_, max_) \
463 case nsIDataType::VTYPE_DOUBLE: { \
464 double value = tempData.u.mDoubleValue; \
465 if (value < min_ || value > max_) \
466 return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
467 *aResult = (Ctype_)value; \
468 return rv; \
469 }
470
471 #define CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(Ctype_, min_, max_) \
472 case nsIDataType::VTYPE_DOUBLE: { \
473 double value = tempData.u.mDoubleValue; \
474 if (value < min_ || value > max_) \
475 return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
476 *aResult = (Ctype_)value; \
477 return (0.0 == fmod(value, 1.0)) ? rv \
478 : NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA; \
479 }
480
481 #define CASES__NUMERIC_CONVERSION_NORMAL(Ctype_, min_, max_) \
482 CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(Ctype_, min_, max_) \
483 CASE__NUMERIC_CONVERSION_UINT32_MAX(Ctype_, max_) \
484 CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(Ctype_, min_, max_)
485
486 #define NUMERIC_CONVERSION_METHOD_END \
487 default: \
488 NS_ERROR("bad type returned from ToManageableNumber"); \
489 return NS_ERROR_CANNOT_CONVERT_DATA; \
490 } \
491 }
492
493 #define NUMERIC_CONVERSION_METHOD_NORMAL(type_, Ctype_, name_, min_, max_) \
494 NUMERIC_CONVERSION_METHOD_BEGIN(type_, Ctype_, name_) \
495 CASES__NUMERIC_CONVERSION_NORMAL(Ctype_, min_, max_) \
496 NUMERIC_CONVERSION_METHOD_END
497
498 /***************************************************************************/
499 // These expand into full public methods...
500
501 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_INT8, uint8_t, Int8, (-127 - 1), 127)
502 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_INT16, int16_t, Int16, (-32767 - 1),
503 32767)
504
NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_INT32,int32_t,Int32)505 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_INT32, int32_t, Int32)
506 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(int32_t)
507 CASE__NUMERIC_CONVERSION_UINT32_MAX(int32_t, 2147483647)
508 CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(int32_t, (-2147483647 - 1),
509 2147483647)
510 NUMERIC_CONVERSION_METHOD_END
511
512 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_UINT8, uint8_t, Uint8, 0, 255)
513 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_UINT16, uint16_t, Uint16, 0, 65535)
514
515 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_UINT32, uint32_t, Uint32)
516 CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(uint32_t, 0, 2147483647)
517 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(uint32_t)
518 CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(uint32_t, 0, 4294967295U)
519 NUMERIC_CONVERSION_METHOD_END
520
521 // XXX toFloat convertions need to be fixed!
522 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_FLOAT, float, Float)
523 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(float)
524 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(float)
525 CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(float)
526 NUMERIC_CONVERSION_METHOD_END
527
528 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_DOUBLE, double, Double)
529 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(double)
530 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(double)
531 CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(double)
532 NUMERIC_CONVERSION_METHOD_END
533
534 // XXX toChar convertions need to be fixed!
535 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_CHAR, char, Char)
536 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(char)
537 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(char)
538 CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(char)
539 NUMERIC_CONVERSION_METHOD_END
540
541 // XXX toWChar convertions need to be fixed!
542 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_WCHAR, char16_t, WChar)
543 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(char16_t)
544 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(char16_t)
545 CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(char16_t)
546 NUMERIC_CONVERSION_METHOD_END
547
548 #undef NUMERIC_CONVERSION_METHOD_BEGIN
549 #undef CASE__NUMERIC_CONVERSION_INT32_JUST_CAST
550 #undef CASE__NUMERIC_CONVERSION_INT32_MIN_MAX
551 #undef CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST
552 #undef CASE__NUMERIC_CONVERSION_UINT32_MIN_MAX
553 #undef CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST
554 #undef CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX
555 #undef CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT
556 #undef CASES__NUMERIC_CONVERSION_NORMAL
557 #undef NUMERIC_CONVERSION_METHOD_END
558 #undef NUMERIC_CONVERSION_METHOD_NORMAL
559
560 /***************************************************************************/
561
562 // Just leverage a numeric converter for bool (but restrict the values).
563 // XXX Is this really what we want to do?
564
565 nsresult nsDiscriminatedUnion::ConvertToBool(bool* aResult) const {
566 TRIVIAL_DATA_CONVERTER(VTYPE_BOOL, mBoolValue, aResult)
567
568 double val;
569 nsresult rv = ConvertToDouble(&val);
570 if (NS_FAILED(rv)) {
571 return rv;
572 }
573 *aResult = 0.0 != val;
574 return rv;
575 }
576
577 /***************************************************************************/
578
ConvertToInt64(int64_t * aResult) const579 nsresult nsDiscriminatedUnion::ConvertToInt64(int64_t* aResult) const {
580 TRIVIAL_DATA_CONVERTER(VTYPE_INT64, mInt64Value, aResult)
581 TRIVIAL_DATA_CONVERTER(VTYPE_UINT64, mUint64Value, aResult)
582
583 nsDiscriminatedUnion tempData;
584 nsresult rv = ToManageableNumber(&tempData);
585 if (NS_FAILED(rv)) {
586 return rv;
587 }
588 switch (tempData.mType) {
589 case nsIDataType::VTYPE_INT32:
590 *aResult = tempData.u.mInt32Value;
591 return rv;
592 case nsIDataType::VTYPE_UINT32:
593 *aResult = tempData.u.mUint32Value;
594 return rv;
595 case nsIDataType::VTYPE_DOUBLE:
596 // XXX should check for data loss here!
597 *aResult = tempData.u.mDoubleValue;
598 return rv;
599 default:
600 NS_ERROR("bad type returned from ToManageableNumber");
601 return NS_ERROR_CANNOT_CONVERT_DATA;
602 }
603 }
604
ConvertToUint64(uint64_t * aResult) const605 nsresult nsDiscriminatedUnion::ConvertToUint64(uint64_t* aResult) const {
606 return ConvertToInt64((int64_t*)aResult);
607 }
608
609 /***************************************************************************/
610
String2ID(nsID * aPid) const611 bool nsDiscriminatedUnion::String2ID(nsID* aPid) const {
612 nsAutoString tempString;
613 nsAString* pString;
614
615 switch (mType) {
616 case nsIDataType::VTYPE_CHAR_STR:
617 case nsIDataType::VTYPE_STRING_SIZE_IS:
618 return aPid->Parse(u.str.mStringValue);
619 case nsIDataType::VTYPE_CSTRING:
620 return aPid->Parse(PromiseFlatCString(*u.mCStringValue).get());
621 case nsIDataType::VTYPE_UTF8STRING:
622 return aPid->Parse(PromiseFlatUTF8String(*u.mUTF8StringValue).get());
623 case nsIDataType::VTYPE_ASTRING:
624 pString = u.mAStringValue;
625 break;
626 case nsIDataType::VTYPE_WCHAR_STR:
627 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
628 tempString.Assign(u.wstr.mWStringValue);
629 pString = &tempString;
630 break;
631 default:
632 NS_ERROR("bad type in call to String2ID");
633 return false;
634 }
635
636 char* pChars = ToNewCString(*pString, mozilla::fallible);
637 if (!pChars) {
638 return false;
639 }
640 bool result = aPid->Parse(pChars);
641 free(pChars);
642 return result;
643 }
644
ConvertToID(nsID * aResult) const645 nsresult nsDiscriminatedUnion::ConvertToID(nsID* aResult) const {
646 nsID id;
647
648 switch (mType) {
649 case nsIDataType::VTYPE_ID:
650 *aResult = u.mIDValue;
651 return NS_OK;
652 case nsIDataType::VTYPE_INTERFACE:
653 *aResult = NS_GET_IID(nsISupports);
654 return NS_OK;
655 case nsIDataType::VTYPE_INTERFACE_IS:
656 *aResult = u.iface.mInterfaceID;
657 return NS_OK;
658 case nsIDataType::VTYPE_ASTRING:
659 case nsIDataType::VTYPE_UTF8STRING:
660 case nsIDataType::VTYPE_CSTRING:
661 case nsIDataType::VTYPE_CHAR_STR:
662 case nsIDataType::VTYPE_WCHAR_STR:
663 case nsIDataType::VTYPE_STRING_SIZE_IS:
664 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
665 if (!String2ID(&id)) {
666 return NS_ERROR_CANNOT_CONVERT_DATA;
667 }
668 *aResult = id;
669 return NS_OK;
670 default:
671 return NS_ERROR_CANNOT_CONVERT_DATA;
672 }
673 }
674
675 /***************************************************************************/
676
ToString(nsACString & aOutString) const677 nsresult nsDiscriminatedUnion::ToString(nsACString& aOutString) const {
678 mozilla::SmprintfPointer pptr;
679
680 switch (mType) {
681 // all the stuff we don't handle...
682 case nsIDataType::VTYPE_ASTRING:
683 case nsIDataType::VTYPE_UTF8STRING:
684 case nsIDataType::VTYPE_CSTRING:
685 case nsIDataType::VTYPE_CHAR_STR:
686 case nsIDataType::VTYPE_WCHAR_STR:
687 case nsIDataType::VTYPE_STRING_SIZE_IS:
688 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
689 case nsIDataType::VTYPE_WCHAR:
690 NS_ERROR("ToString being called for a string type - screwy logic!");
691 [[fallthrough]];
692
693 // XXX We might want stringified versions of these... ???
694
695 case nsIDataType::VTYPE_VOID:
696 case nsIDataType::VTYPE_EMPTY:
697 aOutString.SetIsVoid(true);
698 return NS_OK;
699
700 case nsIDataType::VTYPE_EMPTY_ARRAY:
701 case nsIDataType::VTYPE_ARRAY:
702 case nsIDataType::VTYPE_INTERFACE:
703 case nsIDataType::VTYPE_INTERFACE_IS:
704 default:
705 return NS_ERROR_CANNOT_CONVERT_DATA;
706
707 // nsID has its own text formatter.
708
709 case nsIDataType::VTYPE_ID: {
710 char* ptr = u.mIDValue.ToString();
711 if (!ptr) {
712 return NS_ERROR_OUT_OF_MEMORY;
713 }
714 aOutString.Assign(ptr);
715 free(ptr);
716 return NS_OK;
717 }
718
719 // Can't use Smprintf for floats, since it's locale-dependent
720 #define CASE__APPENDFLOAT_NUMBER(type_, member_) \
721 case nsIDataType::type_: { \
722 nsAutoCString str; \
723 str.AppendFloat(u.member_); \
724 aOutString.Assign(str); \
725 return NS_OK; \
726 }
727
728 CASE__APPENDFLOAT_NUMBER(VTYPE_FLOAT, mFloatValue)
729 CASE__APPENDFLOAT_NUMBER(VTYPE_DOUBLE, mDoubleValue)
730
731 #undef CASE__APPENDFLOAT_NUMBER
732
733 // the rest can be Smprintf'd and use common code.
734
735 #define CASE__SMPRINTF_NUMBER(type_, format_, cast_, member_) \
736 case nsIDataType::type_: \
737 static_assert(sizeof(cast_) >= sizeof(u.member_), \
738 "size of type should be at least as big as member"); \
739 pptr = mozilla::Smprintf(format_, (cast_)u.member_); \
740 break;
741
742 CASE__SMPRINTF_NUMBER(VTYPE_INT8, "%d", int, mInt8Value)
743 CASE__SMPRINTF_NUMBER(VTYPE_INT16, "%d", int, mInt16Value)
744 CASE__SMPRINTF_NUMBER(VTYPE_INT32, "%d", int, mInt32Value)
745 CASE__SMPRINTF_NUMBER(VTYPE_INT64, "%" PRId64, int64_t, mInt64Value)
746
747 CASE__SMPRINTF_NUMBER(VTYPE_UINT8, "%u", unsigned, mUint8Value)
748 CASE__SMPRINTF_NUMBER(VTYPE_UINT16, "%u", unsigned, mUint16Value)
749 CASE__SMPRINTF_NUMBER(VTYPE_UINT32, "%u", unsigned, mUint32Value)
750 CASE__SMPRINTF_NUMBER(VTYPE_UINT64, "%" PRIu64, int64_t, mUint64Value)
751
752 // XXX Would we rather print "true" / "false" ?
753 CASE__SMPRINTF_NUMBER(VTYPE_BOOL, "%d", int, mBoolValue)
754
755 CASE__SMPRINTF_NUMBER(VTYPE_CHAR, "%c", char, mCharValue)
756
757 #undef CASE__SMPRINTF_NUMBER
758 }
759
760 if (!pptr) {
761 return NS_ERROR_OUT_OF_MEMORY;
762 }
763 aOutString.Assign(pptr.get());
764 return NS_OK;
765 }
766
ConvertToAString(nsAString & aResult) const767 nsresult nsDiscriminatedUnion::ConvertToAString(nsAString& aResult) const {
768 switch (mType) {
769 case nsIDataType::VTYPE_ASTRING:
770 aResult.Assign(*u.mAStringValue);
771 return NS_OK;
772 case nsIDataType::VTYPE_CSTRING:
773 CopyASCIItoUTF16(*u.mCStringValue, aResult);
774 return NS_OK;
775 case nsIDataType::VTYPE_UTF8STRING:
776 CopyUTF8toUTF16(*u.mUTF8StringValue, aResult);
777 return NS_OK;
778 case nsIDataType::VTYPE_CHAR_STR:
779 CopyASCIItoUTF16(mozilla::MakeStringSpan(u.str.mStringValue), aResult);
780 return NS_OK;
781 case nsIDataType::VTYPE_WCHAR_STR:
782 aResult.Assign(u.wstr.mWStringValue);
783 return NS_OK;
784 case nsIDataType::VTYPE_STRING_SIZE_IS:
785 CopyASCIItoUTF16(
786 nsDependentCString(u.str.mStringValue, u.str.mStringLength), aResult);
787 return NS_OK;
788 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
789 aResult.Assign(u.wstr.mWStringValue, u.wstr.mWStringLength);
790 return NS_OK;
791 case nsIDataType::VTYPE_WCHAR:
792 aResult.Assign(u.mWCharValue);
793 return NS_OK;
794 default: {
795 nsAutoCString tempCString;
796 nsresult rv = ToString(tempCString);
797 if (NS_FAILED(rv)) {
798 return rv;
799 }
800 CopyASCIItoUTF16(tempCString, aResult);
801 return NS_OK;
802 }
803 }
804 }
805
ConvertToACString(nsACString & aResult) const806 nsresult nsDiscriminatedUnion::ConvertToACString(nsACString& aResult) const {
807 switch (mType) {
808 case nsIDataType::VTYPE_ASTRING:
809 LossyCopyUTF16toASCII(*u.mAStringValue, aResult);
810 return NS_OK;
811 case nsIDataType::VTYPE_CSTRING:
812 aResult.Assign(*u.mCStringValue);
813 return NS_OK;
814 case nsIDataType::VTYPE_UTF8STRING:
815 // XXX This is an extra copy that should be avoided
816 // once Jag lands support for UTF8String and associated
817 // conversion methods.
818 LossyCopyUTF16toASCII(NS_ConvertUTF8toUTF16(*u.mUTF8StringValue),
819 aResult);
820 return NS_OK;
821 case nsIDataType::VTYPE_CHAR_STR:
822 aResult.Assign(*u.str.mStringValue);
823 return NS_OK;
824 case nsIDataType::VTYPE_WCHAR_STR:
825 LossyCopyUTF16toASCII(nsDependentString(u.wstr.mWStringValue), aResult);
826 return NS_OK;
827 case nsIDataType::VTYPE_STRING_SIZE_IS:
828 aResult.Assign(u.str.mStringValue, u.str.mStringLength);
829 return NS_OK;
830 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
831 LossyCopyUTF16toASCII(
832 nsDependentString(u.wstr.mWStringValue, u.wstr.mWStringLength),
833 aResult);
834 return NS_OK;
835 case nsIDataType::VTYPE_WCHAR: {
836 const char16_t* str = &u.mWCharValue;
837 LossyCopyUTF16toASCII(Substring(str, 1), aResult);
838 return NS_OK;
839 }
840 default:
841 return ToString(aResult);
842 }
843 }
844
ConvertToAUTF8String(nsAUTF8String & aResult) const845 nsresult nsDiscriminatedUnion::ConvertToAUTF8String(
846 nsAUTF8String& aResult) const {
847 switch (mType) {
848 case nsIDataType::VTYPE_ASTRING:
849 CopyUTF16toUTF8(*u.mAStringValue, aResult);
850 return NS_OK;
851 case nsIDataType::VTYPE_CSTRING:
852 // XXX Extra copy, can be removed if we're sure CSTRING can
853 // only contain ASCII.
854 CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(*u.mCStringValue), aResult);
855 return NS_OK;
856 case nsIDataType::VTYPE_UTF8STRING:
857 aResult.Assign(*u.mUTF8StringValue);
858 return NS_OK;
859 case nsIDataType::VTYPE_CHAR_STR:
860 // XXX Extra copy, can be removed if we're sure CHAR_STR can
861 // only contain ASCII.
862 CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(u.str.mStringValue), aResult);
863 return NS_OK;
864 case nsIDataType::VTYPE_WCHAR_STR:
865 CopyUTF16toUTF8(mozilla::MakeStringSpan(u.wstr.mWStringValue), aResult);
866 return NS_OK;
867 case nsIDataType::VTYPE_STRING_SIZE_IS:
868 // XXX Extra copy, can be removed if we're sure CHAR_STR can
869 // only contain ASCII.
870 CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(nsDependentCString(
871 u.str.mStringValue, u.str.mStringLength)),
872 aResult);
873 return NS_OK;
874 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
875 CopyUTF16toUTF8(
876 nsDependentString(u.wstr.mWStringValue, u.wstr.mWStringLength),
877 aResult);
878 return NS_OK;
879 case nsIDataType::VTYPE_WCHAR: {
880 const char16_t* str = &u.mWCharValue;
881 CopyUTF16toUTF8(Substring(str, 1), aResult);
882 return NS_OK;
883 }
884 default: {
885 nsAutoCString tempCString;
886 nsresult rv = ToString(tempCString);
887 if (NS_FAILED(rv)) {
888 return rv;
889 }
890 // XXX Extra copy, can be removed if we're sure tempCString can
891 // only contain ASCII.
892 CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(tempCString), aResult);
893 return NS_OK;
894 }
895 }
896 }
897
ConvertToString(char ** aResult) const898 nsresult nsDiscriminatedUnion::ConvertToString(char** aResult) const {
899 uint32_t ignored;
900 return ConvertToStringWithSize(&ignored, aResult);
901 }
902
ConvertToWString(char16_t ** aResult) const903 nsresult nsDiscriminatedUnion::ConvertToWString(char16_t** aResult) const {
904 uint32_t ignored;
905 return ConvertToWStringWithSize(&ignored, aResult);
906 }
907
ConvertToStringWithSize(uint32_t * aSize,char ** aStr) const908 nsresult nsDiscriminatedUnion::ConvertToStringWithSize(uint32_t* aSize,
909 char** aStr) const {
910 nsAutoString tempString;
911 nsAutoCString tempCString;
912 nsresult rv;
913
914 switch (mType) {
915 case nsIDataType::VTYPE_ASTRING:
916 *aSize = u.mAStringValue->Length();
917 *aStr = ToNewCString(*u.mAStringValue);
918 break;
919 case nsIDataType::VTYPE_CSTRING:
920 *aSize = u.mCStringValue->Length();
921 *aStr = ToNewCString(*u.mCStringValue);
922 break;
923 case nsIDataType::VTYPE_UTF8STRING: {
924 // XXX This is doing 1 extra copy. Need to fix this
925 // when Jag lands UTF8String
926 // we want:
927 // *aSize = *mUTF8StringValue->Length();
928 // *aStr = ToNewCString(*mUTF8StringValue);
929 // But this will have to do for now.
930 const NS_ConvertUTF8toUTF16 tempString16(*u.mUTF8StringValue);
931 *aSize = tempString16.Length();
932 *aStr = ToNewCString(tempString16);
933 break;
934 }
935 case nsIDataType::VTYPE_CHAR_STR: {
936 nsDependentCString cString(u.str.mStringValue);
937 *aSize = cString.Length();
938 *aStr = ToNewCString(cString);
939 break;
940 }
941 case nsIDataType::VTYPE_WCHAR_STR: {
942 nsDependentString string(u.wstr.mWStringValue);
943 *aSize = string.Length();
944 *aStr = ToNewCString(string);
945 break;
946 }
947 case nsIDataType::VTYPE_STRING_SIZE_IS: {
948 nsDependentCString cString(u.str.mStringValue, u.str.mStringLength);
949 *aSize = cString.Length();
950 *aStr = ToNewCString(cString);
951 break;
952 }
953 case nsIDataType::VTYPE_WSTRING_SIZE_IS: {
954 nsDependentString string(u.wstr.mWStringValue, u.wstr.mWStringLength);
955 *aSize = string.Length();
956 *aStr = ToNewCString(string);
957 break;
958 }
959 case nsIDataType::VTYPE_WCHAR:
960 tempString.Assign(u.mWCharValue);
961 *aSize = tempString.Length();
962 *aStr = ToNewCString(tempString);
963 break;
964 default:
965 rv = ToString(tempCString);
966 if (NS_FAILED(rv)) {
967 return rv;
968 }
969 *aSize = tempCString.Length();
970 *aStr = ToNewCString(tempCString);
971 break;
972 }
973
974 return *aStr ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
975 }
ConvertToWStringWithSize(uint32_t * aSize,char16_t ** aStr) const976 nsresult nsDiscriminatedUnion::ConvertToWStringWithSize(uint32_t* aSize,
977 char16_t** aStr) const {
978 nsAutoString tempString;
979 nsAutoCString tempCString;
980 nsresult rv;
981
982 switch (mType) {
983 case nsIDataType::VTYPE_ASTRING:
984 *aSize = u.mAStringValue->Length();
985 *aStr = ToNewUnicode(*u.mAStringValue);
986 break;
987 case nsIDataType::VTYPE_CSTRING:
988 *aSize = u.mCStringValue->Length();
989 *aStr = ToNewUnicode(*u.mCStringValue);
990 break;
991 case nsIDataType::VTYPE_UTF8STRING: {
992 *aStr = UTF8ToNewUnicode(*u.mUTF8StringValue, aSize);
993 break;
994 }
995 case nsIDataType::VTYPE_CHAR_STR: {
996 nsDependentCString cString(u.str.mStringValue);
997 *aSize = cString.Length();
998 *aStr = ToNewUnicode(cString);
999 break;
1000 }
1001 case nsIDataType::VTYPE_WCHAR_STR: {
1002 nsDependentString string(u.wstr.mWStringValue);
1003 *aSize = string.Length();
1004 *aStr = ToNewUnicode(string);
1005 break;
1006 }
1007 case nsIDataType::VTYPE_STRING_SIZE_IS: {
1008 nsDependentCString cString(u.str.mStringValue, u.str.mStringLength);
1009 *aSize = cString.Length();
1010 *aStr = ToNewUnicode(cString);
1011 break;
1012 }
1013 case nsIDataType::VTYPE_WSTRING_SIZE_IS: {
1014 nsDependentString string(u.wstr.mWStringValue, u.wstr.mWStringLength);
1015 *aSize = string.Length();
1016 *aStr = ToNewUnicode(string);
1017 break;
1018 }
1019 case nsIDataType::VTYPE_WCHAR:
1020 tempString.Assign(u.mWCharValue);
1021 *aSize = tempString.Length();
1022 *aStr = ToNewUnicode(tempString);
1023 break;
1024 default:
1025 rv = ToString(tempCString);
1026 if (NS_FAILED(rv)) {
1027 return rv;
1028 }
1029 *aSize = tempCString.Length();
1030 *aStr = ToNewUnicode(tempCString);
1031 break;
1032 }
1033
1034 return *aStr ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
1035 }
1036
ConvertToISupports(nsISupports ** aResult) const1037 nsresult nsDiscriminatedUnion::ConvertToISupports(nsISupports** aResult) const {
1038 switch (mType) {
1039 case nsIDataType::VTYPE_INTERFACE:
1040 case nsIDataType::VTYPE_INTERFACE_IS:
1041 if (u.iface.mInterfaceValue) {
1042 return u.iface.mInterfaceValue->QueryInterface(NS_GET_IID(nsISupports),
1043 (void**)aResult);
1044 } else {
1045 *aResult = nullptr;
1046 return NS_OK;
1047 }
1048 default:
1049 return NS_ERROR_CANNOT_CONVERT_DATA;
1050 }
1051 }
1052
ConvertToInterface(nsIID ** aIID,void ** aInterface) const1053 nsresult nsDiscriminatedUnion::ConvertToInterface(nsIID** aIID,
1054 void** aInterface) const {
1055 const nsIID* piid;
1056
1057 switch (mType) {
1058 case nsIDataType::VTYPE_INTERFACE:
1059 piid = &NS_GET_IID(nsISupports);
1060 break;
1061 case nsIDataType::VTYPE_INTERFACE_IS:
1062 piid = &u.iface.mInterfaceID;
1063 break;
1064 default:
1065 return NS_ERROR_CANNOT_CONVERT_DATA;
1066 }
1067
1068 *aIID = piid->Clone();
1069
1070 if (u.iface.mInterfaceValue) {
1071 return u.iface.mInterfaceValue->QueryInterface(*piid, aInterface);
1072 }
1073
1074 *aInterface = nullptr;
1075 return NS_OK;
1076 }
1077
ConvertToArray(uint16_t * aType,nsIID * aIID,uint32_t * aCount,void ** aPtr) const1078 nsresult nsDiscriminatedUnion::ConvertToArray(uint16_t* aType, nsIID* aIID,
1079 uint32_t* aCount,
1080 void** aPtr) const {
1081 // XXX perhaps we'd like to add support for converting each of the various
1082 // types into an array containing one element of that type. We can leverage
1083 // CloneArray to do this if we want to support this.
1084
1085 if (mType == nsIDataType::VTYPE_ARRAY) {
1086 return CloneArray(u.array.mArrayType, &u.array.mArrayInterfaceID,
1087 u.array.mArrayCount, u.array.mArrayValue, aType, aIID,
1088 aCount, aPtr);
1089 }
1090 return NS_ERROR_CANNOT_CONVERT_DATA;
1091 }
1092
1093 /***************************************************************************/
1094 // static setter functions...
1095
1096 #define DATA_SETTER_PROLOGUE Cleanup()
1097
1098 #define DATA_SETTER_EPILOGUE(type_) mType = nsIDataType::type_;
1099
1100 #define DATA_SETTER(type_, member_, value_) \
1101 DATA_SETTER_PROLOGUE; \
1102 u.member_ = value_; \
1103 DATA_SETTER_EPILOGUE(type_)
1104
1105 #define DATA_SETTER_WITH_CAST(type_, member_, cast_, value_) \
1106 DATA_SETTER_PROLOGUE; \
1107 u.member_ = cast_ value_; \
1108 DATA_SETTER_EPILOGUE(type_)
1109
1110 /********************************************/
1111
1112 #define CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_) {
1113 #define CASE__SET_FROM_VARIANT_VTYPE__GETTER(member_, name_) \
1114 rv = aValue->GetAs##name_(&(u.member_));
1115
1116 #define CASE__SET_FROM_VARIANT_VTYPE__GETTER_CAST(cast_, member_, name_) \
1117 rv = aValue->GetAs##name_(cast_ & (u.member_));
1118
1119 #define CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_) \
1120 if (NS_SUCCEEDED(rv)) { \
1121 mType = nsIDataType::type_; \
1122 } \
1123 break; \
1124 }
1125
1126 #define CASE__SET_FROM_VARIANT_TYPE(type_, member_, name_) \
1127 case nsIDataType::type_: \
1128 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_) \
1129 CASE__SET_FROM_VARIANT_VTYPE__GETTER(member_, name_) \
1130 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)
1131
1132 #define CASE__SET_FROM_VARIANT_VTYPE_CAST(type_, cast_, member_, name_) \
1133 case nsIDataType::type_: \
1134 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_) \
1135 CASE__SET_FROM_VARIANT_VTYPE__GETTER_CAST(cast_, member_, name_) \
1136 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)
1137
SetFromVariant(nsIVariant * aValue)1138 nsresult nsDiscriminatedUnion::SetFromVariant(nsIVariant* aValue) {
1139 nsresult rv = NS_OK;
1140
1141 Cleanup();
1142
1143 uint16_t type = aValue->GetDataType();
1144
1145 switch (type) {
1146 CASE__SET_FROM_VARIANT_VTYPE_CAST(VTYPE_INT8, (uint8_t*), mInt8Value, Int8)
1147 CASE__SET_FROM_VARIANT_TYPE(VTYPE_INT16, mInt16Value, Int16)
1148 CASE__SET_FROM_VARIANT_TYPE(VTYPE_INT32, mInt32Value, Int32)
1149 CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT8, mUint8Value, Uint8)
1150 CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT16, mUint16Value, Uint16)
1151 CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT32, mUint32Value, Uint32)
1152 CASE__SET_FROM_VARIANT_TYPE(VTYPE_FLOAT, mFloatValue, Float)
1153 CASE__SET_FROM_VARIANT_TYPE(VTYPE_DOUBLE, mDoubleValue, Double)
1154 CASE__SET_FROM_VARIANT_TYPE(VTYPE_BOOL, mBoolValue, Bool)
1155 CASE__SET_FROM_VARIANT_TYPE(VTYPE_CHAR, mCharValue, Char)
1156 CASE__SET_FROM_VARIANT_TYPE(VTYPE_WCHAR, mWCharValue, WChar)
1157 CASE__SET_FROM_VARIANT_TYPE(VTYPE_ID, mIDValue, ID)
1158
1159 case nsIDataType::VTYPE_ASTRING:
1160 case nsIDataType::VTYPE_WCHAR_STR:
1161 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
1162 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_ASTRING);
1163 u.mAStringValue = new nsString();
1164
1165 rv = aValue->GetAsAString(*u.mAStringValue);
1166 if (NS_FAILED(rv)) {
1167 delete u.mAStringValue;
1168 }
1169 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_ASTRING)
1170
1171 case nsIDataType::VTYPE_CSTRING:
1172 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_CSTRING);
1173 u.mCStringValue = new nsCString();
1174
1175 rv = aValue->GetAsACString(*u.mCStringValue);
1176 if (NS_FAILED(rv)) {
1177 delete u.mCStringValue;
1178 }
1179 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_CSTRING)
1180
1181 case nsIDataType::VTYPE_UTF8STRING:
1182 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_UTF8STRING);
1183 u.mUTF8StringValue = new nsUTF8String();
1184
1185 rv = aValue->GetAsAUTF8String(*u.mUTF8StringValue);
1186 if (NS_FAILED(rv)) {
1187 delete u.mUTF8StringValue;
1188 }
1189 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_UTF8STRING)
1190
1191 case nsIDataType::VTYPE_CHAR_STR:
1192 case nsIDataType::VTYPE_STRING_SIZE_IS:
1193 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_STRING_SIZE_IS);
1194 rv = aValue->GetAsStringWithSize(&u.str.mStringLength,
1195 &u.str.mStringValue);
1196 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_STRING_SIZE_IS)
1197
1198 case nsIDataType::VTYPE_INTERFACE:
1199 case nsIDataType::VTYPE_INTERFACE_IS:
1200 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_INTERFACE_IS);
1201 // XXX This iid handling is ugly!
1202 nsIID* iid;
1203 rv = aValue->GetAsInterface(&iid, (void**)&u.iface.mInterfaceValue);
1204 if (NS_SUCCEEDED(rv)) {
1205 u.iface.mInterfaceID = *iid;
1206 free((char*)iid);
1207 }
1208 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_INTERFACE_IS)
1209
1210 case nsIDataType::VTYPE_ARRAY:
1211 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_ARRAY);
1212 rv = aValue->GetAsArray(&u.array.mArrayType, &u.array.mArrayInterfaceID,
1213 &u.array.mArrayCount, &u.array.mArrayValue);
1214 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_ARRAY)
1215
1216 case nsIDataType::VTYPE_VOID:
1217 SetToVoid();
1218 rv = NS_OK;
1219 break;
1220 case nsIDataType::VTYPE_EMPTY_ARRAY:
1221 SetToEmptyArray();
1222 rv = NS_OK;
1223 break;
1224 case nsIDataType::VTYPE_EMPTY:
1225 SetToEmpty();
1226 rv = NS_OK;
1227 break;
1228 default:
1229 NS_ERROR("bad type in variant!");
1230 rv = NS_ERROR_FAILURE;
1231 break;
1232 }
1233 return rv;
1234 }
1235
SetFromInt8(uint8_t aValue)1236 void nsDiscriminatedUnion::SetFromInt8(uint8_t aValue) {
1237 DATA_SETTER_WITH_CAST(VTYPE_INT8, mInt8Value, (uint8_t), aValue);
1238 }
SetFromInt16(int16_t aValue)1239 void nsDiscriminatedUnion::SetFromInt16(int16_t aValue) {
1240 DATA_SETTER(VTYPE_INT16, mInt16Value, aValue);
1241 }
SetFromInt32(int32_t aValue)1242 void nsDiscriminatedUnion::SetFromInt32(int32_t aValue) {
1243 DATA_SETTER(VTYPE_INT32, mInt32Value, aValue);
1244 }
SetFromInt64(int64_t aValue)1245 void nsDiscriminatedUnion::SetFromInt64(int64_t aValue) {
1246 DATA_SETTER(VTYPE_INT64, mInt64Value, aValue);
1247 }
SetFromUint8(uint8_t aValue)1248 void nsDiscriminatedUnion::SetFromUint8(uint8_t aValue) {
1249 DATA_SETTER(VTYPE_UINT8, mUint8Value, aValue);
1250 }
SetFromUint16(uint16_t aValue)1251 void nsDiscriminatedUnion::SetFromUint16(uint16_t aValue) {
1252 DATA_SETTER(VTYPE_UINT16, mUint16Value, aValue);
1253 }
SetFromUint32(uint32_t aValue)1254 void nsDiscriminatedUnion::SetFromUint32(uint32_t aValue) {
1255 DATA_SETTER(VTYPE_UINT32, mUint32Value, aValue);
1256 }
SetFromUint64(uint64_t aValue)1257 void nsDiscriminatedUnion::SetFromUint64(uint64_t aValue) {
1258 DATA_SETTER(VTYPE_UINT64, mUint64Value, aValue);
1259 }
SetFromFloat(float aValue)1260 void nsDiscriminatedUnion::SetFromFloat(float aValue) {
1261 DATA_SETTER(VTYPE_FLOAT, mFloatValue, aValue);
1262 }
SetFromDouble(double aValue)1263 void nsDiscriminatedUnion::SetFromDouble(double aValue) {
1264 DATA_SETTER(VTYPE_DOUBLE, mDoubleValue, aValue);
1265 }
SetFromBool(bool aValue)1266 void nsDiscriminatedUnion::SetFromBool(bool aValue) {
1267 DATA_SETTER(VTYPE_BOOL, mBoolValue, aValue);
1268 }
SetFromChar(char aValue)1269 void nsDiscriminatedUnion::SetFromChar(char aValue) {
1270 DATA_SETTER(VTYPE_CHAR, mCharValue, aValue);
1271 }
SetFromWChar(char16_t aValue)1272 void nsDiscriminatedUnion::SetFromWChar(char16_t aValue) {
1273 DATA_SETTER(VTYPE_WCHAR, mWCharValue, aValue);
1274 }
SetFromID(const nsID & aValue)1275 void nsDiscriminatedUnion::SetFromID(const nsID& aValue) {
1276 DATA_SETTER(VTYPE_ID, mIDValue, aValue);
1277 }
SetFromAString(const nsAString & aValue)1278 void nsDiscriminatedUnion::SetFromAString(const nsAString& aValue) {
1279 DATA_SETTER_PROLOGUE;
1280 u.mAStringValue = new nsString(aValue);
1281 DATA_SETTER_EPILOGUE(VTYPE_ASTRING);
1282 }
1283
SetFromACString(const nsACString & aValue)1284 void nsDiscriminatedUnion::SetFromACString(const nsACString& aValue) {
1285 DATA_SETTER_PROLOGUE;
1286 u.mCStringValue = new nsCString(aValue);
1287 DATA_SETTER_EPILOGUE(VTYPE_CSTRING);
1288 }
1289
SetFromAUTF8String(const nsAUTF8String & aValue)1290 void nsDiscriminatedUnion::SetFromAUTF8String(const nsAUTF8String& aValue) {
1291 DATA_SETTER_PROLOGUE;
1292 u.mUTF8StringValue = new nsUTF8String(aValue);
1293 DATA_SETTER_EPILOGUE(VTYPE_UTF8STRING);
1294 }
1295
SetFromString(const char * aValue)1296 nsresult nsDiscriminatedUnion::SetFromString(const char* aValue) {
1297 DATA_SETTER_PROLOGUE;
1298 if (!aValue) {
1299 return NS_ERROR_NULL_POINTER;
1300 }
1301 return SetFromStringWithSize(strlen(aValue), aValue);
1302 }
SetFromWString(const char16_t * aValue)1303 nsresult nsDiscriminatedUnion::SetFromWString(const char16_t* aValue) {
1304 DATA_SETTER_PROLOGUE;
1305 if (!aValue) {
1306 return NS_ERROR_NULL_POINTER;
1307 }
1308 return SetFromWStringWithSize(NS_strlen(aValue), aValue);
1309 }
SetFromISupports(nsISupports * aValue)1310 void nsDiscriminatedUnion::SetFromISupports(nsISupports* aValue) {
1311 return SetFromInterface(NS_GET_IID(nsISupports), aValue);
1312 }
SetFromInterface(const nsIID & aIID,nsISupports * aValue)1313 void nsDiscriminatedUnion::SetFromInterface(const nsIID& aIID,
1314 nsISupports* aValue) {
1315 DATA_SETTER_PROLOGUE;
1316 NS_IF_ADDREF(aValue);
1317 u.iface.mInterfaceValue = aValue;
1318 u.iface.mInterfaceID = aIID;
1319 DATA_SETTER_EPILOGUE(VTYPE_INTERFACE_IS);
1320 }
SetFromArray(uint16_t aType,const nsIID * aIID,uint32_t aCount,void * aValue)1321 nsresult nsDiscriminatedUnion::SetFromArray(uint16_t aType, const nsIID* aIID,
1322 uint32_t aCount, void* aValue) {
1323 DATA_SETTER_PROLOGUE;
1324 if (!aValue || !aCount) {
1325 return NS_ERROR_NULL_POINTER;
1326 }
1327
1328 nsresult rv = CloneArray(aType, aIID, aCount, aValue, &u.array.mArrayType,
1329 &u.array.mArrayInterfaceID, &u.array.mArrayCount,
1330 &u.array.mArrayValue);
1331 if (NS_FAILED(rv)) {
1332 return rv;
1333 }
1334 DATA_SETTER_EPILOGUE(VTYPE_ARRAY);
1335 return NS_OK;
1336 }
SetFromStringWithSize(uint32_t aSize,const char * aValue)1337 nsresult nsDiscriminatedUnion::SetFromStringWithSize(uint32_t aSize,
1338 const char* aValue) {
1339 DATA_SETTER_PROLOGUE;
1340 if (!aValue) {
1341 return NS_ERROR_NULL_POINTER;
1342 }
1343 u.str.mStringValue = (char*)moz_xmemdup(aValue, (aSize + 1) * sizeof(char));
1344 u.str.mStringLength = aSize;
1345 DATA_SETTER_EPILOGUE(VTYPE_STRING_SIZE_IS);
1346 return NS_OK;
1347 }
SetFromWStringWithSize(uint32_t aSize,const char16_t * aValue)1348 nsresult nsDiscriminatedUnion::SetFromWStringWithSize(uint32_t aSize,
1349 const char16_t* aValue) {
1350 DATA_SETTER_PROLOGUE;
1351 if (!aValue) {
1352 return NS_ERROR_NULL_POINTER;
1353 }
1354 u.wstr.mWStringValue =
1355 (char16_t*)moz_xmemdup(aValue, (aSize + 1) * sizeof(char16_t));
1356 u.wstr.mWStringLength = aSize;
1357 DATA_SETTER_EPILOGUE(VTYPE_WSTRING_SIZE_IS);
1358 return NS_OK;
1359 }
AllocateWStringWithSize(uint32_t aSize)1360 void nsDiscriminatedUnion::AllocateWStringWithSize(uint32_t aSize) {
1361 DATA_SETTER_PROLOGUE;
1362 u.wstr.mWStringValue = (char16_t*)moz_xmalloc((aSize + 1) * sizeof(char16_t));
1363 u.wstr.mWStringValue[aSize] = '\0';
1364 u.wstr.mWStringLength = aSize;
1365 DATA_SETTER_EPILOGUE(VTYPE_WSTRING_SIZE_IS);
1366 }
SetToVoid()1367 void nsDiscriminatedUnion::SetToVoid() {
1368 DATA_SETTER_PROLOGUE;
1369 DATA_SETTER_EPILOGUE(VTYPE_VOID);
1370 }
SetToEmpty()1371 void nsDiscriminatedUnion::SetToEmpty() {
1372 DATA_SETTER_PROLOGUE;
1373 DATA_SETTER_EPILOGUE(VTYPE_EMPTY);
1374 }
SetToEmptyArray()1375 void nsDiscriminatedUnion::SetToEmptyArray() {
1376 DATA_SETTER_PROLOGUE;
1377 DATA_SETTER_EPILOGUE(VTYPE_EMPTY_ARRAY);
1378 }
1379
1380 /***************************************************************************/
1381
Cleanup()1382 void nsDiscriminatedUnion::Cleanup() {
1383 switch (mType) {
1384 case nsIDataType::VTYPE_INT8:
1385 case nsIDataType::VTYPE_INT16:
1386 case nsIDataType::VTYPE_INT32:
1387 case nsIDataType::VTYPE_INT64:
1388 case nsIDataType::VTYPE_UINT8:
1389 case nsIDataType::VTYPE_UINT16:
1390 case nsIDataType::VTYPE_UINT32:
1391 case nsIDataType::VTYPE_UINT64:
1392 case nsIDataType::VTYPE_FLOAT:
1393 case nsIDataType::VTYPE_DOUBLE:
1394 case nsIDataType::VTYPE_BOOL:
1395 case nsIDataType::VTYPE_CHAR:
1396 case nsIDataType::VTYPE_WCHAR:
1397 case nsIDataType::VTYPE_VOID:
1398 case nsIDataType::VTYPE_ID:
1399 break;
1400 case nsIDataType::VTYPE_ASTRING:
1401 delete u.mAStringValue;
1402 break;
1403 case nsIDataType::VTYPE_CSTRING:
1404 delete u.mCStringValue;
1405 break;
1406 case nsIDataType::VTYPE_UTF8STRING:
1407 delete u.mUTF8StringValue;
1408 break;
1409 case nsIDataType::VTYPE_CHAR_STR:
1410 case nsIDataType::VTYPE_STRING_SIZE_IS:
1411 free((char*)u.str.mStringValue);
1412 break;
1413 case nsIDataType::VTYPE_WCHAR_STR:
1414 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
1415 free((char*)u.wstr.mWStringValue);
1416 break;
1417 case nsIDataType::VTYPE_INTERFACE:
1418 case nsIDataType::VTYPE_INTERFACE_IS:
1419 NS_IF_RELEASE(u.iface.mInterfaceValue);
1420 break;
1421 case nsIDataType::VTYPE_ARRAY:
1422 FreeArray();
1423 break;
1424 case nsIDataType::VTYPE_EMPTY_ARRAY:
1425 case nsIDataType::VTYPE_EMPTY:
1426 break;
1427 default:
1428 NS_ERROR("bad type in variant!");
1429 break;
1430 }
1431
1432 mType = nsIDataType::VTYPE_EMPTY;
1433 }
1434
Traverse(nsCycleCollectionTraversalCallback & aCb) const1435 void nsDiscriminatedUnion::Traverse(
1436 nsCycleCollectionTraversalCallback& aCb) const {
1437 switch (mType) {
1438 case nsIDataType::VTYPE_INTERFACE:
1439 case nsIDataType::VTYPE_INTERFACE_IS:
1440 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mData");
1441 aCb.NoteXPCOMChild(u.iface.mInterfaceValue);
1442 break;
1443 case nsIDataType::VTYPE_ARRAY:
1444 switch (u.array.mArrayType) {
1445 case nsIDataType::VTYPE_INTERFACE:
1446 case nsIDataType::VTYPE_INTERFACE_IS: {
1447 nsISupports** p = (nsISupports**)u.array.mArrayValue;
1448 for (uint32_t i = u.array.mArrayCount; i > 0; ++p, --i) {
1449 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mData[i]");
1450 aCb.NoteXPCOMChild(*p);
1451 }
1452 break;
1453 }
1454 default:
1455 break;
1456 }
1457 break;
1458 default:
1459 break;
1460 }
1461 }
1462
1463 /***************************************************************************/
1464 /***************************************************************************/
1465 // members...
1466
nsVariantBase()1467 nsVariantBase::nsVariantBase() : mWritable(true) {}
1468
1469 // For all the data getters we just forward to the static (and sharable)
1470 // 'ConvertTo' functions.
1471
GetDataType()1472 uint16_t nsVariantBase::GetDataType() { return mData.GetType(); }
1473
1474 NS_IMETHODIMP
GetAsInt8(uint8_t * aResult)1475 nsVariantBase::GetAsInt8(uint8_t* aResult) {
1476 return mData.ConvertToInt8(aResult);
1477 }
1478
1479 NS_IMETHODIMP
GetAsInt16(int16_t * aResult)1480 nsVariantBase::GetAsInt16(int16_t* aResult) {
1481 return mData.ConvertToInt16(aResult);
1482 }
1483
1484 NS_IMETHODIMP
GetAsInt32(int32_t * aResult)1485 nsVariantBase::GetAsInt32(int32_t* aResult) {
1486 return mData.ConvertToInt32(aResult);
1487 }
1488
1489 NS_IMETHODIMP
GetAsInt64(int64_t * aResult)1490 nsVariantBase::GetAsInt64(int64_t* aResult) {
1491 return mData.ConvertToInt64(aResult);
1492 }
1493
1494 NS_IMETHODIMP
GetAsUint8(uint8_t * aResult)1495 nsVariantBase::GetAsUint8(uint8_t* aResult) {
1496 return mData.ConvertToUint8(aResult);
1497 }
1498
1499 NS_IMETHODIMP
GetAsUint16(uint16_t * aResult)1500 nsVariantBase::GetAsUint16(uint16_t* aResult) {
1501 return mData.ConvertToUint16(aResult);
1502 }
1503
1504 NS_IMETHODIMP
GetAsUint32(uint32_t * aResult)1505 nsVariantBase::GetAsUint32(uint32_t* aResult) {
1506 return mData.ConvertToUint32(aResult);
1507 }
1508
1509 NS_IMETHODIMP
GetAsUint64(uint64_t * aResult)1510 nsVariantBase::GetAsUint64(uint64_t* aResult) {
1511 return mData.ConvertToUint64(aResult);
1512 }
1513
1514 NS_IMETHODIMP
GetAsFloat(float * aResult)1515 nsVariantBase::GetAsFloat(float* aResult) {
1516 return mData.ConvertToFloat(aResult);
1517 }
1518
1519 NS_IMETHODIMP
GetAsDouble(double * aResult)1520 nsVariantBase::GetAsDouble(double* aResult) {
1521 return mData.ConvertToDouble(aResult);
1522 }
1523
1524 NS_IMETHODIMP
GetAsBool(bool * aResult)1525 nsVariantBase::GetAsBool(bool* aResult) { return mData.ConvertToBool(aResult); }
1526
1527 NS_IMETHODIMP
GetAsChar(char * aResult)1528 nsVariantBase::GetAsChar(char* aResult) { return mData.ConvertToChar(aResult); }
1529
1530 NS_IMETHODIMP
GetAsWChar(char16_t * aResult)1531 nsVariantBase::GetAsWChar(char16_t* aResult) {
1532 return mData.ConvertToWChar(aResult);
1533 }
1534
NS_IMETHODIMP_(nsresult)1535 NS_IMETHODIMP_(nsresult)
1536 nsVariantBase::GetAsID(nsID* aResult) { return mData.ConvertToID(aResult); }
1537
1538 NS_IMETHODIMP
GetAsAString(nsAString & aResult)1539 nsVariantBase::GetAsAString(nsAString& aResult) {
1540 return mData.ConvertToAString(aResult);
1541 }
1542
1543 NS_IMETHODIMP
GetAsACString(nsACString & aResult)1544 nsVariantBase::GetAsACString(nsACString& aResult) {
1545 return mData.ConvertToACString(aResult);
1546 }
1547
1548 NS_IMETHODIMP
GetAsAUTF8String(nsAUTF8String & aResult)1549 nsVariantBase::GetAsAUTF8String(nsAUTF8String& aResult) {
1550 return mData.ConvertToAUTF8String(aResult);
1551 }
1552
1553 NS_IMETHODIMP
GetAsString(char ** aResult)1554 nsVariantBase::GetAsString(char** aResult) {
1555 return mData.ConvertToString(aResult);
1556 }
1557
1558 NS_IMETHODIMP
GetAsWString(char16_t ** aResult)1559 nsVariantBase::GetAsWString(char16_t** aResult) {
1560 return mData.ConvertToWString(aResult);
1561 }
1562
1563 NS_IMETHODIMP
GetAsISupports(nsISupports ** aResult)1564 nsVariantBase::GetAsISupports(nsISupports** aResult) {
1565 return mData.ConvertToISupports(aResult);
1566 }
1567
1568 NS_IMETHODIMP
GetAsJSVal(JS::MutableHandleValue)1569 nsVariantBase::GetAsJSVal(JS::MutableHandleValue) {
1570 // Can only get the jsval from an XPCVariant.
1571 return NS_ERROR_CANNOT_CONVERT_DATA;
1572 }
1573
1574 NS_IMETHODIMP
GetAsInterface(nsIID ** aIID,void ** aInterface)1575 nsVariantBase::GetAsInterface(nsIID** aIID, void** aInterface) {
1576 return mData.ConvertToInterface(aIID, aInterface);
1577 }
1578
NS_IMETHODIMP_(nsresult)1579 NS_IMETHODIMP_(nsresult)
1580 nsVariantBase::GetAsArray(uint16_t* aType, nsIID* aIID, uint32_t* aCount,
1581 void** aPtr) {
1582 return mData.ConvertToArray(aType, aIID, aCount, aPtr);
1583 }
1584
1585 NS_IMETHODIMP
GetAsStringWithSize(uint32_t * aSize,char ** aStr)1586 nsVariantBase::GetAsStringWithSize(uint32_t* aSize, char** aStr) {
1587 return mData.ConvertToStringWithSize(aSize, aStr);
1588 }
1589
1590 NS_IMETHODIMP
GetAsWStringWithSize(uint32_t * aSize,char16_t ** aStr)1591 nsVariantBase::GetAsWStringWithSize(uint32_t* aSize, char16_t** aStr) {
1592 return mData.ConvertToWStringWithSize(aSize, aStr);
1593 }
1594
1595 /***************************************************************************/
1596
1597 NS_IMETHODIMP
GetWritable(bool * aWritable)1598 nsVariantBase::GetWritable(bool* aWritable) {
1599 *aWritable = mWritable;
1600 return NS_OK;
1601 }
1602 NS_IMETHODIMP
SetWritable(bool aWritable)1603 nsVariantBase::SetWritable(bool aWritable) {
1604 if (!mWritable && aWritable) {
1605 return NS_ERROR_FAILURE;
1606 }
1607 mWritable = aWritable;
1608 return NS_OK;
1609 }
1610
1611 /***************************************************************************/
1612
1613 // For all the data setters we just forward to the static (and sharable)
1614 // 'SetFrom' functions.
1615
1616 NS_IMETHODIMP
SetAsInt8(uint8_t aValue)1617 nsVariantBase::SetAsInt8(uint8_t aValue) {
1618 if (!mWritable) {
1619 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1620 }
1621 mData.SetFromInt8(aValue);
1622 return NS_OK;
1623 }
1624
1625 NS_IMETHODIMP
SetAsInt16(int16_t aValue)1626 nsVariantBase::SetAsInt16(int16_t aValue) {
1627 if (!mWritable) {
1628 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1629 }
1630 mData.SetFromInt16(aValue);
1631 return NS_OK;
1632 }
1633
1634 NS_IMETHODIMP
SetAsInt32(int32_t aValue)1635 nsVariantBase::SetAsInt32(int32_t aValue) {
1636 if (!mWritable) {
1637 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1638 }
1639 mData.SetFromInt32(aValue);
1640 return NS_OK;
1641 }
1642
1643 NS_IMETHODIMP
SetAsInt64(int64_t aValue)1644 nsVariantBase::SetAsInt64(int64_t aValue) {
1645 if (!mWritable) {
1646 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1647 }
1648 mData.SetFromInt64(aValue);
1649 return NS_OK;
1650 }
1651
1652 NS_IMETHODIMP
SetAsUint8(uint8_t aValue)1653 nsVariantBase::SetAsUint8(uint8_t aValue) {
1654 if (!mWritable) {
1655 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1656 }
1657 mData.SetFromUint8(aValue);
1658 return NS_OK;
1659 }
1660
1661 NS_IMETHODIMP
SetAsUint16(uint16_t aValue)1662 nsVariantBase::SetAsUint16(uint16_t aValue) {
1663 if (!mWritable) {
1664 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1665 }
1666 mData.SetFromUint16(aValue);
1667 return NS_OK;
1668 }
1669
1670 NS_IMETHODIMP
SetAsUint32(uint32_t aValue)1671 nsVariantBase::SetAsUint32(uint32_t aValue) {
1672 if (!mWritable) {
1673 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1674 }
1675 mData.SetFromUint32(aValue);
1676 return NS_OK;
1677 }
1678
1679 NS_IMETHODIMP
SetAsUint64(uint64_t aValue)1680 nsVariantBase::SetAsUint64(uint64_t aValue) {
1681 if (!mWritable) {
1682 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1683 }
1684 mData.SetFromUint64(aValue);
1685 return NS_OK;
1686 }
1687
1688 NS_IMETHODIMP
SetAsFloat(float aValue)1689 nsVariantBase::SetAsFloat(float aValue) {
1690 if (!mWritable) {
1691 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1692 }
1693 mData.SetFromFloat(aValue);
1694 return NS_OK;
1695 }
1696
1697 NS_IMETHODIMP
SetAsDouble(double aValue)1698 nsVariantBase::SetAsDouble(double aValue) {
1699 if (!mWritable) {
1700 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1701 }
1702 mData.SetFromDouble(aValue);
1703 return NS_OK;
1704 }
1705
1706 NS_IMETHODIMP
SetAsBool(bool aValue)1707 nsVariantBase::SetAsBool(bool aValue) {
1708 if (!mWritable) {
1709 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1710 }
1711 mData.SetFromBool(aValue);
1712 return NS_OK;
1713 }
1714
1715 NS_IMETHODIMP
SetAsChar(char aValue)1716 nsVariantBase::SetAsChar(char aValue) {
1717 if (!mWritable) {
1718 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1719 }
1720 mData.SetFromChar(aValue);
1721 return NS_OK;
1722 }
1723
1724 NS_IMETHODIMP
SetAsWChar(char16_t aValue)1725 nsVariantBase::SetAsWChar(char16_t aValue) {
1726 if (!mWritable) {
1727 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1728 }
1729 mData.SetFromWChar(aValue);
1730 return NS_OK;
1731 }
1732
1733 NS_IMETHODIMP
SetAsID(const nsID & aValue)1734 nsVariantBase::SetAsID(const nsID& aValue) {
1735 if (!mWritable) {
1736 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1737 }
1738 mData.SetFromID(aValue);
1739 return NS_OK;
1740 }
1741
1742 NS_IMETHODIMP
SetAsAString(const nsAString & aValue)1743 nsVariantBase::SetAsAString(const nsAString& aValue) {
1744 if (!mWritable) {
1745 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1746 }
1747 mData.SetFromAString(aValue);
1748 return NS_OK;
1749 }
1750
1751 NS_IMETHODIMP
SetAsACString(const nsACString & aValue)1752 nsVariantBase::SetAsACString(const nsACString& aValue) {
1753 if (!mWritable) {
1754 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1755 }
1756 mData.SetFromACString(aValue);
1757 return NS_OK;
1758 }
1759
1760 NS_IMETHODIMP
SetAsAUTF8String(const nsAUTF8String & aValue)1761 nsVariantBase::SetAsAUTF8String(const nsAUTF8String& aValue) {
1762 if (!mWritable) {
1763 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1764 }
1765 mData.SetFromAUTF8String(aValue);
1766 return NS_OK;
1767 }
1768
1769 NS_IMETHODIMP
SetAsString(const char * aValue)1770 nsVariantBase::SetAsString(const char* aValue) {
1771 if (!mWritable) {
1772 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1773 }
1774 return mData.SetFromString(aValue);
1775 }
1776
1777 NS_IMETHODIMP
SetAsWString(const char16_t * aValue)1778 nsVariantBase::SetAsWString(const char16_t* aValue) {
1779 if (!mWritable) {
1780 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1781 }
1782 return mData.SetFromWString(aValue);
1783 }
1784
1785 NS_IMETHODIMP
SetAsISupports(nsISupports * aValue)1786 nsVariantBase::SetAsISupports(nsISupports* aValue) {
1787 if (!mWritable) {
1788 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1789 }
1790 mData.SetFromISupports(aValue);
1791 return NS_OK;
1792 }
1793
1794 NS_IMETHODIMP
SetAsInterface(const nsIID & aIID,void * aInterface)1795 nsVariantBase::SetAsInterface(const nsIID& aIID, void* aInterface) {
1796 if (!mWritable) {
1797 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1798 }
1799 mData.SetFromInterface(aIID, (nsISupports*)aInterface);
1800 return NS_OK;
1801 }
1802
1803 NS_IMETHODIMP
SetAsArray(uint16_t aType,const nsIID * aIID,uint32_t aCount,void * aPtr)1804 nsVariantBase::SetAsArray(uint16_t aType, const nsIID* aIID, uint32_t aCount,
1805 void* aPtr) {
1806 if (!mWritable) {
1807 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1808 }
1809 return mData.SetFromArray(aType, aIID, aCount, aPtr);
1810 }
1811
1812 NS_IMETHODIMP
SetAsStringWithSize(uint32_t aSize,const char * aStr)1813 nsVariantBase::SetAsStringWithSize(uint32_t aSize, const char* aStr) {
1814 if (!mWritable) {
1815 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1816 }
1817 return mData.SetFromStringWithSize(aSize, aStr);
1818 }
1819
1820 NS_IMETHODIMP
SetAsWStringWithSize(uint32_t aSize,const char16_t * aStr)1821 nsVariantBase::SetAsWStringWithSize(uint32_t aSize, const char16_t* aStr) {
1822 if (!mWritable) {
1823 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1824 }
1825 return mData.SetFromWStringWithSize(aSize, aStr);
1826 }
1827
1828 NS_IMETHODIMP
SetAsVoid()1829 nsVariantBase::SetAsVoid() {
1830 if (!mWritable) {
1831 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1832 }
1833 mData.SetToVoid();
1834 return NS_OK;
1835 }
1836
1837 NS_IMETHODIMP
SetAsEmpty()1838 nsVariantBase::SetAsEmpty() {
1839 if (!mWritable) {
1840 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1841 }
1842 mData.SetToEmpty();
1843 return NS_OK;
1844 }
1845
1846 NS_IMETHODIMP
SetAsEmptyArray()1847 nsVariantBase::SetAsEmptyArray() {
1848 if (!mWritable) {
1849 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1850 }
1851 mData.SetToEmptyArray();
1852 return NS_OK;
1853 }
1854
1855 NS_IMETHODIMP
SetFromVariant(nsIVariant * aValue)1856 nsVariantBase::SetFromVariant(nsIVariant* aValue) {
1857 if (!mWritable) {
1858 return NS_ERROR_OBJECT_IS_IMMUTABLE;
1859 }
1860 return mData.SetFromVariant(aValue);
1861 }
1862
1863 /* nsVariant implementation */
1864
1865 NS_IMPL_ISUPPORTS(nsVariant, nsIVariant, nsIWritableVariant)
1866
1867 /* nsVariantCC implementation */
1868 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsVariantCC)
1869 NS_INTERFACE_MAP_ENTRY(nsISupports)
1870 NS_INTERFACE_MAP_ENTRY(nsIVariant)
1871 NS_INTERFACE_MAP_ENTRY(nsIWritableVariant)
1872 NS_INTERFACE_MAP_END
1873
1874 NS_IMPL_CYCLE_COLLECTION_CLASS(nsVariantCC)
1875
1876 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsVariantCC)
1877 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsVariantCC)
1878
1879 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsVariantCC)
1880 tmp->mData.Traverse(cb);
1881 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
1882
1883 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsVariantCC)
1884 tmp->mData.Cleanup();
1885 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
1886