first commit

This commit is contained in:
2024-12-06 04:58:55 -06:00
commit 856373b396
61 changed files with 5920 additions and 0 deletions

View File

@ -0,0 +1,19 @@
#pragma once
#include <cstring>
#include <cstdint>
#include <cstddef>
#include <string>
#include <filesystem>
#include <map>
#include <vector>
namespace Tesses::Framework
{
void TF_Init();
void TF_ConnectToSelf(uint16_t port);
void TF_RunEventLoop();
void TF_RunEventLoopItteration();
bool TF_IsRunning();
void TF_Quit();
}

View File

@ -0,0 +1,24 @@
#pragma once
#include "../Streams/Stream.hpp"
namespace Tesses::Framework::Crypto
{
class ClientTLSStream : public Tesses::Framework::Streams::Stream {
void* privateData;
static int strm_send(void* ctx,const unsigned char* buf,size_t len);
static int strm_recv(void* ctx,unsigned char* buf,size_t len);
public:
static std::string GetCertChain();
ClientTLSStream(Tesses::Framework::Streams::Stream* innerStream, bool owns, bool verify, std::string domain);
ClientTLSStream(Tesses::Framework::Streams::Stream* innerStream, bool owns, bool verify, std::string domain, std::string cert);
size_t Read(uint8_t* buff, size_t sz);
size_t Write(const uint8_t* buff, size_t sz);
bool CanRead();
bool CanWrite();
bool EndOfStream();
~ClientTLSStream();
};
}

View File

@ -0,0 +1,28 @@
#pragma once
#include "VFS.hpp"
namespace Tesses::Framework::Filesystem
{
class LocalFilesystem : public VFS
{
public:
Tesses::Framework::Streams::Stream* OpenFile(VFSPath path, std::string mode);
void CreateDirectory(VFSPath path);
void DeleteDirectory(VFSPath path);
bool RegularFileExists(VFSPath path);
bool SymlinkExists(VFSPath path);
bool CharacterDeviceExists(VFSPath path);
bool BlockDeviceExists(VFSPath path);
bool SocketFileExists(VFSPath path);
bool FIFOFileExists(VFSPath path);
bool DirectoryExists(VFSPath path);
void DeleteFile(VFSPath path);
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
void GetPaths(VFSPath path, std::vector<VFSPath>& paths);
void CreateHardlink(VFSPath existingFile, VFSPath newName);
void MoveFile(VFSPath src, VFSPath dest);
void MoveDirectory(VFSPath src, VFSPath dest);
VFSPath ReadLink(VFSPath path);
std::string VFSPathToSystem(VFSPath path);
VFSPath SystemToVFSPath(std::string path);
};
}

View File

@ -0,0 +1,53 @@
#pragma once
#include "VFS.hpp"
namespace Tesses::Framework::Filesystem
{
class MountableDirectory {
public:
std::string name;
VFS* vfs;
bool owns;
std::vector<MountableDirectory*> dirs;
void GetFS(VFSPath srcPath, VFSPath curDir, VFSPath& destRoot, VFSPath& destPath, VFS*& vfs);
~MountableDirectory();
};
class MountableFilesystem : public VFS
{
bool owns;
VFS* root;
std::vector<MountableDirectory*> directories;
void GetFS(VFSPath srcPath, VFSPath& destRoot, VFSPath& destPath, VFS*& vfs);
public:
MountableFilesystem();
MountableFilesystem(VFS* root, bool owns);
void Mount(VFSPath path, VFS* fs, bool owns);
void Unmount(VFSPath path);
Tesses::Framework::Streams::Stream* OpenFile(VFSPath path, std::string mode);
void CreateDirectory(VFSPath path);
void DeleteDirectory(VFSPath path);
bool SpecialFileExists(VFSPath path);
bool FileExists(VFSPath path);
bool RegularFileExists(VFSPath path);
bool SymlinkExists(VFSPath path);
bool CharacterDeviceExists(VFSPath path);
bool BlockDeviceExists(VFSPath path);
bool SocketFileExists(VFSPath path);
bool FIFOFileExists(VFSPath path);
bool DirectoryExists(VFSPath path);
void DeleteFile(VFSPath path);
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
void GetPaths(VFSPath path, std::vector<VFSPath>& paths);
void CreateHardlink(VFSPath existingFile, VFSPath newName);
void MoveFile(VFSPath src, VFSPath dest);
void MoveDirectory(VFSPath src, VFSPath dest);
VFSPath ReadLink(VFSPath path);
std::string VFSPathToSystem(VFSPath path);
VFSPath SystemToVFSPath(std::string path);
~MountableFilesystem();
};
}

