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/. */
11 #include "nsCycleCollectionParticipant.h"
13 #include "nsReadableUtils.h"
15 #include "nsCRTGlue.h"
16 #include "mozilla/FloatingPoint.h"
17 #include "mozilla/IntegerPrintfMacros.h"
18 #include "mozilla/Printf.h"
20 /***************************************************************************/
21 // Helpers for static convert functions...
23 static nsresult
String2Double(const char* aString
, double* aResult
) {
25 double value
= PR_strtod(aString
, &next
);
26 if (next
== aString
) {
27 return NS_ERROR_CANNOT_CONVERT_DATA
;
33 static nsresult
AString2Double(const nsAString
& aString
, double* aResult
) {
34 char* pChars
= ToNewCString(aString
, mozilla::fallible
);
36 return NS_ERROR_OUT_OF_MEMORY
;
38 nsresult rv
= String2Double(pChars
, aResult
);
43 static nsresult
AUTF8String2Double(const nsAUTF8String
& aString
,
45 return String2Double(PromiseFlatUTF8String(aString
).get(), aResult
);
48 static nsresult
ACString2Double(const nsACString
& aString
, double* aResult
) {
49 return String2Double(PromiseFlatCString(aString
).get(), aResult
);
52 // Fills aOutData with double, uint32_t, or int32_t.
53 // Returns NS_OK, an error code, or a non-NS_OK success code
54 nsresult
nsDiscriminatedUnion::ToManageableNumber(
55 nsDiscriminatedUnion
* aOutData
) const {
59 // This group results in a int32_t...
61 #define CASE__NUMBER_INT32(type_, member_) \
62 case nsIDataType::type_: \
63 aOutData->u.mInt32Value = u.member_; \
64 aOutData->mType = nsIDataType::VTYPE_INT32; \
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
)
76 #undef CASE__NUMBER_INT32
78 // This group results in a uint32_t...
80 case nsIDataType::VTYPE_UINT32
:
81 aOutData
->u
.mUint32Value
= u
.mUint32Value
;
82 aOutData
->mType
= nsIDataType::VTYPE_UINT32
;
85 // This group results in a double...
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
;
94 case nsIDataType::VTYPE_FLOAT
:
95 aOutData
->u
.mDoubleValue
= u
.mFloatValue
;
96 aOutData
->mType
= nsIDataType::VTYPE_DOUBLE
;
98 case nsIDataType::VTYPE_DOUBLE
:
99 aOutData
->u
.mDoubleValue
= u
.mDoubleValue
;
100 aOutData
->mType
= nsIDataType::VTYPE_DOUBLE
;
102 case nsIDataType::VTYPE_CHAR_STR
:
103 case nsIDataType::VTYPE_STRING_SIZE_IS
:
104 rv
= String2Double(u
.str
.mStringValue
, &aOutData
->u
.mDoubleValue
);
108 aOutData
->mType
= nsIDataType::VTYPE_DOUBLE
;
110 case nsIDataType::VTYPE_ASTRING
:
111 rv
= AString2Double(*u
.mAStringValue
, &aOutData
->u
.mDoubleValue
);
115 aOutData
->mType
= nsIDataType::VTYPE_DOUBLE
;
117 case nsIDataType::VTYPE_UTF8STRING
:
118 rv
= AUTF8String2Double(*u
.mUTF8StringValue
, &aOutData
->u
.mDoubleValue
);
122 aOutData
->mType
= nsIDataType::VTYPE_DOUBLE
;
124 case nsIDataType::VTYPE_CSTRING
:
125 rv
= ACString2Double(*u
.mCStringValue
, &aOutData
->u
.mDoubleValue
);
129 aOutData
->mType
= nsIDataType::VTYPE_DOUBLE
;
131 case nsIDataType::VTYPE_WCHAR_STR
:
132 case nsIDataType::VTYPE_WSTRING_SIZE_IS
:
133 rv
= AString2Double(nsDependentString(u
.wstr
.mWStringValue
),
134 &aOutData
->u
.mDoubleValue
);
138 aOutData
->mType
= nsIDataType::VTYPE_DOUBLE
;
141 // This group fails...
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
:
151 return NS_ERROR_CANNOT_CONVERT_DATA
;
155 /***************************************************************************/
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");
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); \
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(); \
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
:
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
)
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
:
213 NS_ERROR("bad type in array!");
217 // Free the array memory.
218 free((char*)u
.array
.mArrayValue
);
220 #undef CASE__FREE_ARRAY_PTR
221 #undef CASE__FREE_ARRAY_IFACE
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");
236 // First we figure out the size of the elements for the new u.array.
242 case nsIDataType::VTYPE_INT8
:
243 elementSize
= sizeof(int8_t);
245 case nsIDataType::VTYPE_INT16
:
246 elementSize
= sizeof(int16_t);
248 case nsIDataType::VTYPE_INT32
:
249 elementSize
= sizeof(int32_t);
251 case nsIDataType::VTYPE_INT64
:
252 elementSize
= sizeof(int64_t);
254 case nsIDataType::VTYPE_UINT8
:
255 elementSize
= sizeof(uint8_t);
257 case nsIDataType::VTYPE_UINT16
:
258 elementSize
= sizeof(uint16_t);
260 case nsIDataType::VTYPE_UINT32
:
261 elementSize
= sizeof(uint32_t);
263 case nsIDataType::VTYPE_UINT64
:
264 elementSize
= sizeof(uint64_t);
266 case nsIDataType::VTYPE_FLOAT
:
267 elementSize
= sizeof(float);
269 case nsIDataType::VTYPE_DOUBLE
:
270 elementSize
= sizeof(double);
272 case nsIDataType::VTYPE_BOOL
:
273 elementSize
= sizeof(bool);
275 case nsIDataType::VTYPE_CHAR
:
276 elementSize
= sizeof(char);
278 case nsIDataType::VTYPE_WCHAR
:
279 elementSize
= sizeof(char16_t
);
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*);
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
:
302 NS_ERROR("bad type in array!");
303 return NS_ERROR_CANNOT_CONVERT_DATA
;
306 // Alloc the u.array.
308 allocSize
= aInCount
* elementSize
;
309 *aOutValue
= moz_xmalloc(allocSize
);
311 // Clone the elements.
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
);
330 case nsIDataType::VTYPE_INTERFACE_IS
:
336 case nsIDataType::VTYPE_INTERFACE
: {
337 memcpy(*aOutValue
, aInValue
, allocSize
);
339 nsISupports
** p
= (nsISupports
**)*aOutValue
;
340 for (i
= aInCount
; i
> 0; ++p
, --i
)
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
++);
354 *(outp
++) = idp
->Clone();
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
++);
368 *(outp
++) = moz_xstrdup(str
);
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
++);
382 *(outp
++) = NS_xstrdup(str
);
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
:
401 NS_ERROR("bad type in array!");
402 return NS_ERROR_CANNOT_CONVERT_DATA
;
406 *aOutCount
= aInCount
;
410 /***************************************************************************/
412 #define TRIVIAL_DATA_CONVERTER(type_, member_, retval_) \
413 if (mType == nsIDataType::type_) { \
414 *retval_ = u.member_; \
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); \
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. */ \
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; \
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; \
441 *aResult = (Ctype_)value; \
445 #define CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(Ctype_) \
446 case nsIDataType::VTYPE_UINT32: \
447 *aResult = (Ctype_)tempData.u.mUint32Value; \
450 #define CASE__NUMERIC_CONVERSION_UINT32_MAX(Ctype_, max_) \
451 case nsIDataType::VTYPE_UINT32: { \
452 uint32_t value = tempData.u.mUint32Value; \
453 if (value > (max_)) return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
454 *aResult = (Ctype_)value; \
458 #define CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(Ctype_) \
459 case nsIDataType::VTYPE_DOUBLE: \
460 *aResult = (Ctype_)tempData.u.mDoubleValue; \
463 #define CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(Ctype_, min_, max_) \
464 case nsIDataType::VTYPE_DOUBLE: { \
465 double value = tempData.u.mDoubleValue; \
466 if (std::isnan(value) || value < (min_) || value > (max_)) { \
467 return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA; \
469 *aResult = (Ctype_)value; \
470 return (0.0 == fmod(value, 1.0)) ? rv \
471 : NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA; \
474 #define CASES__NUMERIC_CONVERSION_NORMAL(Ctype_, min_, max_) \
475 CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(Ctype_, min_, max_) \
476 CASE__NUMERIC_CONVERSION_UINT32_MAX(Ctype_, max_) \
477 CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(Ctype_, min_, max_)
479 #define NUMERIC_CONVERSION_METHOD_END \
481 NS_ERROR("bad type returned from ToManageableNumber"); \
482 return NS_ERROR_CANNOT_CONVERT_DATA; \
486 #define NUMERIC_CONVERSION_METHOD_NORMAL(type_, Ctype_, name_, min_, max_) \
487 NUMERIC_CONVERSION_METHOD_BEGIN(type_, Ctype_, name_) \
488 CASES__NUMERIC_CONVERSION_NORMAL(Ctype_, min_, max_) \
489 NUMERIC_CONVERSION_METHOD_END
491 /***************************************************************************/
492 // These expand into full public methods...
494 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_INT8
, uint8_t, Int8
, (-127 - 1), 127)
495 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_INT16
, int16_t, Int16
, (-32767 - 1),
498 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_INT32
, int32_t, Int32
)
499 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(int32_t)
500 CASE__NUMERIC_CONVERSION_UINT32_MAX(int32_t, 2147483647)
501 CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(int32_t, (-2147483647 - 1),
503 NUMERIC_CONVERSION_METHOD_END
505 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_UINT8
, uint8_t, Uint8
, 0, 255)
506 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_UINT16
, uint16_t, Uint16
, 0, 65535)
508 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_UINT32
, uint32_t, Uint32
)
509 CASE__NUMERIC_CONVERSION_INT32_MIN_MAX(uint32_t, 0, 2147483647)
510 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(uint32_t)
511 CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT(uint32_t, 0, 4294967295U)
512 NUMERIC_CONVERSION_METHOD_END
514 // XXX toFloat conversions need to be fixed!
515 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_FLOAT
, float, Float
)
516 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(float)
517 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(float)
518 CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(float)
519 NUMERIC_CONVERSION_METHOD_END
521 NUMERIC_CONVERSION_METHOD_BEGIN(VTYPE_DOUBLE
, double, Double
)
522 CASE__NUMERIC_CONVERSION_INT32_JUST_CAST(double)
523 CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST(double)
524 CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST(double)
525 NUMERIC_CONVERSION_METHOD_END
527 // XXX toChar conversions need to be fixed!
528 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_CHAR
, char, Char
, CHAR_MIN
, CHAR_MAX
)
530 // XXX toWChar conversions need to be fixed!
531 NUMERIC_CONVERSION_METHOD_NORMAL(VTYPE_WCHAR
, char16_t
, WChar
, 0,
532 std::numeric_limits
<char16_t
>::max())
534 #undef NUMERIC_CONVERSION_METHOD_BEGIN
535 #undef CASE__NUMERIC_CONVERSION_INT32_JUST_CAST
536 #undef CASE__NUMERIC_CONVERSION_INT32_MIN_MAX
537 #undef CASE__NUMERIC_CONVERSION_UINT32_JUST_CAST
538 #undef CASE__NUMERIC_CONVERSION_UINT32_MIN_MAX
539 #undef CASE__NUMERIC_CONVERSION_DOUBLE_JUST_CAST
540 #undef CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX
541 #undef CASE__NUMERIC_CONVERSION_DOUBLE_MIN_MAX_INT
542 #undef CASES__NUMERIC_CONVERSION_NORMAL
543 #undef NUMERIC_CONVERSION_METHOD_END
544 #undef NUMERIC_CONVERSION_METHOD_NORMAL
546 /***************************************************************************/
548 // Just leverage a numeric converter for bool (but restrict the values).
549 // XXX Is this really what we want to do?
551 nsresult
nsDiscriminatedUnion::ConvertToBool(bool* aResult
) const {
552 TRIVIAL_DATA_CONVERTER(VTYPE_BOOL
, mBoolValue
, aResult
)
555 nsresult rv
= ConvertToDouble(&val
);
559 // NaN is falsy in JS, so we might as well make it false here.
560 if (std::isnan(val
)) {
563 *aResult
= 0.0 != val
;
568 /***************************************************************************/
570 nsresult
nsDiscriminatedUnion::ConvertToInt64(int64_t* aResult
) const {
571 TRIVIAL_DATA_CONVERTER(VTYPE_INT64
, mInt64Value
, aResult
)
572 TRIVIAL_DATA_CONVERTER(VTYPE_UINT64
, mUint64Value
, aResult
)
574 nsDiscriminatedUnion tempData
;
575 nsresult rv
= ToManageableNumber(&tempData
);
579 switch (tempData
.mType
) {
580 case nsIDataType::VTYPE_INT32
:
581 *aResult
= tempData
.u
.mInt32Value
;
583 case nsIDataType::VTYPE_UINT32
:
584 *aResult
= tempData
.u
.mUint32Value
;
586 case nsIDataType::VTYPE_DOUBLE
: {
587 double value
= tempData
.u
.mDoubleValue
;
588 if (std::isnan(value
)) {
589 return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA
;
591 // XXX should check for data loss here!
596 NS_ERROR("bad type returned from ToManageableNumber");
597 return NS_ERROR_CANNOT_CONVERT_DATA
;
601 nsresult
nsDiscriminatedUnion::ConvertToUint64(uint64_t* aResult
) const {
602 return ConvertToInt64((int64_t*)aResult
);
605 /***************************************************************************/
607 bool nsDiscriminatedUnion::String2ID(nsID
* aPid
) const {
608 nsAutoString tempString
;
612 case nsIDataType::VTYPE_CHAR_STR
:
613 case nsIDataType::VTYPE_STRING_SIZE_IS
:
614 return aPid
->Parse(u
.str
.mStringValue
);
615 case nsIDataType::VTYPE_CSTRING
:
616 return aPid
->Parse(PromiseFlatCString(*u
.mCStringValue
).get());
617 case nsIDataType::VTYPE_UTF8STRING
:
618 return aPid
->Parse(PromiseFlatUTF8String(*u
.mUTF8StringValue
).get());
619 case nsIDataType::VTYPE_ASTRING
:
620 pString
= u
.mAStringValue
;
622 case nsIDataType::VTYPE_WCHAR_STR
:
623 case nsIDataType::VTYPE_WSTRING_SIZE_IS
:
624 tempString
.Assign(u
.wstr
.mWStringValue
);
625 pString
= &tempString
;
628 NS_ERROR("bad type in call to String2ID");
632 char* pChars
= ToNewCString(*pString
, mozilla::fallible
);
636 bool result
= aPid
->Parse(pChars
);
641 nsresult
nsDiscriminatedUnion::ConvertToID(nsID
* aResult
) const {
645 case nsIDataType::VTYPE_ID
:
646 *aResult
= u
.mIDValue
;
648 case nsIDataType::VTYPE_INTERFACE
:
649 *aResult
= NS_GET_IID(nsISupports
);
651 case nsIDataType::VTYPE_INTERFACE_IS
:
652 *aResult
= u
.iface
.mInterfaceID
;
654 case nsIDataType::VTYPE_ASTRING
:
655 case nsIDataType::VTYPE_UTF8STRING
:
656 case nsIDataType::VTYPE_CSTRING
:
657 case nsIDataType::VTYPE_CHAR_STR
:
658 case nsIDataType::VTYPE_WCHAR_STR
:
659 case nsIDataType::VTYPE_STRING_SIZE_IS
:
660 case nsIDataType::VTYPE_WSTRING_SIZE_IS
:
661 if (!String2ID(&id
)) {
662 return NS_ERROR_CANNOT_CONVERT_DATA
;
667 return NS_ERROR_CANNOT_CONVERT_DATA
;
671 /***************************************************************************/
673 nsresult
nsDiscriminatedUnion::ToString(nsACString
& aOutString
) const {
674 mozilla::SmprintfPointer pptr
;
677 // all the stuff we don't handle...
678 case nsIDataType::VTYPE_ASTRING
:
679 case nsIDataType::VTYPE_UTF8STRING
:
680 case nsIDataType::VTYPE_CSTRING
:
681 case nsIDataType::VTYPE_CHAR_STR
:
682 case nsIDataType::VTYPE_WCHAR_STR
:
683 case nsIDataType::VTYPE_STRING_SIZE_IS
:
684 case nsIDataType::VTYPE_WSTRING_SIZE_IS
:
685 case nsIDataType::VTYPE_WCHAR
:
686 NS_ERROR("ToString being called for a string type - screwy logic!");
689 // XXX We might want stringified versions of these... ???
691 case nsIDataType::VTYPE_VOID
:
692 case nsIDataType::VTYPE_EMPTY
:
693 aOutString
.SetIsVoid(true);
696 case nsIDataType::VTYPE_EMPTY_ARRAY
:
697 case nsIDataType::VTYPE_ARRAY
:
698 case nsIDataType::VTYPE_INTERFACE
:
699 case nsIDataType::VTYPE_INTERFACE_IS
:
701 return NS_ERROR_CANNOT_CONVERT_DATA
;
703 // nsID has its own text formatter.
705 case nsIDataType::VTYPE_ID
: {
706 aOutString
.Assign(u
.mIDValue
.ToString().get());
710 // Can't use Smprintf for floats, since it's locale-dependent
711 #define CASE__APPENDFLOAT_NUMBER(type_, member_) \
712 case nsIDataType::type_: { \
714 str.AppendFloat(u.member_); \
715 aOutString.Assign(str); \
719 CASE__APPENDFLOAT_NUMBER(VTYPE_FLOAT
, mFloatValue
)
720 CASE__APPENDFLOAT_NUMBER(VTYPE_DOUBLE
, mDoubleValue
)
722 #undef CASE__APPENDFLOAT_NUMBER
724 // the rest can be Smprintf'd and use common code.
726 #define CASE__SMPRINTF_NUMBER(type_, format_, cast_, member_) \
727 case nsIDataType::type_: \
728 static_assert(sizeof(cast_) >= sizeof(u.member_), \
729 "size of type should be at least as big as member"); \
730 pptr = mozilla::Smprintf(format_, (cast_)u.member_); \
733 CASE__SMPRINTF_NUMBER(VTYPE_INT8
, "%d", int, mInt8Value
)
734 CASE__SMPRINTF_NUMBER(VTYPE_INT16
, "%d", int, mInt16Value
)
735 CASE__SMPRINTF_NUMBER(VTYPE_INT32
, "%d", int, mInt32Value
)
736 CASE__SMPRINTF_NUMBER(VTYPE_INT64
, "%" PRId64
, int64_t, mInt64Value
)
738 CASE__SMPRINTF_NUMBER(VTYPE_UINT8
, "%u", unsigned, mUint8Value
)
739 CASE__SMPRINTF_NUMBER(VTYPE_UINT16
, "%u", unsigned, mUint16Value
)
740 CASE__SMPRINTF_NUMBER(VTYPE_UINT32
, "%u", unsigned, mUint32Value
)
741 CASE__SMPRINTF_NUMBER(VTYPE_UINT64
, "%" PRIu64
, int64_t, mUint64Value
)
743 // XXX Would we rather print "true" / "false" ?
744 CASE__SMPRINTF_NUMBER(VTYPE_BOOL
, "%d", int, mBoolValue
)
746 CASE__SMPRINTF_NUMBER(VTYPE_CHAR
, "%c", char, mCharValue
)
748 #undef CASE__SMPRINTF_NUMBER
752 return NS_ERROR_OUT_OF_MEMORY
;
754 aOutString
.Assign(pptr
.get());
758 nsresult
nsDiscriminatedUnion::ConvertToAString(nsAString
& aResult
) const {
760 case nsIDataType::VTYPE_ASTRING
:
761 aResult
.Assign(*u
.mAStringValue
);
763 case nsIDataType::VTYPE_CSTRING
:
764 CopyASCIItoUTF16(*u
.mCStringValue
, aResult
);
766 case nsIDataType::VTYPE_UTF8STRING
:
767 CopyUTF8toUTF16(*u
.mUTF8StringValue
, aResult
);
769 case nsIDataType::VTYPE_CHAR_STR
:
770 CopyASCIItoUTF16(mozilla::MakeStringSpan(u
.str
.mStringValue
), aResult
);
772 case nsIDataType::VTYPE_WCHAR_STR
:
773 aResult
.Assign(u
.wstr
.mWStringValue
);
775 case nsIDataType::VTYPE_STRING_SIZE_IS
:
777 nsDependentCString(u
.str
.mStringValue
, u
.str
.mStringLength
), aResult
);
779 case nsIDataType::VTYPE_WSTRING_SIZE_IS
:
780 aResult
.Assign(u
.wstr
.mWStringValue
, u
.wstr
.mWStringLength
);
782 case nsIDataType::VTYPE_WCHAR
:
783 aResult
.Assign(u
.mWCharValue
);
786 nsAutoCString tempCString
;
787 nsresult rv
= ToString(tempCString
);
791 CopyASCIItoUTF16(tempCString
, aResult
);
797 nsresult
nsDiscriminatedUnion::ConvertToACString(nsACString
& aResult
) const {
799 case nsIDataType::VTYPE_ASTRING
:
800 LossyCopyUTF16toASCII(*u
.mAStringValue
, aResult
);
802 case nsIDataType::VTYPE_CSTRING
:
803 aResult
.Assign(*u
.mCStringValue
);
805 case nsIDataType::VTYPE_UTF8STRING
:
806 // XXX This is an extra copy that should be avoided
807 // once Jag lands support for UTF8String and associated
808 // conversion methods.
809 LossyCopyUTF16toASCII(NS_ConvertUTF8toUTF16(*u
.mUTF8StringValue
),
812 case nsIDataType::VTYPE_CHAR_STR
:
813 aResult
.Assign(*u
.str
.mStringValue
);
815 case nsIDataType::VTYPE_WCHAR_STR
:
816 LossyCopyUTF16toASCII(nsDependentString(u
.wstr
.mWStringValue
), aResult
);
818 case nsIDataType::VTYPE_STRING_SIZE_IS
:
819 aResult
.Assign(u
.str
.mStringValue
, u
.str
.mStringLength
);
821 case nsIDataType::VTYPE_WSTRING_SIZE_IS
:
822 LossyCopyUTF16toASCII(
823 nsDependentString(u
.wstr
.mWStringValue
, u
.wstr
.mWStringLength
),
826 case nsIDataType::VTYPE_WCHAR
: {
827 const char16_t
* str
= &u
.mWCharValue
;
828 LossyCopyUTF16toASCII(Substring(str
, 1), aResult
);
832 return ToString(aResult
);
836 nsresult
nsDiscriminatedUnion::ConvertToAUTF8String(
837 nsAUTF8String
& aResult
) const {
839 case nsIDataType::VTYPE_ASTRING
:
840 CopyUTF16toUTF8(*u
.mAStringValue
, aResult
);
842 case nsIDataType::VTYPE_CSTRING
:
843 // XXX Extra copy, can be removed if we're sure CSTRING can
844 // only contain ASCII.
845 CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(*u
.mCStringValue
), aResult
);
847 case nsIDataType::VTYPE_UTF8STRING
:
848 aResult
.Assign(*u
.mUTF8StringValue
);
850 case nsIDataType::VTYPE_CHAR_STR
:
851 // XXX Extra copy, can be removed if we're sure CHAR_STR can
852 // only contain ASCII.
853 CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(u
.str
.mStringValue
), aResult
);
855 case nsIDataType::VTYPE_WCHAR_STR
:
856 CopyUTF16toUTF8(mozilla::MakeStringSpan(u
.wstr
.mWStringValue
), aResult
);
858 case nsIDataType::VTYPE_STRING_SIZE_IS
:
859 // XXX Extra copy, can be removed if we're sure CHAR_STR can
860 // only contain ASCII.
861 CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(nsDependentCString(
862 u
.str
.mStringValue
, u
.str
.mStringLength
)),
865 case nsIDataType::VTYPE_WSTRING_SIZE_IS
:
867 nsDependentString(u
.wstr
.mWStringValue
, u
.wstr
.mWStringLength
),
870 case nsIDataType::VTYPE_WCHAR
: {
871 const char16_t
* str
= &u
.mWCharValue
;
872 CopyUTF16toUTF8(Substring(str
, 1), aResult
);
876 nsAutoCString tempCString
;
877 nsresult rv
= ToString(tempCString
);
881 // XXX Extra copy, can be removed if we're sure tempCString can
882 // only contain ASCII.
883 CopyUTF16toUTF8(NS_ConvertASCIItoUTF16(tempCString
), aResult
);
889 nsresult
nsDiscriminatedUnion::ConvertToString(char** aResult
) const {
891 return ConvertToStringWithSize(&ignored
, aResult
);
894 nsresult
nsDiscriminatedUnion::ConvertToWString(char16_t
** aResult
) const {
896 return ConvertToWStringWithSize(&ignored
, aResult
);
899 nsresult
nsDiscriminatedUnion::ConvertToStringWithSize(uint32_t* aSize
,
901 nsAutoString tempString
;
902 nsAutoCString tempCString
;
906 case nsIDataType::VTYPE_ASTRING
:
907 *aSize
= u
.mAStringValue
->Length();
908 *aStr
= ToNewCString(*u
.mAStringValue
);
910 case nsIDataType::VTYPE_CSTRING
:
911 *aSize
= u
.mCStringValue
->Length();
912 *aStr
= ToNewCString(*u
.mCStringValue
);
914 case nsIDataType::VTYPE_UTF8STRING
: {
915 // XXX This is doing 1 extra copy. Need to fix this
916 // when Jag lands UTF8String
918 // *aSize = *mUTF8StringValue->Length();
919 // *aStr = ToNewCString(*mUTF8StringValue);
920 // But this will have to do for now.
921 const NS_ConvertUTF8toUTF16
tempString16(*u
.mUTF8StringValue
);
922 *aSize
= tempString16
.Length();
923 *aStr
= ToNewCString(tempString16
);
926 case nsIDataType::VTYPE_CHAR_STR
: {
927 nsDependentCString
cString(u
.str
.mStringValue
);
928 *aSize
= cString
.Length();
929 *aStr
= ToNewCString(cString
);
932 case nsIDataType::VTYPE_WCHAR_STR
: {
933 nsDependentString
string(u
.wstr
.mWStringValue
);
934 *aSize
= string
.Length();
935 *aStr
= ToNewCString(string
);
938 case nsIDataType::VTYPE_STRING_SIZE_IS
: {
939 nsDependentCString
cString(u
.str
.mStringValue
, u
.str
.mStringLength
);
940 *aSize
= cString
.Length();
941 *aStr
= ToNewCString(cString
);
944 case nsIDataType::VTYPE_WSTRING_SIZE_IS
: {
945 nsDependentString
string(u
.wstr
.mWStringValue
, u
.wstr
.mWStringLength
);
946 *aSize
= string
.Length();
947 *aStr
= ToNewCString(string
);
950 case nsIDataType::VTYPE_WCHAR
:
951 tempString
.Assign(u
.mWCharValue
);
952 *aSize
= tempString
.Length();
953 *aStr
= ToNewCString(tempString
);
956 rv
= ToString(tempCString
);
960 *aSize
= tempCString
.Length();
961 *aStr
= ToNewCString(tempCString
);
965 return *aStr
? NS_OK
: NS_ERROR_OUT_OF_MEMORY
;
967 nsresult
nsDiscriminatedUnion::ConvertToWStringWithSize(uint32_t* aSize
,
968 char16_t
** aStr
) const {
969 nsAutoString tempString
;
970 nsAutoCString tempCString
;
974 case nsIDataType::VTYPE_ASTRING
:
975 *aSize
= u
.mAStringValue
->Length();
976 *aStr
= ToNewUnicode(*u
.mAStringValue
);
978 case nsIDataType::VTYPE_CSTRING
:
979 *aSize
= u
.mCStringValue
->Length();
980 *aStr
= ToNewUnicode(*u
.mCStringValue
);
982 case nsIDataType::VTYPE_UTF8STRING
: {
983 *aStr
= UTF8ToNewUnicode(*u
.mUTF8StringValue
, aSize
);
986 case nsIDataType::VTYPE_CHAR_STR
: {
987 nsDependentCString
cString(u
.str
.mStringValue
);
988 *aSize
= cString
.Length();
989 *aStr
= ToNewUnicode(cString
);
992 case nsIDataType::VTYPE_WCHAR_STR
: {
993 nsDependentString
string(u
.wstr
.mWStringValue
);
994 *aSize
= string
.Length();
995 *aStr
= ToNewUnicode(string
);
998 case nsIDataType::VTYPE_STRING_SIZE_IS
: {
999 nsDependentCString
cString(u
.str
.mStringValue
, u
.str
.mStringLength
);
1000 *aSize
= cString
.Length();
1001 *aStr
= ToNewUnicode(cString
);
1004 case nsIDataType::VTYPE_WSTRING_SIZE_IS
: {
1005 nsDependentString
string(u
.wstr
.mWStringValue
, u
.wstr
.mWStringLength
);
1006 *aSize
= string
.Length();
1007 *aStr
= ToNewUnicode(string
);
1010 case nsIDataType::VTYPE_WCHAR
:
1011 tempString
.Assign(u
.mWCharValue
);
1012 *aSize
= tempString
.Length();
1013 *aStr
= ToNewUnicode(tempString
);
1016 rv
= ToString(tempCString
);
1017 if (NS_FAILED(rv
)) {
1020 *aSize
= tempCString
.Length();
1021 *aStr
= ToNewUnicode(tempCString
);
1025 return *aStr
? NS_OK
: NS_ERROR_OUT_OF_MEMORY
;
1028 nsresult
nsDiscriminatedUnion::ConvertToISupports(nsISupports
** aResult
) const {
1030 case nsIDataType::VTYPE_INTERFACE
:
1031 case nsIDataType::VTYPE_INTERFACE_IS
:
1032 if (u
.iface
.mInterfaceValue
) {
1033 return u
.iface
.mInterfaceValue
->QueryInterface(NS_GET_IID(nsISupports
),
1040 return NS_ERROR_CANNOT_CONVERT_DATA
;
1044 nsresult
nsDiscriminatedUnion::ConvertToInterface(nsIID
** aIID
,
1045 void** aInterface
) const {
1049 case nsIDataType::VTYPE_INTERFACE
:
1050 piid
= &NS_GET_IID(nsISupports
);
1052 case nsIDataType::VTYPE_INTERFACE_IS
:
1053 piid
= &u
.iface
.mInterfaceID
;
1056 return NS_ERROR_CANNOT_CONVERT_DATA
;
1059 *aIID
= piid
->Clone();
1061 if (u
.iface
.mInterfaceValue
) {
1062 return u
.iface
.mInterfaceValue
->QueryInterface(*piid
, aInterface
);
1065 *aInterface
= nullptr;
1069 nsresult
nsDiscriminatedUnion::ConvertToArray(uint16_t* aType
, nsIID
* aIID
,
1071 void** aPtr
) const {
1072 // XXX perhaps we'd like to add support for converting each of the various
1073 // types into an array containing one element of that type. We can leverage
1074 // CloneArray to do this if we want to support this.
1076 if (mType
== nsIDataType::VTYPE_ARRAY
) {
1077 return CloneArray(u
.array
.mArrayType
, &u
.array
.mArrayInterfaceID
,
1078 u
.array
.mArrayCount
, u
.array
.mArrayValue
, aType
, aIID
,
1081 return NS_ERROR_CANNOT_CONVERT_DATA
;
1084 /***************************************************************************/
1085 // static setter functions...
1087 #define DATA_SETTER_PROLOGUE Cleanup()
1089 #define DATA_SETTER_EPILOGUE(type_) mType = nsIDataType::type_;
1091 #define DATA_SETTER(type_, member_, value_) \
1092 DATA_SETTER_PROLOGUE; \
1093 u.member_ = value_; \
1094 DATA_SETTER_EPILOGUE(type_)
1096 #define DATA_SETTER_WITH_CAST(type_, member_, cast_, value_) \
1097 DATA_SETTER_PROLOGUE; \
1098 u.member_ = cast_ value_; \
1099 DATA_SETTER_EPILOGUE(type_)
1101 /********************************************/
1103 #define CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_) {
1104 #define CASE__SET_FROM_VARIANT_VTYPE__GETTER(member_, name_) \
1105 rv = aValue->GetAs##name_(&(u.member_));
1107 #define CASE__SET_FROM_VARIANT_VTYPE__GETTER_CAST(cast_, member_, name_) \
1108 rv = aValue->GetAs##name_(cast_ & (u.member_));
1110 #define CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_) \
1111 if (NS_SUCCEEDED(rv)) { \
1112 mType = nsIDataType::type_; \
1117 #define CASE__SET_FROM_VARIANT_TYPE(type_, member_, name_) \
1118 case nsIDataType::type_: \
1119 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_) \
1120 CASE__SET_FROM_VARIANT_VTYPE__GETTER(member_, name_) \
1121 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)
1123 #define CASE__SET_FROM_VARIANT_VTYPE_CAST(type_, cast_, member_, name_) \
1124 case nsIDataType::type_: \
1125 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(type_) \
1126 CASE__SET_FROM_VARIANT_VTYPE__GETTER_CAST(cast_, member_, name_) \
1127 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(type_)
1129 nsresult
nsDiscriminatedUnion::SetFromVariant(nsIVariant
* aValue
) {
1130 nsresult rv
= NS_OK
;
1134 uint16_t type
= aValue
->GetDataType();
1137 CASE__SET_FROM_VARIANT_VTYPE_CAST(VTYPE_INT8
, (uint8_t*), mInt8Value
, Int8
)
1138 CASE__SET_FROM_VARIANT_TYPE(VTYPE_INT16
, mInt16Value
, Int16
)
1139 CASE__SET_FROM_VARIANT_TYPE(VTYPE_INT32
, mInt32Value
, Int32
)
1140 CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT8
, mUint8Value
, Uint8
)
1141 CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT16
, mUint16Value
, Uint16
)
1142 CASE__SET_FROM_VARIANT_TYPE(VTYPE_UINT32
, mUint32Value
, Uint32
)
1143 CASE__SET_FROM_VARIANT_TYPE(VTYPE_FLOAT
, mFloatValue
, Float
)
1144 CASE__SET_FROM_VARIANT_TYPE(VTYPE_DOUBLE
, mDoubleValue
, Double
)
1145 CASE__SET_FROM_VARIANT_TYPE(VTYPE_BOOL
, mBoolValue
, Bool
)
1146 CASE__SET_FROM_VARIANT_TYPE(VTYPE_CHAR
, mCharValue
, Char
)
1147 CASE__SET_FROM_VARIANT_TYPE(VTYPE_WCHAR
, mWCharValue
, WChar
)
1148 CASE__SET_FROM_VARIANT_TYPE(VTYPE_ID
, mIDValue
, ID
)
1150 case nsIDataType::VTYPE_ASTRING
:
1151 case nsIDataType::VTYPE_WCHAR_STR
:
1152 case nsIDataType::VTYPE_WSTRING_SIZE_IS
:
1153 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_ASTRING
);
1154 u
.mAStringValue
= new nsString();
1156 rv
= aValue
->GetAsAString(*u
.mAStringValue
);
1157 if (NS_FAILED(rv
)) {
1158 delete u
.mAStringValue
;
1160 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_ASTRING
)
1162 case nsIDataType::VTYPE_CSTRING
:
1163 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_CSTRING
);
1164 u
.mCStringValue
= new nsCString();
1166 rv
= aValue
->GetAsACString(*u
.mCStringValue
);
1167 if (NS_FAILED(rv
)) {
1168 delete u
.mCStringValue
;
1170 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_CSTRING
)
1172 case nsIDataType::VTYPE_UTF8STRING
:
1173 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_UTF8STRING
);
1174 u
.mUTF8StringValue
= new nsUTF8String();
1176 rv
= aValue
->GetAsAUTF8String(*u
.mUTF8StringValue
);
1177 if (NS_FAILED(rv
)) {
1178 delete u
.mUTF8StringValue
;
1180 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_UTF8STRING
)
1182 case nsIDataType::VTYPE_CHAR_STR
:
1183 case nsIDataType::VTYPE_STRING_SIZE_IS
:
1184 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_STRING_SIZE_IS
);
1185 rv
= aValue
->GetAsStringWithSize(&u
.str
.mStringLength
,
1186 &u
.str
.mStringValue
);
1187 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_STRING_SIZE_IS
)
1189 case nsIDataType::VTYPE_INTERFACE
:
1190 case nsIDataType::VTYPE_INTERFACE_IS
:
1191 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_INTERFACE_IS
);
1192 // XXX This iid handling is ugly!
1194 rv
= aValue
->GetAsInterface(&iid
, (void**)&u
.iface
.mInterfaceValue
);
1195 if (NS_SUCCEEDED(rv
)) {
1196 u
.iface
.mInterfaceID
= *iid
;
1199 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_INTERFACE_IS
)
1201 case nsIDataType::VTYPE_ARRAY
:
1202 CASE__SET_FROM_VARIANT_VTYPE_PROLOGUE(VTYPE_ARRAY
);
1203 rv
= aValue
->GetAsArray(&u
.array
.mArrayType
, &u
.array
.mArrayInterfaceID
,
1204 &u
.array
.mArrayCount
, &u
.array
.mArrayValue
);
1205 CASE__SET_FROM_VARIANT_VTYPE_EPILOGUE(VTYPE_ARRAY
)
1207 case nsIDataType::VTYPE_VOID
:
1211 case nsIDataType::VTYPE_EMPTY_ARRAY
:
1215 case nsIDataType::VTYPE_EMPTY
:
1220 NS_ERROR("bad type in variant!");
1221 rv
= NS_ERROR_FAILURE
;
1227 void nsDiscriminatedUnion::SetFromInt8(uint8_t aValue
) {
1228 DATA_SETTER_WITH_CAST(VTYPE_INT8
, mInt8Value
, (uint8_t), aValue
);
1230 void nsDiscriminatedUnion::SetFromInt16(int16_t aValue
) {
1231 DATA_SETTER(VTYPE_INT16
, mInt16Value
, aValue
);
1233 void nsDiscriminatedUnion::SetFromInt32(int32_t aValue
) {
1234 DATA_SETTER(VTYPE_INT32
, mInt32Value
, aValue
);
1236 void nsDiscriminatedUnion::SetFromInt64(int64_t aValue
) {
1237 DATA_SETTER(VTYPE_INT64
, mInt64Value
, aValue
);
1239 void nsDiscriminatedUnion::SetFromUint8(uint8_t aValue
) {
1240 DATA_SETTER(VTYPE_UINT8
, mUint8Value
, aValue
);
1242 void nsDiscriminatedUnion::SetFromUint16(uint16_t aValue
) {
1243 DATA_SETTER(VTYPE_UINT16
, mUint16Value
, aValue
);
1245 void nsDiscriminatedUnion::SetFromUint32(uint32_t aValue
) {
1246 DATA_SETTER(VTYPE_UINT32
, mUint32Value
, aValue
);
1248 void nsDiscriminatedUnion::SetFromUint64(uint64_t aValue
) {
1249 DATA_SETTER(VTYPE_UINT64
, mUint64Value
, aValue
);
1251 void nsDiscriminatedUnion::SetFromFloat(float aValue
) {
1252 DATA_SETTER(VTYPE_FLOAT
, mFloatValue
, aValue
);
1254 void nsDiscriminatedUnion::SetFromDouble(double aValue
) {
1255 DATA_SETTER(VTYPE_DOUBLE
, mDoubleValue
, aValue
);
1257 void nsDiscriminatedUnion::SetFromBool(bool aValue
) {
1258 DATA_SETTER(VTYPE_BOOL
, mBoolValue
, aValue
);
1260 void nsDiscriminatedUnion::SetFromChar(char aValue
) {
1261 DATA_SETTER(VTYPE_CHAR
, mCharValue
, aValue
);
1263 void nsDiscriminatedUnion::SetFromWChar(char16_t aValue
) {
1264 DATA_SETTER(VTYPE_WCHAR
, mWCharValue
, aValue
);
1266 void nsDiscriminatedUnion::SetFromID(const nsID
& aValue
) {
1267 DATA_SETTER(VTYPE_ID
, mIDValue
, aValue
);
1269 void nsDiscriminatedUnion::SetFromAString(const nsAString
& aValue
) {
1270 DATA_SETTER_PROLOGUE
;
1271 u
.mAStringValue
= new nsString(aValue
);
1272 DATA_SETTER_EPILOGUE(VTYPE_ASTRING
);
1275 void nsDiscriminatedUnion::SetFromACString(const nsACString
& aValue
) {
1276 DATA_SETTER_PROLOGUE
;
1277 u
.mCStringValue
= new nsCString(aValue
);
1278 DATA_SETTER_EPILOGUE(VTYPE_CSTRING
);
1281 void nsDiscriminatedUnion::SetFromAUTF8String(const nsAUTF8String
& aValue
) {
1282 DATA_SETTER_PROLOGUE
;
1283 u
.mUTF8StringValue
= new nsUTF8String(aValue
);
1284 DATA_SETTER_EPILOGUE(VTYPE_UTF8STRING
);
1287 nsresult
nsDiscriminatedUnion::SetFromString(const char* aValue
) {
1288 DATA_SETTER_PROLOGUE
;
1290 return NS_ERROR_NULL_POINTER
;
1292 return SetFromStringWithSize(strlen(aValue
), aValue
);
1294 nsresult
nsDiscriminatedUnion::SetFromWString(const char16_t
* aValue
) {
1295 DATA_SETTER_PROLOGUE
;
1297 return NS_ERROR_NULL_POINTER
;
1299 return SetFromWStringWithSize(NS_strlen(aValue
), aValue
);
1301 void nsDiscriminatedUnion::SetFromISupports(nsISupports
* aValue
) {
1302 return SetFromInterface(NS_GET_IID(nsISupports
), aValue
);
1304 void nsDiscriminatedUnion::SetFromInterface(const nsIID
& aIID
,
1305 nsISupports
* aValue
) {
1306 DATA_SETTER_PROLOGUE
;
1307 NS_IF_ADDREF(aValue
);
1308 u
.iface
.mInterfaceValue
= aValue
;
1309 u
.iface
.mInterfaceID
= aIID
;
1310 DATA_SETTER_EPILOGUE(VTYPE_INTERFACE_IS
);
1312 nsresult
nsDiscriminatedUnion::SetFromArray(uint16_t aType
, const nsIID
* aIID
,
1313 uint32_t aCount
, void* aValue
) {
1314 DATA_SETTER_PROLOGUE
;
1315 if (!aValue
|| !aCount
) {
1316 return NS_ERROR_NULL_POINTER
;
1319 nsresult rv
= CloneArray(aType
, aIID
, aCount
, aValue
, &u
.array
.mArrayType
,
1320 &u
.array
.mArrayInterfaceID
, &u
.array
.mArrayCount
,
1321 &u
.array
.mArrayValue
);
1322 if (NS_FAILED(rv
)) {
1325 DATA_SETTER_EPILOGUE(VTYPE_ARRAY
);
1328 nsresult
nsDiscriminatedUnion::SetFromStringWithSize(uint32_t aSize
,
1329 const char* aValue
) {
1330 DATA_SETTER_PROLOGUE
;
1332 return NS_ERROR_NULL_POINTER
;
1334 u
.str
.mStringValue
= (char*)moz_xmemdup(aValue
, (aSize
+ 1) * sizeof(char));
1335 u
.str
.mStringLength
= aSize
;
1336 DATA_SETTER_EPILOGUE(VTYPE_STRING_SIZE_IS
);
1339 nsresult
nsDiscriminatedUnion::SetFromWStringWithSize(uint32_t aSize
,
1340 const char16_t
* aValue
) {
1341 DATA_SETTER_PROLOGUE
;
1343 return NS_ERROR_NULL_POINTER
;
1345 u
.wstr
.mWStringValue
=
1346 (char16_t
*)moz_xmemdup(aValue
, (aSize
+ 1) * sizeof(char16_t
));
1347 u
.wstr
.mWStringLength
= aSize
;
1348 DATA_SETTER_EPILOGUE(VTYPE_WSTRING_SIZE_IS
);
1351 void nsDiscriminatedUnion::AllocateWStringWithSize(uint32_t aSize
) {
1352 DATA_SETTER_PROLOGUE
;
1353 u
.wstr
.mWStringValue
= (char16_t
*)moz_xmalloc((aSize
+ 1) * sizeof(char16_t
));
1354 u
.wstr
.mWStringValue
[aSize
] = '\0';
1355 u
.wstr
.mWStringLength
= aSize
;
1356 DATA_SETTER_EPILOGUE(VTYPE_WSTRING_SIZE_IS
);
1358 void nsDiscriminatedUnion::SetToVoid() {
1359 DATA_SETTER_PROLOGUE
;
1360 DATA_SETTER_EPILOGUE(VTYPE_VOID
);
1362 void nsDiscriminatedUnion::SetToEmpty() {
1363 DATA_SETTER_PROLOGUE
;
1364 DATA_SETTER_EPILOGUE(VTYPE_EMPTY
);
1366 void nsDiscriminatedUnion::SetToEmptyArray() {
1367 DATA_SETTER_PROLOGUE
;
1368 DATA_SETTER_EPILOGUE(VTYPE_EMPTY_ARRAY
);
1371 /***************************************************************************/
1373 void nsDiscriminatedUnion::Cleanup() {
1375 case nsIDataType::VTYPE_INT8
:
1376 case nsIDataType::VTYPE_INT16
:
1377 case nsIDataType::VTYPE_INT32
:
1378 case nsIDataType::VTYPE_INT64
:
1379 case nsIDataType::VTYPE_UINT8
:
1380 case nsIDataType::VTYPE_UINT16
:
1381 case nsIDataType::VTYPE_UINT32
:
1382 case nsIDataType::VTYPE_UINT64
:
1383 case nsIDataType::VTYPE_FLOAT
:
1384 case nsIDataType::VTYPE_DOUBLE
:
1385 case nsIDataType::VTYPE_BOOL
:
1386 case nsIDataType::VTYPE_CHAR
:
1387 case nsIDataType::VTYPE_WCHAR
:
1388 case nsIDataType::VTYPE_VOID
:
1389 case nsIDataType::VTYPE_ID
:
1391 case nsIDataType::VTYPE_ASTRING
:
1392 delete u
.mAStringValue
;
1394 case nsIDataType::VTYPE_CSTRING
:
1395 delete u
.mCStringValue
;
1397 case nsIDataType::VTYPE_UTF8STRING
:
1398 delete u
.mUTF8StringValue
;
1400 case nsIDataType::VTYPE_CHAR_STR
:
1401 case nsIDataType::VTYPE_STRING_SIZE_IS
:
1402 free((char*)u
.str
.mStringValue
);
1404 case nsIDataType::VTYPE_WCHAR_STR
:
1405 case nsIDataType::VTYPE_WSTRING_SIZE_IS
:
1406 free((char*)u
.wstr
.mWStringValue
);
1408 case nsIDataType::VTYPE_INTERFACE
:
1409 case nsIDataType::VTYPE_INTERFACE_IS
:
1410 NS_IF_RELEASE(u
.iface
.mInterfaceValue
);
1412 case nsIDataType::VTYPE_ARRAY
:
1415 case nsIDataType::VTYPE_EMPTY_ARRAY
:
1416 case nsIDataType::VTYPE_EMPTY
:
1419 NS_ERROR("bad type in variant!");
1423 mType
= nsIDataType::VTYPE_EMPTY
;
1426 void nsDiscriminatedUnion::Traverse(
1427 nsCycleCollectionTraversalCallback
& aCb
) const {
1429 case nsIDataType::VTYPE_INTERFACE
:
1430 case nsIDataType::VTYPE_INTERFACE_IS
:
1431 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb
, "mData");
1432 aCb
.NoteXPCOMChild(u
.iface
.mInterfaceValue
);
1434 case nsIDataType::VTYPE_ARRAY
:
1435 switch (u
.array
.mArrayType
) {
1436 case nsIDataType::VTYPE_INTERFACE
:
1437 case nsIDataType::VTYPE_INTERFACE_IS
: {
1438 nsISupports
** p
= (nsISupports
**)u
.array
.mArrayValue
;
1439 for (uint32_t i
= u
.array
.mArrayCount
; i
> 0; ++p
, --i
) {
1440 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb
, "mData[i]");
1441 aCb
.NoteXPCOMChild(*p
);
1454 /***************************************************************************/
1455 /***************************************************************************/
1458 nsVariantBase::nsVariantBase() : mWritable(true) {}
1460 // For all the data getters we just forward to the static (and sharable)
1461 // 'ConvertTo' functions.
1463 uint16_t nsVariantBase::GetDataType() { return mData
.GetType(); }
1466 nsVariantBase::GetAsInt8(uint8_t* aResult
) {
1467 return mData
.ConvertToInt8(aResult
);
1471 nsVariantBase::GetAsInt16(int16_t* aResult
) {
1472 return mData
.ConvertToInt16(aResult
);
1476 nsVariantBase::GetAsInt32(int32_t* aResult
) {
1477 return mData
.ConvertToInt32(aResult
);
1481 nsVariantBase::GetAsInt64(int64_t* aResult
) {
1482 return mData
.ConvertToInt64(aResult
);
1486 nsVariantBase::GetAsUint8(uint8_t* aResult
) {
1487 return mData
.ConvertToUint8(aResult
);
1491 nsVariantBase::GetAsUint16(uint16_t* aResult
) {
1492 return mData
.ConvertToUint16(aResult
);
1496 nsVariantBase::GetAsUint32(uint32_t* aResult
) {
1497 return mData
.ConvertToUint32(aResult
);
1501 nsVariantBase::GetAsUint64(uint64_t* aResult
) {
1502 return mData
.ConvertToUint64(aResult
);
1506 nsVariantBase::GetAsFloat(float* aResult
) {
1507 return mData
.ConvertToFloat(aResult
);
1511 nsVariantBase::GetAsDouble(double* aResult
) {
1512 return mData
.ConvertToDouble(aResult
);
1516 nsVariantBase::GetAsBool(bool* aResult
) { return mData
.ConvertToBool(aResult
); }
1519 nsVariantBase::GetAsChar(char* aResult
) { return mData
.ConvertToChar(aResult
); }
1522 nsVariantBase::GetAsWChar(char16_t
* aResult
) {
1523 return mData
.ConvertToWChar(aResult
);
1526 NS_IMETHODIMP_(nsresult
)
1527 nsVariantBase::GetAsID(nsID
* aResult
) { return mData
.ConvertToID(aResult
); }
1530 nsVariantBase::GetAsAString(nsAString
& aResult
) {
1531 return mData
.ConvertToAString(aResult
);
1535 nsVariantBase::GetAsACString(nsACString
& aResult
) {
1536 return mData
.ConvertToACString(aResult
);
1540 nsVariantBase::GetAsAUTF8String(nsAUTF8String
& aResult
) {
1541 return mData
.ConvertToAUTF8String(aResult
);
1545 nsVariantBase::GetAsString(char** aResult
) {
1546 return mData
.ConvertToString(aResult
);
1550 nsVariantBase::GetAsWString(char16_t
** aResult
) {
1551 return mData
.ConvertToWString(aResult
);
1555 nsVariantBase::GetAsISupports(nsISupports
** aResult
) {
1556 return mData
.ConvertToISupports(aResult
);
1560 nsVariantBase::GetAsJSVal(JS::MutableHandleValue
) {
1561 // Can only get the jsval from an XPCVariant.
1562 return NS_ERROR_CANNOT_CONVERT_DATA
;
1566 nsVariantBase::GetAsInterface(nsIID
** aIID
, void** aInterface
) {
1567 return mData
.ConvertToInterface(aIID
, aInterface
);
1570 NS_IMETHODIMP_(nsresult
)
1571 nsVariantBase::GetAsArray(uint16_t* aType
, nsIID
* aIID
, uint32_t* aCount
,
1573 return mData
.ConvertToArray(aType
, aIID
, aCount
, aPtr
);
1577 nsVariantBase::GetAsStringWithSize(uint32_t* aSize
, char** aStr
) {
1578 return mData
.ConvertToStringWithSize(aSize
, aStr
);
1582 nsVariantBase::GetAsWStringWithSize(uint32_t* aSize
, char16_t
** aStr
) {
1583 return mData
.ConvertToWStringWithSize(aSize
, aStr
);
1586 /***************************************************************************/
1589 nsVariantBase::GetWritable(bool* aWritable
) {
1590 *aWritable
= mWritable
;
1594 nsVariantBase::SetWritable(bool aWritable
) {
1595 if (!mWritable
&& aWritable
) {
1596 return NS_ERROR_FAILURE
;
1598 mWritable
= aWritable
;
1602 /***************************************************************************/
1604 // For all the data setters we just forward to the static (and sharable)
1605 // 'SetFrom' functions.
1608 nsVariantBase::SetAsInt8(uint8_t aValue
) {
1610 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1612 mData
.SetFromInt8(aValue
);
1617 nsVariantBase::SetAsInt16(int16_t aValue
) {
1619 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1621 mData
.SetFromInt16(aValue
);
1626 nsVariantBase::SetAsInt32(int32_t aValue
) {
1628 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1630 mData
.SetFromInt32(aValue
);
1635 nsVariantBase::SetAsInt64(int64_t aValue
) {
1637 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1639 mData
.SetFromInt64(aValue
);
1644 nsVariantBase::SetAsUint8(uint8_t aValue
) {
1646 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1648 mData
.SetFromUint8(aValue
);
1653 nsVariantBase::SetAsUint16(uint16_t aValue
) {
1655 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1657 mData
.SetFromUint16(aValue
);
1662 nsVariantBase::SetAsUint32(uint32_t aValue
) {
1664 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1666 mData
.SetFromUint32(aValue
);
1671 nsVariantBase::SetAsUint64(uint64_t aValue
) {
1673 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1675 mData
.SetFromUint64(aValue
);
1680 nsVariantBase::SetAsFloat(float aValue
) {
1682 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1684 mData
.SetFromFloat(aValue
);
1689 nsVariantBase::SetAsDouble(double aValue
) {
1691 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1693 mData
.SetFromDouble(aValue
);
1698 nsVariantBase::SetAsBool(bool aValue
) {
1700 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1702 mData
.SetFromBool(aValue
);
1707 nsVariantBase::SetAsChar(char aValue
) {
1709 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1711 mData
.SetFromChar(aValue
);
1716 nsVariantBase::SetAsWChar(char16_t aValue
) {
1718 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1720 mData
.SetFromWChar(aValue
);
1725 nsVariantBase::SetAsID(const nsID
& aValue
) {
1727 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1729 mData
.SetFromID(aValue
);
1734 nsVariantBase::SetAsAString(const nsAString
& aValue
) {
1736 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1738 mData
.SetFromAString(aValue
);
1743 nsVariantBase::SetAsACString(const nsACString
& aValue
) {
1745 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1747 mData
.SetFromACString(aValue
);
1752 nsVariantBase::SetAsAUTF8String(const nsAUTF8String
& aValue
) {
1754 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1756 mData
.SetFromAUTF8String(aValue
);
1761 nsVariantBase::SetAsString(const char* aValue
) {
1763 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1765 return mData
.SetFromString(aValue
);
1769 nsVariantBase::SetAsWString(const char16_t
* aValue
) {
1771 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1773 return mData
.SetFromWString(aValue
);
1777 nsVariantBase::SetAsISupports(nsISupports
* aValue
) {
1779 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1781 mData
.SetFromISupports(aValue
);
1786 nsVariantBase::SetAsInterface(const nsIID
& aIID
, void* aInterface
) {
1788 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1790 mData
.SetFromInterface(aIID
, (nsISupports
*)aInterface
);
1795 nsVariantBase::SetAsArray(uint16_t aType
, const nsIID
* aIID
, uint32_t aCount
,
1798 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1800 return mData
.SetFromArray(aType
, aIID
, aCount
, aPtr
);
1804 nsVariantBase::SetAsStringWithSize(uint32_t aSize
, const char* aStr
) {
1806 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1808 return mData
.SetFromStringWithSize(aSize
, aStr
);
1812 nsVariantBase::SetAsWStringWithSize(uint32_t aSize
, const char16_t
* aStr
) {
1814 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1816 return mData
.SetFromWStringWithSize(aSize
, aStr
);
1820 nsVariantBase::SetAsVoid() {
1822 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1829 nsVariantBase::SetAsEmpty() {
1831 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1838 nsVariantBase::SetAsEmptyArray() {
1840 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1842 mData
.SetToEmptyArray();
1847 nsVariantBase::SetFromVariant(nsIVariant
* aValue
) {
1849 return NS_ERROR_OBJECT_IS_IMMUTABLE
;
1851 return mData
.SetFromVariant(aValue
);
1854 /* nsVariant implementation */
1856 NS_IMPL_ISUPPORTS(nsVariant
, nsIVariant
, nsIWritableVariant
)
1858 /* nsVariantCC implementation */
1859 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsVariantCC
)
1860 NS_INTERFACE_MAP_ENTRY(nsISupports
)
1861 NS_INTERFACE_MAP_ENTRY(nsIVariant
)
1862 NS_INTERFACE_MAP_ENTRY(nsIWritableVariant
)
1863 NS_INTERFACE_MAP_END
1865 NS_IMPL_CYCLE_COLLECTION_CLASS(nsVariantCC
)
1867 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsVariantCC
)
1868 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsVariantCC
)
1870 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsVariantCC
)
1871 tmp
->mData
.Traverse(cb
);
1872 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
1874 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsVariantCC
)
1875 tmp
->mData
.Cleanup();
1876 NS_IMPL_CYCLE_COLLECTION_UNLINK_END