liblinux++

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

commit 8532467e15086a625e148204eb8c42ab9ce22a32
parent 85674f738ed181c0a42531e0ac8a4c09b156ab46
Author: Henry Wilson <henry@henryandlizzy.uk>
Date:   Sun, 28 Dec 2025 21:05:45 +0000

Add tee, move vector to own header

Diffstat:
Maarch64.s | 1+
Mlinux.hpp | 1+
Atee.cpp | 19+++++++++++++++++++
Avector.hpp | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mwriter.cpp | 80+------------------------------------------------------------------------------
Mx86_64.s | 1+
6 files changed, 102 insertions(+), 79 deletions(-)

diff --git a/aarch64.s b/aarch64.s @@ -34,6 +34,7 @@ syscall 61 extern read extern_alias _Z4read4filePcm +extern_alias _Z4read4file4spanIcE syscall 63 extern write diff --git a/linux.hpp b/linux.hpp @@ -21,6 +21,7 @@ enum { O_RDONLY = 0, O_WRONLY = 1, O_RDWR = 2, + O_CREAT = 0100, PROT_READ = 0x1, PROT_WRITE = 0x2, diff --git a/tee.cpp b/tee.cpp @@ -0,0 +1,19 @@ +#include "linux.hpp" +#include "vector.hpp" + +int main(int argc, char* argv[]) +{ + vector<file> files; + for (int i = 1; i < argc; ++i) + files.push_back(*openat(AT_FDCWD, argv[i], O_WRONLY | O_CREAT, 0666)); + + char buf[0x1000]; + for (;;) + { + auto n = *read(stdin, buf); + if (not n) + break; + for (auto f : files) + *write(f, buf, n); + } +} diff --git a/vector.hpp b/vector.hpp @@ -0,0 +1,79 @@ +#pragma once +#include "linux.hpp" + +inline void* operator new(size_t, void* p) noexcept +{ + return p; +} + +constexpr 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 +{ + vector() = default; + ~vector() + { + 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) + { + new (new_buf + i) T{buf[i]}; + buf[i].~T(); + } + 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; } + T* data() { return buf; } + size_t size() const { return used; } + + operator span<T>() const { return {buf, used}; } + T* begin() { return buf; } + T* end() { return buf + used; } + +private: + T* buf = nullptr; + size_t capacity = 0, used = 0; +}; diff --git a/writer.cpp b/writer.cpp @@ -1,9 +1,4 @@ -#include "linux.hpp" - -void* operator new(size_t, void* p) noexcept -{ - return p; -} +#include "vector.hpp" struct writer { @@ -24,79 +19,6 @@ private: file out; }; -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 -{ - vector() = default; - ~vector() - { - 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) - { - new (new_buf + i) T{buf[i]}; - buf[i].~T(); - } - 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; } - 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; diff --git a/x86_64.s b/x86_64.s @@ -46,6 +46,7 @@ syscall6: extern read extern_alias _Z4read4filePcm +extern_alias _Z4read4file4spanIcE _syscall 0 syscall3 extern write