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