flatten 20260225

This commit is contained in:
Timothy Prepscius
2026-02-25 12:39:24 -05:00
commit fa54be052a
315 changed files with 49791 additions and 0 deletions

85
tjp/core/pipe/Pipe.h Executable file
View File

@@ -0,0 +1,85 @@
// TJP COPYRIGHT HEADER
#pragma once
#include <list>
#include <tjp/core/types/Types.h>
#include <tjp/core/threads/Lock.hpp>
#include <string.h>
namespace tjp {
namespace core {
template<typename Packet, typename Mutex=core::Mutex>
struct Pipe
{
mutable Mutex mutex;
Pipe();
~Pipe();
typedef std::list<Packet> PacketList;
PacketList pipe;
size_t size_;
bool open;
bool flush_;
size_t sizeReadRequested = 0;
size_t sizeRead = 0;
void clearSizeRead();
size_t write (Packet &&);
size_t write_no_lock (Packet &&);
Packet read ();
Packet read_no_lock ();
bool empty() const;
bool empty_no_lock() const;
void close();
bool isOpen() const;
bool eos() const;
bool finishing() const;
bool flushing() const;
void flush() { flush_ = true; }
bool flushed();
size_t offset;
template<typename PipeOut>
void readInto (PipeOut &rhs)
{
while (!empty())
{
rhs.write(read());
}
if (flushed())
rhs.flush();
}
size_t read (char *buffer, size_t size_t);
size_t read_no_lock (char *buffer, size_t size_t);
size_t write (const char *buffer, size_t size_t);
size_t peek (char *buffer, size_t size_t) const;
size_t peek_no_lock (char *buffer, size_t size_t) const;
size_t skip(size_t size);
size_t skip_no_lock(size_t size);
size_t resize (size_t maximumSize);
size_t size () const;
const Packet *peek() const;
void clear();
} ;
} // namespace
} // namespace
#include "Pipe.inl"

294
tjp/core/pipe/Pipe.inl Executable file
View File

