VirtualBox

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

最後變更 在這個檔案從104488是 102345,由 vboxsync 提交於 13 月 前

libs/xpcom: Replace remaining APIs from prprf.h with IPRT equivalents, bugref:10545

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette