liblinux++

A hosted C++ runtime without any libc.
git clone git://henryandlizzy.uk/liblinux++
Log | Files | Refs

commit cf6f735c777f6f3313c16d2cdf28009dd0ffbdaf
parent e73acf0554f059c01739e12aa2a18301943a3d6b
Author: Henry Wilson <henry@henryandlizzy.uk>
Date:   Sun, 28 Dec 2025 01:29:44 +0000

Improve vector

Diffstat:
Mwriter.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 {