1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker #ifndef ART_LIBARTBASE_BASE_VARIANT_MAP_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_LIBARTBASE_BASE_VARIANT_MAP_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include <memory.h> 21*795d594fSAndroid Build Coastguard Worker #include <map> 22*795d594fSAndroid Build Coastguard Worker #include <type_traits> 23*795d594fSAndroid Build Coastguard Worker #include <utility> 24*795d594fSAndroid Build Coastguard Worker 25*795d594fSAndroid Build Coastguard Worker #include "android-base/logging.h" 26*795d594fSAndroid Build Coastguard Worker #include "stl_util_identity.h" 27*795d594fSAndroid Build Coastguard Worker 28*795d594fSAndroid Build Coastguard Worker namespace art { 29*795d594fSAndroid Build Coastguard Worker 30*795d594fSAndroid Build Coastguard Worker // 31*795d594fSAndroid Build Coastguard Worker // A variant map is a heterogenous, type safe key->value map. It allows 32*795d594fSAndroid Build Coastguard Worker // for multiple different value types to be stored dynamically in the same map. 33*795d594fSAndroid Build Coastguard Worker // 34*795d594fSAndroid Build Coastguard Worker // It provides the following interface in a nutshell: 35*795d594fSAndroid Build Coastguard Worker // 36*795d594fSAndroid Build Coastguard Worker // struct VariantMap { 37*795d594fSAndroid Build Coastguard Worker // template <typename TValue> 38*795d594fSAndroid Build Coastguard Worker // TValue* Get(Key<T> key); // null if the value was never set, otherwise the value. 39*795d594fSAndroid Build Coastguard Worker // 40*795d594fSAndroid Build Coastguard Worker // template <typename TValue> 41*795d594fSAndroid Build Coastguard Worker // void Set(Key<T> key, TValue value); 42*795d594fSAndroid Build Coastguard Worker // }; 43*795d594fSAndroid Build Coastguard Worker // 44*795d594fSAndroid Build Coastguard Worker // Since the key is strongly typed at compile-time, it is impossible to accidentally 45*795d594fSAndroid Build Coastguard Worker // read/write a value with a different type than the key at either compile-time or run-time. 46*795d594fSAndroid Build Coastguard Worker // 47*795d594fSAndroid Build Coastguard Worker // Do not use VariantMap/VariantMapKey directly. Instead subclass each of them and use 48*795d594fSAndroid Build Coastguard Worker // the subclass, for example: 49*795d594fSAndroid Build Coastguard Worker // 50*795d594fSAndroid Build Coastguard Worker // template <typename TValue> 51*795d594fSAndroid Build Coastguard Worker // struct FruitMapKey : VariantMapKey<TValue> { 52*795d594fSAndroid Build Coastguard Worker // FruitMapKey() {} 53*795d594fSAndroid Build Coastguard Worker // }; 54*795d594fSAndroid Build Coastguard Worker // 55*795d594fSAndroid Build Coastguard Worker // struct FruitMap : VariantMap<FruitMap, FruitMapKey> { 56*795d594fSAndroid Build Coastguard Worker // // This 'using' line is necessary to inherit the variadic constructor. 57*795d594fSAndroid Build Coastguard Worker // using VariantMap<FruitMap, FruitMapKey>::VariantMap; 58*795d594fSAndroid Build Coastguard Worker // 59*795d594fSAndroid Build Coastguard Worker // // Make the next '4' usages of Key slightly shorter to type. 60*795d594fSAndroid Build Coastguard Worker // template <typename TValue> 61*795d594fSAndroid Build Coastguard Worker // using Key = FruitMapKey<TValue>; 62*795d594fSAndroid Build Coastguard Worker // 63*795d594fSAndroid Build Coastguard Worker // static const Key<int> Apple; 64*795d594fSAndroid Build Coastguard Worker // static const Key<double> Orange; 65*795d594fSAndroid Build Coastguard Worker // static const Key<std::string> Banana; 66*795d594fSAndroid Build Coastguard Worker // }; 67*795d594fSAndroid Build Coastguard Worker // 68*795d594fSAndroid Build Coastguard Worker // const FruitMap::Key<int> FruitMap::Apple; 69*795d594fSAndroid Build Coastguard Worker // const FruitMap::Key<double> FruitMap::Orange; 70*795d594fSAndroid Build Coastguard Worker // const FruitMap::Key<std::string> Banana; 71*795d594fSAndroid Build Coastguard Worker // 72*795d594fSAndroid Build Coastguard Worker // See variant_map_test.cc for more examples. 73*795d594fSAndroid Build Coastguard Worker // 74*795d594fSAndroid Build Coastguard Worker 75*795d594fSAndroid Build Coastguard Worker // Implementation details for VariantMap. 76*795d594fSAndroid Build Coastguard Worker namespace detail { 77*795d594fSAndroid Build Coastguard Worker // Allocate a unique counter value each time it's called. 78*795d594fSAndroid Build Coastguard Worker struct VariantMapKeyCounterAllocator { AllocateCounterVariantMapKeyCounterAllocator79*795d594fSAndroid Build Coastguard Worker static size_t AllocateCounter() { 80*795d594fSAndroid Build Coastguard Worker static size_t counter = 0; 81*795d594fSAndroid Build Coastguard Worker counter++; 82*795d594fSAndroid Build Coastguard Worker 83*795d594fSAndroid Build Coastguard Worker return counter; 84*795d594fSAndroid Build Coastguard Worker } 85*795d594fSAndroid Build Coastguard Worker }; 86*795d594fSAndroid Build Coastguard Worker 87*795d594fSAndroid Build Coastguard Worker // Type-erased version of VariantMapKey<T> 88*795d594fSAndroid Build Coastguard Worker struct VariantMapKeyRaw { 89*795d594fSAndroid Build Coastguard Worker // TODO: this may need to call a virtual function to support string comparisons 90*795d594fSAndroid Build Coastguard Worker bool operator<(const VariantMapKeyRaw& other) const { 91*795d594fSAndroid Build Coastguard Worker return key_counter_ < other.key_counter_; 92*795d594fSAndroid Build Coastguard Worker } 93*795d594fSAndroid Build Coastguard Worker 94*795d594fSAndroid Build Coastguard Worker // The following functions need to be virtual since we don't know the compile-time type anymore: 95*795d594fSAndroid Build Coastguard Worker 96*795d594fSAndroid Build Coastguard Worker // Clone the key, creating a copy of the contents. 97*795d594fSAndroid Build Coastguard Worker virtual VariantMapKeyRaw* Clone() const = 0; 98*795d594fSAndroid Build Coastguard Worker 99*795d594fSAndroid Build Coastguard Worker // Delete a value whose runtime type is that of the non-erased key's TValue. 100*795d594fSAndroid Build Coastguard Worker virtual void ValueDelete(void* value) const = 0; 101*795d594fSAndroid Build Coastguard Worker 102*795d594fSAndroid Build Coastguard Worker // Clone a value whose runtime type is that of the non-erased key's TValue. 103*795d594fSAndroid Build Coastguard Worker virtual void* ValueClone(void* value) const = 0; 104*795d594fSAndroid Build Coastguard Worker 105*795d594fSAndroid Build Coastguard Worker // Compare one key to another (same as operator<). CompareVariantMapKeyRaw106*795d594fSAndroid Build Coastguard Worker virtual bool Compare(const VariantMapKeyRaw* other) const { 107*795d594fSAndroid Build Coastguard Worker if (other == nullptr) { 108*795d594fSAndroid Build Coastguard Worker return false; 109*795d594fSAndroid Build Coastguard Worker } 110*795d594fSAndroid Build Coastguard Worker return key_counter_ < other->key_counter_; 111*795d594fSAndroid Build Coastguard Worker } 112*795d594fSAndroid Build Coastguard Worker ~VariantMapKeyRawVariantMapKeyRaw113*795d594fSAndroid Build Coastguard Worker virtual ~VariantMapKeyRaw() {} 114*795d594fSAndroid Build Coastguard Worker 115*795d594fSAndroid Build Coastguard Worker protected: VariantMapKeyRawVariantMapKeyRaw116*795d594fSAndroid Build Coastguard Worker VariantMapKeyRaw() 117*795d594fSAndroid Build Coastguard Worker : key_counter_(VariantMapKeyCounterAllocator::AllocateCounter()) {} 118*795d594fSAndroid Build Coastguard Worker // explicit VariantMapKeyRaw(size_t counter) 119*795d594fSAndroid Build Coastguard Worker // : key_counter_(counter) {} 120*795d594fSAndroid Build Coastguard Worker GetCounterVariantMapKeyRaw121*795d594fSAndroid Build Coastguard Worker size_t GetCounter() const { 122*795d594fSAndroid Build Coastguard Worker return key_counter_; 123*795d594fSAndroid Build Coastguard Worker } 124*795d594fSAndroid Build Coastguard Worker 125*795d594fSAndroid Build Coastguard Worker protected: 126*795d594fSAndroid Build Coastguard Worker // Avoid the object slicing problem; use Clone() instead. 127*795d594fSAndroid Build Coastguard Worker VariantMapKeyRaw(const VariantMapKeyRaw&) = default; 128*795d594fSAndroid Build Coastguard Worker VariantMapKeyRaw(VariantMapKeyRaw&&) noexcept = default; 129*795d594fSAndroid Build Coastguard Worker 130*795d594fSAndroid Build Coastguard Worker private: 131*795d594fSAndroid Build Coastguard Worker size_t key_counter_; // Runtime type ID. Unique each time a new type is reified. 132*795d594fSAndroid Build Coastguard Worker }; 133*795d594fSAndroid Build Coastguard Worker } // namespace detail 134*795d594fSAndroid Build Coastguard Worker 135*795d594fSAndroid Build Coastguard Worker // The base type for keys used by the VariantMap. Users must subclass this type. 136*795d594fSAndroid Build Coastguard Worker template <typename TValue> 137*795d594fSAndroid Build Coastguard Worker struct VariantMapKey : detail::VariantMapKeyRaw { 138*795d594fSAndroid Build Coastguard Worker // Instantiate a default value for this key. If an explicit default value was provided 139*795d594fSAndroid Build Coastguard Worker // then that is used. Otherwise, the default value for the type TValue{} is returned. CreateDefaultValueVariantMapKey140*795d594fSAndroid Build Coastguard Worker TValue CreateDefaultValue() const { 141*795d594fSAndroid Build Coastguard Worker if (default_value_ == nullptr) { 142*795d594fSAndroid Build Coastguard Worker return TValue{}; 143*795d594fSAndroid Build Coastguard Worker } else { 144*795d594fSAndroid Build Coastguard Worker return TValue(*default_value_); 145*795d594fSAndroid Build Coastguard Worker } 146*795d594fSAndroid Build Coastguard Worker } 147*795d594fSAndroid Build Coastguard Worker 148*795d594fSAndroid Build Coastguard Worker protected: 149*795d594fSAndroid Build Coastguard Worker // explicit VariantMapKey(size_t counter) : detail::VariantMapKeyRaw(counter) {} VariantMapKeyVariantMapKey150*795d594fSAndroid Build Coastguard Worker explicit VariantMapKey(const TValue& default_value) 151*795d594fSAndroid Build Coastguard Worker : default_value_(std::make_shared<TValue>(default_value)) {} VariantMapKeyVariantMapKey152*795d594fSAndroid Build Coastguard Worker explicit VariantMapKey(TValue&& default_value) 153*795d594fSAndroid Build Coastguard Worker : default_value_(std::make_shared<TValue>(default_value)) {} VariantMapKeyVariantMapKey154*795d594fSAndroid Build Coastguard Worker VariantMapKey() {} ~VariantMapKeyVariantMapKey155*795d594fSAndroid Build Coastguard Worker virtual ~VariantMapKey() {} 156*795d594fSAndroid Build Coastguard Worker 157*795d594fSAndroid Build Coastguard Worker private: CloneVariantMapKey158*795d594fSAndroid Build Coastguard Worker virtual VariantMapKeyRaw* Clone() const { 159*795d594fSAndroid Build Coastguard Worker return new VariantMapKey<TValue>(*this); 160*795d594fSAndroid Build Coastguard Worker } 161*795d594fSAndroid Build Coastguard Worker ValueCloneVariantMapKey162*795d594fSAndroid Build Coastguard Worker virtual void* ValueClone(void* value) const { 163*795d594fSAndroid Build Coastguard Worker if (value == nullptr) { 164*795d594fSAndroid Build Coastguard Worker return nullptr; 165*795d594fSAndroid Build Coastguard Worker } 166*795d594fSAndroid Build Coastguard Worker 167*795d594fSAndroid Build Coastguard Worker TValue* strong_value = reinterpret_cast<TValue*>(value); 168*795d594fSAndroid Build Coastguard Worker return new TValue(*strong_value); 169*795d594fSAndroid Build Coastguard Worker } 170*795d594fSAndroid Build Coastguard Worker ValueDeleteVariantMapKey171*795d594fSAndroid Build Coastguard Worker virtual void ValueDelete(void* value) const { 172*795d594fSAndroid Build Coastguard Worker if (value == nullptr) { 173*795d594fSAndroid Build Coastguard Worker return; 174*795d594fSAndroid Build Coastguard Worker } 175*795d594fSAndroid Build Coastguard Worker 176*795d594fSAndroid Build Coastguard Worker // Smartly invoke the proper delete/delete[]/etc 177*795d594fSAndroid Build Coastguard Worker const std::default_delete<TValue> deleter = std::default_delete<TValue>(); 178*795d594fSAndroid Build Coastguard Worker deleter(reinterpret_cast<TValue*>(value)); 179*795d594fSAndroid Build Coastguard Worker } 180*795d594fSAndroid Build Coastguard Worker 181*795d594fSAndroid Build Coastguard Worker VariantMapKey(const VariantMapKey&) = default; 182*795d594fSAndroid Build Coastguard Worker VariantMapKey(VariantMapKey&&) noexcept = default; 183*795d594fSAndroid Build Coastguard Worker 184*795d594fSAndroid Build Coastguard Worker template <typename Base, template <typename TV> class TKey> friend struct VariantMap; 185*795d594fSAndroid Build Coastguard Worker 186*795d594fSAndroid Build Coastguard Worker // Store a prototype of the key's default value, for usage with VariantMap::GetOrDefault 187*795d594fSAndroid Build Coastguard Worker std::shared_ptr<TValue> default_value_; 188*795d594fSAndroid Build Coastguard Worker }; 189*795d594fSAndroid Build Coastguard Worker 190*795d594fSAndroid Build Coastguard Worker // Implementation details for a stringified VariantMapStringKey. 191*795d594fSAndroid Build Coastguard Worker namespace detail { 192*795d594fSAndroid Build Coastguard Worker struct VariantMapStringKeyRegistry { 193*795d594fSAndroid Build Coastguard Worker // TODO 194*795d594fSAndroid Build Coastguard Worker }; 195*795d594fSAndroid Build Coastguard Worker } // namespace detail 196*795d594fSAndroid Build Coastguard Worker 197*795d594fSAndroid Build Coastguard Worker // Alternative base type for all keys used by VariantMap, supports runtime strings as the name. 198*795d594fSAndroid Build Coastguard Worker template <typename TValue> 199*795d594fSAndroid Build Coastguard Worker struct VariantMapStringKey : VariantMapKey<TValue> { VariantMapStringKeyVariantMapStringKey200*795d594fSAndroid Build Coastguard Worker explicit VariantMapStringKey(const char* name) 201*795d594fSAndroid Build Coastguard Worker : // VariantMapKey(/*std::hash<std::string>()(name)*/), 202*795d594fSAndroid Build Coastguard Worker name_(name) { 203*795d594fSAndroid Build Coastguard Worker } 204*795d594fSAndroid Build Coastguard Worker 205*795d594fSAndroid Build Coastguard Worker private: 206*795d594fSAndroid Build Coastguard Worker const char* name_; 207*795d594fSAndroid Build Coastguard Worker }; 208*795d594fSAndroid Build Coastguard Worker 209*795d594fSAndroid Build Coastguard Worker // A variant map allows type-safe heteregeneous key->value mappings. 210*795d594fSAndroid Build Coastguard Worker // All possible key types must be specified at compile-time. Values may be added/removed 211*795d594fSAndroid Build Coastguard Worker // at runtime. 212*795d594fSAndroid Build Coastguard Worker template <typename Base, template <typename TV> class TKey> 213*795d594fSAndroid Build Coastguard Worker struct VariantMap { 214*795d594fSAndroid Build Coastguard Worker // Allow users of this static interface to use the key type. 215*795d594fSAndroid Build Coastguard Worker template <typename TValue> 216*795d594fSAndroid Build Coastguard Worker using Key = TKey<TValue>; 217*795d594fSAndroid Build Coastguard Worker 218*795d594fSAndroid Build Coastguard Worker // Look up the value from the key. The pointer becomes invalid if this key is overwritten/removed. 219*795d594fSAndroid Build Coastguard Worker // A null value is returned only when the key does not exist in this map. 220*795d594fSAndroid Build Coastguard Worker template <typename TValue> GetVariantMap221*795d594fSAndroid Build Coastguard Worker const TValue* Get(const TKey<TValue>& key) const { 222*795d594fSAndroid Build Coastguard Worker return GetValuePtr(key); 223*795d594fSAndroid Build Coastguard Worker } 224*795d594fSAndroid Build Coastguard Worker 225*795d594fSAndroid Build Coastguard Worker // Look up the value from the key. The pointer becomes invalid if this key is overwritten/removed. 226*795d594fSAndroid Build Coastguard Worker // A null value is returned only when the key does not exist in this map. 227*795d594fSAndroid Build Coastguard Worker template <typename TValue> GetVariantMap228*795d594fSAndroid Build Coastguard Worker TValue* Get(const TKey<TValue>& key) { 229*795d594fSAndroid Build Coastguard Worker return GetValuePtr(key); 230*795d594fSAndroid Build Coastguard Worker } 231*795d594fSAndroid Build Coastguard Worker 232*795d594fSAndroid Build Coastguard Worker // Look up the value from the key and return the value wrapped in a std::optional. If it was not 233*795d594fSAndroid Build Coastguard Worker // set in the map, return an empty std::optional. 234*795d594fSAndroid Build Coastguard Worker template <typename TValue> GetOptionalVariantMap235*795d594fSAndroid Build Coastguard Worker std::optional<TValue> GetOptional(const TKey<TValue>& key) const { 236*795d594fSAndroid Build Coastguard Worker auto* ptr = Get(key); 237*795d594fSAndroid Build Coastguard Worker return (ptr == nullptr) ? std::optional<TValue>{} : std::make_optional(*ptr); 238*795d594fSAndroid Build Coastguard Worker } 239*795d594fSAndroid Build Coastguard Worker 240*795d594fSAndroid Build Coastguard Worker // Lookup the value from the key. If it was not set in the map, return the default value. 241*795d594fSAndroid Build Coastguard Worker // The default value is either the key's default, or TValue{} if the key doesn't have a default. 242*795d594fSAndroid Build Coastguard Worker template <typename TValue> GetOrDefaultVariantMap243*795d594fSAndroid Build Coastguard Worker TValue GetOrDefault(const TKey<TValue>& key) const { 244*795d594fSAndroid Build Coastguard Worker auto* ptr = Get(key); 245*795d594fSAndroid Build Coastguard Worker return (ptr == nullptr) ? key.CreateDefaultValue() : *ptr; 246*795d594fSAndroid Build Coastguard Worker } 247*795d594fSAndroid Build Coastguard Worker 248*795d594fSAndroid Build Coastguard Worker template <typename T, typename U> AssignIfExistsVariantMap249*795d594fSAndroid Build Coastguard Worker void AssignIfExists(const TKey<T>& key, U* out) { 250*795d594fSAndroid Build Coastguard Worker DCHECK(out != nullptr); 251*795d594fSAndroid Build Coastguard Worker if (Exists(key)) { 252*795d594fSAndroid Build Coastguard Worker *out = std::move(*Get(key)); 253*795d594fSAndroid Build Coastguard Worker } 254*795d594fSAndroid Build Coastguard Worker } 255*795d594fSAndroid Build Coastguard Worker 256*795d594fSAndroid Build Coastguard Worker private: 257*795d594fSAndroid Build Coastguard Worker // TODO: move to detail, or make it more generic like a ScopeGuard(function) 258*795d594fSAndroid Build Coastguard Worker template <typename TValue> 259*795d594fSAndroid Build Coastguard Worker struct ScopedRemove { ScopedRemoveVariantMap::ScopedRemove260*795d594fSAndroid Build Coastguard Worker ScopedRemove(VariantMap& map, const TKey<TValue>& key) : map_(map), key_(key) {} ~ScopedRemoveVariantMap::ScopedRemove261*795d594fSAndroid Build Coastguard Worker ~ScopedRemove() { 262*795d594fSAndroid Build Coastguard Worker map_.Remove(key_); 263*795d594fSAndroid Build Coastguard Worker } 264*795d594fSAndroid Build Coastguard Worker 265*795d594fSAndroid Build Coastguard Worker VariantMap& map_; 266*795d594fSAndroid Build Coastguard Worker const TKey<TValue>& key_; 267*795d594fSAndroid Build Coastguard Worker }; 268*795d594fSAndroid Build Coastguard Worker 269*795d594fSAndroid Build Coastguard Worker public: 270*795d594fSAndroid Build Coastguard Worker // Release the value from the key. If it was not set in the map, returns the default value. 271*795d594fSAndroid Build Coastguard Worker // If the key was set, it is removed as a side effect. 272*795d594fSAndroid Build Coastguard Worker template <typename TValue> ReleaseOrDefaultVariantMap273*795d594fSAndroid Build Coastguard Worker TValue ReleaseOrDefault(const TKey<TValue>& key) { 274*795d594fSAndroid Build Coastguard Worker ScopedRemove<TValue> remove_on_return(*this, key); 275*795d594fSAndroid Build Coastguard Worker 276*795d594fSAndroid Build Coastguard Worker TValue* ptr = Get(key); 277*795d594fSAndroid Build Coastguard Worker if (ptr != nullptr) { 278*795d594fSAndroid Build Coastguard Worker return std::move(*ptr); 279*795d594fSAndroid Build Coastguard Worker } else { 280*795d594fSAndroid Build Coastguard Worker return key.CreateDefaultValue(); 281*795d594fSAndroid Build Coastguard Worker } 282*795d594fSAndroid Build Coastguard Worker } 283*795d594fSAndroid Build Coastguard Worker 284*795d594fSAndroid Build Coastguard Worker // See if a value is stored for this key. 285*795d594fSAndroid Build Coastguard Worker template <typename TValue> ExistsVariantMap286*795d594fSAndroid Build Coastguard Worker bool Exists(const TKey<TValue>& key) const { 287*795d594fSAndroid Build Coastguard Worker return GetKeyValueIterator(key) != storage_map_.end(); 288*795d594fSAndroid Build Coastguard Worker } 289*795d594fSAndroid Build Coastguard Worker 290*795d594fSAndroid Build Coastguard Worker // Set a value for a given key, overwriting the previous value if any. 291*795d594fSAndroid Build Coastguard Worker // Note: Omit the `value` from TValue type deduction, deduce only from the `key` argument. 292*795d594fSAndroid Build Coastguard Worker template <typename TValue> SetVariantMap293*795d594fSAndroid Build Coastguard Worker void Set(const TKey<TValue>& key, const typename Identity<TValue>::type& value) { 294*795d594fSAndroid Build Coastguard Worker // Clone the value first, to protect against &value == GetValuePtr(key). 295*795d594fSAndroid Build Coastguard Worker auto* new_value = new TValue(value); 296*795d594fSAndroid Build Coastguard Worker 297*795d594fSAndroid Build Coastguard Worker Remove(key); 298*795d594fSAndroid Build Coastguard Worker bool inserted = storage_map_.insert({key.Clone(), new_value}).second; 299*795d594fSAndroid Build Coastguard Worker DCHECK(inserted); // ensure key.Clone() does not leak memory. 300*795d594fSAndroid Build Coastguard Worker } 301*795d594fSAndroid Build Coastguard Worker 302*795d594fSAndroid Build Coastguard Worker // Set a value for a given key, only if there was no previous value before. 303*795d594fSAndroid Build Coastguard Worker // Returns true if the value was set, false if a previous value existed. 304*795d594fSAndroid Build Coastguard Worker // Note: Omit the `value` from TValue type deduction, deduce only from the `key` argument. 305*795d594fSAndroid Build Coastguard Worker template <typename TValue> SetIfMissingVariantMap306*795d594fSAndroid Build Coastguard Worker bool SetIfMissing(const TKey<TValue>& key, const typename Identity<TValue>::type& value) { 307*795d594fSAndroid Build Coastguard Worker TValue* ptr = Get(key); 308*795d594fSAndroid Build Coastguard Worker if (ptr == nullptr) { 309*795d594fSAndroid Build Coastguard Worker Set(key, value); 310*795d594fSAndroid Build Coastguard Worker return true; 311*795d594fSAndroid Build Coastguard Worker } 312*795d594fSAndroid Build Coastguard Worker return false; 313*795d594fSAndroid Build Coastguard Worker } 314*795d594fSAndroid Build Coastguard Worker 315*795d594fSAndroid Build Coastguard Worker // Remove the value for a given key, or a no-op if there was no previously set value. 316*795d594fSAndroid Build Coastguard Worker template <typename TValue> RemoveVariantMap317*795d594fSAndroid Build Coastguard Worker void Remove(const TKey<TValue>& key) { 318*795d594fSAndroid Build Coastguard Worker StaticAssertKeyType<TValue>(); 319*795d594fSAndroid Build Coastguard Worker 320*795d594fSAndroid Build Coastguard Worker auto&& it = GetKeyValueIterator(key); 321*795d594fSAndroid Build Coastguard Worker if (it != storage_map_.end()) { 322*795d594fSAndroid Build Coastguard Worker key.ValueDelete(it->second); 323*795d594fSAndroid Build Coastguard Worker delete it->first; 324*795d594fSAndroid Build Coastguard Worker storage_map_.erase(it); 325*795d594fSAndroid Build Coastguard Worker } 326*795d594fSAndroid Build Coastguard Worker } 327*795d594fSAndroid Build Coastguard Worker 328*795d594fSAndroid Build Coastguard Worker // Remove all key/value pairs. ClearVariantMap329*795d594fSAndroid Build Coastguard Worker void Clear() { 330*795d594fSAndroid Build Coastguard Worker DeleteStoredValues(); 331*795d594fSAndroid Build Coastguard Worker storage_map_.clear(); 332*795d594fSAndroid Build Coastguard Worker } 333*795d594fSAndroid Build Coastguard Worker 334*795d594fSAndroid Build Coastguard Worker // How many key/value pairs are stored in this map. SizeVariantMap335*795d594fSAndroid Build Coastguard Worker size_t Size() const { 336*795d594fSAndroid Build Coastguard Worker return storage_map_.size(); 337*795d594fSAndroid Build Coastguard Worker } 338*795d594fSAndroid Build Coastguard Worker 339*795d594fSAndroid Build Coastguard Worker // Construct an empty map. VariantMapVariantMap340*795d594fSAndroid Build Coastguard Worker VariantMap() {} 341*795d594fSAndroid Build Coastguard Worker 342*795d594fSAndroid Build Coastguard Worker template <typename ... TKeyValue> VariantMapVariantMap343*795d594fSAndroid Build Coastguard Worker explicit VariantMap(const TKeyValue& ... key_value_list) { 344*795d594fSAndroid Build Coastguard Worker static_assert(sizeof...(TKeyValue) % 2 == 0, "Must be an even number of key/value elements"); 345*795d594fSAndroid Build Coastguard Worker InitializeParameters(key_value_list...); 346*795d594fSAndroid Build Coastguard Worker } 347*795d594fSAndroid Build Coastguard Worker 348*795d594fSAndroid Build Coastguard Worker // Create a new map from an existing map, copying all the key/value pairs. VariantMapVariantMap349*795d594fSAndroid Build Coastguard Worker VariantMap(const VariantMap& other) { 350*795d594fSAndroid Build Coastguard Worker operator=(other); 351*795d594fSAndroid Build Coastguard Worker } 352*795d594fSAndroid Build Coastguard Worker 353*795d594fSAndroid Build Coastguard Worker // Copy the key/value pairs from the other map into this one. Existing key/values are cleared. 354*795d594fSAndroid Build Coastguard Worker VariantMap& operator=(const VariantMap& other) { 355*795d594fSAndroid Build Coastguard Worker if (this == &other) { 356*795d594fSAndroid Build Coastguard Worker return *this; 357*795d594fSAndroid Build Coastguard Worker } 358*795d594fSAndroid Build Coastguard Worker 359*795d594fSAndroid Build Coastguard Worker Clear(); 360*795d594fSAndroid Build Coastguard Worker 361*795d594fSAndroid Build Coastguard Worker for (auto&& kv_pair : other.storage_map_) { 362*795d594fSAndroid Build Coastguard Worker const detail::VariantMapKeyRaw* raw_key_other = kv_pair.first; 363*795d594fSAndroid Build Coastguard Worker void* value = kv_pair.second; 364*795d594fSAndroid Build Coastguard Worker 365*795d594fSAndroid Build Coastguard Worker detail::VariantMapKeyRaw* cloned_raw_key = raw_key_other->Clone(); 366*795d594fSAndroid Build Coastguard Worker void* cloned_value = raw_key_other->ValueClone(value); 367*795d594fSAndroid Build Coastguard Worker 368*795d594fSAndroid Build Coastguard Worker storage_map_.insert({{ cloned_raw_key, cloned_value }}); 369*795d594fSAndroid Build Coastguard Worker } 370*795d594fSAndroid Build Coastguard Worker 371*795d594fSAndroid Build Coastguard Worker return *this; 372*795d594fSAndroid Build Coastguard Worker } 373*795d594fSAndroid Build Coastguard Worker 374*795d594fSAndroid Build Coastguard Worker // Create a new map by moving an existing map into this one. The other map becomes empty. VariantMapVariantMap375*795d594fSAndroid Build Coastguard Worker VariantMap(VariantMap&& other) noexcept { 376*795d594fSAndroid Build Coastguard Worker operator=(std::forward<VariantMap>(other)); 377*795d594fSAndroid Build Coastguard Worker } 378*795d594fSAndroid Build Coastguard Worker 379*795d594fSAndroid Build Coastguard Worker // Move the existing map's key/value pairs into this one. The other map becomes empty. 380*795d594fSAndroid Build Coastguard Worker VariantMap& operator=(VariantMap&& other) noexcept { 381*795d594fSAndroid Build Coastguard Worker if (this != &other) { 382*795d594fSAndroid Build Coastguard Worker Clear(); 383*795d594fSAndroid Build Coastguard Worker storage_map_.swap(other.storage_map_); 384*795d594fSAndroid Build Coastguard Worker other.storage_map_.clear(); 385*795d594fSAndroid Build Coastguard Worker } 386*795d594fSAndroid Build Coastguard Worker return *this; 387*795d594fSAndroid Build Coastguard Worker } 388*795d594fSAndroid Build Coastguard Worker ~VariantMapVariantMap389*795d594fSAndroid Build Coastguard Worker ~VariantMap() { 390*795d594fSAndroid Build Coastguard Worker DeleteStoredValues(); 391*795d594fSAndroid Build Coastguard Worker } 392*795d594fSAndroid Build Coastguard Worker 393*795d594fSAndroid Build Coastguard Worker private: InitializeParametersVariantMap394*795d594fSAndroid Build Coastguard Worker void InitializeParameters() {} 395*795d594fSAndroid Build Coastguard Worker 396*795d594fSAndroid Build Coastguard Worker template <typename TK, typename TValue, typename ... Rest> InitializeParametersVariantMap397*795d594fSAndroid Build Coastguard Worker void InitializeParameters(const TK& key, const TValue& value, const Rest& ... rest) { 398*795d594fSAndroid Build Coastguard Worker static_assert(std::is_same_v<TK, TKey<TValue>>, "The 0th/2nd/4th/etc parameters must be a key"); 399*795d594fSAndroid Build Coastguard Worker 400*795d594fSAndroid Build Coastguard Worker const TKey<TValue>& key_refined = key; 401*795d594fSAndroid Build Coastguard Worker 402*795d594fSAndroid Build Coastguard Worker Set(key_refined, value); 403*795d594fSAndroid Build Coastguard Worker InitializeParameters(rest...); 404*795d594fSAndroid Build Coastguard Worker } 405*795d594fSAndroid Build Coastguard Worker 406*795d594fSAndroid Build Coastguard Worker // Custom key comparator for std::map, needed since we are storing raw pointers as the keys. 407*795d594fSAndroid Build Coastguard Worker struct KeyComparator { operatorVariantMap::KeyComparator408*795d594fSAndroid Build Coastguard Worker bool operator()(const detail::VariantMapKeyRaw* lhs, 409*795d594fSAndroid Build Coastguard Worker const detail::VariantMapKeyRaw* rhs) const { 410*795d594fSAndroid Build Coastguard Worker if (lhs == nullptr) { 411*795d594fSAndroid Build Coastguard Worker return lhs != rhs; 412*795d594fSAndroid Build Coastguard Worker } 413*795d594fSAndroid Build Coastguard Worker 414*795d594fSAndroid Build Coastguard Worker return lhs->Compare(rhs); 415*795d594fSAndroid Build Coastguard Worker } 416*795d594fSAndroid Build Coastguard Worker }; 417*795d594fSAndroid Build Coastguard Worker 418*795d594fSAndroid Build Coastguard Worker // Map of key pointers to value pointers. Pointers are never null. 419*795d594fSAndroid Build Coastguard Worker using StorageMap = std::map<const detail::VariantMapKeyRaw*, void*, KeyComparator>; 420*795d594fSAndroid Build Coastguard Worker 421*795d594fSAndroid Build Coastguard Worker template <typename TValue> GetKeyValueIteratorVariantMap422*795d594fSAndroid Build Coastguard Worker typename StorageMap::iterator GetKeyValueIterator(const TKey<TValue>& key) { 423*795d594fSAndroid Build Coastguard Worker StaticAssertKeyType<TValue>(); 424*795d594fSAndroid Build Coastguard Worker 425*795d594fSAndroid Build Coastguard Worker const TKey<TValue>* key_ptr = &key; 426*795d594fSAndroid Build Coastguard Worker const detail::VariantMapKeyRaw* raw_ptr = key_ptr; 427*795d594fSAndroid Build Coastguard Worker return storage_map_.find(raw_ptr); 428*795d594fSAndroid Build Coastguard Worker } 429*795d594fSAndroid Build Coastguard Worker 430*795d594fSAndroid Build Coastguard Worker template <typename TValue> GetKeyValueIteratorVariantMap431*795d594fSAndroid Build Coastguard Worker typename StorageMap::const_iterator GetKeyValueIterator(const TKey<TValue>& key) const { 432*795d594fSAndroid Build Coastguard Worker StaticAssertKeyType<TValue>(); 433*795d594fSAndroid Build Coastguard Worker 434*795d594fSAndroid Build Coastguard Worker const TKey<TValue>* key_ptr = &key; 435*795d594fSAndroid Build Coastguard Worker const detail::VariantMapKeyRaw* raw_ptr = key_ptr; 436*795d594fSAndroid Build Coastguard Worker return storage_map_.find(raw_ptr); 437*795d594fSAndroid Build Coastguard Worker } 438*795d594fSAndroid Build Coastguard Worker 439*795d594fSAndroid Build Coastguard Worker template <typename TValue> GetValuePtrVariantMap440*795d594fSAndroid Build Coastguard Worker TValue* GetValuePtr(const TKey<TValue>& key) { 441*795d594fSAndroid Build Coastguard Worker return const_cast<TValue*>(GetValueConstPtr(key)); 442*795d594fSAndroid Build Coastguard Worker } 443*795d594fSAndroid Build Coastguard Worker 444*795d594fSAndroid Build Coastguard Worker template <typename TValue> GetValuePtrVariantMap445*795d594fSAndroid Build Coastguard Worker const TValue* GetValuePtr(const TKey<TValue>& key) const { 446*795d594fSAndroid Build Coastguard Worker return GetValueConstPtr(key); 447*795d594fSAndroid Build Coastguard Worker } 448*795d594fSAndroid Build Coastguard Worker 449*795d594fSAndroid Build Coastguard Worker template <typename TValue> GetValueConstPtrVariantMap450*795d594fSAndroid Build Coastguard Worker const TValue* GetValueConstPtr(const TKey<TValue>& key) const { 451*795d594fSAndroid Build Coastguard Worker auto&& it = GetKeyValueIterator(key); 452*795d594fSAndroid Build Coastguard Worker if (it == storage_map_.end()) { 453*795d594fSAndroid Build Coastguard Worker return nullptr; 454*795d594fSAndroid Build Coastguard Worker } 455*795d594fSAndroid Build Coastguard Worker 456*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<const TValue*>(it->second); 457*795d594fSAndroid Build Coastguard Worker } 458*795d594fSAndroid Build Coastguard Worker 459*795d594fSAndroid Build Coastguard Worker template <typename TValue> StaticAssertKeyTypeVariantMap460*795d594fSAndroid Build Coastguard Worker static void StaticAssertKeyType() { 461*795d594fSAndroid Build Coastguard Worker static_assert(std::is_base_of_v<VariantMapKey<TValue>, TKey<TValue>>, 462*795d594fSAndroid Build Coastguard Worker "The provided key type (TKey) must be a subclass of VariantMapKey"); 463*795d594fSAndroid Build Coastguard Worker } 464*795d594fSAndroid Build Coastguard Worker DeleteStoredValuesVariantMap465*795d594fSAndroid Build Coastguard Worker void DeleteStoredValues() { 466*795d594fSAndroid Build Coastguard Worker for (auto&& kv_pair : storage_map_) { 467*795d594fSAndroid Build Coastguard Worker kv_pair.first->ValueDelete(kv_pair.second); 468*795d594fSAndroid Build Coastguard Worker delete kv_pair.first; 469*795d594fSAndroid Build Coastguard Worker } 470*795d594fSAndroid Build Coastguard Worker } 471*795d594fSAndroid Build Coastguard Worker 472*795d594fSAndroid Build Coastguard Worker StorageMap storage_map_; 473*795d594fSAndroid Build Coastguard Worker }; 474*795d594fSAndroid Build Coastguard Worker 475*795d594fSAndroid Build Coastguard Worker } // namespace art 476*795d594fSAndroid Build Coastguard Worker 477*795d594fSAndroid Build Coastguard Worker #endif // ART_LIBARTBASE_BASE_VARIANT_MAP_H_ 478