View File

@ -0,0 +1,19 @@
#pragma once
#include "VFS.hpp"
namespace Tesses::Framework::Filesystem
{
class NullFilesystem : public VFS
{
public:
Tesses::Framework::Streams::Stream* OpenFile(VFSPath path, std::string mode);
void CreateDirectory(VFSPath path);
void DeleteDirectory(VFSPath path);
bool RegularFileExists(VFSPath path);
bool DirectoryExists(VFSPath path);
void DeleteFile(VFSPath path);
void GetPaths(VFSPath path, std::vector<VFSPath>& paths);
void MoveFile(VFSPath src, VFSPath dest);
std::string VFSPathToSystem(VFSPath path);
VFSPath SystemToVFSPath(std::string path);
};
}

View File

@ -0,0 +1,38 @@
#pragma once
#include "VFS.hpp"
namespace Tesses::Framework::Filesystem
{
class SubdirFilesystem : public VFS
{
bool owns;
VFS* parent;
VFSPath path;
VFSPath ToParent(VFSPath path);
VFSPath FromParent(VFSPath path);
public:
SubdirFilesystem(VFS* parent, VFSPath path, bool owns);
Tesses::Framework::Streams::Stream* OpenFile(VFSPath path, std::string mode);
void CreateDirectory(VFSPath path);
void DeleteDirectory(VFSPath path);
bool SpecialFileExists(VFSPath path);
bool FileExists(VFSPath path);
bool RegularFileExists(VFSPath path);
bool SymlinkExists(VFSPath path);
bool CharacterDeviceExists(VFSPath path);
bool BlockDeviceExists(VFSPath path);
bool SocketFileExists(VFSPath path);
bool FIFOFileExists(VFSPath path);
bool DirectoryExists(VFSPath path);
void DeleteFile(VFSPath path);
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
void GetPaths(VFSPath path, std::vector<VFSPath>& paths);
void CreateHardlink(VFSPath existingFile, VFSPath newName);
void MoveFile(VFSPath src, VFSPath dest);
void MoveDirectory(VFSPath src, VFSPath dest);
void DeleteDirectoryRecurse(VFSPath path);
VFSPath ReadLink(VFSPath path);
std::string VFSPathToSystem(VFSPath path);
VFSPath SystemToVFSPath(std::string path);
~SubdirFilesystem();
};
}

View File

@ -0,0 +1,50 @@
#pragma once
#include "../Common.hpp"
#include "../Streams/Stream.hpp"
namespace Tesses::Framework::Filesystem
{
class VFSPath {
public:
static VFSPath RelativeCurrentDirectory();
bool relative;
static std::vector<std::string> SplitPath(std::string path,bool native=false);
std::vector<std::string> path;
VFSPath();
VFSPath(std::vector<std::string> path);
VFSPath(std::string path);
VFSPath(VFSPath p, std::string subent);
VFSPath(VFSPath p, VFSPath p2);
VFSPath GetParent();
VFSPath CollapseRelativeParents();
std::string GetFileName();
std::string ToString();
};
class VFS {
public:
virtual Tesses::Framework::Streams::Stream* OpenFile(VFSPath path, std::string mode)=0;
virtual void CreateDirectory(VFSPath path)=0;
virtual void DeleteDirectory(VFSPath path)=0;
virtual bool RegularFileExists(VFSPath path)=0;
virtual bool SymlinkExists(VFSPath path);
virtual bool CharacterDeviceExists(VFSPath path);
virtual bool BlockDeviceExists(VFSPath path);
virtual bool SocketFileExists(VFSPath path);
virtual bool FIFOFileExists(VFSPath path);
virtual bool FileExists(VFSPath path);
virtual bool SpecialFileExists(VFSPath path);
virtual void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
virtual void CreateHardlink(VFSPath existingFile, VFSPath newName);
virtual bool DirectoryExists(VFSPath path)=0;
virtual void DeleteFile(VFSPath path)=0;
virtual void DeleteDirectoryRecurse(VFSPath path);
virtual void GetPaths(VFSPath path, std::vector<VFSPath>& paths)=0;
virtual void MoveFile(VFSPath src, VFSPath dest)=0;
virtual void MoveDirectory(VFSPath src, VFSPath dest);
virtual VFSPath ReadLink(VFSPath path);
virtual std::string VFSPathToSystem(VFSPath path)=0;
virtual VFSPath SystemToVFSPath(std::string path)=0;
virtual ~VFS();
};
}

