|
7 | 7 | #include "../Variant/VariantRef.hpp"
|
8 | 8 |
|
9 | 9 | namespace ARDUINOJSON_NAMESPACE {
|
| 10 | + |
| 11 | +template <typename T, typename Enable = void> |
| 12 | +struct Comparer; |
| 13 | + |
| 14 | +template <typename T> |
| 15 | +struct Comparer<T, typename enable_if<IsString<T>::value>::type> { |
| 16 | + T rhs; |
| 17 | + int result; |
| 18 | + |
| 19 | + explicit Comparer(T value) : rhs(value), result(1) {} |
| 20 | + |
| 21 | + void visitArray(const CollectionData &) {} |
| 22 | + void visitObject(const CollectionData &) {} |
| 23 | + void visitFloat(Float) {} |
| 24 | + void visitString(const char *lhs) { |
| 25 | + result = -adaptString(rhs).compare(lhs); |
| 26 | + } |
| 27 | + void visitRawJson(const char *, size_t) {} |
| 28 | + void visitNegativeInteger(UInt) {} |
| 29 | + void visitPositiveInteger(UInt) {} |
| 30 | + void visitBoolean(bool) {} |
| 31 | + void visitNull() { |
| 32 | + result = adaptString(rhs).compare(NULL); |
| 33 | + } |
| 34 | +}; |
| 35 | + |
| 36 | +template <typename T> |
| 37 | +typename enable_if<is_signed<T>::value, int>::type sign(const T &value) { |
| 38 | + return value < 0 ? -1 : value > 0 ? 1 : 0; |
| 39 | +} |
| 40 | + |
10 | 41 | template <typename T>
|
11 |
| -struct is_simple_value { |
12 |
| - static const bool value = is_integral<T>::value || |
13 |
| - is_floating_point<T>::value || |
14 |
| - is_same<T, bool>::value; |
| 42 | +typename enable_if<is_unsigned<T>::value, int>::type sign(const T &value) { |
| 43 | + return value > 0 ? 1 : 0; |
| 44 | +} |
| 45 | + |
| 46 | +template <typename T> |
| 47 | +struct Comparer<T, typename enable_if<is_integral<T>::value || |
| 48 | + is_floating_point<T>::value>::type> { |
| 49 | + T rhs; |
| 50 | + int result; |
| 51 | + |
| 52 | + explicit Comparer(T value) : rhs(value), result(1) {} |
| 53 | + |
| 54 | + void visitArray(const CollectionData &) {} |
| 55 | + void visitObject(const CollectionData &) {} |
| 56 | + void visitFloat(Float lhs) { |
| 57 | + result = sign(lhs - static_cast<Float>(rhs)); |
| 58 | + } |
| 59 | + void visitString(const char *) {} |
| 60 | + void visitRawJson(const char *, size_t) {} |
| 61 | + void visitNegativeInteger(UInt lhs) { |
| 62 | + result = -sign(static_cast<T>(lhs) + rhs); |
| 63 | + } |
| 64 | + void visitPositiveInteger(UInt lhs) { |
| 65 | + result = static_cast<T>(lhs) < rhs ? -1 : static_cast<T>(lhs) > rhs ? 1 : 0; |
| 66 | + } |
| 67 | + void visitBoolean(bool) {} |
| 68 | + void visitNull() {} |
| 69 | +}; |
| 70 | + |
| 71 | +template <> |
| 72 | +struct Comparer<bool, void> { |
| 73 | + bool rhs; |
| 74 | + int result; |
| 75 | + |
| 76 | + explicit Comparer(bool value) : rhs(value), result(1) {} |
| 77 | + |
| 78 | + void visitArray(const CollectionData &) {} |
| 79 | + void visitObject(const CollectionData &) {} |
| 80 | + void visitFloat(Float) {} |
| 81 | + void visitString(const char *) {} |
| 82 | + void visitRawJson(const char *, size_t) {} |
| 83 | + void visitNegativeInteger(UInt) {} |
| 84 | + void visitPositiveInteger(UInt) {} |
| 85 | + void visitBoolean(bool lhs) { |
| 86 | + result = static_cast<int>(lhs - rhs); |
| 87 | + } |
| 88 | + void visitNull() {} |
15 | 89 | };
|
16 | 90 |
|
17 | 91 | template <typename TVariant>
|
18 | 92 | class VariantComparisons {
|
19 |
| - public: |
20 |
| - // const char* == TVariant |
| 93 | + private: |
21 | 94 | template <typename T>
|
22 |
| - friend typename enable_if<IsString<T *>::value, bool>::type operator==( |
23 |
| - T *lhs, TVariant rhs) { |
24 |
| - return adaptString(lhs).equals(rhs.template as<const char *>()); |
| 95 | + static int compare(TVariant lhs, const T &rhs) { |
| 96 | + Comparer<T> comparer(rhs); |
| 97 | + lhs.accept(comparer); |
| 98 | + return comparer.result; |
25 | 99 | }
|
26 | 100 |
|
27 |
| - // std::string == TVariant |
| 101 | + public: |
| 102 | + // value == TVariant |
28 | 103 | template <typename T>
|
29 |
| - friend typename enable_if<IsString<T>::value, bool>::type operator==( |
30 |
| - const T &lhs, TVariant rhs) { |
31 |
| - return adaptString(lhs).equals(rhs.template as<const char *>()); |
| 104 | + friend bool operator==(T *lhs, TVariant rhs) { |
| 105 | + return compare(rhs, lhs) == 0; |
32 | 106 | }
|
33 |
| - |
34 |
| - // TVariant == const char* |
35 | 107 | template <typename T>
|
36 |
| - friend typename enable_if<IsString<T *>::value, bool>::type operator==( |
37 |
| - TVariant lhs, T *rhs) { |
38 |
| - return adaptString(rhs).equals(lhs.template as<const char *>()); |
| 108 | + friend bool operator==(const T &lhs, TVariant rhs) { |
| 109 | + return compare(rhs, lhs) == 0; |
39 | 110 | }
|
40 | 111 |
|
41 |
| - // TVariant == std::string |
| 112 | + // TVariant == value |
42 | 113 | template <typename T>
|
43 |
| - friend typename enable_if<IsString<T>::value, bool>::type operator==( |
44 |
| - TVariant lhs, const T &rhs) { |
45 |
| - return adaptString(rhs).equals(lhs.template as<const char *>()); |
| 114 | + friend bool operator==(TVariant lhs, T *rhs) { |
| 115 | + return compare(lhs, rhs) == 0; |
46 | 116 | }
|
47 |
| - |
48 |
| - // bool/int/float == TVariant |
49 | 117 | template <typename T>
|
50 |
| - friend typename enable_if<is_simple_value<T>::value, bool>::type operator==( |
51 |
| - const T &lhs, TVariant rhs) { |
52 |
| - return lhs == rhs.template as<T>(); |
| 118 | + friend bool operator==(TVariant lhs, const T &rhs) { |
| 119 | + return compare(lhs, rhs) == 0; |
53 | 120 | }
|
54 | 121 |
|
55 |
| - // TVariant == bool/int/float |
| 122 | + // value != TVariant |
56 | 123 | template <typename T>
|
57 |
| - friend typename enable_if<is_simple_value<T>::value, bool>::type operator==( |
58 |
| - TVariant lhs, const T &rhs) { |
59 |
| - return lhs.template as<T>() == rhs; |
| 124 | + friend bool operator!=(T *lhs, TVariant rhs) { |
| 125 | + return compare(rhs, lhs) != 0; |
60 | 126 | }
|
61 |
| - |
62 |
| - // const char* != TVariant |
63 | 127 | template <typename T>
|
64 |
| - friend typename enable_if<IsString<T *>::value, bool>::type operator!=( |
65 |
| - T *lhs, TVariant rhs) { |
66 |
| - return !adaptString(lhs).equals(rhs.template as<const char *>()); |
| 128 | + friend bool operator!=(const T &lhs, TVariant rhs) { |
| 129 | + return compare(rhs, lhs) != 0; |
67 | 130 | }
|
68 | 131 |
|
69 |
| - // std::string != TVariant |
| 132 | + // TVariant != value |
70 | 133 | template <typename T>
|
71 |
| - friend typename enable_if<IsString<T>::value, bool>::type operator!=( |
72 |
| - const T &lhs, TVariant rhs) { |
73 |
| - return !adaptString(lhs).equals(rhs.template as<const char *>()); |
| 134 | + friend bool operator!=(TVariant lhs, T *rhs) { |
| 135 | + return compare(lhs, rhs) != 0; |
74 | 136 | }
|
75 |
| - |
76 |
| - // TVariant != const char* |
77 | 137 | template <typename T>
|
78 |
| - friend typename enable_if<IsString<T *>::value, bool>::type operator!=( |
79 |
| - TVariant lhs, T *rhs) { |
80 |
| - return !adaptString(rhs).equals(lhs.template as<const char *>()); |
| 138 | + friend bool operator!=(TVariant lhs, const T &rhs) { |
| 139 | + return compare(lhs, rhs) != 0; |
81 | 140 | }
|
82 | 141 |
|
83 |
| - // TVariant != std::string |
| 142 | + // value < TVariant |
84 | 143 | template <typename T>
|
85 |
| - friend typename enable_if<IsString<T>::value, bool>::type operator!=( |
86 |
| - TVariant lhs, const T &rhs) { |
87 |
| - return !adaptString(rhs).equals(lhs.template as<const char *>()); |
| 144 | + friend bool operator<(T *lhs, TVariant rhs) { |
| 145 | + return compare(rhs, lhs) > 0; |
88 | 146 | }
|
89 |
| - |
90 |
| - // bool/int/float != TVariant |
91 | 147 | template <typename T>
|
92 |
| - friend typename enable_if<is_simple_value<T>::value, bool>::type operator!=( |
93 |
| - const T &lhs, TVariant rhs) { |
94 |
| - return lhs != rhs.template as<T>(); |
| 148 | + friend bool operator<(const T &lhs, TVariant rhs) { |
| 149 | + return compare(rhs, lhs) > 0; |
95 | 150 | }
|
96 | 151 |
|
97 |
| - // TVariant != bool/int/float |
| 152 | + // TVariant < value |
98 | 153 | template <typename T>
|
99 |
| - friend typename enable_if<is_simple_value<T>::value, bool>::type operator!=( |
100 |
| - TVariant lhs, const T &rhs) { |
101 |
| - return lhs.template as<T>() != rhs; |
| 154 | + friend bool operator<(TVariant lhs, T *rhs) { |
| 155 | + return compare(lhs, rhs) < 0; |
102 | 156 | }
|
103 |
| - |
104 |
| - // bool/int/float < TVariant |
105 | 157 | template <typename T>
|
106 |
| - friend typename enable_if<is_simple_value<T>::value, bool>::type operator<( |
107 |
| - const T &lhs, TVariant rhs) { |
108 |
| - return lhs < rhs.template as<T>(); |
| 158 | + friend bool operator<(TVariant lhs, const T &rhs) { |
| 159 | + return compare(lhs, rhs) < 0; |
109 | 160 | }
|
110 | 161 |
|
111 |
| - // TVariant < bool/int/float |
| 162 | + // value <= TVariant |
112 | 163 | template <typename T>
|
113 |
| - friend typename enable_if<is_simple_value<T>::value, bool>::type operator<( |
114 |
| - TVariant lhs, const T &rhs) { |
115 |
| - return lhs.template as<T>() < rhs; |
| 164 | + friend bool operator<=(T *lhs, TVariant rhs) { |
| 165 | + return compare(rhs, lhs) >= 0; |
116 | 166 | }
|
117 |
| - |
118 |
| - // bool/int/float <= TVariant |
119 | 167 | template <typename T>
|
120 |
| - friend typename enable_if<is_simple_value<T>::value, bool>::type operator<=( |
121 |
| - const T &lhs, TVariant rhs) { |
122 |
| - return lhs <= rhs.template as<T>(); |
| 168 | + friend bool operator<=(const T &lhs, TVariant rhs) { |
| 169 | + return compare(rhs, lhs) >= 0; |
123 | 170 | }
|
124 | 171 |
|
125 |
| - // TVariant <= bool/int/float |
| 172 | + // TVariant <= value |
126 | 173 | template <typename T>
|
127 |
| - friend typename enable_if<is_simple_value<T>::value, bool>::type operator<=( |
128 |
| - TVariant lhs, const T &rhs) { |
129 |
| - return lhs.template as<T>() <= rhs; |
| 174 | + friend bool operator<=(TVariant lhs, T *rhs) { |
| 175 | + return compare(lhs, rhs) <= 0; |
| 176 | + } |
| 177 | + template <typename T> |
| 178 | + friend bool operator<=(TVariant lhs, const T &rhs) { |
| 179 | + return compare(lhs, rhs) <= 0; |
130 | 180 | }
|
131 | 181 |
|
132 |
| - // bool/int/float > TVariant |
| 182 | + // value > TVariant |
133 | 183 | template <typename T>
|
134 |
| - friend typename enable_if<is_simple_value<T>::value, bool>::type operator>( |
135 |
| - const T &lhs, TVariant rhs) { |
136 |
| - return lhs > rhs.template as<T>(); |
| 184 | + friend bool operator>(T *lhs, TVariant rhs) { |
| 185 | + return compare(rhs, lhs) < 0; |
| 186 | + } |
| 187 | + template <typename T> |
| 188 | + friend bool operator>(const T &lhs, TVariant rhs) { |
| 189 | + return compare(rhs, lhs) < 0; |
137 | 190 | }
|
138 | 191 |
|
139 |
| - // TVariant > bool/int/float |
| 192 | + // TVariant > value |
| 193 | + template <typename T> |
| 194 | + friend bool operator>(TVariant lhs, T *rhs) { |
| 195 | + return compare(lhs, rhs) > 0; |
| 196 | + } |
140 | 197 | template <typename T>
|
141 |
| - friend typename enable_if<is_simple_value<T>::value, bool>::type operator>( |
142 |
| - TVariant lhs, const T &rhs) { |
143 |
| - return lhs.template as<T>() > rhs; |
| 198 | + friend bool operator>(TVariant lhs, const T &rhs) { |
| 199 | + return compare(lhs, rhs) > 0; |
144 | 200 | }
|
145 | 201 |
|
146 |
| - // bool/int/float >= TVariant |
| 202 | + // value >= TVariant |
| 203 | + template <typename T> |
| 204 | + friend bool operator>=(T *lhs, TVariant rhs) { |
| 205 | + return compare(rhs, lhs) <= 0; |
| 206 | + } |
147 | 207 | template <typename T>
|
148 |
| - friend typename enable_if<is_simple_value<T>::value, bool>::type operator>=( |
149 |
| - const T &lhs, TVariant rhs) { |
150 |
| - return lhs >= rhs.template as<T>(); |
| 208 | + friend bool operator>=(const T &lhs, TVariant rhs) { |
| 209 | + return compare(rhs, lhs) <= 0; |
151 | 210 | }
|
152 | 211 |
|
153 |
| - // TVariant >= bool/int/float |
| 212 | + // TVariant >= value |
| 213 | + template <typename T> |
| 214 | + friend bool operator>=(TVariant lhs, T *rhs) { |
| 215 | + return compare(lhs, rhs) >= 0; |
| 216 | + } |
154 | 217 | template <typename T>
|
155 |
| - friend typename enable_if<is_simple_value<T>::value, bool>::type operator>=( |
156 |
| - TVariant lhs, const T &rhs) { |
157 |
| - return lhs.template as<T>() >= rhs; |
| 218 | + friend bool operator>=(TVariant lhs, const T &rhs) { |
| 219 | + return compare(lhs, rhs) >= 0; |
158 | 220 | }
|
159 | 221 | };
|
160 | 222 |
|
|
0 commit comments