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