View File

@ -0,0 +1,13 @@
#pragma once
#include "../Common.hpp"
namespace Tesses::Framework::Http
{
class ContentDisposition {
public:
std::string filename;
std::string type;
std::string fieldName;
static bool TryParse(std::string str, ContentDisposition& cd);
std::string ToString();
};
}

View File

@ -0,0 +1,25 @@
#pragma once
#include "../Filesystem/VFS.hpp"
#include "HttpServer.hpp"
namespace Tesses::Framework::Http
{
class FileServer : public IHttpServer
{
Tesses::Framework::Filesystem::VFS* vfs;
bool ownsVFS;
bool SendFile(ServerContext& ctx,Tesses::Framework::Filesystem::VFSPath path);
public:
bool allowListing;
bool spa;
std::vector<std::string> defaultNames;
FileServer(std::filesystem::path path,bool allowListing,bool spa);
FileServer(std::filesystem::path path,bool allowListing, bool spa, std::vector<std::string> defaultNames);
FileServer(Tesses::Framework::Filesystem::VFS* fs, bool owns, bool allowListing, bool spa);
FileServer(Tesses::Framework::Filesystem::VFS* fs, bool owns, bool allowListing, bool spa, std::vector<std::string> defaultNames);
bool Handle(ServerContext& ctx);
~FileServer();
};
}

View File

@ -0,0 +1,63 @@
#pragma once
#include "../Streams/Stream.hpp"
#include "HttpUtils.hpp"
namespace Tesses::Framework::Http
{
class HttpRequestBody {
public:
virtual void HandleHeaders(HttpDictionary& dict);
virtual void Write(Tesses::Framework::Streams::Stream* strm)=0;
};
class StreamHttpRequestBody : public HttpRequestBody {
Tesses::Framework::Streams::Stream* strm;
bool owns;
std::string mimeType;
public:
StreamHttpRequestBody(Tesses::Framework::Streams::Stream* strm, bool owns, std::string mimeType);
void HandleHeaders(HttpDictionary& dict);
void Write(Tesses::Framework::Streams::Stream* strm);
~StreamHttpRequestBody();
};
class HttpRequest {
public:
HttpRequest();
std::string trusted_root_cert_bundle;
bool ignoreSSLErrors;
bool followRedirects;
std::string method;
std::string url;
HttpDictionary requestHeaders;
HttpRequestBody* body;
static Tesses::Framework::Streams::Stream* EstablishConnection(Uri uri,bool ignoreSSLErrors,std::string trusted_root_cert_bundle);
void SendRequest(Tesses::Framework::Streams::Stream* strm);
};
class HttpResponse {
private:
bool owns;
Tesses::Framework::Streams::Stream* handleStrm;
public:
HttpResponse(Tesses::Framework::Streams::Stream* strm, bool owns);
HttpResponse(HttpRequest& request);
std::string version;
StatusCode statusCode;
HttpDictionary responseHeaders;
std::string ReadAsString();
Tesses::Framework::Streams::Stream* ReadAsStream();
void CopyToStream(Tesses::Framework::Streams::Stream* strm);
~HttpResponse();
};
}

