xref: /aosp_15_r20/external/libtextclassifier/native/utils/variant.h (revision 993b0882672172b81d12fad7a7ac0c3e5c824a12)
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef LIBTEXTCLASSIFIER_UTILS_VARIANT_H_
18 #define LIBTEXTCLASSIFIER_UTILS_VARIANT_H_
19 
20 #include <map>
21 #include <string>
22 #include <vector>
23 
24 #include "utils/base/integral_types.h"
25 #include "utils/base/logging.h"
26 #include "utils/strings/stringpiece.h"
27 
28 namespace libtextclassifier3 {
29 
30 // Represents a type-tagged union of different basic types.
31 class Variant {
32  public:
33   enum Type {
34     TYPE_EMPTY = 0,
35     TYPE_INT8_VALUE = 1,
36     TYPE_UINT8_VALUE = 2,
37     TYPE_INT_VALUE = 3,
38     TYPE_UINT_VALUE = 4,
39     TYPE_INT64_VALUE = 5,
40     TYPE_UINT64_VALUE = 6,
41     TYPE_FLOAT_VALUE = 7,
42     TYPE_DOUBLE_VALUE = 8,
43     TYPE_BOOL_VALUE = 9,
44     TYPE_STRING_VALUE = 10,
45     TYPE_STRING_VECTOR_VALUE = 11,
46     TYPE_FLOAT_VECTOR_VALUE = 12,
47     TYPE_INT_VECTOR_VALUE = 13,
48     TYPE_STRING_VARIANT_MAP_VALUE = 14,
49   };
50 
Variant()51   Variant() : type_(TYPE_EMPTY) {}
Variant(const int8_t value)52   explicit Variant(const int8_t value)
53       : type_(TYPE_INT8_VALUE), int8_value_(value) {}
Variant(const uint8_t value)54   explicit Variant(const uint8_t value)
55       : type_(TYPE_UINT8_VALUE), uint8_value_(value) {}
Variant(const int value)56   explicit Variant(const int value)
57       : type_(TYPE_INT_VALUE), int_value_(value) {}
Variant(const uint value)58   explicit Variant(const uint value)
59       : type_(TYPE_UINT_VALUE), uint_value_(value) {}
Variant(const int64 value)60   explicit Variant(const int64 value)
61       : type_(TYPE_INT64_VALUE), long_value_(value) {}
Variant(const uint64 value)62   explicit Variant(const uint64 value)
63       : type_(TYPE_UINT64_VALUE), ulong_value_(value) {}
Variant(const float value)64   explicit Variant(const float value)
65       : type_(TYPE_FLOAT_VALUE), float_value_(value) {}
Variant(const double value)66   explicit Variant(const double value)
67       : type_(TYPE_DOUBLE_VALUE), double_value_(value) {}
Variant(const StringPiece value)68   explicit Variant(const StringPiece value)
69       : type_(TYPE_STRING_VALUE), string_value_(value.ToString()) {}
Variant(const std::string value)70   explicit Variant(const std::string value)
71       : type_(TYPE_STRING_VALUE), string_value_(value) {}
Variant(const char * value)72   explicit Variant(const char* value)
73       : type_(TYPE_STRING_VALUE), string_value_(value) {}
Variant(const bool value)74   explicit Variant(const bool value)
75       : type_(TYPE_BOOL_VALUE), bool_value_(value) {}
Variant(const std::vector<std::string> & value)76   explicit Variant(const std::vector<std::string>& value)
77       : type_(TYPE_STRING_VECTOR_VALUE), string_vector_value_(value) {}
Variant(const std::vector<float> & value)78   explicit Variant(const std::vector<float>& value)
79       : type_(TYPE_FLOAT_VECTOR_VALUE), float_vector_value_(value) {}
Variant(const std::vector<int> & value)80   explicit Variant(const std::vector<int>& value)
81       : type_(TYPE_INT_VECTOR_VALUE), int_vector_value_(value) {}
Variant(const std::map<std::string,Variant> & value)82   explicit Variant(const std::map<std::string, Variant>& value)
83       : type_(TYPE_STRING_VARIANT_MAP_VALUE),
84         string_variant_map_value_(value) {}
85 
86   Variant(const Variant&) = default;
87   Variant& operator=(const Variant&) = default;
88 
89   template <class T>
90   struct dependent_false : std::false_type {};
91 
92   template <typename T>
Value()93   T Value() const {
94     static_assert(dependent_false<T>::value, "Not supported.");
95   }
96 
97   template <>
Value()98   int8 Value() const {
99     TC3_CHECK(Has<int8>());
100     return int8_value_;
101   }
102 
103   template <>
Value()104   uint8 Value() const {
105     TC3_CHECK(Has<uint8>());
106     return uint8_value_;
107   }
108 
109   template <>
Value()110   int Value() const {
111     TC3_CHECK(Has<int>());
112     return int_value_;
113   }
114 
115   template <>
Value()116   uint Value() const {
117     TC3_CHECK(Has<uint>());
118     return uint_value_;
119   }
120 
121   template <>
Value()122   int64 Value() const {
123     TC3_CHECK(Has<int64>());
124     return long_value_;
125   }
126 
127   template <>
Value()128   uint64 Value() const {
129     TC3_CHECK(Has<uint64>());
130     return ulong_value_;
131   }
132 
133   template <>
Value()134   float Value() const {
135     TC3_CHECK(Has<float>());
136     return float_value_;
137   }
138 
139   template <>
Value()140   double Value() const {
141     TC3_CHECK(Has<double>());
142     return double_value_;
143   }
144 
145   template <>
Value()146   bool Value() const {
147     TC3_CHECK(Has<bool>());
148     return bool_value_;
149   }
150 
151   template <typename T>
152   const T& ConstRefValue() const;
153 
154   template <>
ConstRefValue()155   const std::string& ConstRefValue() const {
156     TC3_CHECK(Has<std::string>());
157     return string_value_;
158   }
159 
160   template <>
ConstRefValue()161   const std::vector<std::string>& ConstRefValue() const {
162     TC3_CHECK(Has<std::vector<std::string>>());
163     return string_vector_value_;
164   }
165 
166   template <>
ConstRefValue()167   const std::vector<float>& ConstRefValue() const {
168     TC3_CHECK(Has<std::vector<float>>());
169     return float_vector_value_;
170   }
171 
172   template <>
ConstRefValue()173   const std::vector<int>& ConstRefValue() const {
174     TC3_CHECK(Has<std::vector<int>>());
175     return int_vector_value_;
176   }
177 
178   template <>
ConstRefValue()179   const std::map<std::string, Variant>& ConstRefValue() const {
180     TC3_CHECK((Has<std::map<std::string, Variant>>()));
181     return string_variant_map_value_;
182   }
183 
184   template <typename T>
185   bool Has() const;
186 
187   template <>
188   bool Has<int8>() const {
189     return type_ == TYPE_INT8_VALUE;
190   }
191 
192   template <>
193   bool Has<uint8>() const {
194     return type_ == TYPE_UINT8_VALUE;
195   }
196 
197   template <>
198   bool Has<int>() const {
199     return type_ == TYPE_INT_VALUE;
200   }
201 
202   template <>
203   bool Has<uint>() const {
204     return type_ == TYPE_UINT_VALUE;
205   }
206 
207   template <>
208   bool Has<int64>() const {
209     return type_ == TYPE_INT64_VALUE;
210   }
211 
212   template <>
213   bool Has<uint64>() const {
214     return type_ == TYPE_UINT64_VALUE;
215   }
216 
217   template <>
218   bool Has<float>() const {
219     return type_ == TYPE_FLOAT_VALUE;
220   }
221 
222   template <>
223   bool Has<double>() const {
224     return type_ == TYPE_DOUBLE_VALUE;
225   }
226 
227   template <>
228   bool Has<bool>() const {
229     return type_ == TYPE_BOOL_VALUE;
230   }
231 
232   template <>
233   bool Has<std::string>() const {
234     return type_ == TYPE_STRING_VALUE;
235   }
236 
237   template <>
238   bool Has<std::vector<std::string>>() const {
239     return type_ == TYPE_STRING_VECTOR_VALUE;
240   }
241 
242   template <>
243   bool Has<std::vector<float>>() const {
244     return type_ == TYPE_FLOAT_VECTOR_VALUE;
245   }
246 
247   template <>
248   bool Has<std::vector<int>>() const {
249     return type_ == TYPE_INT_VECTOR_VALUE;
250   }
251 
252   template <>
253   bool Has<std::map<std::string, Variant>>() const {
254     return type_ == TYPE_STRING_VARIANT_MAP_VALUE;
255   }
256 
257   // Converts the value of this variant to its string representation, regardless
258   // of the type of the actual value.
259   std::string ToString() const;
260 
GetType()261   Type GetType() const { return type_; }
262 
HasValue()263   bool HasValue() const { return type_ != TYPE_EMPTY; }
264 
265  private:
266   Type type_;
267   union {
268     int8_t int8_value_;
269     uint8_t uint8_value_;
270     int int_value_;
271     uint uint_value_;
272     int64 long_value_;
273     uint64 ulong_value_;
274     float float_value_;
275     double double_value_;
276     bool bool_value_;
277   };
278   std::string string_value_;
279   std::vector<std::string> string_vector_value_;
280   std::vector<float> float_vector_value_;
281   std::vector<int> int_vector_value_;
282   std::map<std::string, Variant> string_variant_map_value_;
283 };
284 
285 // Pretty-printing function for Variant.
286 logging::LoggingStringStream& operator<<(logging::LoggingStringStream& stream,
287                                          const Variant& value);
288 
289 }  // namespace libtextclassifier3
290 
291 #endif  // LIBTEXTCLASSIFIER_UTILS_VARIANT_H_
292