vector.h 13 KB

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