View File

@ -0,0 +1,70 @@
#pragma once
#include "../Streams/NetworkStream.hpp"
#include "HttpUtils.hpp"
#include "../Threading/Thread.hpp"
namespace Tesses::Framework::Http
{
class ServerContext {
bool sent;
Tesses::Framework::Streams::Stream* strm;
public:
HttpDictionary requestHeaders;
HttpDictionary responseHeaders;
HttpDictionary queryParams;
std::string path;
std::string originalPath;
std::string method;
StatusCode statusCode;
std::string ip;
uint16_t port;
std::string version;
bool encrypted;
ServerContext(Tesses::Framework::Streams::Stream* strm);
Tesses::Framework::Streams::Stream& GetStream();
std::string GetOriginalPathWithQuery();
std::string GetUrlWithQuery();
bool Sent();
bool NeedToParseFormData();
void ParseFormData(std::function<Tesses::Framework::Streams::Stream*(std::string mime, std::string filename, std::string name)> cb);
void ReadStream(Tesses::Framework::Streams::Stream& strm);
void ReadStream(Tesses::Framework::Streams::Stream* strm);
std::string ReadString();
void SendBytes(std::vector<uint8_t> buffer);
void SendText(std::string text);
void SendStream(Tesses::Framework::Streams::Stream& strm);
void SendStream(Tesses::Framework::Streams::Stream* strm);
void SendErrorPage(bool showPath);
void SendNotFound();
void SendBadRequest();
void SendException(std::exception& ex);
Tesses::Framework::Streams::Stream* OpenResponseStream();
Tesses::Framework::Streams::Stream* OpenRequestStream();
ServerContext& WithHeader(std::string key, std::string value);
ServerContext& WithSingleHeader(std::string key, std::string value);
ServerContext& WithMimeType(std::string mime);
ServerContext& WithContentDisposition(std::string filename, bool isInline);
ServerContext& WriteHeaders();
};
class IHttpServer {
public:
virtual bool Handle(ServerContext& ctx)=0;
virtual ~IHttpServer();
};
class HttpServer {
Tesses::Framework::Streams::TcpServer* server;
IHttpServer* http;
Tesses::Framework::Threading::Thread* thrd;
bool owns;
uint16_t port;
public:
HttpServer(uint16_t port, IHttpServer& http);
HttpServer(uint16_t port, IHttpServer* http, bool owns);
void StartAccepting();
static void Process(Tesses::Framework::Streams::Stream& strm, IHttpServer& server, std::string ip, uint16_t port, bool encrypted);
~HttpServer();
};
}

View File

@ -0,0 +1,32 @@
#pragma once
#include "../Streams/Stream.hpp"
namespace Tesses::Framework::Http
{
class HttpStream : public Tesses::Framework::Streams::Stream {
Tesses::Framework::Streams::Stream* strm;
size_t offset;
size_t read;
int64_t length;
int64_t position;
bool owns;
bool recv;
bool http1_1;
bool done;
public:
HttpStream(Tesses::Framework::Streams::Stream* strm, bool owns, int64_t length, bool recv, bool http1_1);
HttpStream(Tesses::Framework::Streams::Stream& strm, int64_t length, bool recv,bool http1_1);
bool CanRead();
bool CanWrite();
bool EndOfStream();
int64_t GetLength();
int64_t GetPosition();
size_t Read(uint8_t* buffer, size_t len);
size_t Write(const uint8_t* buffer, size_t len);
~HttpStream();
};
}

View File

