xref: /aosp_15_r20/external/cronet/base/win/enum_variant.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2011 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/win/enum_variant.h"
6 
7 #include <wrl/client.h>
8 
9 #include <algorithm>
10 
11 #include "base/check_op.h"
12 
13 namespace base {
14 namespace win {
15 
EnumVariant(ULONG count)16 EnumVariant::EnumVariant(ULONG count) : current_index_(0) {
17   for (ULONG i = 0; i < count; ++i)
18     items_.emplace_back(ScopedVariant::kEmptyVariant);
19 }
20 
21 EnumVariant::~EnumVariant() = default;
22 
ItemAt(ULONG index)23 VARIANT* EnumVariant::ItemAt(ULONG index) {
24   DCHECK_LT(index, items_.size());
25   // This is a hack to return a mutable pointer to the ScopedVariant, even
26   // though the original intent of the AsInput method was to allow only readonly
27   // access to the wrapped variant.
28   return items_[index].AsInput();
29 }
30 
Next(ULONG requested_count,VARIANT * out_elements,ULONG * out_elements_received)31 HRESULT EnumVariant::Next(ULONG requested_count,
32                           VARIANT* out_elements,
33                           ULONG* out_elements_received) {
34   if (!out_elements)
35     return E_INVALIDARG;
36 
37   DCHECK_LE(current_index_, items_.size());
38   ULONG available_count = static_cast<ULONG>(items_.size()) - current_index_;
39   ULONG count = std::min(requested_count, available_count);
40   for (ULONG i = 0; i < count; ++i)
41     out_elements[i] = items_[current_index_ + i].Copy();
42   current_index_ += count;
43 
44   // The caller can choose not to get the number of received elements by setting
45   // |out_elements_received| to nullptr.
46   if (out_elements_received)
47     *out_elements_received = count;
48 
49   return (count == requested_count ? S_OK : S_FALSE);
50 }
51 
Skip(ULONG skip_count)52 HRESULT EnumVariant::Skip(ULONG skip_count) {
53   ULONG count = skip_count;
54   if (current_index_ + count > static_cast<ULONG>(items_.size()))
55     count = static_cast<ULONG>(items_.size()) - current_index_;
56 
57   current_index_ += count;
58   return (count == skip_count ? S_OK : S_FALSE);
59 }
60 
Reset()61 HRESULT EnumVariant::Reset() {
62   current_index_ = 0;
63   return S_OK;
64 }
65 
Clone(IEnumVARIANT ** out_cloned_object)66 HRESULT EnumVariant::Clone(IEnumVARIANT** out_cloned_object) {
67   if (!out_cloned_object)
68     return E_INVALIDARG;
69 
70   size_t count = items_.size();
71   Microsoft::WRL::ComPtr<EnumVariant> other =
72       Microsoft::WRL::Make<EnumVariant>(static_cast<ULONG>(count));
73   for (size_t i = 0; i < count; ++i)
74     other->items_[i] = static_cast<const VARIANT&>(items_[i]);
75 
76   other->Skip(current_index_);
77   return other.CopyTo(IID_PPV_ARGS(out_cloned_object));
78 }
79 
80 }  // namespace win
81 }  // namespace base
82