@@ -0,0 +1,294 @@
// TJP COPYRIGHT HEADER
#include "Pipe.h"
#include <tjp/core/assert/debug_assert.h>
namespace tjp {
namespace core {
template<typename Packet, typename Mutex>
Pipe<Packet,Mutex>::Pipe () :
offset(0),
size_(0),
open(true)
{
}
template<typename Packet, typename Mutex>
Pipe<Packet,Mutex>::~Pipe ()
{
}
template<typename Packet, typename Mutex>
void Pipe<Packet,Mutex>::close()
{
auto l = lock_of(mutex);
open = false;
}
template<typename Packet, typename Mutex>
bool Pipe<Packet,Mutex>::isOpen() const
{
auto l = lock_of(mutex);
return open;
}
template<typename Packet, typename Mutex>
size_t Pipe<Packet,Mutex>::write_no_lock (Packet &&packet)
{
debug_assert(mutex.locked_by_caller());
if (packet.size() == 0)
return size_;
size_ += packet.size();
pipe.emplace_back(std::move(packet));
return size_;
}
template<typename Packet, typename Mutex>
size_t Pipe<Packet,Mutex>::write (Packet &&packet)
{
auto l = lock_of(mutex);
return write_no_lock(std::move(packet));
}
template<typename Packet, typename Mutex>
Packet Pipe<Packet,Mutex>::read_no_lock ()
{
debug_assert(!pipe.empty());
debug_assert(offset == 0);
debug_assert(mutex.locked_by_caller());
auto p = std::move(pipe.front());
pipe.pop_front();
debug_assert(size_ >= p.size());
size_ -= p.size();
offset = 0;
return p;
}
template<typename Packet, typename Mutex>
Packet Pipe<Packet,Mutex>::read ()
{
auto l = lock_of(mutex);
return read_no_lock();
}
template<typename Packet, typename Mutex>
bool Pipe<Packet,Mutex>::empty_no_lock() const
{
return pipe.empty();
}
template<typename Packet, typename Mutex>
bool Pipe<Packet,Mutex>::empty() const
{
auto l = lock_of(mutex);
return empty_no_lock();
}
// ---------------------
template<typename Packet, typename Mutex>
size_t Pipe<Packet,Mutex>::peek_no_lock (char *buffer, size_t size) const
{
debug_assert(mutex.locked_by_caller());
size_t ptr = 0;
size_t offset = this->offset;
auto &buffers = pipe;
typename PacketList::const_iterator i=buffers.begin();
while (i!=buffers.end() && (size > 0))
{
auto chunksize = i->size() - offset;
size_t newoffset = 0;
if (chunksize > size)
{
newoffset = offset + size;
chunksize = size;
}
if (buffer)
memcpy (buffer + ptr, i->data() + offset, chunksize);
ptr += chunksize;
size -= chunksize;
offset = newoffset;
i++;
}
return ptr;
}
template<typename Packet, typename Mutex>
size_t Pipe<Packet,Mutex>::peek (char *buffer, size_t size) const
{
auto l = lock_of(mutex);
return peek_no_lock(buffer, size);
}
template<typename Packet, typename Mutex>
size_t Pipe<Packet,Mutex>::read_no_lock (char *buffer, size_t requestedSize)
{
auto size = requestedSize;
size_t ptr = 0;
auto &buffers = pipe;
while (!buffers.empty() && (size > 0))
{
auto chunksize = buffers.front().size() - offset;
size_t newoffset = 0;
if (chunksize > size)
{
newoffset = offset + size;
chunksize = size;
}
if (buffer)
{
debug_assert(ptr + chunksize <= requestedSize);
memcpy (buffer + ptr, buffers.front().data() + offset, chunksize);
}
ptr += chunksize;
size -= chunksize;
offset = newoffset;
if (offset == 0)
{
size_ -= buffers.front().size();
buffers.pop_front();
}
}
sizeReadRequested += requestedSize;
sizeRead += ptr;
return ptr;
} ;
template<typename Packet, typename Mutex>
void Pipe<Packet,Mutex>::clearSizeRead ()
{
sizeReadRequested = sizeRead = 0;
}
template<typename Packet, typename Mutex>
size_t Pipe<Packet,Mutex>::read (char *buffer, size_t requestedSize)
{
auto l = lock_of(mutex);
return read_no_lock(buffer, requestedSize);
}
template<typename Packet, typename Mutex>
size_t Pipe<Packet,Mutex>::write (const char *buffer, size_t size)
{
if (size == 0)
return size;
write(Packet(buffer, buffer+size));
return size;
}
template<typename Packet, typename Mutex>
size_t Pipe<Packet,Mutex>::skip_no_lock(size_t size)
{
return read_no_lock(nullptr, size);
}
template<typename Packet, typename Mutex>
size_t Pipe<Packet,Mutex>::skip(size_t size)
{
auto l = lock_of(mutex);
return skip_no_lock(size);
}
template<typename Packet, typename Mutex>
size_t Pipe<Packet,Mutex>::size () const
{
auto l = lock_of(mutex);
return size_ - offset;
}
template<typename Packet, typename Mutex>
void Pipe<Packet,Mutex>::clear ()
{
auto l = lock_of(mutex);
pipe.clear();
size_ = offset = 0;
flush_ = false;
}
template<typename Packet, typename Mutex>
size_t Pipe<Packet,Mutex>::resize (size_t maximumSize)
{
auto l = lock_of(mutex);
if (size_ > maximumSize)
{
skip_no_lock(size_ - maximumSize);
}
return size_;
}
template<typename Packet, typename Mutex>
const Packet *Pipe<Packet,Mutex>::peek() const
{
auto l = lock_of(mutex);
if (pipe.empty())
return nullptr;
return &pipe.front();
}
template<typename Packet, typename Mutex>
bool Pipe<Packet,Mutex>::eos() const
{
return !open && empty();
}
template<typename Packet, typename Mutex>
bool Pipe<Packet,Mutex>::finishing() const
{
return !open && !empty();
}
template<typename Packet, typename Mutex>
bool Pipe<Packet,Mutex>::flushing() const
{
return flush_ && !empty();
}
template<typename Packet, typename Mutex>
bool Pipe<Packet,Mutex>::flushed()
{
if (!flush_)
return false;
if (!empty())
return false;
flush_ = false;
return true;
}
} // namespace
} // namespace

