commit e73acf0554f059c01739e12aa2a18301943a3d6b
parent a962c85ccf6076e754363a6ea207ef20e3172b6a
Author: Henry Wilson <henry@henryandlizzy.uk>
Date: Fri, 26 Dec 2025 20:03:31 +0000
writer: demo equivalent of std::ostringstream
Diffstat:
| M | Tupfile | | | 2 | +- |
| M | linux.hpp | | | 21 | +++++++++++++++++++-- |
| A | writer.cpp | | | 81 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 101 insertions(+), 3 deletions(-)
diff --git a/Tupfile b/Tupfile
@@ -1,4 +1,4 @@
-CXXFLAGS = -g -Os -fno-exceptions -fno-asynchronous-unwind-tables -fno-builtin -fno-pic -fno-pie -fno-stack-protector -fdiagnostics-color=always
+CXXFLAGS = -g -Os -fno-exceptions -fno-rtti -fno-asynchronous-unwind-tables -fno-builtin -fno-pic -fno-pie -fno-stack-protector -fdiagnostics-color=always
LDFLAGS = --gc-sections
: foreach *.cpp |> clang++ --target=aarch64 $(CXXFLAGS) -c -o %o %f |> obj/%B.aarch64.o {objs-aarch64}
diff --git a/linux.hpp b/linux.hpp
@@ -46,7 +46,7 @@ struct span
{
span() = default;
inline span(T* p, size_t n)
- : data{p}
+ : ptr{p}
, len{n}
{}
@@ -54,8 +54,25 @@ struct span
inline span(T (&arr)[N])
: span{arr, N}
{}
+
+ T* data() const noexcept
+ {
+ return ptr;
+ }
+ size_t size() const noexcept
+ {
+ return len;
+ }
+ T* begin() const noexcept
+ {
+ return data();
+ }
+ T* end() const noexcept
+ {
+ return begin() + size();
+ }
private:
- T* data = nullptr;
+ T* ptr = nullptr;
size_t len = 0;
};
diff --git a/writer.cpp b/writer.cpp
@@ -0,0 +1,81 @@
+#include "linux.hpp"
+
+struct writer
+{
+ virtual void write(span<char const>) = 0;
+protected:
+ ~writer() = default;
+};
+
+struct fd_writer : writer
+{
+ fd_writer(file f) : out{f} {}
+
+ void write(span<char const> data) override
+ {
+ if (*::write(out, data) != data.size())
+ __builtin_trap();
+ }
+private:
+ file out;
+};
+
+template <typename T>
+struct vector
+{
+ void push_back(T c)
+ {
+ if (used * sizeof(T) >= capacity)
+ {
+ 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;
+ }
+
+ buf[used++] = c;
+ }
+
+ T const* data() const { return buf; }
+ T* data() { return buf; }
+ size_t size() const { return used; }
+private:
+ T* buf = nullptr;
+ size_t capacity = 0, used = 0;
+};
+
+struct buf_writer : writer
+{
+ buf_writer() noexcept = default;
+
+ void write(span<char const> data) override
+ {
+ for (char c : data)
+ buffer.push_back(c);
+ }
+ span<char const> get() const noexcept
+ {
+ return {buffer.data(), buffer.size()};
+ }
+private:
+ vector<char> buffer;
+};
+
+int main()
+{
+ buf_writer x;
+ writer* w = &x;
+ for (int i = 0; i < 240; ++i)
+ {
+ w->write("Hello, ");
+ w->write("World! Wow what a lovely day!\n");
+ }
+ fd_writer cout{stdout};
+ w = &cout;
+ w->write(x.get());
+}