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