| // Copyright 2011 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/win/enum_variant.h" |
| |
| #include <wrl/client.h> |
| |
| #include <algorithm> |
| |
| #include "base/check_op.h" |
| |
| namespace base { |
| namespace win { |
| |
| EnumVariant::EnumVariant(ULONG count) : current_index_(0) { |
| for (ULONG i = 0; i < count; ++i) |
| items_.emplace_back(ScopedVariant::kEmptyVariant); |
| } |
| |
| EnumVariant::~EnumVariant() = default; |
| |
| VARIANT* EnumVariant::ItemAt(ULONG index) { |
| DCHECK_LT(index, items_.size()); |
| // This is a hack to return a mutable pointer to the ScopedVariant, even |
| // though the original intent of the AsInput method was to allow only readonly |
| // access to the wrapped variant. |
| return items_[index].AsInput(); |
| } |
| |
| HRESULT EnumVariant::Next(ULONG requested_count, |
| VARIANT* out_elements, |
| ULONG* out_elements_received) { |
| if (!out_elements) |
| return E_INVALIDARG; |
| |
| DCHECK_LE(current_index_, items_.size()); |
| ULONG available_count = static_cast<ULONG>(items_.size()) - current_index_; |
| ULONG count = std::min(requested_count, available_count); |
| for (ULONG i = 0; i < count; ++i) |
| out_elements[i] = items_[current_index_ + i].Copy(); |
| current_index_ += count; |
| |
| // The caller can choose not to get the number of received elements by setting |
| // |out_elements_received| to nullptr. |
| if (out_elements_received) |
| *out_elements_received = count; |
| |
| return (count == requested_count ? S_OK : S_FALSE); |
| } |
| |
| HRESULT EnumVariant::Skip(ULONG skip_count) { |
| ULONG count = skip_count; |
| if (current_index_ + count > static_cast<ULONG>(items_.size())) |
| count = static_cast<ULONG>(items_.size()) - current_index_; |
| |
| current_index_ += count; |
| return (count == skip_count ? S_OK : S_FALSE); |
| } |
| |
| HRESULT EnumVariant::Reset() { |
| current_index_ = 0; |
| return S_OK; |
| } |
| |
| HRESULT EnumVariant::Clone(IEnumVARIANT** out_cloned_object) { |
| if (!out_cloned_object) |
| return E_INVALIDARG; |
| |
| size_t count = items_.size(); |
| Microsoft::WRL::ComPtr<EnumVariant> other = |
| Microsoft::WRL::Make<EnumVariant>(static_cast<ULONG>(count)); |
| for (size_t i = 0; i < count; ++i) |
| other->items_[i] = static_cast<const VARIANT&>(items_[i]); |
| |
| other->Skip(current_index_); |
| return other.CopyTo(IID_PPV_ARGS(out_cloned_object)); |
| } |
| |
| } // namespace win |
| } // namespace base |