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& operator=(const Variant&) = default; 87 88 template <class T> 89 struct dependent_false : std::false_type {}; 90 91 template <typename T> Value()92 T Value() const { 93 static_assert(dependent_false<T>::value, "Not supported."); 94 } 95 96 template <> Value()97 int8 Value() const { 98 TC3_CHECK(Has<int8>()); 99 return int8_value_; 100 } 101 102 template <> Value()103 uint8 Value() const { 104 TC3_CHECK(Has<uint8>()); 105 return uint8_value_; 106 } 107 108 template <> Value()109 int Value() const { 110 TC3_CHECK(Has<int>()); 111 return int_value_; 112 } 113 114 template <> Value()115 uint Value() const { 116 TC3_CHECK(Has<uint>()); 117 return uint_value_; 118 } 119 120 template <> Value()121 int64 Value() const { 122 TC3_CHECK(Has<int64>()); 123 return long_value_; 124 } 125 126 template <> Value()127 uint64 Value() const { 128 TC3_CHECK(Has<uint64>()); 129 return ulong_value_; 130 } 131 132 template <> Value()133 float Value() const { 134 TC3_CHECK(Has<float>()); 135 return float_value_; 136 } 137 138 template <> Value()139 double Value() const { 140 TC3_CHECK(Has<double>()); 141 return double_value_; 142 } 143 144 template <> Value()145 bool Value() const { 146 TC3_CHECK(Has<bool>()); 147 return bool_value_; 148 } 149 150 template <typename T> 151 const T& ConstRefValue() const; 152 153 template <> ConstRefValue()154 const std::string& ConstRefValue() const { 155 TC3_CHECK(Has<std::string>()); 156 return string_value_; 157 } 158 159 template <> ConstRefValue()160 const std::vector<std::string>& ConstRefValue() const { 161 TC3_CHECK(Has<std::vector<std::string>>()); 162 return string_vector_value_; 163 } 164 165 template <> ConstRefValue()166 const std::vector<float>& ConstRefValue() const { 167 TC3_CHECK(Has<std::vector<float>>()); 168 return float_vector_value_; 169 } 170 171 template <> ConstRefValue()172 const std::vector<int>& ConstRefValue() const { 173 TC3_CHECK(Has<std::vector<int>>()); 174 return int_vector_value_; 175 } 176 177 template <> ConstRefValue()178 const std::map<std::string, Variant>& ConstRefValue() const { 179 TC3_CHECK((Has<std::map<std::string, Variant>>())); 180 return string_variant_map_value_; 181 } 182 183 template <typename T> 184 bool Has() const; 185 186 template <> 187 bool Has<int8>() const { 188 return type_ == TYPE_INT8_VALUE; 189 } 190 191 template <> 192 bool Has<uint8>() const { 193 return type_ == TYPE_UINT8_VALUE; 194 } 195 196 template <> 197 bool Has<int>() const { 198 return type_ == TYPE_INT_VALUE; 199 } 200 201 template <> 202 bool Has<uint>() const { 203 return type_ == TYPE_UINT_VALUE; 204 } 205 206 template <> 207 bool Has<int64>() const { 208 return type_ == TYPE_INT64_VALUE; 209 } 210 211 template <> 212 bool Has<uint64>() const { 213 return type_ == TYPE_UINT64_VALUE; 214 } 215 216 template <> 217 bool Has<float>() const { 218 return type_ == TYPE_FLOAT_VALUE; 219 } 220 221 template <> 222 bool Has<double>() const { 223 return type_ == TYPE_DOUBLE_VALUE; 224 } 225 226 template <> 227 bool Has<bool>() const { 228 return type_ == TYPE_BOOL_VALUE; 229 } 230 231 template <> 232 bool Has<std::string>() const { 233 return type_ == TYPE_STRING_VALUE; 234 } 235 236 template <> 237 bool Has<std::vector<std::string>>() const { 238 return type_ == TYPE_STRING_VECTOR_VALUE; 239 } 240 241 template <> 242 bool Has<std::vector<float>>() const { 243 return type_ == TYPE_FLOAT_VECTOR_VALUE; 244 } 245 246 template <> 247 bool Has<std::vector<int>>() const { 248 return type_ == TYPE_INT_VECTOR_VALUE; 249 } 250 251 template <> 252 bool Has<std::map<std::string, Variant>>() const { 253 return type_ == TYPE_STRING_VARIANT_MAP_VALUE; 254 } 255 256 // Converts the value of this variant to its string representation, regardless 257 // of the type of the actual value. 258 std::string ToString() const; 259 GetType()260 Type GetType() const { return type_; } 261 HasValue()262 bool HasValue() const { return type_ != TYPE_EMPTY; } 263 264 private: 265 Type type_; 266 union { 267 int8_t int8_value_; 268 uint8_t uint8_value_; 269 int int_value_; 270 uint uint_value_; 271 int64 long_value_; 272 uint64 ulong_value_; 273 float float_value_; 274 double double_value_; 275 bool bool_value_; 276 }; 277 std::string string_value_; 278 std::vector<std::string> string_vector_value_; 279 std::vector<float> float_vector_value_; 280 std::vector<int> int_vector_value_; 281 std::map<std::string, Variant> string_variant_map_value_; 282 }; 283 284 // Pretty-printing function for Variant. 285 logging::LoggingStringStream& operator<<(logging::LoggingStringStream& stream, 286 const Variant& value); 287 288 } // namespace libtextclassifier3 289 290 #endif // LIBTEXTCLASSIFIER_UTILS_VARIANT_H_ 291