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