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