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