1*6777b538SAndroid Build Coastguard Worker // Copyright 2019 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_WIN_MAP_H_ 6*6777b538SAndroid Build Coastguard Worker #define BASE_WIN_MAP_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <windows.foundation.collections.h> 9*6777b538SAndroid Build Coastguard Worker #include <wrl/implements.h> 10*6777b538SAndroid Build Coastguard Worker 11*6777b538SAndroid Build Coastguard Worker #include <map> 12*6777b538SAndroid Build Coastguard Worker #include <utility> 13*6777b538SAndroid Build Coastguard Worker 14*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h" 15*6777b538SAndroid Build Coastguard Worker #include "base/containers/contains.h" 16*6777b538SAndroid Build Coastguard Worker #include "base/notimplemented.h" 17*6777b538SAndroid Build Coastguard Worker #include "base/win/vector.h" 18*6777b538SAndroid Build Coastguard Worker #include "base/win/winrt_foundation_helpers.h" 19*6777b538SAndroid Build Coastguard Worker 20*6777b538SAndroid Build Coastguard Worker namespace base { 21*6777b538SAndroid Build Coastguard Worker namespace win { 22*6777b538SAndroid Build Coastguard Worker 23*6777b538SAndroid Build Coastguard Worker template <typename K, typename V> 24*6777b538SAndroid Build Coastguard Worker class Map; 25*6777b538SAndroid Build Coastguard Worker 26*6777b538SAndroid Build Coastguard Worker namespace internal { 27*6777b538SAndroid Build Coastguard Worker 28*6777b538SAndroid Build Coastguard Worker // Template tricks needed to dispatch to the correct implementation. 29*6777b538SAndroid Build Coastguard Worker // See base/win/winrt_foundation_helpers.h for explanation. 30*6777b538SAndroid Build Coastguard Worker 31*6777b538SAndroid Build Coastguard Worker template <typename K, typename V> 32*6777b538SAndroid Build Coastguard Worker using ComplexK = 33*6777b538SAndroid Build Coastguard Worker typename ABI::Windows::Foundation::Collections::IMap<K, V>::K_complex; 34*6777b538SAndroid Build Coastguard Worker 35*6777b538SAndroid Build Coastguard Worker template <typename K, typename V> 36*6777b538SAndroid Build Coastguard Worker using ComplexV = 37*6777b538SAndroid Build Coastguard Worker typename ABI::Windows::Foundation::Collections::IMap<K, V>::V_complex; 38*6777b538SAndroid Build Coastguard Worker 39*6777b538SAndroid Build Coastguard Worker template <typename K, typename V> 40*6777b538SAndroid Build Coastguard Worker using LogicalK = LogicalType<ComplexK<K, V>>; 41*6777b538SAndroid Build Coastguard Worker 42*6777b538SAndroid Build Coastguard Worker template <typename K, typename V> 43*6777b538SAndroid Build Coastguard Worker using LogicalV = LogicalType<ComplexV<K, V>>; 44*6777b538SAndroid Build Coastguard Worker 45*6777b538SAndroid Build Coastguard Worker template <typename K, typename V> 46*6777b538SAndroid Build Coastguard Worker using AbiK = AbiType<ComplexK<K, V>>; 47*6777b538SAndroid Build Coastguard Worker 48*6777b538SAndroid Build Coastguard Worker template <typename K, typename V> 49*6777b538SAndroid Build Coastguard Worker using AbiV = AbiType<ComplexV<K, V>>; 50*6777b538SAndroid Build Coastguard Worker 51*6777b538SAndroid Build Coastguard Worker template <typename K, typename V> 52*6777b538SAndroid Build Coastguard Worker using StorageK = StorageType<ComplexK<K, V>>; 53*6777b538SAndroid Build Coastguard Worker 54*6777b538SAndroid Build Coastguard Worker template <typename K, typename V> 55*6777b538SAndroid Build Coastguard Worker using StorageV = StorageType<ComplexV<K, V>>; 56*6777b538SAndroid Build Coastguard Worker 57*6777b538SAndroid Build Coastguard Worker template <typename K, typename V> 58*6777b538SAndroid Build Coastguard Worker class KeyValuePair : public Microsoft::WRL::RuntimeClass< 59*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::RuntimeClassFlags< 60*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::WinRtClassicComMix | 61*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::InhibitRoOriginateError>, 62*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections:: 63*6777b538SAndroid Build Coastguard Worker IKeyValuePair<LogicalK<K, V>, LogicalV<K, V>>> { 64*6777b538SAndroid Build Coastguard Worker public: 65*6777b538SAndroid Build Coastguard Worker using AbiK = AbiK<K, V>; 66*6777b538SAndroid Build Coastguard Worker using AbiV = AbiV<K, V>; 67*6777b538SAndroid Build Coastguard Worker using StorageK = StorageK<K, V>; 68*6777b538SAndroid Build Coastguard Worker using StorageV = StorageV<K, V>; 69*6777b538SAndroid Build Coastguard Worker KeyValuePair(StorageK key,StorageV value)70*6777b538SAndroid Build Coastguard Worker KeyValuePair(StorageK key, StorageV value) 71*6777b538SAndroid Build Coastguard Worker : key_(std::move(key)), value_(std::move(value)) {} 72*6777b538SAndroid Build Coastguard Worker 73*6777b538SAndroid Build Coastguard Worker // ABI::Windows::Foundation::Collections::IKeyValuePair: get_Key(AbiK * key)74*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP get_Key(AbiK* key) { return CopyTo(key_, key); } 75*6777b538SAndroid Build Coastguard Worker get_Value(AbiV * value)76*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP get_Value(AbiV* value) { return CopyTo(value_, value); } 77*6777b538SAndroid Build Coastguard Worker 78*6777b538SAndroid Build Coastguard Worker private: 79*6777b538SAndroid Build Coastguard Worker StorageK key_; 80*6777b538SAndroid Build Coastguard Worker StorageV value_; 81*6777b538SAndroid Build Coastguard Worker }; 82*6777b538SAndroid Build Coastguard Worker 83*6777b538SAndroid Build Coastguard Worker template <typename K> 84*6777b538SAndroid Build Coastguard Worker class MapChangedEventArgs 85*6777b538SAndroid Build Coastguard Worker : public Microsoft::WRL::RuntimeClass< 86*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::RuntimeClassFlags< 87*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::WinRtClassicComMix | 88*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::InhibitRoOriginateError>, 89*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IMapChangedEventArgs<K>> { 90*6777b538SAndroid Build Coastguard Worker public: MapChangedEventArgs(ABI::Windows::Foundation::Collections::CollectionChange change,K key)91*6777b538SAndroid Build Coastguard Worker MapChangedEventArgs( 92*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::CollectionChange change, 93*6777b538SAndroid Build Coastguard Worker K key) 94*6777b538SAndroid Build Coastguard Worker : change_(change), key_(std::move(key)) {} 95*6777b538SAndroid Build Coastguard Worker 96*6777b538SAndroid Build Coastguard Worker ~MapChangedEventArgs() override = default; 97*6777b538SAndroid Build Coastguard Worker 98*6777b538SAndroid Build Coastguard Worker // ABI::Windows::Foundation::Collections::IMapChangedEventArgs: get_CollectionChange(ABI::Windows::Foundation::Collections::CollectionChange * value)99*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP get_CollectionChange( 100*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::CollectionChange* value) override { 101*6777b538SAndroid Build Coastguard Worker *value = change_; 102*6777b538SAndroid Build Coastguard Worker return S_OK; 103*6777b538SAndroid Build Coastguard Worker } 104*6777b538SAndroid Build Coastguard Worker get_Key(K * value)105*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP get_Key(K* value) override { 106*6777b538SAndroid Build Coastguard Worker *value = key_; 107*6777b538SAndroid Build Coastguard Worker return S_OK; 108*6777b538SAndroid Build Coastguard Worker } 109*6777b538SAndroid Build Coastguard Worker 110*6777b538SAndroid Build Coastguard Worker private: 111*6777b538SAndroid Build Coastguard Worker const ABI::Windows::Foundation::Collections::CollectionChange change_; 112*6777b538SAndroid Build Coastguard Worker K key_; 113*6777b538SAndroid Build Coastguard Worker }; 114*6777b538SAndroid Build Coastguard Worker 115*6777b538SAndroid Build Coastguard Worker } // namespace internal 116*6777b538SAndroid Build Coastguard Worker 117*6777b538SAndroid Build Coastguard Worker // This file provides an implementation of Windows::Foundation::IMap. It 118*6777b538SAndroid Build Coastguard Worker // functions as a thin wrapper around an std::map, and dispatches 119*6777b538SAndroid Build Coastguard Worker // method calls to either the corresponding std::map API or 120*6777b538SAndroid Build Coastguard Worker // appropriate std algorithms. Furthermore, it notifies its observers whenever 121*6777b538SAndroid Build Coastguard Worker // its observable state changes, and is iterable. Please notice also that if the 122*6777b538SAndroid Build Coastguard Worker // map is modified while iterating over it, iterator methods will return 123*6777b538SAndroid Build Coastguard Worker // E_CHANGED_STATE. A base::win::Map can be constructed for any types <K,V>, and 124*6777b538SAndroid Build Coastguard Worker // is implicitly constructible from a std::map. In the case where K or V is a 125*6777b538SAndroid Build Coastguard Worker // pointer derived from IUnknown, the std::map needs to be of type 126*6777b538SAndroid Build Coastguard Worker // Microsoft::WRL::ComPtr<K> or Microsoft::WRL::ComPtr<V>. This enforces proper 127*6777b538SAndroid Build Coastguard Worker // reference counting and improves safety. 128*6777b538SAndroid Build Coastguard Worker template <typename K, typename V> 129*6777b538SAndroid Build Coastguard Worker class Map 130*6777b538SAndroid Build Coastguard Worker : public Microsoft::WRL::RuntimeClass< 131*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::RuntimeClassFlags< 132*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>, 133*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IMap<internal::LogicalK<K, V>, 134*6777b538SAndroid Build Coastguard Worker internal::LogicalV<K, V>>, 135*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IObservableMap< 136*6777b538SAndroid Build Coastguard Worker internal::LogicalK<K, V>, 137*6777b538SAndroid Build Coastguard Worker internal::LogicalV<K, V>>, 138*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IIterable< 139*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IKeyValuePair< 140*6777b538SAndroid Build Coastguard Worker internal::LogicalK<K, V>, 141*6777b538SAndroid Build Coastguard Worker internal::LogicalV<K, V>>*>> { 142*6777b538SAndroid Build Coastguard Worker public: 143*6777b538SAndroid Build Coastguard Worker using LogicalK = internal::LogicalK<K, V>; 144*6777b538SAndroid Build Coastguard Worker using LogicalV = internal::LogicalV<K, V>; 145*6777b538SAndroid Build Coastguard Worker using AbiK = internal::AbiK<K, V>; 146*6777b538SAndroid Build Coastguard Worker using AbiV = internal::AbiV<K, V>; 147*6777b538SAndroid Build Coastguard Worker using StorageK = internal::StorageK<K, V>; 148*6777b538SAndroid Build Coastguard Worker using StorageV = internal::StorageV<K, V>; 149*6777b538SAndroid Build Coastguard Worker 150*6777b538SAndroid Build Coastguard Worker private: 151*6777b538SAndroid Build Coastguard Worker class MapView; 152*6777b538SAndroid Build Coastguard Worker 153*6777b538SAndroid Build Coastguard Worker // Iterates over base::win::Map. 154*6777b538SAndroid Build Coastguard Worker // Its methods return E_CHANGED_STATE is the map is modified. 155*6777b538SAndroid Build Coastguard Worker // TODO(https://crbug.com/987533): Refactor MapIterator to leverage 156*6777b538SAndroid Build Coastguard Worker // std::map::iterator. 157*6777b538SAndroid Build Coastguard Worker class MapIterator 158*6777b538SAndroid Build Coastguard Worker : public Microsoft::WRL::RuntimeClass< 159*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::RuntimeClassFlags< 160*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::WinRtClassicComMix | 161*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::InhibitRoOriginateError>, 162*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IIterator< 163*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IKeyValuePair< 164*6777b538SAndroid Build Coastguard Worker internal::LogicalK<K, V>, 165*6777b538SAndroid Build Coastguard Worker internal::LogicalV<K, V>>*>> { 166*6777b538SAndroid Build Coastguard Worker public: MapIterator(Microsoft::WRL::ComPtr<MapView> view)167*6777b538SAndroid Build Coastguard Worker explicit MapIterator(Microsoft::WRL::ComPtr<MapView> view) 168*6777b538SAndroid Build Coastguard Worker : view_(std::move(view)) { 169*6777b538SAndroid Build Coastguard Worker DCHECK(view_->ValidState()); 170*6777b538SAndroid Build Coastguard Worker ConvertMapToVectorIterator(); 171*6777b538SAndroid Build Coastguard Worker } 172*6777b538SAndroid Build Coastguard Worker 173*6777b538SAndroid Build Coastguard Worker // ABI::Windows::Foundation::Collections::IIterator: get_Current(ABI::Windows::Foundation::Collections::IKeyValuePair<LogicalK,LogicalV> ** current)174*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP get_Current( 175*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IKeyValuePair<LogicalK, 176*6777b538SAndroid Build Coastguard Worker LogicalV>** 177*6777b538SAndroid Build Coastguard Worker current) override { 178*6777b538SAndroid Build Coastguard Worker return view_->ValidState() ? iterator_->get_Current(current) 179*6777b538SAndroid Build Coastguard Worker : E_CHANGED_STATE; 180*6777b538SAndroid Build Coastguard Worker } 181*6777b538SAndroid Build Coastguard Worker get_HasCurrent(boolean * has_current)182*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP get_HasCurrent(boolean* has_current) override { 183*6777b538SAndroid Build Coastguard Worker return view_->ValidState() ? iterator_->get_HasCurrent(has_current) 184*6777b538SAndroid Build Coastguard Worker : E_CHANGED_STATE; 185*6777b538SAndroid Build Coastguard Worker } 186*6777b538SAndroid Build Coastguard Worker MoveNext(boolean * has_current)187*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP MoveNext(boolean* has_current) override { 188*6777b538SAndroid Build Coastguard Worker return view_->ValidState() ? iterator_->MoveNext(has_current) 189*6777b538SAndroid Build Coastguard Worker : E_CHANGED_STATE; 190*6777b538SAndroid Build Coastguard Worker } 191*6777b538SAndroid Build Coastguard Worker GetMany(unsigned capacity,ABI::Windows::Foundation::Collections::IKeyValuePair<LogicalK,LogicalV> ** value,unsigned * actual)192*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP GetMany( 193*6777b538SAndroid Build Coastguard Worker unsigned capacity, 194*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IKeyValuePair<LogicalK, 195*6777b538SAndroid Build Coastguard Worker LogicalV>** value, 196*6777b538SAndroid Build Coastguard Worker unsigned* actual) override { 197*6777b538SAndroid Build Coastguard Worker return view_->ValidState() ? iterator_->GetMany(capacity, value, actual) 198*6777b538SAndroid Build Coastguard Worker : E_CHANGED_STATE; 199*6777b538SAndroid Build Coastguard Worker } 200*6777b538SAndroid Build Coastguard Worker 201*6777b538SAndroid Build Coastguard Worker private: 202*6777b538SAndroid Build Coastguard Worker // Helper for iteration: ConvertMapToVectorIterator()203*6777b538SAndroid Build Coastguard Worker void ConvertMapToVectorIterator() { 204*6777b538SAndroid Build Coastguard Worker // Create a vector that will hold Map's key-value pairs. 205*6777b538SAndroid Build Coastguard Worker auto vector = Microsoft::WRL::Make< 206*6777b538SAndroid Build Coastguard Worker Vector<ABI::Windows::Foundation::Collections::IKeyValuePair< 207*6777b538SAndroid Build Coastguard Worker LogicalK, LogicalV>*>>(); 208*6777b538SAndroid Build Coastguard Worker 209*6777b538SAndroid Build Coastguard Worker // Fill the vector with container data. 210*6777b538SAndroid Build Coastguard Worker for (const auto& pair : view_->get_map()) { 211*6777b538SAndroid Build Coastguard Worker auto key_value_pair = 212*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::Make<internal::KeyValuePair<AbiK, AbiV>>( 213*6777b538SAndroid Build Coastguard Worker pair.first, pair.second); 214*6777b538SAndroid Build Coastguard Worker vector->Append(key_value_pair.Get()); 215*6777b538SAndroid Build Coastguard Worker } 216*6777b538SAndroid Build Coastguard Worker 217*6777b538SAndroid Build Coastguard Worker // Return an iterator to that vector. 218*6777b538SAndroid Build Coastguard Worker // Iterator is immutable (wraps an IVectorView) and Vector's lifecycle is 219*6777b538SAndroid Build Coastguard Worker // ensured cause the view holds a reference to the vector, and iterator 220*6777b538SAndroid Build Coastguard Worker // holds a reference to the view. 221*6777b538SAndroid Build Coastguard Worker HRESULT hr = vector->First(&iterator_); 222*6777b538SAndroid Build Coastguard Worker DCHECK(SUCCEEDED(hr)); 223*6777b538SAndroid Build Coastguard Worker } 224*6777b538SAndroid Build Coastguard Worker 225*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::ComPtr<MapView> view_; 226*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Collections::IIterator< 227*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IKeyValuePair<LogicalK, 228*6777b538SAndroid Build Coastguard Worker LogicalV>*>> 229*6777b538SAndroid Build Coastguard Worker iterator_; 230*6777b538SAndroid Build Coastguard Worker }; 231*6777b538SAndroid Build Coastguard Worker 232*6777b538SAndroid Build Coastguard Worker class MapView 233*6777b538SAndroid Build Coastguard Worker : public Microsoft::WRL::RuntimeClass< 234*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::RuntimeClassFlags< 235*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::WinRtClassicComMix | 236*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::InhibitRoOriginateError>, 237*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections:: 238*6777b538SAndroid Build Coastguard Worker IMapView<internal::LogicalK<K, V>, internal::LogicalV<K, V>>, 239*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IIterable< 240*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IKeyValuePair< 241*6777b538SAndroid Build Coastguard Worker internal::LogicalK<K, V>, 242*6777b538SAndroid Build Coastguard Worker internal::LogicalV<K, V>>*>, 243*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::MapChangedEventHandler< 244*6777b538SAndroid Build Coastguard Worker internal::LogicalK<K, V>, 245*6777b538SAndroid Build Coastguard Worker internal::LogicalV<K, V>>> { 246*6777b538SAndroid Build Coastguard Worker public: MapView(Microsoft::WRL::ComPtr<Map<LogicalK,LogicalV>> map)247*6777b538SAndroid Build Coastguard Worker explicit MapView(Microsoft::WRL::ComPtr<Map<LogicalK, LogicalV>> map) 248*6777b538SAndroid Build Coastguard Worker : map_(std::move(map)) { 249*6777b538SAndroid Build Coastguard Worker map_->add_MapChanged(this, &map_changed_token_); 250*6777b538SAndroid Build Coastguard Worker } 251*6777b538SAndroid Build Coastguard Worker ~MapView()252*6777b538SAndroid Build Coastguard Worker ~MapView() override { 253*6777b538SAndroid Build Coastguard Worker if (map_) 254*6777b538SAndroid Build Coastguard Worker map_->remove_MapChanged(map_changed_token_); 255*6777b538SAndroid Build Coastguard Worker } 256*6777b538SAndroid Build Coastguard Worker 257*6777b538SAndroid Build Coastguard Worker // ABI::Windows::Foundation::Collections::IMapView: Lookup(AbiK key,AbiV * value)258*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP Lookup(AbiK key, AbiV* value) override { 259*6777b538SAndroid Build Coastguard Worker return map_ ? map_->Lookup(key, value) : E_CHANGED_STATE; 260*6777b538SAndroid Build Coastguard Worker } 261*6777b538SAndroid Build Coastguard Worker get_Size(unsigned int * size)262*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP get_Size(unsigned int* size) override { 263*6777b538SAndroid Build Coastguard Worker return map_ ? map_->get_Size(size) : E_CHANGED_STATE; 264*6777b538SAndroid Build Coastguard Worker } 265*6777b538SAndroid Build Coastguard Worker HasKey(AbiK key,boolean * found)266*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP HasKey(AbiK key, boolean* found) override { 267*6777b538SAndroid Build Coastguard Worker return map_ ? map_->HasKey(key, found) : E_CHANGED_STATE; 268*6777b538SAndroid Build Coastguard Worker } 269*6777b538SAndroid Build Coastguard Worker Split(ABI::Windows::Foundation::Collections::IMapView<LogicalK,LogicalV> ** first_partition,ABI::Windows::Foundation::Collections::IMapView<LogicalK,LogicalV> ** second_partition)270*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP Split( 271*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IMapView<LogicalK, LogicalV>** 272*6777b538SAndroid Build Coastguard Worker first_partition, 273*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IMapView<LogicalK, LogicalV>** 274*6777b538SAndroid Build Coastguard Worker second_partition) override { 275*6777b538SAndroid Build Coastguard Worker NOTIMPLEMENTED(); 276*6777b538SAndroid Build Coastguard Worker return E_NOTIMPL; 277*6777b538SAndroid Build Coastguard Worker } 278*6777b538SAndroid Build Coastguard Worker 279*6777b538SAndroid Build Coastguard Worker // ABI::Windows::Foundation::Collections::IIterable: First(ABI::Windows::Foundation::Collections::IIterator<ABI::Windows::Foundation::Collections::IKeyValuePair<LogicalK,LogicalV> * > ** first)280*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP First( 281*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IIterator< 282*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IKeyValuePair<LogicalK, 283*6777b538SAndroid Build Coastguard Worker LogicalV>*>** 284*6777b538SAndroid Build Coastguard Worker first) override { 285*6777b538SAndroid Build Coastguard Worker return map_ ? map_->First(first) : E_CHANGED_STATE; 286*6777b538SAndroid Build Coastguard Worker } 287*6777b538SAndroid Build Coastguard Worker 288*6777b538SAndroid Build Coastguard Worker // ABI::Windows::Foundation::Collections::MapChangedEventHandler: Invoke(ABI::Windows::Foundation::Collections::IObservableMap<LogicalK,LogicalV> * sender,ABI::Windows::Foundation::Collections::IMapChangedEventArgs<LogicalK> * e)289*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP Invoke( 290*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IObservableMap<LogicalK, 291*6777b538SAndroid Build Coastguard Worker LogicalV>* sender, 292*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IMapChangedEventArgs<LogicalK>* 293*6777b538SAndroid Build Coastguard Worker e) override { 294*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(map_.Get(), sender); 295*6777b538SAndroid Build Coastguard Worker map_.Reset(); 296*6777b538SAndroid Build Coastguard Worker sender->remove_MapChanged(map_changed_token_); 297*6777b538SAndroid Build Coastguard Worker return S_OK; 298*6777b538SAndroid Build Coastguard Worker } 299*6777b538SAndroid Build Coastguard Worker 300*6777b538SAndroid Build Coastguard Worker // Accessor used in MapIterator for iterating over Map's container. 301*6777b538SAndroid Build Coastguard Worker // Will remain valid during the entire iteration. get_map()302*6777b538SAndroid Build Coastguard Worker const std::map<StorageK, StorageV, internal::Less>& get_map() { 303*6777b538SAndroid Build Coastguard Worker DCHECK(map_); 304*6777b538SAndroid Build Coastguard Worker return map_->map_; 305*6777b538SAndroid Build Coastguard Worker } 306*6777b538SAndroid Build Coastguard Worker ValidState()307*6777b538SAndroid Build Coastguard Worker bool ValidState() const { return map_; } 308*6777b538SAndroid Build Coastguard Worker 309*6777b538SAndroid Build Coastguard Worker private: 310*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::ComPtr<Map<LogicalK, LogicalV>> map_; 311*6777b538SAndroid Build Coastguard Worker EventRegistrationToken map_changed_token_; 312*6777b538SAndroid Build Coastguard Worker }; 313*6777b538SAndroid Build Coastguard Worker 314*6777b538SAndroid Build Coastguard Worker public: 315*6777b538SAndroid Build Coastguard Worker Map() = default; Map(const std::map<StorageK,StorageV,internal::Less> & map)316*6777b538SAndroid Build Coastguard Worker explicit Map(const std::map<StorageK, StorageV, internal::Less>& map) 317*6777b538SAndroid Build Coastguard Worker : map_(map) {} Map(std::map<StorageK,StorageV,internal::Less> && map)318*6777b538SAndroid Build Coastguard Worker explicit Map(std::map<StorageK, StorageV, internal::Less>&& map) 319*6777b538SAndroid Build Coastguard Worker : map_(std::move(map)) {} 320*6777b538SAndroid Build Coastguard Worker 321*6777b538SAndroid Build Coastguard Worker // ABI::Windows::Foundation::Collections::IMap: Lookup(AbiK key,AbiV * value)322*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP Lookup(AbiK key, AbiV* value) override { 323*6777b538SAndroid Build Coastguard Worker auto it = map_.find(key); 324*6777b538SAndroid Build Coastguard Worker if (it == map_.cend()) 325*6777b538SAndroid Build Coastguard Worker return E_BOUNDS; 326*6777b538SAndroid Build Coastguard Worker 327*6777b538SAndroid Build Coastguard Worker return internal::CopyTo(it->second, value); 328*6777b538SAndroid Build Coastguard Worker } 329*6777b538SAndroid Build Coastguard Worker get_Size(unsigned int * size)330*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP get_Size(unsigned int* size) override { 331*6777b538SAndroid Build Coastguard Worker *size = map_.size(); 332*6777b538SAndroid Build Coastguard Worker return S_OK; 333*6777b538SAndroid Build Coastguard Worker } 334*6777b538SAndroid Build Coastguard Worker HasKey(AbiK key,boolean * found)335*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP HasKey(AbiK key, boolean* found) override { 336*6777b538SAndroid Build Coastguard Worker *found = Contains(map_, key); 337*6777b538SAndroid Build Coastguard Worker return S_OK; 338*6777b538SAndroid Build Coastguard Worker } 339*6777b538SAndroid Build Coastguard Worker GetView(ABI::Windows::Foundation::Collections::IMapView<LogicalK,LogicalV> ** view)340*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP GetView( 341*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IMapView<LogicalK, LogicalV>** 342*6777b538SAndroid Build Coastguard Worker view) override { 343*6777b538SAndroid Build Coastguard Worker return Microsoft::WRL::Make<MapView>(this).CopyTo(view); 344*6777b538SAndroid Build Coastguard Worker } 345*6777b538SAndroid Build Coastguard Worker Insert(AbiK key,AbiV value,boolean * replaced)346*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP Insert(AbiK key, AbiV value, boolean* replaced) override { 347*6777b538SAndroid Build Coastguard Worker auto [it, inserted] = map_.insert_or_assign(key, std::move(value)); 348*6777b538SAndroid Build Coastguard Worker *replaced = !inserted; 349*6777b538SAndroid Build Coastguard Worker NotifyMapChanged(*replaced ? ABI::Windows::Foundation::Collections:: 350*6777b538SAndroid Build Coastguard Worker CollectionChange_ItemChanged 351*6777b538SAndroid Build Coastguard Worker : ABI::Windows::Foundation::Collections:: 352*6777b538SAndroid Build Coastguard Worker CollectionChange_ItemInserted, 353*6777b538SAndroid Build Coastguard Worker key); 354*6777b538SAndroid Build Coastguard Worker return S_OK; 355*6777b538SAndroid Build Coastguard Worker } 356*6777b538SAndroid Build Coastguard Worker Remove(AbiK key)357*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP Remove(AbiK key) override { 358*6777b538SAndroid Build Coastguard Worker if (!map_.erase(key)) 359*6777b538SAndroid Build Coastguard Worker return E_BOUNDS; 360*6777b538SAndroid Build Coastguard Worker 361*6777b538SAndroid Build Coastguard Worker NotifyMapChanged( 362*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::CollectionChange_ItemRemoved, 363*6777b538SAndroid Build Coastguard Worker key); 364*6777b538SAndroid Build Coastguard Worker return S_OK; 365*6777b538SAndroid Build Coastguard Worker } 366*6777b538SAndroid Build Coastguard Worker Clear()367*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP Clear() override { 368*6777b538SAndroid Build Coastguard Worker map_.clear(); 369*6777b538SAndroid Build Coastguard Worker NotifyMapChanged( 370*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::CollectionChange_Reset, 0); 371*6777b538SAndroid Build Coastguard Worker return S_OK; 372*6777b538SAndroid Build Coastguard Worker } 373*6777b538SAndroid Build Coastguard Worker 374*6777b538SAndroid Build Coastguard Worker // ABI::Windows::Foundation::Collections::IObservableMap: add_MapChanged(ABI::Windows::Foundation::Collections::MapChangedEventHandler<LogicalK,LogicalV> * handler,EventRegistrationToken * token)375*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP add_MapChanged( 376*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::MapChangedEventHandler<LogicalK, 377*6777b538SAndroid Build Coastguard Worker LogicalV>* 378*6777b538SAndroid Build Coastguard Worker handler, 379*6777b538SAndroid Build Coastguard Worker EventRegistrationToken* token) override { 380*6777b538SAndroid Build Coastguard Worker token->value = handler_id_++; 381*6777b538SAndroid Build Coastguard Worker handlers_.emplace_hint(handlers_.end(), token->value, handler); 382*6777b538SAndroid Build Coastguard Worker return S_OK; 383*6777b538SAndroid Build Coastguard Worker } 384*6777b538SAndroid Build Coastguard Worker remove_MapChanged(EventRegistrationToken token)385*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP remove_MapChanged(EventRegistrationToken token) override { 386*6777b538SAndroid Build Coastguard Worker return handlers_.erase(token.value) ? S_OK : E_BOUNDS; 387*6777b538SAndroid Build Coastguard Worker } 388*6777b538SAndroid Build Coastguard Worker 389*6777b538SAndroid Build Coastguard Worker // ABI::Windows::Foundation::Collections::IIterable: First(ABI::Windows::Foundation::Collections::IIterator<ABI::Windows::Foundation::Collections::IKeyValuePair<LogicalK,LogicalV> * > ** first)390*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP First( 391*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IIterator< 392*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IKeyValuePair<LogicalK, 393*6777b538SAndroid Build Coastguard Worker LogicalV>*>** 394*6777b538SAndroid Build Coastguard Worker first) override { 395*6777b538SAndroid Build Coastguard Worker return Microsoft::WRL::Make<MapIterator>( 396*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::Make<MapView>(this)) 397*6777b538SAndroid Build Coastguard Worker .CopyTo(first); 398*6777b538SAndroid Build Coastguard Worker } 399*6777b538SAndroid Build Coastguard Worker 400*6777b538SAndroid Build Coastguard Worker private: ~Map()401*6777b538SAndroid Build Coastguard Worker ~Map() override { 402*6777b538SAndroid Build Coastguard Worker // Handlers should not outlive the Map. Furthermore, they must ensure 403*6777b538SAndroid Build Coastguard Worker // they are unregistered before the handler is destroyed. This implies 404*6777b538SAndroid Build Coastguard Worker // there should be no handlers left when the Map is destructed. 405*6777b538SAndroid Build Coastguard Worker DCHECK(handlers_.empty()); 406*6777b538SAndroid Build Coastguard Worker } 407*6777b538SAndroid Build Coastguard Worker NotifyMapChanged(ABI::Windows::Foundation::Collections::CollectionChange change,AbiK key)408*6777b538SAndroid Build Coastguard Worker void NotifyMapChanged( 409*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::CollectionChange change, 410*6777b538SAndroid Build Coastguard Worker AbiK key) { 411*6777b538SAndroid Build Coastguard Worker auto args = 412*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::Make<internal::MapChangedEventArgs<AbiK>>(change, key); 413*6777b538SAndroid Build Coastguard Worker 414*6777b538SAndroid Build Coastguard Worker // Invoking the handlers could result in mutations to the map, thus we make 415*6777b538SAndroid Build Coastguard Worker // a copy beforehand. 416*6777b538SAndroid Build Coastguard Worker auto handlers = handlers_; 417*6777b538SAndroid Build Coastguard Worker for (auto& handler : handlers) 418*6777b538SAndroid Build Coastguard Worker handler.second->Invoke(this, args.Get()); 419*6777b538SAndroid Build Coastguard Worker } 420*6777b538SAndroid Build Coastguard Worker 421*6777b538SAndroid Build Coastguard Worker std::map<StorageK, StorageV, internal::Less> map_; 422*6777b538SAndroid Build Coastguard Worker base::flat_map<int64_t, 423*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections:: 424*6777b538SAndroid Build Coastguard Worker MapChangedEventHandler<LogicalK, LogicalV>*> 425*6777b538SAndroid Build Coastguard Worker handlers_; 426*6777b538SAndroid Build Coastguard Worker int64_t handler_id_ = 0; 427*6777b538SAndroid Build Coastguard Worker }; 428*6777b538SAndroid Build Coastguard Worker 429*6777b538SAndroid Build Coastguard Worker } // namespace win 430*6777b538SAndroid Build Coastguard Worker } // namespace base 431*6777b538SAndroid Build Coastguard Worker 432*6777b538SAndroid Build Coastguard Worker #endif // BASE_WIN_MAP_H_ 433