#pragma once #include "log/Log.h" #include "std/ensure.h" #include "std/stdlib.h" #include "std/string.h" #include "utils/new.h" #define __noinline __attribute__((noinline)) template struct Dynamic { Dynamic() { set_expand_rate(16); ensure(expand_fixed()); } Dynamic(size_t capacity) { set_expand_rate(16); ensure(expand_fixed()); } Dynamic(const Dynamic& other) { set_expand_rate(other.m_expand_rate); ensure_capacity(other.capacity()); m_size = other.size(); memcpy(m_buf, other.data(), m_capacity * sizeof(T)); } Dynamic(Dynamic&& other) { set_expand_rate(other.m_expand_rate); m_buf = other.release_data(); m_capacity = other.capacity(); m_size = other.size(); } Dynamic& operator=(const Dynamic& other) { if (this == &other) return *this; if (m_buf) { while (m_size) pop(); // destroy all objects kfree(m_buf); } set_expand_rate(other.m_expand_rate); ensure_capacity(other.capacity()); m_size = other.size(); memcpy(m_buf, other.data(), m_capacity * sizeof(T)); return *this; } ~Dynamic() { if (m_buf) { while (m_size) pop(); // destroy all objects kfree(m_buf); } } T& at(size_t index) { ensure(index < m_size); return m_buf[index]; } const T& at(size_t index) const { ensure(index < m_size); return m_buf[index]; } T& operator[](size_t index) { return at(index); } const T& operator[](size_t index) const { return at(index); } bool expand_capacity(size_t capacity) { return expand(capacity); } void ensure_capacity(size_t capacity) { ensure(expand(capacity)); } void set_expand_rate(size_t rate) { if (!rate) return; m_expand_rate = rate; } __noinline bool push(const T& item) { if (m_size == m_capacity) if (!expand_fixed()) return false; m_size++; T* loc = ptr_at(m_size - 1); new (loc) T(item); return true; } void pop() { at(m_size - 1).~T(); m_size--; } size_t capacity() const { return m_capacity; } size_t size() const { return m_size; } const T* data() const { return m_buf; } T* release_data() { T* result = m_buf; m_buf = nullptr; return result; } private: T* m_buf = nullptr; size_t m_capacity = 0; size_t m_size = 0; size_t m_expand_rate = 16; bool expand(size_t new_capacity) { m_buf = (T*)krealloc(m_buf, new_capacity * sizeof(T)); if (!m_buf) return false; m_capacity = new_capacity; return true; } bool expand_fixed() { ensure(m_expand_rate != 0); return expand(m_capacity + m_expand_rate); } T* ptr_at(size_t index) { return (T*)((char*)m_buf + index * sizeof(T)); } };