83
tjp/core/pipe/_tests/Pipe.cpp Executable file
View File

@@ -0,0 +1,83 @@
// TJP COPYRIGHT HEADER
#include <tjp/core/pipe/Pipe.h>
#include <tjp/core/algorithm/copy_of.hpp>
#include <catch2/catch.hpp>
namespace tjp {
namespace core {
namespace test {
SCENARIO("audio pipe")
{
typedef std::vector<char> Packet;
Packet a({'a', 'a', 'a', 'a', 'a'});
Packet b({'b', 'b', 'b' });
GIVEN("a pipe")
{
Pipe<Packet> p;
REQUIRE(p.empty());
WHEN("write 1 packet")
{
p.write(core::copy_of(a));
REQUIRE(p.size() == a.size());
REQUIRE(!p.empty());
}
WHEN("write 2 packets")
{
p.write(core::copy_of(a));
p.write(core::copy_of(b));
REQUIRE(p.size() == a.size() + b.size());
}
WHEN("write 2 packets and read 1")
{
p.write(core::copy_of(a));
p.write(core::copy_of(b));
p.read();
REQUIRE(p.size() == b.size());
}
WHEN("write 2 packets and read 2")
{
p.write(core::copy_of(a));
p.write(core::copy_of(b));
p.read();
p.read();
REQUIRE(p.size() == 0);
REQUIRE(p.empty());
}
WHEN("write 2 packets and read some")
{
p.write(core::copy_of(a));
p.write(core::copy_of(b));
Packet u, v;
u.resize(7);
v = a;
v.insert(v.end(), b.begin(), b.end());
v.resize(u.size());
p.read(u.data(), u.size());
REQUIRE(u == v);
REQUIRE(p.size() == (a.size() + b.size() - u.size()));
}
}
}
} // namespace
} // namespace
} // namespace

173
tjp/core/pipe/obsolete/Pipe.cpp Executable file
View File

