vector.hpp (1515B)
1 #pragma once 2 #include "linux.hpp" 3 4 inline void* operator new(size_t, void* p) noexcept 5 { 6 return p; 7 } 8 9 constexpr size_t next_power_of_two(size_t n) 10 { 11 if (not n) 12 return n; 13 --n; 14 for (unsigned i = 1; i <= 32; i <<= 1) 15 n |= n >> i; 16 return ++n; 17 } 18 19 template <typename T> 20 struct vector 21 { 22 vector() = default; 23 ~vector() 24 { 25 for (auto p = buf + used; p != buf; --p) 26 p->~T(); 27 if (buf) 28 *munmap(buf, capacity); 29 } 30 vector(vector const& old) 31 { 32 reserve(old.size()); 33 push_back(old); 34 } 35 vector& operator =(vector const&) = delete; // todo: clear, assign 36 37 void reserve(size_t min) 38 { 39 min *= sizeof(T); 40 if (min <= capacity) 41 return; 42 min = min <= 4096u ? 4096u : next_power_of_two(min); 43 auto new_buf = reinterpret_cast<T*>(*mmap(nullptr, min, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, {}, 0)); 44 for (size_t i = 0; i < used; ++i) 45 { 46 new (new_buf + i) T{buf[i]}; 47 buf[i].~T(); 48 } 49 if (buf) 50 *munmap(buf, capacity); 51 buf = new_buf; 52 capacity = min; 53 } 54 void push_back(T c) 55 { 56 reserve(used + 1); 57 new (buf + used++) T{c}; 58 } 59 void push_back(span<T const> data) 60 { 61 reserve(size() + data.size()); 62 T* p = buf + used; 63 for (auto const& x : data) 64 new (p++) T{x}; 65 used += data.size(); 66 } 67 68 T const* data() const { return buf; } 69 T* data() { return buf; } 70 size_t size() const { return used; } 71 72 operator span<T>() const { return {buf, used}; } 73 T* begin() { return buf; } 74 T* end() { return buf + used; } 75 76 private: 77 T* buf = nullptr; 78 size_t capacity = 0, used = 0; 79 };