1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkVariant.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15 /*-------------------------------------------------------------------------
16 Copyright 2008 Sandia Corporation.
17 Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
18 the U.S. Government retains certain rights in this software.
19 -------------------------------------------------------------------------*/
20
21 #include "vtkVariant.h"
22
23 #include "vtkStdString.h"
24 #include "vtkUnicodeString.h"
25 #include "vtkArrayIteratorIncludes.h"
26 #include "vtkAbstractArray.h"
27 #include "vtkDataArray.h"
28 #include "vtkVariantArray.h"
29 #include "vtkType.h"
30 #include "vtkSetGet.h"
31 #include "vtkObjectBase.h"
32 #include "vtkStringArray.h"
33 #include "vtkMath.h"
34
35 #include <sstream>
36 #include "vtksys/SystemTools.hxx"
37 #include <locale> // C++ locale
38
39 //----------------------------------------------------------------------------
40
41 // Implementation of vtkVariant's
42 // fast-but-potentially-counterintuitive < operation
operator ()(const vtkVariant & s1,const vtkVariant & s2) const43 bool vtkVariantStrictWeakOrder::operator()(const vtkVariant& s1, const vtkVariant& s2) const
44 {
45 // First sort on type if they are different
46 if (s1.Type != s2.Type)
47 {
48 return s1.Type < s2.Type;
49 }
50
51 // Next check for nulls
52 if (!(s1.Valid && s2.Valid))
53 {
54 if (!(s1.Valid || s2.Valid))
55 {
56 return false; // nulls are equal to one another
57 }
58 else if (!s1.Valid)
59 {
60 return true; // null is less than any valid value
61 }
62 else
63 {
64 return false;
65 }
66 }
67
68 switch (s1.Type)
69 {
70 case VTK_STRING:
71 return (*(s1.Data.String) < *(s2.Data.String));
72
73 case VTK_UNICODE_STRING:
74 return (*(s1.Data.UnicodeString) < *(s2.Data.UnicodeString));
75
76 case VTK_OBJECT:
77 return (s1.Data.VTKObject < s2.Data.VTKObject);
78
79 case VTK_CHAR:
80 return (s1.Data.Char < s2.Data.Char);
81
82 case VTK_SIGNED_CHAR:
83 return (s1.Data.SignedChar < s2.Data.SignedChar);
84
85 case VTK_UNSIGNED_CHAR:
86 return (s1.Data.UnsignedChar < s2.Data.UnsignedChar);
87
88 case VTK_SHORT:
89 return (s1.Data.Short < s2.Data.Short);
90
91 case VTK_UNSIGNED_SHORT:
92 return (s1.Data.UnsignedShort < s2.Data.UnsignedShort);
93
94 case VTK_INT:
95 return (s1.Data.Int < s2.Data.Int);
96
97 case VTK_UNSIGNED_INT:
98 return (s1.Data.UnsignedInt < s2.Data.UnsignedInt);
99
100 case VTK_LONG:
101 return (s1.Data.Long < s2.Data.Long);
102
103 case VTK_UNSIGNED_LONG:
104 return (s1.Data.UnsignedLong < s2.Data.UnsignedLong);
105
106 case VTK_LONG_LONG:
107 return (s1.Data.LongLong < s2.Data.LongLong);
108
109 case VTK_UNSIGNED_LONG_LONG:
110 return (s1.Data.UnsignedLongLong < s2.Data.UnsignedLongLong);
111
112 case VTK_FLOAT:
113 return (s1.Data.Float < s2.Data.Float);
114
115 case VTK_DOUBLE:
116 return (s1.Data.Double < s2.Data.Double);
117
118 default:
119 cerr << "ERROR: Unhandled type " << s1.Type << " in vtkVariantStrictWeakOrder\n";
120 return false;
121 }
122 }
123
124 // ----------------------------------------------------------------------
125
126 bool
operator ()(const vtkVariant & s1,const vtkVariant & s2) const127 vtkVariantStrictEquality::operator()(const vtkVariant &s1, const vtkVariant &s2) const
128 {
129 // First sort on type if they are different
130 if (s1.Type != s2.Type)
131 {
132 cerr << "Types differ: " << s1.Type << " and " << s2.Type << "\n";
133 return false;
134 }
135
136 // Next check for nulls
137 if (!(s1.Valid && s2.Valid))
138 {
139 cerr << "Validity may differ: " << s1.Valid << " and " << s2.Valid << "\n";
140 return (s1.Valid == s2.Valid);
141 }
142
143 // At this point we know that both variants contain a valid value.
144 switch (s1.Type)
145 {
146 case VTK_STRING:
147 {
148 if (*(s1.Data.String) != *(s2.Data.String))
149 {
150 cerr << "Strings differ: '"
151 << *(s1.Data.String) << "' and '"
152 << *(s2.Data.String) << "'\n";
153 }
154 return (*(s1.Data.String) == *(s2.Data.String));
155 };
156
157 case VTK_UNICODE_STRING:
158 return (*(s1.Data.UnicodeString) == *(s2.Data.UnicodeString));
159
160 case VTK_OBJECT:
161 return (s1.Data.VTKObject == s2.Data.VTKObject);
162
163 case VTK_CHAR:
164 return (s1.Data.Char == s2.Data.Char);
165
166 case VTK_SIGNED_CHAR:
167 return (s1.Data.SignedChar == s2.Data.SignedChar);
168
169 case VTK_UNSIGNED_CHAR:
170 return (s1.Data.UnsignedChar == s2.Data.UnsignedChar);
171
172 case VTK_SHORT:
173 return (s1.Data.Short == s2.Data.Short);
174
175 case VTK_UNSIGNED_SHORT:
176 return (s1.Data.UnsignedShort == s2.Data.UnsignedShort);
177
178 case VTK_INT:
179 return (s1.Data.Int == s2.Data.Int);
180
181 case VTK_UNSIGNED_INT:
182 return (s1.Data.UnsignedInt == s2.Data.UnsignedInt);
183
184 case VTK_LONG:
185 return (s1.Data.Long == s2.Data.Long);
186
187 case VTK_UNSIGNED_LONG:
188 return (s1.Data.UnsignedLong == s2.Data.UnsignedLong);
189
190 case VTK_LONG_LONG:
191 return (s1.Data.LongLong == s2.Data.LongLong);
192
193 case VTK_UNSIGNED_LONG_LONG:
194 return (s1.Data.UnsignedLongLong == s2.Data.UnsignedLongLong);
195
196 case VTK_FLOAT:
197 return (s1.Data.Float == s2.Data.Float);
198
199 case VTK_DOUBLE:
200 return (s1.Data.Double == s2.Data.Double);
201
202 default:
203 cerr << "ERROR: Unhandled type " << s1.Type << " in vtkVariantStrictEquality\n";
204 return false;
205 }
206 }
207
208 // ----------------------------------------------------------------------
209
210 bool
operator ()(const vtkVariant & v1,const vtkVariant & v2) const211 vtkVariantLessThan::operator()(const vtkVariant &v1, const vtkVariant &v2) const
212 {
213 return v1.operator<(v2);
214 }
215
216 // ----------------------------------------------------------------------
217
218 bool
operator ()(const vtkVariant & v1,const vtkVariant & v2) const219 vtkVariantEqual::operator()(const vtkVariant &v1, const vtkVariant &v2) const
220 {
221 return v1.operator==(v2);
222 }
223
224 //----------------------------------------------------------------------------
vtkVariant()225 vtkVariant::vtkVariant()
226 {
227 this->Valid = 0;
228 this->Type = 0;
229 }
230
vtkVariant(const vtkVariant & other)231 vtkVariant::vtkVariant(const vtkVariant & other)
232 {
233 this->Valid = other.Valid;
234 this->Type = other.Type;
235 this->Data = other.Data;
236 if (this->Valid)
237 {
238 switch (other.Type)
239 {
240 case VTK_STRING:
241 this->Data.String = new vtkStdString(*other.Data.String);
242 break;
243 case VTK_UNICODE_STRING:
244 this->Data.UnicodeString = new vtkUnicodeString(*other.Data.UnicodeString);
245 break;
246 case VTK_OBJECT:
247 this->Data.VTKObject->Register(nullptr);
248 break;
249 }
250 }
251 }
252
vtkVariant(const vtkVariant & s2,unsigned int type)253 vtkVariant::vtkVariant(const vtkVariant &s2, unsigned int type)
254 {
255 bool valid = false;
256
257 if (s2.Valid)
258 {
259 switch (type)
260 {
261 case VTK_STRING:
262 this->Data.String = new vtkStdString(s2.ToString());
263 valid = true;
264 break;
265
266 case VTK_UNICODE_STRING:
267 this->Data.UnicodeString =
268 new vtkUnicodeString(s2.ToUnicodeString());
269 valid = true;
270 break;
271
272 case VTK_OBJECT:
273 this->Data.VTKObject = s2.ToVTKObject();
274 if (this->Data.VTKObject)
275 {
276 this->Data.VTKObject->Register(nullptr);
277 valid = true;
278 }
279 break;
280
281 case VTK_CHAR:
282 this->Data.Char = s2.ToChar(&valid);
283 break;
284
285 case VTK_SIGNED_CHAR:
286 this->Data.SignedChar = s2.ToSignedChar(&valid);
287 break;
288
289 case VTK_UNSIGNED_CHAR:
290 this->Data.UnsignedChar = s2.ToUnsignedChar(&valid);
291 break;
292
293 case VTK_SHORT:
294 this->Data.Short = s2.ToShort(&valid);
295 break;
296
297 case VTK_UNSIGNED_SHORT:
298 this->Data.UnsignedShort = s2.ToUnsignedShort(&valid);
299 break;
300
301 case VTK_INT:
302 this->Data.Int = s2.ToInt(&valid);
303 break;
304
305 case VTK_UNSIGNED_INT:
306 this->Data.UnsignedInt = s2.ToUnsignedInt(&valid);
307 break;
308
309 case VTK_LONG:
310 this->Data.Long = s2.ToLong(&valid);
311 break;
312
313 case VTK_UNSIGNED_LONG:
314 this->Data.UnsignedLong = s2.ToUnsignedLong(&valid);
315 break;
316
317 case VTK_LONG_LONG:
318 this->Data.LongLong = s2.ToLongLong(&valid);
319 break;
320
321 case VTK_UNSIGNED_LONG_LONG:
322 this->Data.UnsignedLongLong = s2.ToUnsignedLongLong(&valid);
323 break;
324
325 case VTK_FLOAT:
326 this->Data.Float = s2.ToFloat(&valid);
327 break;
328
329 case VTK_DOUBLE:
330 this->Data.Double = s2.ToDouble(&valid);
331 break;
332 }
333 }
334
335 this->Type = (valid ? type : 0);
336 this->Valid = valid;
337 }
338
operator =(const vtkVariant & other)339 vtkVariant & vtkVariant::operator= (const vtkVariant & other)
340 {
341 // Short circuit if assigning to self:
342 if (this == &other)
343 {
344 return *this;
345 }
346
347 // First delete current variant item.
348 if (this->Valid)
349 {
350 switch (this->Type)
351 {
352 case VTK_STRING:
353 delete this->Data.String;
354 break;
355 case VTK_UNICODE_STRING:
356 delete this->Data.UnicodeString;
357 break;
358 case VTK_OBJECT:
359 this->Data.VTKObject->Delete();
360 break;
361 }
362 }
363
364 // Then set the appropriate value.
365 this->Valid = other.Valid;
366 this->Type = other.Type;
367 this->Data = other.Data;
368 if (this->Valid)
369 {
370 switch (other.Type)
371 {
372 case VTK_STRING:
373 this->Data.String = new vtkStdString(*other.Data.String);
374 break;
375 case VTK_UNICODE_STRING:
376 this->Data.UnicodeString = new vtkUnicodeString(*other.Data.UnicodeString);
377 break;
378 case VTK_OBJECT:
379 this->Data.VTKObject->Register(nullptr);
380 break;
381 }
382 }
383 return *this;
384 }
385
~vtkVariant()386 vtkVariant::~vtkVariant()
387 {
388 if (this->Valid)
389 {
390 switch (this->Type)
391 {
392 case VTK_STRING:
393 delete this->Data.String;
394 break;
395 case VTK_UNICODE_STRING:
396 delete this->Data.UnicodeString;
397 break;
398 case VTK_OBJECT:
399 this->Data.VTKObject->Delete();
400 break;
401 }
402 }
403 }
404
vtkVariant(bool value)405 vtkVariant::vtkVariant(bool value)
406 {
407 this->Data.Char = value;
408 this->Valid = 1;
409 this->Type = VTK_CHAR;
410 }
411
vtkVariant(char value)412 vtkVariant::vtkVariant(char value)
413 {
414 this->Data.Char = value;
415 this->Valid = 1;
416 this->Type = VTK_CHAR;
417 }
418
vtkVariant(unsigned char value)419 vtkVariant::vtkVariant(unsigned char value)
420 {
421 this->Data.UnsignedChar = value;
422 this->Valid = 1;
423 this->Type = VTK_UNSIGNED_CHAR;
424 }
425
vtkVariant(signed char value)426 vtkVariant::vtkVariant(signed char value)
427 {
428 this->Data.SignedChar = value;
429 this->Valid = 1;
430 this->Type = VTK_SIGNED_CHAR;
431 }
432
vtkVariant(short value)433 vtkVariant::vtkVariant(short value)
434 {
435 this->Data.Short = value;
436 this->Valid = 1;
437 this->Type = VTK_SHORT;
438 }
439
vtkVariant(unsigned short value)440 vtkVariant::vtkVariant(unsigned short value)
441 {
442 this->Data.UnsignedShort = value;
443 this->Valid = 1;
444 this->Type = VTK_UNSIGNED_SHORT;
445 }
446
vtkVariant(int value)447 vtkVariant::vtkVariant(int value)
448 {
449 this->Data.Int = value;
450 this->Valid = 1;
451 this->Type = VTK_INT;
452 }
453
vtkVariant(unsigned int value)454 vtkVariant::vtkVariant(unsigned int value)
455 {
456 this->Data.UnsignedInt = value;
457 this->Valid = 1;
458 this->Type = VTK_UNSIGNED_INT;
459 }
460
vtkVariant(long value)461 vtkVariant::vtkVariant(long value)
462 {
463 this->Data.Long = value;
464 this->Valid = 1;
465 this->Type = VTK_LONG;
466 }
467
vtkVariant(unsigned long value)468 vtkVariant::vtkVariant(unsigned long value)
469 {
470 this->Data.UnsignedLong = value;
471 this->Valid = 1;
472 this->Type = VTK_UNSIGNED_LONG;
473 }
474
vtkVariant(long long value)475 vtkVariant::vtkVariant(long long value)
476 {
477 this->Data.LongLong = value;
478 this->Valid = 1;
479 this->Type = VTK_LONG_LONG;
480 }
481
vtkVariant(unsigned long long value)482 vtkVariant::vtkVariant(unsigned long long value)
483 {
484 this->Data.UnsignedLongLong = value;
485 this->Valid = 1;
486 this->Type = VTK_UNSIGNED_LONG_LONG;
487 }
488
vtkVariant(float value)489 vtkVariant::vtkVariant(float value)
490 {
491 this->Data.Float = value;
492 this->Valid = 1;
493 this->Type = VTK_FLOAT;
494 }
495
vtkVariant(double value)496 vtkVariant::vtkVariant(double value)
497 {
498 this->Data.Double = value;
499 this->Valid = 1;
500 this->Type = VTK_DOUBLE;
501 }
502
vtkVariant(const char * value)503 vtkVariant::vtkVariant(const char* value)
504 {
505 this->Valid = 0;
506 this->Type = 0;
507 if (value)
508 {
509 this->Data.String = new vtkStdString(value);
510 this->Valid = 1;
511 this->Type = VTK_STRING;
512 }
513 }
514
vtkVariant(vtkStdString value)515 vtkVariant::vtkVariant(vtkStdString value)
516 {
517 this->Data.String = new vtkStdString(value);
518 this->Valid = 1;
519 this->Type = VTK_STRING;
520 }
521
vtkVariant(const vtkUnicodeString & value)522 vtkVariant::vtkVariant(const vtkUnicodeString& value)
523 {
524 this->Data.UnicodeString = new vtkUnicodeString(value);
525 this->Valid = 1;
526 this->Type = VTK_UNICODE_STRING;
527 }
528
vtkVariant(vtkObjectBase * value)529 vtkVariant::vtkVariant(vtkObjectBase* value)
530 {
531 this->Valid = 0;
532 this->Type = 0;
533 if (value)
534 {
535 value->Register(nullptr);
536 this->Data.VTKObject = value;
537 this->Valid = 1;
538 this->Type = VTK_OBJECT;
539 }
540 }
541
IsValid() const542 bool vtkVariant::IsValid() const
543 {
544 return this->Valid != 0;
545 }
546
IsString() const547 bool vtkVariant::IsString() const
548 {
549 return this->Type == VTK_STRING;
550 }
551
IsUnicodeString() const552 bool vtkVariant::IsUnicodeString() const
553 {
554 return this->Type == VTK_UNICODE_STRING;
555 }
556
IsNumeric() const557 bool vtkVariant::IsNumeric() const
558 {
559 return this->IsFloat()
560 || this->IsDouble()
561 || this->IsChar()
562 || this->IsUnsignedChar()
563 || this->IsSignedChar()
564 || this->IsShort()
565 || this->IsUnsignedShort()
566 || this->IsInt()
567 || this->IsUnsignedInt()
568 || this->IsLong()
569 || this->IsUnsignedLong()
570 || this->IsLongLong()
571 || this->IsUnsignedLongLong();
572 }
573
IsFloat() const574 bool vtkVariant::IsFloat() const
575 {
576 return this->Type == VTK_FLOAT;
577 }
578
IsDouble() const579 bool vtkVariant::IsDouble() const
580 {
581 return this->Type == VTK_DOUBLE;
582 }
583
IsChar() const584 bool vtkVariant::IsChar() const
585 {
586 return this->Type == VTK_CHAR;
587 }
588
IsUnsignedChar() const589 bool vtkVariant::IsUnsignedChar() const
590 {
591 return this->Type == VTK_UNSIGNED_CHAR;
592 }
593
IsSignedChar() const594 bool vtkVariant::IsSignedChar() const
595 {
596 return this->Type == VTK_SIGNED_CHAR;
597 }
598
IsShort() const599 bool vtkVariant::IsShort() const
600 {
601 return this->Type == VTK_SHORT;
602 }
603
IsUnsignedShort() const604 bool vtkVariant::IsUnsignedShort() const
605 {
606 return this->Type == VTK_UNSIGNED_SHORT;
607 }
608
IsInt() const609 bool vtkVariant::IsInt() const
610 {
611 return this->Type == VTK_INT;
612 }
613
IsUnsignedInt() const614 bool vtkVariant::IsUnsignedInt() const
615 {
616 return this->Type == VTK_UNSIGNED_INT;
617 }
618
IsLong() const619 bool vtkVariant::IsLong() const
620 {
621 return this->Type == VTK_LONG;
622 }
623
IsUnsignedLong() const624 bool vtkVariant::IsUnsignedLong() const
625 {
626 return this->Type == VTK_UNSIGNED_LONG;
627 }
628
Is__Int64() const629 bool vtkVariant::Is__Int64() const
630 {
631 return false;
632 }
633
IsUnsigned__Int64() const634 bool vtkVariant::IsUnsigned__Int64() const
635 {
636 return false;
637 }
638
IsLongLong() const639 bool vtkVariant::IsLongLong() const
640 {
641 return this->Type == VTK_LONG_LONG;
642 }
643
IsUnsignedLongLong() const644 bool vtkVariant::IsUnsignedLongLong() const
645 {
646 return this->Type == VTK_UNSIGNED_LONG_LONG;
647 }
648
IsVTKObject() const649 bool vtkVariant::IsVTKObject() const
650 {
651 return this->Type == VTK_OBJECT;
652 }
653
IsArray() const654 bool vtkVariant::IsArray() const
655 {
656 return this->Type == VTK_OBJECT
657 && this->Valid
658 && this->Data.VTKObject->IsA("vtkAbstractArray");
659 }
660
GetType() const661 unsigned int vtkVariant::GetType() const
662 {
663 return this->Type;
664 }
665
GetTypeAsString() const666 const char* vtkVariant::GetTypeAsString() const
667 {
668 if (this->Type == VTK_OBJECT && this->Valid)
669 {
670 return this->Data.VTKObject->GetClassName();
671 }
672 return vtkImageScalarTypeNameMacro(this->Type);
673 }
674
675 template <typename iterT>
vtkVariantArrayToString(iterT * it)676 vtkStdString vtkVariantArrayToString(iterT* it)
677 {
678 vtkIdType maxInd = it->GetNumberOfValues();
679 std::ostringstream ostr;
680 for (vtkIdType i = 0; i < maxInd; i++)
681 {
682 if (i > 0)
683 {
684 ostr << " ";
685 }
686 ostr << it->GetValue(i);
687 }
688 return ostr.str();
689 }
690
ToString() const691 vtkStdString vtkVariant::ToString() const
692 {
693 if (!this->IsValid())
694 {
695 return vtkStdString();
696 }
697 if (this->IsString())
698 {
699 return vtkStdString(*(this->Data.String));
700 }
701 if (this->IsUnicodeString())
702 {
703 return vtkUnicodeString(*(this->Data.UnicodeString)).utf8_str();
704 }
705 if (this->IsFloat())
706 {
707 std::ostringstream ostr;
708 ostr.imbue(std::locale::classic());
709 ostr << this->Data.Float;
710 return vtkStdString(ostr.str());
711 }
712 if (this->IsDouble())
713 {
714 std::ostringstream ostr;
715 ostr.imbue(std::locale::classic());
716 ostr << this->Data.Double;
717 return vtkStdString(ostr.str());
718 }
719 if (this->IsChar())
720 {
721 std::ostringstream ostr;
722 ostr << this->Data.Char;
723 return vtkStdString(ostr.str());
724 }
725 if (this->IsUnsignedChar())
726 {
727 std::ostringstream ostr;
728 ostr << static_cast<unsigned int>(this->Data.UnsignedChar);
729 return vtkStdString(ostr.str());
730 }
731 if (this->IsSignedChar())
732 {
733 std::ostringstream ostr;
734 ostr << this->Data.SignedChar;
735 return vtkStdString(ostr.str());
736 }
737 if (this->IsShort())
738 {
739 std::ostringstream ostr;
740 ostr << this->Data.Short;
741 return vtkStdString(ostr.str());
742 }
743 if (this->IsUnsignedShort())
744 {
745 std::ostringstream ostr;
746 ostr << this->Data.UnsignedShort;
747 return vtkStdString(ostr.str());
748 }
749 if (this->IsInt())
750 {
751 std::ostringstream ostr;
752 ostr.imbue(std::locale::classic());
753 ostr << this->Data.Int;
754 return vtkStdString(ostr.str());
755 }
756 if (this->IsUnsignedInt())
757 {
758 std::ostringstream ostr;
759 ostr.imbue(std::locale::classic());
760 ostr << this->Data.UnsignedInt;
761 return vtkStdString(ostr.str());
762 }
763 if (this->IsLong())
764 {
765 std::ostringstream ostr;
766 ostr.imbue(std::locale::classic());
767 ostr << this->Data.Long;
768 return vtkStdString(ostr.str());
769 }
770 if (this->IsUnsignedLong())
771 {
772 std::ostringstream ostr;
773 ostr.imbue(std::locale::classic());
774 ostr << this->Data.UnsignedLong;
775 return vtkStdString(ostr.str());
776 }
777 if (this->IsLongLong())
778 {
779 std::ostringstream ostr;
780 ostr.imbue(std::locale::classic());
781 ostr << this->Data.LongLong;
782 return vtkStdString(ostr.str());
783 }
784 if (this->IsUnsignedLongLong())
785 {
786 std::ostringstream ostr;
787 ostr.imbue(std::locale::classic());
788 ostr << this->Data.UnsignedLongLong;
789 return vtkStdString(ostr.str());
790 }
791 if (this->IsArray())
792 {
793 vtkAbstractArray* arr = vtkAbstractArray::SafeDownCast(this->Data.VTKObject);
794 vtkArrayIterator* iter = arr->NewIterator();
795 vtkStdString str;
796 switch(arr->GetDataType())
797 {
798 vtkArrayIteratorTemplateMacro(
799 str = vtkVariantArrayToString(static_cast<VTK_TT*>(iter)));
800 }
801 iter->Delete();
802 return str;
803 }
804 vtkGenericWarningMacro(
805 << "Cannot convert unknown type (" << this->GetTypeAsString() << ") to a string.");
806 return vtkStdString();
807 }
808
ToUnicodeString() const809 vtkUnicodeString vtkVariant::ToUnicodeString() const
810 {
811 if (!this->IsValid())
812 {
813 return vtkUnicodeString();
814 }
815 if (this->IsString())
816 {
817 return vtkUnicodeString::from_utf8(*this->Data.String);
818 }
819 if (this->IsUnicodeString())
820 {
821 return *this->Data.UnicodeString;
822 }
823
824 return vtkUnicodeString::from_utf8(this->ToString());
825 }
826
ToVTKObject() const827 vtkObjectBase* vtkVariant::ToVTKObject() const
828 {
829 if (this->IsVTKObject())
830 {
831 return this->Data.VTKObject;
832 }
833 return nullptr;
834 }
835
ToArray() const836 vtkAbstractArray* vtkVariant::ToArray() const
837 {
838 if (this->IsArray())
839 {
840 return vtkAbstractArray::SafeDownCast(this->Data.VTKObject);
841 }
842 return nullptr;
843 }
844
845 // Used internally by vtkVariantStringToNumeric to find non-finite numbers.
846 // Most numerics do not support non-finite numbers, hence the default simply
847 // fails. Overload for doubles and floats detect non-finite numbers they
848 // support
849 template <typename T>
vtkVariantStringToNonFiniteNumeric(vtkStdString vtkNotUsed (str),bool * valid)850 T vtkVariantStringToNonFiniteNumeric(vtkStdString vtkNotUsed(str), bool *valid)
851 {
852 if (valid) *valid = 0;
853 return 0;
854 }
855
vtkVariantStringToNonFiniteNumeric(vtkStdString str,bool * valid)856 template<> double vtkVariantStringToNonFiniteNumeric<double>(vtkStdString str,
857 bool *valid)
858 {
859 if (vtksys::SystemTools::Strucmp(str.c_str(), "nan") == 0)
860 {
861 if (valid) *valid = true;
862 return vtkMath::Nan();
863 }
864 if ( (vtksys::SystemTools::Strucmp(str.c_str(), "infinity") == 0)
865 || (vtksys::SystemTools::Strucmp(str.c_str(), "inf") == 0) )
866 {
867 if (valid) *valid = true;
868 return vtkMath::Inf();
869 }
870 if ( (vtksys::SystemTools::Strucmp(str.c_str(), "-infinity") == 0)
871 || (vtksys::SystemTools::Strucmp(str.c_str(), "-inf") == 0) )
872 {
873 if (valid) *valid = true;
874 return vtkMath::NegInf();
875 }
876 if (valid) *valid = false;
877 return vtkMath::Nan();
878 }
879
vtkVariantStringToNonFiniteNumeric(vtkStdString str,bool * valid)880 template<> float vtkVariantStringToNonFiniteNumeric<float>(vtkStdString str,
881 bool *valid)
882 {
883 return static_cast<float>(
884 vtkVariantStringToNonFiniteNumeric<double>(str, valid));
885 }
886
887 template <typename T>
vtkVariantStringToNumeric(vtkStdString str,bool * valid,T * vtkNotUsed (ignored)=nullptr)888 T vtkVariantStringToNumeric(vtkStdString str, bool* valid, T* vtkNotUsed(ignored) = nullptr)
889 {
890 std::istringstream vstr(str);
891 T data = 0;
892 vstr >> data;
893 if(!vstr.eof())
894 {
895 // take in white space so that it can reach eof.
896 vstr >> std::ws;
897 }
898 bool v = ( !vstr.fail() && vstr.eof() );
899 if (valid) *valid = v;
900 if (!v)
901 {
902 data = vtkVariantStringToNonFiniteNumeric<T>(str, valid);
903 }
904 return data;
905 }
906
907 //----------------------------------------------------------------------------
908 // Definition of ToNumeric
909
910 #include "vtkVariantToNumeric.cxx"
911
912 //----------------------------------------------------------------------------
913 // Explicitly instantiate the ToNumeric member template to make sure
914 // the symbols are exported from this object file.
915 // This explicit instantiation exists to resolve VTK issue #5791.
916
917 #if !defined(VTK_VARIANT_NO_INSTANTIATE)
918
919 #define vtkVariantToNumericInstantiateMacro(x) \
920 template x vtkVariant::ToNumeric< x >(bool*, x*) const
921
922 vtkVariantToNumericInstantiateMacro(char);
923 vtkVariantToNumericInstantiateMacro(float);
924 vtkVariantToNumericInstantiateMacro(double);
925 vtkVariantToNumericInstantiateMacro(unsigned char);
926 vtkVariantToNumericInstantiateMacro(signed char);
927 vtkVariantToNumericInstantiateMacro(short);
928 vtkVariantToNumericInstantiateMacro(unsigned short);
929 vtkVariantToNumericInstantiateMacro(int);
930 vtkVariantToNumericInstantiateMacro(unsigned int);
931 vtkVariantToNumericInstantiateMacro(long);
932 vtkVariantToNumericInstantiateMacro(unsigned long);
933 vtkVariantToNumericInstantiateMacro(long long);
934 vtkVariantToNumericInstantiateMacro(unsigned long long);
935
936 #endif
937
938 //----------------------------------------------------------------------------
939 // Callers causing implicit instantiations of ToNumeric
940
ToFloat(bool * valid) const941 float vtkVariant::ToFloat(bool *valid) const
942 {
943 return this->ToNumeric(valid, static_cast<float *>(nullptr));
944 }
945
ToDouble(bool * valid) const946 double vtkVariant::ToDouble(bool *valid) const
947 {
948 return this->ToNumeric(valid, static_cast<double *>(nullptr));
949 }
950
ToChar(bool * valid) const951 char vtkVariant::ToChar(bool *valid) const
952 {
953 return this->ToNumeric(valid, static_cast<char *>(nullptr));
954 }
955
ToUnsignedChar(bool * valid) const956 unsigned char vtkVariant::ToUnsignedChar(bool *valid) const
957 {
958 return this->ToNumeric(valid, static_cast<unsigned char *>(nullptr));
959 }
960
ToSignedChar(bool * valid) const961 signed char vtkVariant::ToSignedChar(bool *valid) const
962 {
963 return this->ToNumeric(valid, static_cast<signed char *>(nullptr));
964 }
965
ToShort(bool * valid) const966 short vtkVariant::ToShort(bool *valid) const
967 {
968 return this->ToNumeric(valid, static_cast<short *>(nullptr));
969 }
970
ToUnsignedShort(bool * valid) const971 unsigned short vtkVariant::ToUnsignedShort(bool *valid) const
972 {
973 return this->ToNumeric(valid, static_cast<unsigned short *>(nullptr));
974 }
975
ToInt(bool * valid) const976 int vtkVariant::ToInt(bool *valid) const
977 {
978 return this->ToNumeric(valid, static_cast<int *>(nullptr));
979 }
980
ToUnsignedInt(bool * valid) const981 unsigned int vtkVariant::ToUnsignedInt(bool *valid) const
982 {
983 return this->ToNumeric(valid, static_cast<unsigned int *>(nullptr));
984 }
985
ToLong(bool * valid) const986 long vtkVariant::ToLong(bool *valid) const
987 {
988 return this->ToNumeric(valid, static_cast<long *>(nullptr));
989 }
990
ToUnsignedLong(bool * valid) const991 unsigned long vtkVariant::ToUnsignedLong(bool *valid) const
992 {
993 return this->ToNumeric(valid, static_cast<unsigned long *>(nullptr));
994 }
995
ToLongLong(bool * valid) const996 long long vtkVariant::ToLongLong(bool *valid) const
997 {
998 return this->ToNumeric(valid, static_cast<long long *>(nullptr));
999 }
1000
ToUnsignedLongLong(bool * valid) const1001 unsigned long long vtkVariant::ToUnsignedLongLong(bool *valid) const
1002 {
1003 return this->ToNumeric(valid, static_cast<unsigned long long *>(nullptr));
1004 }
1005
ToTypeInt64(bool * valid) const1006 vtkTypeInt64 vtkVariant::ToTypeInt64(bool *valid) const
1007 {
1008 return this->ToNumeric(valid, static_cast<vtkTypeInt64 *>(nullptr));
1009 }
1010
ToTypeUInt64(bool * valid) const1011 vtkTypeUInt64 vtkVariant::ToTypeUInt64(bool *valid) const
1012 {
1013 return this->ToNumeric(valid, static_cast<vtkTypeUInt64 *>(nullptr));
1014 }
1015
IsEqual(const vtkVariant & other) const1016 bool vtkVariant::IsEqual(const vtkVariant& other) const
1017 {
1018 return this->operator==(other);
1019 }
1020
operator <<(ostream & os,const vtkVariant & val)1021 ostream& operator << ( ostream& os, const vtkVariant& val )
1022 {
1023 if ( ! val.Valid )
1024 {
1025 os << "(invalid)";
1026 return os;
1027 }
1028 switch ( val.Type )
1029 {
1030 case VTK_STRING:
1031 if ( val.Data.String )
1032 {
1033 os << "\"" << val.Data.String->c_str() << "\"";
1034 }
1035 else
1036 {
1037 os << "\"\"";
1038 }
1039 break;
1040 case VTK_UNICODE_STRING:
1041 if ( val.Data.UnicodeString )
1042 {
1043 os << "\"" << val.Data.UnicodeString->utf8_str() << "\"";
1044 }
1045 else
1046 {
1047 os << "\"\"";
1048 }
1049 break;
1050 case VTK_FLOAT:
1051 os << val.Data.Float;
1052 break;
1053 case VTK_DOUBLE:
1054 os << val.Data.Double;
1055 break;
1056 case VTK_CHAR:
1057 os << val.Data.Char;
1058 break;
1059 case VTK_UNSIGNED_CHAR:
1060 os << val.Data.UnsignedChar;
1061 break;
1062 case VTK_SIGNED_CHAR:
1063 os << val.Data.SignedChar;
1064 break;
1065 case VTK_SHORT:
1066 os << val.Data.Short;
1067 break;
1068 case VTK_UNSIGNED_SHORT:
1069 os << val.Data.UnsignedShort;
1070 break;
1071 case VTK_INT:
1072 os << val.Data.Int;
1073 break;
1074 case VTK_UNSIGNED_INT:
1075 os << val.Data.UnsignedInt;
1076 break;
1077 case VTK_LONG:
1078 os << val.Data.Long;
1079 break;
1080 case VTK_UNSIGNED_LONG:
1081 os << val.Data.UnsignedLong;
1082 break;
1083 case VTK_LONG_LONG:
1084 os << val.Data.LongLong;
1085 break;
1086 case VTK_UNSIGNED_LONG_LONG:
1087 os << val.Data.UnsignedLongLong;
1088 break;
1089 case VTK_OBJECT:
1090 if ( val.Data.VTKObject )
1091 {
1092 os << "(" << val.Data.VTKObject->GetClassName() << ")" << hex << val.Data.VTKObject << dec;
1093 }
1094 else
1095 {
1096 os << "(vtkObjectBase)0x0";
1097 }
1098 break;
1099 }
1100 return os;
1101 }
1102