@ -0,0 +1,144 @@
#pragma once
#include "../Common.hpp"
namespace Tesses::Framework::Http
{
typedef enum StatusCode {
Continue=100,
SwitchingProtocols=101,
Processing=102,
EarlyHints=103,
OK=200,
Created=201,
Accepted=202,
NonAuthoritativeInformation=203,
NoContent=204,
ResetContent=205,
PartialContent=206,
MultiStatus=207,
AlreadyReported=208,
IMUsed=226,
MultipleChoices=300,
MovedPermanently=301,
Found=302,
SeeOther=303,
NotModified=304,
UseProxy=305,
TemporaryRedirect=307,
PermanentRedirect=308,
BadRequest=400,
Unauthorized=401,
PaymentRequired=402,
Forbidden=403,
NotFound=404,
MethodNotAllowed=405,
NotAcceptable=406,
ProxyAuthenticationRequired=407,
RequestTimeout=408,
Conflict=409,
Gone=410,
LengthRequired=411,
PreconditionFailed=412,
PayloadTooLarge=413,
URITooLong=414,
UnsupportedMediaType=415,
RangeNotSatisfiable=416,
ExpectationFailed=417,
ImATeapot=418,
MisdirectedRequest=421,
UnprocessableContent=422,
Locked=423,
FailedDependency=424,
TooEarly=425,
UpgradeRequired=426,
PreconditionRequired=428,
TooManyRequests=429,
RequestHeaderFieldsTooLarge=431,
UnavailableForLegalReasons=451,
InternalServerError=500,
NotImplemented=501,
BadGateway=502,
ServiceUnavailable=503,
GatewayTimeout=504,
HTTPVersionNotSupported=505,
VariantAlsoNegotiates=506,
InsufficientStorage=507,
LoopDetected=508,
NotExtended=510,
NetworkAuthenticationRequired=511
} StatusCode;
class HttpDictionary {
public:
std::map<std::string,std::vector<std::string>> kvp;
void Clear();
void Clear(std::string key, bool kvpExistsAfter);
void SetValue(std::string key, std::string value);
void SetValue(std::string key, std::vector<std::string> value);
template<typename Itterator>
void SetValue(std::string key, Itterator begin, Itterator end)
{
Clear(key,true);
AddValue(key, begin, end);
}
void AddValue(std::string key, std::string value);
void AddValue(std::string key, std::vector<std::string> value);
template<typename Itterator>
void AddValue(std::string key, Itterator begin, Itterator end)
{
auto& ls = kvp[key];
ls.insert(ls.end(), begin, end);
}
bool TryGetFirst(std::string key, std::string& value);
bool TryGetFirstInt(std::string key, int64_t& value);
bool TryGetFirstDouble(std::string key, double& value);
bool GetFirstBoolean(std::string key);
};
class Uri {
public:
std::string GetQuery();
std::string GetPathAndQuery();
uint16_t GetPort();
std::string HostPort();
bool Relative(std::string url, Uri& uri);
std::string ToString();
static bool TryParse(std::string url, Uri& uri);
std::string scheme;
std::string host;
uint16_t port;
std::string path;
HttpDictionary query;
std::string hash;
};
class HttpUtils
{
public:
static char NibbleToHex(uint8_t nibble);
static uint8_t HexToNibble(char c);
static std::string MimeType(std::filesystem::path p);
static bool Invalid(char c);
static std::string Sanitise(std::string text);
static void QueryParamsDecode(HttpDictionary& dict,std::string query);
static std::string Join(std::string joinStr, std::vector<std::string> ents);
static std::string QueryParamsEncode(HttpDictionary& dict);
static std::string UrlDecode(std::string v);
static std::string UrlEncode(std::string v);
static std::string UrlPathDecode(std::string v);
static std::string UrlPathEncode(std::string v, bool ignoreSpace=false);
static std::string HtmlEncode(std::string v);
static std::vector<std::string> SplitString(std::string text, std::string delimiter,std::size_t maxCnt = std::string::npos);
static std::string StatusCodeString(StatusCode code);
};
}

View File

@ -0,0 +1,27 @@
#pragma once
#include "Stream.hpp"
namespace Tesses::Framework::Streams
{
class BufferedStream : public Stream
{
private:
Stream* strm;
bool owns;
uint8_t* buffer;
size_t bufferSize;
size_t offset;
size_t read;
public:
BufferedStream(Stream* strm, bool owns, size_t bufferSize=1024);
BufferedStream(Stream& strm, size_t bufferSize=1024);
bool EndOfStream();
bool CanRead();
bool CanWrite();
size_t Read(uint8_t* buff, size_t sz);
size_t Write(const uint8_t* buff, size_t sz);
~BufferedStream();
};
}

