1*6777b538SAndroid Build Coastguard Worker // Copyright 2018 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_VECTOR_H_ 6*6777b538SAndroid Build Coastguard Worker #define BASE_WIN_VECTOR_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <ivectorchangedeventargs.h> 9*6777b538SAndroid Build Coastguard Worker #include <windows.foundation.collections.h> 10*6777b538SAndroid Build Coastguard Worker #include <wrl/implements.h> 11*6777b538SAndroid Build Coastguard Worker 12*6777b538SAndroid Build Coastguard Worker #include <algorithm> 13*6777b538SAndroid Build Coastguard Worker #include <iterator> 14*6777b538SAndroid Build Coastguard Worker #include <utility> 15*6777b538SAndroid Build Coastguard Worker #include <vector> 16*6777b538SAndroid Build Coastguard Worker 17*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h" 18*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h" 19*6777b538SAndroid Build Coastguard Worker #include "base/containers/flat_map.h" 20*6777b538SAndroid Build Coastguard Worker #include "base/ranges/algorithm.h" 21*6777b538SAndroid Build Coastguard Worker #include "base/win/winrt_foundation_helpers.h" 22*6777b538SAndroid Build Coastguard Worker 23*6777b538SAndroid Build Coastguard Worker namespace base { 24*6777b538SAndroid Build Coastguard Worker namespace win { 25*6777b538SAndroid Build Coastguard Worker 26*6777b538SAndroid Build Coastguard Worker template <typename T> 27*6777b538SAndroid Build Coastguard Worker class Vector; 28*6777b538SAndroid Build Coastguard Worker 29*6777b538SAndroid Build Coastguard Worker namespace internal { 30*6777b538SAndroid Build Coastguard Worker 31*6777b538SAndroid Build Coastguard Worker // Template tricks needed to dispatch to the correct implementation. 32*6777b538SAndroid Build Coastguard Worker // See base/win/winrt_foundation_helpers.h for explanation. 33*6777b538SAndroid Build Coastguard Worker 34*6777b538SAndroid Build Coastguard Worker template <typename T> 35*6777b538SAndroid Build Coastguard Worker using VectorComplex = 36*6777b538SAndroid Build Coastguard Worker typename ABI::Windows::Foundation::Collections::IVector<T>::T_complex; 37*6777b538SAndroid Build Coastguard Worker 38*6777b538SAndroid Build Coastguard Worker template <typename T> 39*6777b538SAndroid Build Coastguard Worker using VectorLogical = LogicalType<VectorComplex<T>>; 40*6777b538SAndroid Build Coastguard Worker 41*6777b538SAndroid Build Coastguard Worker template <typename T> 42*6777b538SAndroid Build Coastguard Worker using VectorAbi = AbiType<VectorComplex<T>>; 43*6777b538SAndroid Build Coastguard Worker 44*6777b538SAndroid Build Coastguard Worker template <typename T> 45*6777b538SAndroid Build Coastguard Worker using VectorStorage = StorageType<VectorComplex<T>>; 46*6777b538SAndroid Build Coastguard Worker 47*6777b538SAndroid Build Coastguard Worker template <typename T> 48*6777b538SAndroid Build Coastguard Worker class VectorIterator 49*6777b538SAndroid Build Coastguard Worker : public Microsoft::WRL::RuntimeClass< 50*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::RuntimeClassFlags< 51*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::WinRtClassicComMix | 52*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::InhibitRoOriginateError>, 53*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IIterator<VectorLogical<T>>> { 54*6777b538SAndroid Build Coastguard Worker public: 55*6777b538SAndroid Build Coastguard Worker using LogicalT = VectorLogical<T>; 56*6777b538SAndroid Build Coastguard Worker using AbiT = VectorAbi<T>; 57*6777b538SAndroid Build Coastguard Worker VectorIterator(Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Collections::IVectorView<LogicalT>> view)58*6777b538SAndroid Build Coastguard Worker explicit VectorIterator( 59*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::ComPtr< 60*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IVectorView<LogicalT>> view) 61*6777b538SAndroid Build Coastguard Worker : view_(std::move(view)) {} 62*6777b538SAndroid Build Coastguard Worker 63*6777b538SAndroid Build Coastguard Worker // ABI::Windows::Foundation::Collections::IIterator: get_Current(AbiT * current)64*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP get_Current(AbiT* current) override { 65*6777b538SAndroid Build Coastguard Worker return view_->GetAt(current_index_, current); 66*6777b538SAndroid Build Coastguard Worker } 67*6777b538SAndroid Build Coastguard Worker get_HasCurrent(boolean * has_current)68*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP get_HasCurrent(boolean* has_current) override { 69*6777b538SAndroid Build Coastguard Worker *has_current = FALSE; 70*6777b538SAndroid Build Coastguard Worker unsigned size; 71*6777b538SAndroid Build Coastguard Worker HRESULT hr = view_->get_Size(&size); 72*6777b538SAndroid Build Coastguard Worker if (SUCCEEDED(hr)) { 73*6777b538SAndroid Build Coastguard Worker if (current_index_ < size) { 74*6777b538SAndroid Build Coastguard Worker *has_current = TRUE; 75*6777b538SAndroid Build Coastguard Worker } 76*6777b538SAndroid Build Coastguard Worker } 77*6777b538SAndroid Build Coastguard Worker return hr; 78*6777b538SAndroid Build Coastguard Worker } 79*6777b538SAndroid Build Coastguard Worker MoveNext(boolean * has_current)80*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP MoveNext(boolean* has_current) override { 81*6777b538SAndroid Build Coastguard Worker *has_current = FALSE; 82*6777b538SAndroid Build Coastguard Worker unsigned size; 83*6777b538SAndroid Build Coastguard Worker HRESULT hr = view_->get_Size(&size); 84*6777b538SAndroid Build Coastguard Worker if (FAILED(hr)) 85*6777b538SAndroid Build Coastguard Worker return hr; 86*6777b538SAndroid Build Coastguard Worker 87*6777b538SAndroid Build Coastguard Worker // Check if we're already past the last item. 88*6777b538SAndroid Build Coastguard Worker if (current_index_ >= size) 89*6777b538SAndroid Build Coastguard Worker return E_BOUNDS; 90*6777b538SAndroid Build Coastguard Worker 91*6777b538SAndroid Build Coastguard Worker // Move to the next item. 92*6777b538SAndroid Build Coastguard Worker current_index_++; 93*6777b538SAndroid Build Coastguard Worker 94*6777b538SAndroid Build Coastguard Worker // Set |has_current| to TRUE if we're still on a valid item. 95*6777b538SAndroid Build Coastguard Worker if (current_index_ < size) 96*6777b538SAndroid Build Coastguard Worker *has_current = TRUE; 97*6777b538SAndroid Build Coastguard Worker 98*6777b538SAndroid Build Coastguard Worker return hr; 99*6777b538SAndroid Build Coastguard Worker } 100*6777b538SAndroid Build Coastguard Worker GetMany(unsigned capacity,AbiT * value,unsigned * actual)101*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP GetMany(unsigned capacity, 102*6777b538SAndroid Build Coastguard Worker AbiT* value, 103*6777b538SAndroid Build Coastguard Worker unsigned* actual) override { 104*6777b538SAndroid Build Coastguard Worker return view_->GetMany(current_index_, capacity, value, actual); 105*6777b538SAndroid Build Coastguard Worker } 106*6777b538SAndroid Build Coastguard Worker 107*6777b538SAndroid Build Coastguard Worker private: 108*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::ComPtr< 109*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IVectorView<LogicalT>> 110*6777b538SAndroid Build Coastguard Worker view_; 111*6777b538SAndroid Build Coastguard Worker unsigned current_index_ = 0; 112*6777b538SAndroid Build Coastguard Worker }; 113*6777b538SAndroid Build Coastguard Worker 114*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT VectorChangedEventArgs 115*6777b538SAndroid Build Coastguard Worker : public Microsoft::WRL::RuntimeClass< 116*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::RuntimeClassFlags< 117*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::WinRtClassicComMix | 118*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::InhibitRoOriginateError>, 119*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IVectorChangedEventArgs> { 120*6777b538SAndroid Build Coastguard Worker public: VectorChangedEventArgs(ABI::Windows::Foundation::Collections::CollectionChange change,unsigned int index)121*6777b538SAndroid Build Coastguard Worker VectorChangedEventArgs( 122*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::CollectionChange change, 123*6777b538SAndroid Build Coastguard Worker unsigned int index) 124*6777b538SAndroid Build Coastguard Worker : change_(change), index_(index) {} 125*6777b538SAndroid Build Coastguard Worker 126*6777b538SAndroid Build Coastguard Worker ~VectorChangedEventArgs() override = default; 127*6777b538SAndroid Build Coastguard Worker 128*6777b538SAndroid Build Coastguard Worker // ABI::Windows::Foundation::Collections::IVectorChangedEventArgs: 129*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP get_CollectionChange( 130*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::CollectionChange* value) override; 131*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP get_Index(unsigned int* value) override; 132*6777b538SAndroid Build Coastguard Worker 133*6777b538SAndroid Build Coastguard Worker private: 134*6777b538SAndroid Build Coastguard Worker const ABI::Windows::Foundation::Collections::CollectionChange change_; 135*6777b538SAndroid Build Coastguard Worker const unsigned int index_; 136*6777b538SAndroid Build Coastguard Worker }; 137*6777b538SAndroid Build Coastguard Worker 138*6777b538SAndroid Build Coastguard Worker template <typename T> 139*6777b538SAndroid Build Coastguard Worker class VectorView 140*6777b538SAndroid Build Coastguard Worker : public Microsoft::WRL::RuntimeClass< 141*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::RuntimeClassFlags< 142*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::WinRtClassicComMix | 143*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::InhibitRoOriginateError>, 144*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IVectorView<VectorLogical<T>>, 145*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::VectorChangedEventHandler< 146*6777b538SAndroid Build Coastguard Worker VectorLogical<T>>> { 147*6777b538SAndroid Build Coastguard Worker public: 148*6777b538SAndroid Build Coastguard Worker using LogicalT = VectorLogical<T>; 149*6777b538SAndroid Build Coastguard Worker using AbiT = VectorAbi<T>; 150*6777b538SAndroid Build Coastguard Worker VectorView(Microsoft::WRL::ComPtr<Vector<LogicalT>> vector)151*6777b538SAndroid Build Coastguard Worker explicit VectorView(Microsoft::WRL::ComPtr<Vector<LogicalT>> vector) 152*6777b538SAndroid Build Coastguard Worker : vector_(std::move(vector)) { 153*6777b538SAndroid Build Coastguard Worker vector_->add_VectorChanged(this, &vector_changed_token_); 154*6777b538SAndroid Build Coastguard Worker } 155*6777b538SAndroid Build Coastguard Worker ~VectorView()156*6777b538SAndroid Build Coastguard Worker ~VectorView() override { 157*6777b538SAndroid Build Coastguard Worker if (vector_) 158*6777b538SAndroid Build Coastguard Worker vector_->remove_VectorChanged(vector_changed_token_); 159*6777b538SAndroid Build Coastguard Worker } 160*6777b538SAndroid Build Coastguard Worker 161*6777b538SAndroid Build Coastguard Worker // ABI::Windows::Foundation::Collections::IVectorView: GetAt(unsigned index,AbiT * item)162*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP GetAt(unsigned index, AbiT* item) override { 163*6777b538SAndroid Build Coastguard Worker return vector_ ? vector_->GetAt(index, item) : E_CHANGED_STATE; 164*6777b538SAndroid Build Coastguard Worker } 165*6777b538SAndroid Build Coastguard Worker get_Size(unsigned * size)166*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP get_Size(unsigned* size) override { 167*6777b538SAndroid Build Coastguard Worker return vector_ ? vector_->get_Size(size) : E_CHANGED_STATE; 168*6777b538SAndroid Build Coastguard Worker } 169*6777b538SAndroid Build Coastguard Worker IndexOf(AbiT value,unsigned * index,boolean * found)170*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP IndexOf(AbiT value, unsigned* index, boolean* found) override { 171*6777b538SAndroid Build Coastguard Worker return vector_ ? vector_->IndexOf(std::move(value), index, found) 172*6777b538SAndroid Build Coastguard Worker : E_CHANGED_STATE; 173*6777b538SAndroid Build Coastguard Worker } 174*6777b538SAndroid Build Coastguard Worker GetMany(unsigned start_index,unsigned capacity,AbiT * value,unsigned * actual)175*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP GetMany(unsigned start_index, 176*6777b538SAndroid Build Coastguard Worker unsigned capacity, 177*6777b538SAndroid Build Coastguard Worker AbiT* value, 178*6777b538SAndroid Build Coastguard Worker unsigned* actual) override { 179*6777b538SAndroid Build Coastguard Worker return vector_ ? vector_->GetMany(start_index, capacity, value, actual) 180*6777b538SAndroid Build Coastguard Worker : E_CHANGED_STATE; 181*6777b538SAndroid Build Coastguard Worker } 182*6777b538SAndroid Build Coastguard Worker 183*6777b538SAndroid Build Coastguard Worker // ABI::Windows::Foundation::Collections::VectorChangedEventHandler: Invoke(ABI::Windows::Foundation::Collections::IObservableVector<LogicalT> * sender,ABI::Windows::Foundation::Collections::IVectorChangedEventArgs * e)184*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP Invoke( 185*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IObservableVector<LogicalT>* 186*6777b538SAndroid Build Coastguard Worker sender, 187*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IVectorChangedEventArgs* e) 188*6777b538SAndroid Build Coastguard Worker override { 189*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(vector_.Get(), sender); 190*6777b538SAndroid Build Coastguard Worker vector_.Reset(); 191*6777b538SAndroid Build Coastguard Worker sender->remove_VectorChanged(vector_changed_token_); 192*6777b538SAndroid Build Coastguard Worker return S_OK; 193*6777b538SAndroid Build Coastguard Worker } 194*6777b538SAndroid Build Coastguard Worker 195*6777b538SAndroid Build Coastguard Worker private: 196*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::ComPtr<Vector<LogicalT>> vector_; 197*6777b538SAndroid Build Coastguard Worker EventRegistrationToken vector_changed_token_; 198*6777b538SAndroid Build Coastguard Worker }; 199*6777b538SAndroid Build Coastguard Worker 200*6777b538SAndroid Build Coastguard Worker } // namespace internal 201*6777b538SAndroid Build Coastguard Worker 202*6777b538SAndroid Build Coastguard Worker // This file provides an implementation of Windows::Foundation::IVector. It 203*6777b538SAndroid Build Coastguard Worker // functions as a thin wrapper around an std::vector, and dispatches method 204*6777b538SAndroid Build Coastguard Worker // calls to either the corresponding std::vector API or appropriate 205*6777b538SAndroid Build Coastguard Worker // std::algorithms. Furthermore, it notifies its observers whenever its 206*6777b538SAndroid Build Coastguard Worker // observable state changes. A base::win::Vector can be constructed for any type 207*6777b538SAndroid Build Coastguard Worker // T, and is implicitly constructible from a std::vector. In the case where T is 208*6777b538SAndroid Build Coastguard Worker // a pointer derived from IUnknown, the std::vector needs to be of type 209*6777b538SAndroid Build Coastguard Worker // Microsoft::WRL::ComPtr<T>. This enforces proper reference counting and 210*6777b538SAndroid Build Coastguard Worker // improves safety. 211*6777b538SAndroid Build Coastguard Worker template <typename T> 212*6777b538SAndroid Build Coastguard Worker class Vector 213*6777b538SAndroid Build Coastguard Worker : public Microsoft::WRL::RuntimeClass< 214*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::RuntimeClassFlags< 215*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>, 216*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IVector< 217*6777b538SAndroid Build Coastguard Worker internal::VectorLogical<T>>, 218*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IObservableVector< 219*6777b538SAndroid Build Coastguard Worker internal::VectorLogical<T>>, 220*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IIterable< 221*6777b538SAndroid Build Coastguard Worker internal::VectorLogical<T>>> { 222*6777b538SAndroid Build Coastguard Worker public: 223*6777b538SAndroid Build Coastguard Worker using LogicalT = internal::VectorLogical<T>; 224*6777b538SAndroid Build Coastguard Worker using AbiT = internal::VectorAbi<T>; 225*6777b538SAndroid Build Coastguard Worker using StorageT = internal::VectorStorage<T>; 226*6777b538SAndroid Build Coastguard Worker 227*6777b538SAndroid Build Coastguard Worker Vector() = default; Vector(const std::vector<StorageT> & vector)228*6777b538SAndroid Build Coastguard Worker explicit Vector(const std::vector<StorageT>& vector) : vector_(vector) {} Vector(std::vector<StorageT> && vector)229*6777b538SAndroid Build Coastguard Worker explicit Vector(std::vector<StorageT>&& vector) 230*6777b538SAndroid Build Coastguard Worker : vector_(std::move(vector)) {} 231*6777b538SAndroid Build Coastguard Worker 232*6777b538SAndroid Build Coastguard Worker // ABI::Windows::Foundation::Collections::IVector: GetAt(unsigned index,AbiT * item)233*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP GetAt(unsigned index, AbiT* item) override { 234*6777b538SAndroid Build Coastguard Worker if (index >= vector_.size()) 235*6777b538SAndroid Build Coastguard Worker return E_BOUNDS; 236*6777b538SAndroid Build Coastguard Worker return internal::CopyTo(vector_[index], item); 237*6777b538SAndroid Build Coastguard Worker } 238*6777b538SAndroid Build Coastguard Worker get_Size(unsigned * size)239*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP get_Size(unsigned* size) override { 240*6777b538SAndroid Build Coastguard Worker *size = vector_.size(); 241*6777b538SAndroid Build Coastguard Worker return S_OK; 242*6777b538SAndroid Build Coastguard Worker } 243*6777b538SAndroid Build Coastguard Worker GetView(ABI::Windows::Foundation::Collections::IVectorView<LogicalT> ** view)244*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP GetView( 245*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IVectorView<LogicalT>** view) 246*6777b538SAndroid Build Coastguard Worker override { 247*6777b538SAndroid Build Coastguard Worker return Microsoft::WRL::Make<internal::VectorView<LogicalT>>(this).CopyTo( 248*6777b538SAndroid Build Coastguard Worker view); 249*6777b538SAndroid Build Coastguard Worker } 250*6777b538SAndroid Build Coastguard Worker IndexOf(AbiT value,unsigned * index,boolean * found)251*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP IndexOf(AbiT value, unsigned* index, boolean* found) override { 252*6777b538SAndroid Build Coastguard Worker auto iter = base::ranges::find_if(vector_, [&value](const StorageT& elem) { 253*6777b538SAndroid Build Coastguard Worker return internal::IsEqual(elem, value); 254*6777b538SAndroid Build Coastguard Worker }); 255*6777b538SAndroid Build Coastguard Worker *index = iter != vector_.end() ? std::distance(vector_.begin(), iter) : 0; 256*6777b538SAndroid Build Coastguard Worker *found = iter != vector_.end(); 257*6777b538SAndroid Build Coastguard Worker return S_OK; 258*6777b538SAndroid Build Coastguard Worker } 259*6777b538SAndroid Build Coastguard Worker SetAt(unsigned index,AbiT item)260*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP SetAt(unsigned index, AbiT item) override { 261*6777b538SAndroid Build Coastguard Worker if (index >= vector_.size()) 262*6777b538SAndroid Build Coastguard Worker return E_BOUNDS; 263*6777b538SAndroid Build Coastguard Worker 264*6777b538SAndroid Build Coastguard Worker vector_[index] = std::move(item); 265*6777b538SAndroid Build Coastguard Worker NotifyVectorChanged( 266*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::CollectionChange_ItemChanged, 267*6777b538SAndroid Build Coastguard Worker index); 268*6777b538SAndroid Build Coastguard Worker return S_OK; 269*6777b538SAndroid Build Coastguard Worker } 270*6777b538SAndroid Build Coastguard Worker InsertAt(unsigned index,AbiT item)271*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP InsertAt(unsigned index, AbiT item) override { 272*6777b538SAndroid Build Coastguard Worker if (index > vector_.size()) 273*6777b538SAndroid Build Coastguard Worker return E_BOUNDS; 274*6777b538SAndroid Build Coastguard Worker 275*6777b538SAndroid Build Coastguard Worker vector_.insert(std::next(vector_.begin(), index), std::move(item)); 276*6777b538SAndroid Build Coastguard Worker NotifyVectorChanged( 277*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::CollectionChange_ItemInserted, 278*6777b538SAndroid Build Coastguard Worker index); 279*6777b538SAndroid Build Coastguard Worker return S_OK; 280*6777b538SAndroid Build Coastguard Worker } 281*6777b538SAndroid Build Coastguard Worker RemoveAt(unsigned index)282*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP RemoveAt(unsigned index) override { 283*6777b538SAndroid Build Coastguard Worker if (index >= vector_.size()) 284*6777b538SAndroid Build Coastguard Worker return E_BOUNDS; 285*6777b538SAndroid Build Coastguard Worker 286*6777b538SAndroid Build Coastguard Worker vector_.erase(std::next(vector_.begin(), index)); 287*6777b538SAndroid Build Coastguard Worker NotifyVectorChanged( 288*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::CollectionChange_ItemRemoved, 289*6777b538SAndroid Build Coastguard Worker index); 290*6777b538SAndroid Build Coastguard Worker return S_OK; 291*6777b538SAndroid Build Coastguard Worker } 292*6777b538SAndroid Build Coastguard Worker Append(AbiT item)293*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP Append(AbiT item) override { 294*6777b538SAndroid Build Coastguard Worker vector_.push_back(std::move(item)); 295*6777b538SAndroid Build Coastguard Worker NotifyVectorChanged( 296*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::CollectionChange_ItemInserted, 297*6777b538SAndroid Build Coastguard Worker vector_.size() - 1); 298*6777b538SAndroid Build Coastguard Worker return S_OK; 299*6777b538SAndroid Build Coastguard Worker } 300*6777b538SAndroid Build Coastguard Worker RemoveAtEnd()301*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP RemoveAtEnd() override { 302*6777b538SAndroid Build Coastguard Worker if (vector_.empty()) 303*6777b538SAndroid Build Coastguard Worker return E_BOUNDS; 304*6777b538SAndroid Build Coastguard Worker 305*6777b538SAndroid Build Coastguard Worker vector_.pop_back(); 306*6777b538SAndroid Build Coastguard Worker NotifyVectorChanged( 307*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::CollectionChange_ItemRemoved, 308*6777b538SAndroid Build Coastguard Worker vector_.size()); 309*6777b538SAndroid Build Coastguard Worker return S_OK; 310*6777b538SAndroid Build Coastguard Worker } 311*6777b538SAndroid Build Coastguard Worker Clear()312*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP Clear() override { 313*6777b538SAndroid Build Coastguard Worker vector_.clear(); 314*6777b538SAndroid Build Coastguard Worker NotifyVectorChanged( 315*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::CollectionChange_Reset, 0); 316*6777b538SAndroid Build Coastguard Worker return S_OK; 317*6777b538SAndroid Build Coastguard Worker } 318*6777b538SAndroid Build Coastguard Worker GetMany(unsigned start_index,unsigned capacity,AbiT * value,unsigned * actual)319*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP GetMany(unsigned start_index, 320*6777b538SAndroid Build Coastguard Worker unsigned capacity, 321*6777b538SAndroid Build Coastguard Worker AbiT* value, 322*6777b538SAndroid Build Coastguard Worker unsigned* actual) override { 323*6777b538SAndroid Build Coastguard Worker if (start_index > vector_.size()) 324*6777b538SAndroid Build Coastguard Worker return E_BOUNDS; 325*6777b538SAndroid Build Coastguard Worker 326*6777b538SAndroid Build Coastguard Worker *actual = std::min<unsigned>(vector_.size() - start_index, capacity); 327*6777b538SAndroid Build Coastguard Worker return internal::CopyN(std::next(vector_.begin(), start_index), *actual, 328*6777b538SAndroid Build Coastguard Worker value); 329*6777b538SAndroid Build Coastguard Worker } 330*6777b538SAndroid Build Coastguard Worker ReplaceAll(unsigned count,AbiT * value)331*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP ReplaceAll(unsigned count, AbiT* value) override { 332*6777b538SAndroid Build Coastguard Worker vector_.assign(value, std::next(value, count)); 333*6777b538SAndroid Build Coastguard Worker NotifyVectorChanged( 334*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::CollectionChange_Reset, 0); 335*6777b538SAndroid Build Coastguard Worker return S_OK; 336*6777b538SAndroid Build Coastguard Worker } 337*6777b538SAndroid Build Coastguard Worker 338*6777b538SAndroid Build Coastguard Worker // ABI::Windows::Foundation::Collections::IObservableVector: add_VectorChanged(ABI::Windows::Foundation::Collections::VectorChangedEventHandler<LogicalT> * handler,EventRegistrationToken * token)339*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP add_VectorChanged( 340*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::VectorChangedEventHandler< 341*6777b538SAndroid Build Coastguard Worker LogicalT>* handler, 342*6777b538SAndroid Build Coastguard Worker EventRegistrationToken* token) override { 343*6777b538SAndroid Build Coastguard Worker token->value = handler_id_++; 344*6777b538SAndroid Build Coastguard Worker handlers_.emplace_hint(handlers_.end(), token->value, handler); 345*6777b538SAndroid Build Coastguard Worker return S_OK; 346*6777b538SAndroid Build Coastguard Worker } 347*6777b538SAndroid Build Coastguard Worker remove_VectorChanged(EventRegistrationToken token)348*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP remove_VectorChanged(EventRegistrationToken token) override { 349*6777b538SAndroid Build Coastguard Worker handlers_.erase(token.value); 350*6777b538SAndroid Build Coastguard Worker return S_OK; 351*6777b538SAndroid Build Coastguard Worker } 352*6777b538SAndroid Build Coastguard Worker NotifyVectorChanged(ABI::Windows::Foundation::Collections::CollectionChange change,unsigned int index)353*6777b538SAndroid Build Coastguard Worker void NotifyVectorChanged( 354*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::CollectionChange change, 355*6777b538SAndroid Build Coastguard Worker unsigned int index) { 356*6777b538SAndroid Build Coastguard Worker auto args = 357*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::Make<internal::VectorChangedEventArgs>(change, index); 358*6777b538SAndroid Build Coastguard Worker 359*6777b538SAndroid Build Coastguard Worker // Invoking the handlers could result in mutations to the map, thus we make 360*6777b538SAndroid Build Coastguard Worker // a copy beforehand. 361*6777b538SAndroid Build Coastguard Worker auto handlers = handlers_; 362*6777b538SAndroid Build Coastguard Worker for (auto& handler : handlers) 363*6777b538SAndroid Build Coastguard Worker handler.second->Invoke(this, args.Get()); 364*6777b538SAndroid Build Coastguard Worker } 365*6777b538SAndroid Build Coastguard Worker 366*6777b538SAndroid Build Coastguard Worker // ABI::Windows::Foundation::Collections::IIterable: First(ABI::Windows::Foundation::Collections::IIterator<LogicalT> ** first)367*6777b538SAndroid Build Coastguard Worker IFACEMETHODIMP First( 368*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IIterator<LogicalT>** first) 369*6777b538SAndroid Build Coastguard Worker override { 370*6777b538SAndroid Build Coastguard Worker Microsoft::WRL::ComPtr< 371*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections::IVectorView<LogicalT>> 372*6777b538SAndroid Build Coastguard Worker view; 373*6777b538SAndroid Build Coastguard Worker HRESULT hr = GetView(&view); 374*6777b538SAndroid Build Coastguard Worker if (SUCCEEDED(hr)) { 375*6777b538SAndroid Build Coastguard Worker return Microsoft::WRL::Make<internal::VectorIterator<LogicalT>>(view) 376*6777b538SAndroid Build Coastguard Worker .CopyTo(first); 377*6777b538SAndroid Build Coastguard Worker } else { 378*6777b538SAndroid Build Coastguard Worker return hr; 379*6777b538SAndroid Build Coastguard Worker } 380*6777b538SAndroid Build Coastguard Worker } 381*6777b538SAndroid Build Coastguard Worker vector_for_testing()382*6777b538SAndroid Build Coastguard Worker const std::vector<AbiT>& vector_for_testing() { return vector_; } 383*6777b538SAndroid Build Coastguard Worker 384*6777b538SAndroid Build Coastguard Worker private: ~Vector()385*6777b538SAndroid Build Coastguard Worker ~Vector() override { 386*6777b538SAndroid Build Coastguard Worker // Handlers should not outlive the Vector. Furthermore, they must ensure 387*6777b538SAndroid Build Coastguard Worker // they are unregistered before the handler is destroyed. This implies 388*6777b538SAndroid Build Coastguard Worker // there should be no handlers left when the Vector is destructed. 389*6777b538SAndroid Build Coastguard Worker DCHECK(handlers_.empty()); 390*6777b538SAndroid Build Coastguard Worker } 391*6777b538SAndroid Build Coastguard Worker 392*6777b538SAndroid Build Coastguard Worker std::vector<StorageT> vector_; 393*6777b538SAndroid Build Coastguard Worker base::flat_map<int64_t, 394*6777b538SAndroid Build Coastguard Worker ABI::Windows::Foundation::Collections:: 395*6777b538SAndroid Build Coastguard Worker VectorChangedEventHandler<LogicalT>*> 396*6777b538SAndroid Build Coastguard Worker handlers_; 397*6777b538SAndroid Build Coastguard Worker int64_t handler_id_ = 0; 398*6777b538SAndroid Build Coastguard Worker }; 399*6777b538SAndroid Build Coastguard Worker 400*6777b538SAndroid Build Coastguard Worker } // namespace win 401*6777b538SAndroid Build Coastguard Worker } // namespace base 402*6777b538SAndroid Build Coastguard Worker 403*6777b538SAndroid Build Coastguard Worker #endif // BASE_WIN_VECTOR_H_ 404