VirtualBox

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

最後變更 在這個檔案從102005是 102005,由 vboxsync 提交於 14 月 前

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

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