View File

@ -0,0 +1,27 @@
#pragma once
#include "Stream.hpp"
#include <cstdio>
namespace Tesses::Framework::Streams
{
class FileStream : public Stream {
bool canRead;
bool canWrite;
bool canSeek;
bool owns;
FILE* f;
void SetMode(std::string mode);
public:
FileStream(std::filesystem::path p, std::string mode);
FileStream(FILE* f, bool owns, std::string mode , bool canSeek=true);
size_t Read(uint8_t* buff, size_t sz);
size_t Write(const uint8_t* buff, size_t sz);
bool CanRead();
bool CanWrite();
bool CanSeek();
int64_t GetPosition();
void Flush();
void Seek(int64_t pos, SeekOrigin whence);
~FileStream();
};
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "Stream.hpp"
namespace Tesses::Framework::Streams
{
class MemoryStream : public Stream {
std::vector<uint8_t> buffer;
size_t offset;
bool writable;
public:
MemoryStream(bool isWritable);
std::vector<uint8_t>& GetBuffer();
size_t Read(uint8_t* buff, size_t sz);
size_t Write(const uint8_t* buff, size_t sz);
bool CanRead();
bool CanWrite();
bool CanSeek();
int64_t GetLength();
int64_t GetPosition();
void Seek(int64_t pos, SeekOrigin whence);
};
}

View File

@ -0,0 +1,43 @@
#pragma once
#include "Stream.hpp"
namespace Tesses::Framework::Streams
{
class NetworkStream;
class TcpServer {
int32_t sock;
bool owns;
bool valid;
public:
TcpServer(int32_t sock,bool owns);
TcpServer(uint16_t port, int32_t backlog);
TcpServer(std::string ip, uint16_t port, int32_t backlog);
NetworkStream* GetStream(std::string& ip, uint16_t& port);
~TcpServer();
void Close();
};
class NetworkStream : public Stream {
int32_t sock;
bool owns;
bool success;
bool endOfStream;
public:
bool EndOfStream();
bool CanRead();
bool CanWrite();
NetworkStream(bool ipV6,bool datagram);
NetworkStream(std::string ipOrFqdn, uint16_t port, bool datagram,bool broadcast,bool supportIPv6);
NetworkStream(int32_t sock, bool owns);
void Listen(int32_t backlog);
void Bind(std::string ip, uint16_t port);
void SetBroadcast(bool bC);
NetworkStream* Accept(std::string& ip, uint16_t& port);
size_t Read(uint8_t* buff, size_t sz);
size_t Write(const uint8_t* buff, size_t sz);
size_t ReadFrom(uint8_t* buff, size_t sz, std::string& ip, uint16_t& port);
size_t WriteTo(const uint8_t* buff, size_t sz, std::string ip, uint16_t port);
static std::vector<std::pair<std::string,std::string>> GetIPs(bool ipV6=false);
~NetworkStream();
};
}

View File

@ -0,0 +1,31 @@
#pragma once
#include "../Common.hpp"
namespace Tesses::Framework::Streams
{
enum class SeekOrigin : uint8_t {
Begin=0,
Current=1,
End=2
};
class Stream {
public:
int32_t ReadByte();
void WriteByte(uint8_t b);
virtual bool EndOfStream();
virtual size_t Read(uint8_t* buff, size_t sz);
virtual size_t Write(const uint8_t* buff, size_t sz);
size_t ReadBlock(uint8_t* buff, size_t sz);
void WriteBlock(const uint8_t* buff, size_t sz);
virtual bool CanRead();
virtual bool CanWrite();
virtual bool CanSeek();
virtual int64_t GetPosition();
virtual int64_t GetLength();
virtual void Flush();
virtual void Seek(int64_t pos, SeekOrigin whence);
void CopyTo(Stream* strm, size_t buffSize=1024);
void CopyTo(Stream& strm, size_t buffSize=1024);
virtual ~Stream();
};
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "Http/HttpServer.hpp"
#include "Http/HttpClient.hpp"
#include "Http/FileServer.hpp"
#include "Http/ContentDisposition.hpp"
#include "Streams/FileStream.hpp"
#include "Streams/MemoryStream.hpp"
#include "Streams/NetworkStream.hpp"
#include "Streams/BufferedStream.hpp"
#include "TextStreams/StreamReader.hpp"
#include "TextStreams/StreamWriter.hpp"
#include "Threading/Thread.hpp"
#include "Filesystem/LocalFS.hpp"
#include "Filesystem/SubdirFilesystem.hpp"
#include "Filesystem/NullFilesystem.hpp"
#include "Filesystem/MountableFilesystem.hpp"
#include "Crypto/ClientTLSStream.hpp"

View File

@ -0,0 +1,19 @@
#pragma once
#include "TextReader.hpp"
#include "../Streams/Stream.hpp"
namespace Tesses::Framework::TextStreams
{
class StreamReader : public TextReader
{
private:
Tesses::Framework::Streams::Stream* strm;
bool owns;
public:
Tesses::Framework::Streams::Stream& GetStream();
StreamReader(Tesses::Framework::Streams::Stream& strm);
StreamReader(Tesses::Framework::Streams::Stream* strm, bool owns);
StreamReader(std::filesystem::path filename);
bool ReadBlock(std::string& str,size_t sz);
~StreamReader();
};
}

View File

@ -0,0 +1,19 @@
#pragma once
#include "../Streams/Stream.hpp"
#include "TextWriter.hpp"
namespace Tesses::Framework::TextStreams
{
class StreamWriter : public TextWriter {
private:
Tesses::Framework::Streams::Stream* strm;
bool owns;
public:
Tesses::Framework::Streams::Stream& GetStream();
StreamWriter(Tesses::Framework::Streams::Stream& strm);
StreamWriter(Tesses::Framework::Streams::Stream* strm, bool owns);
StreamWriter(std::filesystem::path filename, bool append=false);
void WriteData(const char* text, size_t len);
~StreamWriter();
};
}

View File

@ -0,0 +1,18 @@
#pragma once
#include "../Common.hpp"
#include "TextWriter.hpp"
namespace Tesses::Framework::TextStreams
{
class TextReader
{
public:
virtual bool ReadBlock(std::string& str,size_t sz)=0;
int32_t ReadChar();
std::string ReadLine();
bool ReadLine(std::string& str);
std::string ReadToEnd();
void ReadToEnd(std::string& str);
void CopyTo(TextWriter& writer, size_t bufSz=1024);
virtual ~TextReader();
};
}

View File

@ -0,0 +1,16 @@
#pragma once
#include "../Common.hpp"
namespace Tesses::Framework::TextStreams
{
class TextWriter {
public:
TextWriter();
std::string newline;
virtual void WriteData(const char* text, size_t len)=0;
void Write(std::string txt);
void WriteLine(std::string txt);
void WriteLine();
virtual ~TextWriter();
};
}

View File

@ -0,0 +1,22 @@
#pragma once
#if defined(GEKKO)
#include <ogc/mutex.h>
#else
#include <threads.h>
#endif
namespace Tesses::Framework::Threading
{
class Mutex {
#if defined(GEKKO)
mutex_t mtx;
#else
mtx_t mtx;
#endif
public:
Mutex();
void Lock();
void Unlock();
bool TryLock();
~Mutex();
};
}

View File

@ -0,0 +1,27 @@
#pragma once
#include <functional>
#if defined(GEKKO)
#include <ogc/lwp.h>
#else
#include <threads.h>
#endif
#include <atomic>
namespace Tesses::Framework::Threading
{
class Thread
{
std::atomic<bool> hasInvoked;
#if defined(GEKKO)
lwp_t thrd;
static void* cb(void* ptr);
#else
thrd_t thrd;
static int cb(void* ptr);
#endif
std::function<void()> fn;
public:
Thread(std::function<void()> fn);
void Join();
void Detach();
};
}