#pragma once #include "Assertions.h" #include "Retainable.h" #include "RetainPtr.h" #include "StdLibExtras.h" #include "kmalloc.h" namespace AK { template class Buffer : public Retainable> { public: static RetainPtr create_uninitialized(size_t count); static RetainPtr copy(const T*, size_t count); static RetainPtr wrap(T*, size_t count); static RetainPtr adopt(T*, size_t count); ~Buffer() { clear(); } void clear() { if (!m_elements) return; if (m_owned) kfree(m_elements); m_elements = nullptr; } T& operator[](size_t i) { ASSERT(i < m_size); return m_elements[i]; } const T& operator[](size_t i) const { ASSERT(i < m_size); return m_elements[i]; } bool is_empty() const { return !m_size; } size_t size() const { return m_size; } T* pointer() { return m_elements; } const T* pointer() const { return m_elements; } T* offset_pointer(size_t offset) { return m_elements + offset; } const T* offset_pointer(size_t offset) const { return m_elements + offset; } const void* end_pointer() const { return m_elements + m_size; } // NOTE: trim() does not reallocate. void trim(size_t size) { ASSERT(size <= m_size); m_size = size; } private: enum ConstructionMode { Uninitialized, Copy, Wrap, Adopt }; explicit Buffer(size_t); // For ConstructionMode=Uninitialized Buffer(const T*, size_t, ConstructionMode); // For ConstructionMode=Copy Buffer(T*, size_t, ConstructionMode); // For ConstructionMode=Wrap/Adopt Buffer() { } T* m_elements { nullptr }; size_t m_size { 0 }; bool m_owned { false }; }; template inline Buffer::Buffer(size_t size) : m_size(size) { m_elements = static_cast(kmalloc(size * sizeof(T))); m_owned = true; } template inline Buffer::Buffer(const T* elements, size_t size, ConstructionMode mode) : m_size(size) { ASSERT(mode == Copy); m_elements = static_cast(kmalloc(size * sizeof(T))); memcpy(m_elements, elements, size * sizeof(T)); m_owned = true; } template inline Buffer::Buffer(T* elements, size_t size, ConstructionMode mode) : m_elements(elements) , m_size(size) { if (mode == Adopt) { m_owned = true; } else if (mode == Wrap) { m_owned = false; } } template inline RetainPtr> Buffer::create_uninitialized(size_t size) { return ::adopt(*new Buffer(size)); } template inline RetainPtr> Buffer::copy(const T* elements, size_t size) { return ::adopt(*new Buffer(elements, size, Copy)); } template inline RetainPtr> Buffer::wrap(T* elements, size_t size) { return ::adopt(*new Buffer(elements, size, Wrap)); } template inline RetainPtr> Buffer::adopt(T* elements, size_t size) { return ::adopt(*new Buffer(elements, size, Adopt)); } } using AK::Buffer;