xref: /aosp_15_r20/external/cronet/base/win/vector.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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