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:
| M | aarch64.s | | | 1 | + |
| M | linux.hpp | | | 1 | + |
| A | tee.cpp | | | 19 | +++++++++++++++++++ |
| A | vector.hpp | | | 79 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | writer.cpp | | | 80 | +------------------------------------------------------------------------------ |
| M | x86_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