vector.h 12 KB

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