@@ -0,0 +1,173 @@
// TJP COPYRIGHT HEADER
#include "Pipe.h"
namespace tjp {
namespace core {
Pipe::~Pipe ()
{
}
PipeStream::PipeStream ()
{
writing = reading = true;
offset = 0;
size = 0;
}
PipeStream::~PipeStream ()
{
while (!buffers.empty())
{
delete[] buffers.front().first;
buffers.pop_front();
}
}
bool PipeStream::isReading () const
{
return reading;
}
bool PipeStream::isWriting () const
{
return writing;
}
void PipeStream::write (const char *buffer, size_t size)
{
char *copy = new char[size];
memcpy (copy, buffer, size);
buffers.push_back (std::pair<char *, size_t>(copy, size));
this->size += size;
}
void PipeStream::unread (const char *buffer, size_t size)
{
auto amountToWriteToExisting = std::min(offset, size);
memcpy (buffers.front().first + (offset - amountToWriteToExisting), buffer + (size - amountToWriteToExisting), amountToWriteToExisting);
auto amountToNewBuffer = size - amountToWriteToExisting;
char *copy = new char[amountToNewBuffer];
memcpy (copy, buffer, amountToNewBuffer);
buffers.push_front (std::pair<char *, size_t>(copy, amountToNewBuffer));
this->size += size;
}
char *PipeStream::write (size_t size)
{
char *copy = new char[size];
buffers.push_back (std::pair<char *, size_t>(copy, size));
this->size += size;
return copy;
}
void PipeStream::closeWrite ()
{
writing = false;
if (!reading)
delete this;
}
void PipeStream::closeRead ()
{
reading = false;
if (!writing)
delete this;
}
Pipe::size_t PipeStream::peek (char *buffer, size_t size) const
{
size_t ptr = 0;
size_t offset = this->offset;
std::list< std::pair<char *, size_t> >::const_iterator i=buffers.begin();
while (i!=buffers.end() && (size > 0))
{
auto chunksize = i->second - offset;
size_t newoffset = 0;
if (chunksize > size)
{
newoffset = offset + size;
chunksize = size;
}
if (buffer)
memcpy (buffer + ptr, i->first + offset, chunksize);
ptr += chunksize;
size -= chunksize;
offset = newoffset;
i++;
}
return ptr;
}
PipeStream::size_t PipeStream::read (char *buffer, size_t size)
{
size_t ptr = 0;
while (!buffers.empty() && (size > 0))
{
auto chunksize = buffers.front().second - offset;
size_t newoffset = 0;
if (chunksize > size)
{
newoffset = offset + size;
chunksize = size;
}
if (buffer)
memcpy (buffer + ptr, buffers.front().first + offset, chunksize);
ptr += chunksize;
size -= chunksize;
offset = newoffset;
if (offset == 0)
{
delete[] buffers.front().first;
buffers.pop_front();
}
}
this->size -= ptr;
return ptr;
} ;
PipeStream::size_t PipeStream::getSize () const
{
return size;
}
bool PipeStream::eos () const
{
return getSize() == 0 && !isWriting();
}
void PipeStream::clear ()
{
while (!buffers.empty())
{
delete[] buffers.front().first;
buffers.pop_front();
}
size = 0;
offset = 0;
}
} // namespace
} // namespace

102
tjp/core/pipe/obsolete/Pipe.h Executable file
View File

@@ -0,0 +1,102 @@
// TJP COPYRIGHT HEADER
#pragma once
#include <list>
namespace tjp {
namespace core {
class Pipe
{
public:
typedef ::size_t size_t;
virtual ~Pipe ();
virtual bool isReading () const = 0;
virtual bool isWriting () const = 0;
virtual void write (const char *buffer, size_t size_t) = 0;
virtual void closeWrite () = 0;
virtual size_t peek (char *buffer, size_t size_t) const = 0;
virtual size_t read (char *buffer, size_t size_t) = 0;
int readChar ()
{
unsigned char c;
auto size_t = read((char *)&c, 1);
if (size_t != 1)
return -1;
return c;
}
virtual void closeRead () = 0;
virtual size_t getSize () const = 0;
virtual bool eos () const = 0;
virtual void clear () = 0;
} ;
class PipeStream : public Pipe
{
protected:
bool reading, writing;
std::list< std::pair<char *, size_t> > buffers;
size_t offset, size;
public:
PipeStream ();
virtual ~PipeStream ();
virtual bool isReading () const;
virtual bool isWriting () const;
virtual void write (const char *buffer, size_t size_t);
virtual char *write(size_t size_t);
virtual void closeWrite ();
virtual size_t peek (char *buffer, size_t size_t) const;
void unread (const char *buffer, size_t size_t);
virtual size_t read (char *buffer, size_t size_t);
virtual void closeRead ();
virtual size_t getSize () const;
virtual bool eos () const;
virtual void clear ();
} ;
class PacketStream
{
protected:
bool reading, writing;
std::list< std::vector<char> > buffers;
public:
PacketStream ();
virtual ~PacketStream ();
virtual void read (const char *buffer, size_t size_t);
virtual char *write(size_t size_t);
virtual void closeWrite ();
virtual size_t peek (char *buffer, size_t size_t) const;
void unread (const char *buffer, size_t size_t);
virtual size_t read (char *buffer, size_t size_t);
virtual void closeRead ();
virtual size_t getSize () const;
virtual bool eos () const;
virtual void clear ();
} ;
} // namespace core
} // namespace tjp