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)16EnumVariant::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)23VARIANT* 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)31HRESULT 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)52HRESULT 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()61HRESULT EnumVariant::Reset() { 62 current_index_ = 0; 63 return S_OK; 64 } 65 Clone(IEnumVARIANT ** out_cloned_object)66HRESULT 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