blob: 075f3ba757d642772bad23ae78ac30d1d1a789c2 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// An RAII wrapper around ACPI_BUFFER to handle memory ownership and allow easy iteration.
#ifndef SRC_DEVICES_BOARD_DRIVERS_X86_INCLUDE_ACPI_BUFFER_H_
#define SRC_DEVICES_BOARD_DRIVERS_X86_INCLUDE_ACPI_BUFFER_H_
#include <acpica/acpi.h>
namespace acpi {
// AcpiBuffer provides RAII memory management for ACPI_BUFFERs as well as range
// based iterators for a specified ACPI_BUFFER type T.
template <class T>
class AcpiBuffer : public ACPI_BUFFER {
public:
AcpiBuffer() : ACPI_BUFFER{ACPI_ALLOCATE_BUFFER, nullptr} {}
AcpiBuffer(const AcpiBuffer&& acpi_buffer) noexcept : ACPI_BUFFER(std::move(acpi_buffer)) {}
AcpiBuffer(ACPI_SIZE length, void* pointer) : ACPI_BUFFER{length, pointer} {}
AcpiBuffer(const AcpiBuffer&) = delete;
~AcpiBuffer() { AcpiOsFree(Pointer); }
class iterator {
public:
explicit iterator(ACPI_BUFFER buffer)
: length_(buffer.Length), pointer_(static_cast<T*>(buffer.Pointer)) {}
iterator() : pointer_(nullptr) {}
T& operator*() { return *pointer_; }
bool operator==(const AcpiBuffer::iterator& ai) { return pointer_ == ai.pointer_; }
bool operator!=(const AcpiBuffer::iterator& ai) { return !(*this == ai); }
iterator& operator++() {
length_ -= pointer_->Length;
pointer_ = reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(pointer_) + pointer_->Length);
// If we've reached ACPI's end of list node then return the end() sentinel
if (length_ == 0 || pointer_->Length == 0) {
pointer_ = nullptr;
}
return *this;
}
private:
ACPI_SIZE length_ = 0;
T* pointer_;
};
auto begin() const { return AcpiBuffer::iterator(*this); }
auto end() const { return AcpiBuffer::iterator(); }
};
} // namespace acpi
#endif // SRC_DEVICES_BOARD_DRIVERS_X86_INCLUDE_ACPI_BUFFER_H_