VTK  9.6.20260524
vtkVariantInlineOperators.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
2// SPDX-License-Identifier: BSD-3-Clause
3
4#ifndef vtkVariantInlineOperators_h
5#define vtkVariantInlineOperators_h
6
7#include "vtkABINamespace.h"
8
9#include <climits>
10
11// ----------------------------------------------------------------------
12
13// First we have several helper functions that will determine what
14// type we're actually dealing with. With any luck the compiler will
15// inline these so they have very little overhead.
16
17VTK_ABI_NAMESPACE_BEGIN
18inline bool IsSigned64Bit(int VariantType)
19{
20#if VTK_LONG_LONG == VTK_TYPE_INT64
21 return (VariantType == VTK_TYPE_INT64);
22#else
23 return ((VariantType == VTK_LONG_LONG) || (VariantType == VTK_TYPE_INT64));
24#endif
25}
26
27inline bool IsSigned(int VariantType)
28{
29#if (CHAR_MIN == SCHAR_MIN && CHAR_MAX == SCHAR_MAX)
30 // the char type is signed on this compiler
31 return ((VariantType == VTK_CHAR) || (VariantType == VTK_SIGNED_CHAR) ||
32 (VariantType == VTK_SHORT) || (VariantType == VTK_INT) || (VariantType == VTK_LONG) ||
33 (VariantType == VTK_ID_TYPE) || IsSigned64Bit(VariantType));
34#else
35 // char is unsigned
36 return ((VariantType == VTK_SIGNED_CHAR) || (VariantType == VTK_SHORT) ||
37 (VariantType == VTK_INT) || (VariantType == VTK_LONG) || (VariantType == VTK_ID_TYPE) ||
38 IsSigned64Bit(VariantType));
39#endif
40}
41// Overload prevents warnings about enums stored as signed or unsigned.
42inline bool IsSigned(unsigned int VariantType)
43{
44 return IsSigned(static_cast<int>(VariantType));
45}
46
47// ----------------------------------------------------------------------
48
49inline bool IsFloatingPoint(int VariantType)
50{
51 return ((VariantType == VTK_FLOAT) || (VariantType == VTK_DOUBLE));
52}
53// Overload prevents warnings about enums stored as signed or unsigned.
54inline bool IsFloatingPoint(unsigned int VariantType)
55{
56 return IsFloatingPoint(static_cast<int>(VariantType));
57}
58
59// ----------------------------------------------------------------------
60
62 const vtkVariant& SignedVariant, const vtkVariant& UnsignedVariant)
63{
64 // If the signed value is less than zero then they cannot possibly
65 // be equal.
66 vtkTypeInt64 A = SignedVariant.ToTypeInt64();
67 return (A >= 0) && (A == UnsignedVariant.ToTypeInt64());
68}
69
70// ----------------------------------------------------------------------
71
73 const vtkVariant& SignedVariant, const vtkVariant& UnsignedVariant)
74{
75 vtkTypeInt64 A = SignedVariant.ToTypeInt64();
76 return ((A < 0) || (static_cast<vtkTypeUInt64>(A) < UnsignedVariant.ToTypeUInt64()));
77}
78
79// ----------------------------------------------------------------------
80
82 const vtkVariant& UnsignedVariant, const vtkVariant& SignedVariant)
83{
84 vtkTypeInt64 B = SignedVariant.ToTypeInt64();
85 return ((B > 0) && (UnsignedVariant.ToTypeUInt64() < static_cast<vtkTypeUInt64>(B)));
86}
87
88// ----------------------------------------------------------------------
89
90inline bool CompareSignedLessThan(const vtkVariant& A, const vtkVariant& B)
91{
92 return (A.ToTypeInt64() < B.ToTypeInt64());
93}
94
95// ----------------------------------------------------------------------
96
97inline bool CompareUnsignedLessThan(const vtkVariant& A, const vtkVariant& B)
98{
99 return (A.ToTypeUInt64() < B.ToTypeUInt64());
100}
101
102// ----------------------------------------------------------------------
103
104inline bool vtkVariant::operator==(const vtkVariant& other) const
105{
106 // First test: nullptr values are always equal to one another and
107 // unequal to anything else.
108 if (!(this->Valid && other.Valid))
109 {
110 return (!(this->Valid || other.Valid));
111 }
112
113 // Second test: VTK objects can only be compared with other VTK
114 // objects.
115 if ((this->Type == VTK_OBJECT) || (other.Type == VTK_OBJECT))
116 {
117 return ((this->Type == VTK_OBJECT) && (other.Type == VTK_OBJECT) &&
118 (this->Data.VTKObject == other.Data.VTKObject));
119 }
120
121 // Third test: the STRING type dominates all else. If either item
122 // is a string then they must both be compared as strings.
123 if ((this->Type == VTK_STRING) || (other.Type == VTK_STRING))
124 {
125 return (this->ToString() == other.ToString());
126 }
127
128 // Fifth: floating point dominates integer types.
129 // Demote to the lowest-floating-point precision for the comparison.
130 // This effectively makes the lower-precision number an interval
131 // corresponding to the range of double values that get rounded to
132 // that float. Otherwise, comparisons of numbers that cannot fit in
133 // the smaller mantissa exactly will never be equal to their
134 // corresponding higher-precision representations.
135 if (this->Type == VTK_FLOAT || other.Type == VTK_FLOAT)
136 {
137 return this->ToFloat() == other.ToFloat();
138 }
139 else if (this->Type == VTK_DOUBLE || other.Type == VTK_DOUBLE)
140 {
141 return (this->ToDouble() == other.ToDouble());
142 }
143
144 // Sixth: we must be comparing integers.
145
146 // 6A: catch signed/unsigned comparison. If the signed object is
147 // less than zero then they cannot be equal.
148 bool thisSigned = IsSigned(this->Type);
149 bool otherSigned = IsSigned(other.Type);
150
151 if (thisSigned ^ otherSigned)
152 {
153 if (thisSigned)
154 {
155 return CompareSignedUnsignedEqual(*this, other);
156 }
157 else
158 {
159 return CompareSignedUnsignedEqual(other, *this);
160 }
161 }
162 else // 6B: both are signed or both are unsigned. In either event
163 // all we have to do is check whether the bit patterns are
164 // equal.
165 {
166 return (this->ToTypeInt64() == other.ToTypeInt64());
167 }
168}
169
170// ----------------------------------------------------------------------
171
172inline bool vtkVariant::operator<(const vtkVariant& other) const
173{
174 // First test: a nullptr value is less than anything except another
175 // nullptr value. unequal to anything else.
176 if (!(this->Valid && other.Valid))
177 {
178 return ((!this->Valid) && (other.Valid));
179 }
180
181 // Second test: VTK objects can only be compared with other VTK
182 // objects.
183 if ((this->Type == VTK_OBJECT) || (other.Type == VTK_OBJECT))
184 {
185 return ((this->Type == VTK_OBJECT) && (other.Type == VTK_OBJECT) &&
186 (this->Data.VTKObject < other.Data.VTKObject));
187 }
188
189 // Third test: the STRING type dominates all else. If either item
190 // is a string then they must both be compared as strings.
191 if ((this->Type == VTK_STRING) || (other.Type == VTK_STRING))
192 {
193 return (this->ToString() < other.ToString());
194 }
195
196 // Fourth: floating point dominates integer types.
197 // Demote to the lowest-floating-point precision for the comparison.
198 // This effectively makes the lower-precision number an interval
199 // corresponding to the range of double values that get rounded to
200 // that float. Otherwise, comparisons of numbers that cannot fit in
201 // the smaller mantissa exactly will never be equal to their
202 // corresponding higher-precision representations.
203 if (this->Type == VTK_FLOAT || other.Type == VTK_FLOAT)
204 {
205 return this->ToFloat() < other.ToFloat();
206 }
207 else if (this->Type == VTK_DOUBLE || other.Type == VTK_DOUBLE)
208 {
209 return (this->ToDouble() < other.ToDouble());
210 }
211
212 // Fifth: we must be comparing integers.
213
214 // 5A: catch signed/unsigned comparison. If the signed object is
215 // less than zero then they cannot be equal.
216 bool thisSigned = IsSigned(this->Type);
217 bool otherSigned = IsSigned(other.Type);
218
219 if (thisSigned ^ otherSigned)
220 {
221 if (thisSigned)
222 {
223 return CompareSignedUnsignedLessThan(*this, other);
224 }
225 else
226 {
227 return CompareUnsignedSignedLessThan(*this, other);
228 }
229 }
230 else if (thisSigned)
231 {
232 return CompareSignedLessThan(*this, other);
233 }
234 else
235 {
236 return CompareUnsignedLessThan(*this, other);
237 }
238}
239
240// ----------------------------------------------------------------------
241
242// Below this point are operators defined in terms of other operators.
243// Again, this may sacrifice some speed, but reduces the chance of
244// inconsistent behavior.
245
246// ----------------------------------------------------------------------
247
248inline bool vtkVariant::operator!=(const vtkVariant& other) const
249{
250 return !(this->operator==(other));
251}
252
253inline bool vtkVariant::operator>(const vtkVariant& other) const
254{
255 return (!(this->operator==(other) || this->operator<(other)));
256}
257
258inline bool vtkVariant::operator<=(const vtkVariant& other) const
259{
260 return (this->operator==(other) || this->operator<(other));
261}
262
263inline bool vtkVariant::operator>=(const vtkVariant& other) const
264{
265 return (!this->operator<(other));
266}
267
268VTK_ABI_NAMESPACE_END
269#endif
270// VTK-HeaderTest-Exclude: vtkVariantInlineOperators.h
A type representing the union of many types.
Definition vtkVariant.h:162
vtkTypeInt64 ToTypeInt64() const
Convert the variant to a numeric type: If it holds a numeric, cast to the appropriate type.
Definition vtkVariant.h:445
double ToDouble(bool *valid) const
Convert the variant to a numeric type: If it holds a numeric, cast to the appropriate type.
vtkTypeUInt64 ToTypeUInt64(bool *valid) const
Convert the variant to a numeric type: If it holds a numeric, cast to the appropriate type.
bool operator==(const vtkVariant &other) const
Compare two variants for equality, greater than, and less than.
bool operator>(const vtkVariant &other) const
Compare two variants for equality, greater than, and less than.
double ToDouble() const
Convert the variant to a numeric type: If it holds a numeric, cast to the appropriate type.
Definition vtkVariant.h:421
bool operator<=(const vtkVariant &other) const
Compare two variants for equality, greater than, and less than.
bool operator!=(const vtkVariant &other) const
Compare two variants for equality, greater than, and less than.
float ToFloat() const
Convert the variant to a numeric type: If it holds a numeric, cast to the appropriate type.
Definition vtkVariant.h:419
vtkStdString ToString(int formatting=DEFAULT_FORMATTING, int precision=6) const
Convert the variant to a string.
float ToFloat(bool *valid) const
Convert the variant to a numeric type: If it holds a numeric, cast to the appropriate type.
bool operator>=(const vtkVariant &other) const
Compare two variants for equality, greater than, and less than.
bool operator<(const vtkVariant &other) const
Compare two variants for equality, greater than, and less than.
vtkTypeInt64 ToTypeInt64(bool *valid) const
Convert the variant to a numeric type: If it holds a numeric, cast to the appropriate type.
vtkVariant()
Create an invalid variant.
vtkObjectBase * VTKObject
Definition vtkVariant.h:533
#define VTK_SHORT
Definition vtkType.h:37
#define VTK_OBJECT
Definition vtkType.h:57
#define VTK_LONG_LONG
Definition vtkType.h:52
#define VTK_DOUBLE
Definition vtkType.h:44
#define VTK_INT
Definition vtkType.h:39
#define VTK_SIGNED_CHAR
Definition vtkType.h:35
#define VTK_STRING
Definition vtkType.h:49
#define VTK_FLOAT
Definition vtkType.h:43
#define VTK_CHAR
Definition vtkType.h:34
#define VTK_LONG
Definition vtkType.h:41
#define VTK_ID_TYPE
Definition vtkType.h:45
bool CompareSignedUnsignedLessThan(const vtkVariant &SignedVariant, const vtkVariant &UnsignedVariant)
bool CompareSignedUnsignedEqual(const vtkVariant &SignedVariant, const vtkVariant &UnsignedVariant)
bool CompareUnsignedLessThan(const vtkVariant &A, const vtkVariant &B)
bool IsFloatingPoint(int VariantType)
bool CompareSignedLessThan(const vtkVariant &A, const vtkVariant &B)
bool IsSigned(int VariantType)
bool CompareUnsignedSignedLessThan(const vtkVariant &UnsignedVariant, const vtkVariant &SignedVariant)
bool IsSigned64Bit(int VariantType)