VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/ds/nsVariant.cpp@ 4837

Last change on this file since 4837 was 1, checked in by vboxsync, 54 years ago

import

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

© 2023 Oracle
ContactPrivacy policyTerms of Use