commit cf6f735c777f6f3313c16d2cdf28009dd0ffbdaf
parent e73acf0554f059c01739e12aa2a18301943a3d6b
Author: Henry Wilson <henry@henryandlizzy.uk>
Date: Sun, 28 Dec 2025 01:29:44 +0000
Improve vector
Diffstat:
| M | writer.cpp | | | 78 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------- |
1 file changed, 63 insertions(+), 15 deletions(-)
diff --git a/writer.cpp b/writer.cpp
@@ -1,5 +1,10 @@
#include "linux.hpp"
+void* operator new(size_t, void* p) noexcept
+{
+ return p;
+}
+
struct writer
{
virtual void write(span<char const>) = 0;
@@ -21,24 +26,68 @@ private:
};
template <typename T>
+T div_round_up(T n, T d)
+{
+ return (n + (d-1)) / d;
+}
+
+size_t next_power_of_two(size_t n)
+{
+ if (not n)
+ return n;
+ --n;
+ for (unsigned i = 1; i <= 32; i <<= 1)
+ n |= n >> i;
+ return ++n;
+}
+
+template <typename T>
struct vector
{
- void push_back(T c)
+ vector() = default;
+ ~vector()
{
- if (used * sizeof(T) >= capacity)
+ for (auto p = buf + used; p != buf; --p)
+ p->~T();
+ if (buf)
+ *munmap(buf, capacity);
+ }
+ vector(vector const& old)
+ {
+ reserve(old.size());
+ push_back(old);
+ }
+ vector& operator =(vector const&) = delete; // todo: clear, assign
+
+ void reserve(size_t min)
+ {
+ min *= sizeof(T);
+ if (min <= capacity)
+ return;
+ min = min <= 4096u ? 4096u : next_power_of_two(min);
+ auto new_buf = reinterpret_cast<T*>(*mmap(nullptr, min, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, {}, 0));
+ for (size_t i = 0; i < used; ++i)
{
- size_t const old_cap = capacity;
- size_t const new_cap = capacity ? capacity * 2 : 0x1000;
- T* new_buf = (T*)*mmap(nullptr, new_cap, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, {}, 0);
- for (size_t i = 0; i < used; ++i)
- new_buf[i] = buf[i];
- capacity = new_cap;
- if (buf)
- *munmap(buf, old_cap);
- buf = new_buf;
+ new (new_buf + i) T{buf[i]};
+ buf[i].~T();
}
-
- buf[used++] = c;
+ if (buf)
+ *munmap(buf, capacity);
+ buf = new_buf;
+ capacity = min;
+ }
+ void push_back(T c)
+ {
+ reserve(used + 1);
+ new (buf + used++) T{c};
+ }
+ void push_back(span<T const> data)
+ {
+ reserve(size() + data.size());
+ T* p = buf + used;
+ for (auto const& x : data)
+ new (p++) T{x};
+ used = p - buf;
}
T const* data() const { return buf; }
@@ -55,8 +104,7 @@ struct buf_writer : writer
void write(span<char const> data) override
{
- for (char c : data)
- buffer.push_back(c);
+ buffer.push_back(data);
}
span<char const> get() const noexcept
{