Added memoryfilesystem and working on c wrapper
This commit is contained in:
@ -24,11 +24,13 @@ src/Threading/Thread.cpp
|
||||
src/Threading/Mutex.cpp
|
||||
src/Filesystem/VFS.cpp
|
||||
src/Filesystem/LocalFS.cpp
|
||||
src/Filesystem/MemoryFilesystem.cpp
|
||||
src/Filesystem/SubdirFilesystem.cpp
|
||||
src/Filesystem/NullFilesystem.cpp
|
||||
src/Filesystem/MountableFilesystem.cpp
|
||||
src/Crypto/ClientTLSStream.cpp
|
||||
src/TF_Init.cpp
|
||||
src/wrapper.cpp
|
||||
)
|
||||
|
||||
set(TESSESFRAMEWORK_CERT_BUNDLE_FILE "/etc/ssl/certs/ca-certificates.crt" CACHE FILEPATH "Path to ca-chain")
|
||||
|
||||
21
examples/wrappertest.c
Normal file
21
examples/wrappertest.c
Normal file
@ -0,0 +1,21 @@
|
||||
#include "TessesFramework.h"
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
tf_vfs_t* local = tf_vfs_create_local();
|
||||
|
||||
tf_vfs_dir_t* dir = tf_vfs_opendir(local, "/home/mike");
|
||||
|
||||
string_t* str;
|
||||
while(str = tf_vfs_readdir(dir))
|
||||
{
|
||||
string_println(str);
|
||||
}
|
||||
tf_vfs_closedir(dir);
|
||||
|
||||
tf_stream_t* strm = tf_vfs_open(local,"/home/mike/myPhoto.png", "wb");
|
||||
|
||||
|
||||
|
||||
tf_vfs_close(local);
|
||||
}
|
||||
99
include/TessesFramework/Filesystem/MemoryFilesystem.hpp
Normal file
99
include/TessesFramework/Filesystem/MemoryFilesystem.hpp
Normal file
@ -0,0 +1,99 @@
|
||||
#pragma once
|
||||
#include "VFS.hpp"
|
||||
#include "VFSFix.hpp"
|
||||
#include "../Threading/Mutex.hpp"
|
||||
#include <atomic>
|
||||
namespace Tesses::Framework::Filesystem
|
||||
{
|
||||
class MemoryEntry {
|
||||
public:
|
||||
std::string name;
|
||||
virtual ~MemoryEntry();
|
||||
};
|
||||
class MemoryFileData {
|
||||
public:
|
||||
MemoryFileData();
|
||||
time_t lastWrite;
|
||||
|
||||
bool canAccess;
|
||||
size_t readers;
|
||||
std::vector<uint8_t> file;
|
||||
};
|
||||
|
||||
class MemoryFile : public MemoryEntry
|
||||
{
|
||||
public:
|
||||
std::shared_ptr<MemoryFileData> data;
|
||||
~MemoryFile();
|
||||
};
|
||||
|
||||
class MemoryDirectory : public MemoryEntry
|
||||
{
|
||||
public:
|
||||
MemoryDirectory();
|
||||
time_t lastWrite;
|
||||
std::vector<MemoryEntry*> entries;
|
||||
~MemoryDirectory();
|
||||
};
|
||||
|
||||
class MemorySymlink : public MemoryEntry
|
||||
{
|
||||
public:
|
||||
time_t lastWrite;
|
||||
VFSPath linkedTo;
|
||||
};
|
||||
|
||||
class MemoryFilesystemStream : public Streams::Stream
|
||||
{
|
||||
public:
|
||||
std::shared_ptr<Tesses::Framework::Threading::Mutex> mtx;
|
||||
std::shared_ptr<MemoryFileData> data;
|
||||
bool canRead;
|
||||
bool canWrite;
|
||||
bool canSeek;
|
||||
int64_t pos;
|
||||
MemoryFilesystemStream(std::shared_ptr<Tesses::Framework::Threading::Mutex> mtx, std::shared_ptr<MemoryFileData> data,bool canRead, bool canWrite, bool canSeek);
|
||||
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, Streams::SeekOrigin whence);
|
||||
~MemoryFilesystemStream();
|
||||
};
|
||||
|
||||
|
||||
class MemoryFilesystem : public VFS
|
||||
{
|
||||
std::shared_ptr<Tesses::Framework::Threading::Mutex> mtx;
|
||||
MemoryDirectory root;
|
||||
|
||||
MemoryEntry* GetEntry(VFSPath path,bool followSymlink);
|
||||
public:
|
||||
MemoryFilesystem();
|
||||
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 DirectoryExists(VFSPath path);
|
||||
|
||||
void DeleteFile(VFSPath path);
|
||||
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
|
||||
VFSPathEnumerator EnumeratePaths(VFSPath path);
|
||||
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);
|
||||
void GetDate(VFSPath path, time_t& lastWrite, time_t& lastAccess);
|
||||
void SetDate(VFSPath path, time_t lastWrite, time_t lastAccess);
|
||||
~MemoryFilesystem();
|
||||
};
|
||||
};
|
||||
@ -15,6 +15,7 @@ namespace Tesses::Framework::Streams
|
||||
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 EndOfStream();
|
||||
bool CanRead();
|
||||
bool CanWrite();
|
||||
bool CanSeek();
|
||||
|
||||
77
include/TessesFramework/TessesFramework.h
Normal file
77
include/TessesFramework/TessesFramework.h
Normal file
@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef void string_t;
|
||||
typedef void tf_vfs_t;
|
||||
typedef void tf_stream_t;
|
||||
typedef void tf_thread_t;
|
||||
typedef void tf_mutex_t;
|
||||
typedef void tf_vfs_dir_t;
|
||||
|
||||
typedef void (*tf_action_user_data_t)(void* ptr);
|
||||
|
||||
|
||||
typedef enum {
|
||||
TF_SEEK_BEGIN,
|
||||
TF_SEEK_CURRENT,
|
||||
TF_SEEK_END
|
||||
} TF_WHENCE;
|
||||
|
||||
string_t* string_create();
|
||||
string_t* string_create_from_buff(const void* text, size_t len);
|
||||
string_t* string_create_from_charpointer(const char* text);
|
||||
string_t* string_resize(string_t* str, size_t len);
|
||||
string_t* string_set_char(string_t* str, size_t index, char c);
|
||||
char string_get_char(string_t* str,size_t index);
|
||||
string_t* string_append_char(string_t* str, char c);
|
||||
string_t* string_append_from_buff(string_t* str,const void* text, size_t len);
|
||||
string_t* string_append_from_charpointer(string_t* str,const char* text);
|
||||
string_t* string_append(string_t* str, string_t* toAppend);
|
||||
string_t* string_append_signed(string_t* str, int64_t num);
|
||||
string_t* string_append_unsigned(string_t* str, uint64_t num);
|
||||
string_t* string_append_double(string_t* str, double num);
|
||||
void string_print(string_t* str);
|
||||
void string_println(string_t* str);
|
||||
size_t string_size(string_t* str);
|
||||
const char* string_c_str(string_t* str);
|
||||
void string_free(string_t* str);
|
||||
|
||||
void tf_init();
|
||||
tf_thread_t* tf_create_thread(void* userData, tf_action_user_data_t cb);
|
||||
void tf_join_thread(tf_thread_t* thrd);
|
||||
void tf_detach_thread(tf_thread_t* thrd);
|
||||
|
||||
tf_mutex_t* tf_mutex_create();
|
||||
void tf_mutex_lock(tf_mutex_t* mtx);
|
||||
bool tf_mutex_trylock(tf_mutex_t* mtx);
|
||||
void tf_mutex_unlock(tf_mutex_t* mtx);
|
||||
void tf_mutex_free(tf_mutex_t* mtx);
|
||||
|
||||
bool tf_stream_canread(tf_stream_t* strm);
|
||||
bool tf_stream_canwrite(tf_stream_t* strm);
|
||||
bool tf_stream_canseek(tf_stream_t* strm);
|
||||
bool tf_stream_eof(tf_stream_t* strm);
|
||||
int64_t tf_stream_getlen(tf_stream_t* strm);
|
||||
int64_t tf_stream_getpos(tf_stream_t* strm);
|
||||
void tf_stream_seek(tf_stream_t* strm, int64_t pos, TF_WHENCE whence);
|
||||
size_t tf_stream_read(tf_stream_t* strm, uint8_t* buffer, size_t length);
|
||||
size_t tf_stream_write(tf_stream_t* strm, const uint8_t* buffer, size_t length);
|
||||
size_t tf_stream_readblock(tf_stream_t* strm, uint8_t* buffer, size_t length);
|
||||
void tf_stream_writeblock(tf_stream_t* strm, const uint8_t* buffer, size_t length);
|
||||
void tf_stream_copyto(tf_stream_t* src, tf_stream_t* dest, size_t blockSize);
|
||||
void tf_stream_close(tf_stream_t* strm);
|
||||
void tf_stream_flush(tf_stream_t* strm);
|
||||
int32_t tf_stream_readbyte(tf_stream_t* strm);
|
||||
void tf_stream_writebyte(tf_stream_t* strm, uint8_t val);
|
||||
|
||||
tf_stream_t* tf_stream_fopen(const char* file, const char* mode);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
@ -11,8 +11,10 @@
|
||||
#include "TextStreams/StreamWriter.hpp"
|
||||
#include "Threading/Thread.hpp"
|
||||
#include "Threading/Mutex.hpp"
|
||||
#include "Threading/ThreadPool.hpp"
|
||||
#include "Filesystem/LocalFS.hpp"
|
||||
#include "Filesystem/SubdirFilesystem.hpp"
|
||||
#include "Filesystem/NullFilesystem.hpp"
|
||||
#include "Filesystem/MountableFilesystem.hpp"
|
||||
#include "Filesystem/MemoryFilesystem.hpp"
|
||||
#include "Crypto/ClientTLSStream.hpp"
|
||||
23
include/TessesFramework/Threading/ThreadPool.hpp
Normal file
23
include/TessesFramework/Threading/ThreadPool.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include <functional>
|
||||
#include "Thread.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
|
||||
namespace Tesses::Framework::Threading
|
||||
{
|
||||
|
||||
class ThreadPool
|
||||
{
|
||||
std::vector<Thread*> threads;
|
||||
std::queue<std::function<void()>> callbacks;
|
||||
Mutex mtx;
|
||||
volatile bool isRunning;
|
||||
public:
|
||||
static size_t GetNumberOfCores();
|
||||
ThreadPool(size_t threads);
|
||||
void Schedule(std::function<void()> cb);
|
||||
~ThreadPool();
|
||||
};
|
||||
}
|
||||
666
src/Filesystem/MemoryFilesystem.cpp
Normal file
666
src/Filesystem/MemoryFilesystem.cpp
Normal file
@ -0,0 +1,666 @@
|
||||
#include "TessesFramework/Filesystem/MemoryFilesystem.hpp"
|
||||
#include <iostream>
|
||||
|
||||
namespace Tesses::Framework::Filesystem
|
||||
{
|
||||
MemoryFilesystemStream::MemoryFilesystemStream(std::shared_ptr<Tesses::Framework::Threading::Mutex> mtx, std::shared_ptr<MemoryFileData> data,bool canRead, bool canWrite, bool canSeek)
|
||||
{
|
||||
this->mtx = mtx;
|
||||
this->data = data;
|
||||
this->canRead = canRead;
|
||||
this->canWrite = canWrite;
|
||||
this->canSeek = canSeek;
|
||||
this->pos=0;
|
||||
}
|
||||
size_t MemoryFilesystemStream::Read(uint8_t* buff, size_t sz)
|
||||
{
|
||||
if(!this->canRead) return 0;
|
||||
if(this->pos >= this->data->file.size()) return 0;
|
||||
size_t toRead = std::min(sz, (size_t)(this->data->file.size()-this->pos));
|
||||
memcpy(buff, this->data->file.data() + this->pos, toRead);
|
||||
|
||||
this->pos += toRead;
|
||||
return toRead;
|
||||
}
|
||||
size_t MemoryFilesystemStream::Write(const uint8_t* buff, size_t sz)
|
||||
{
|
||||
if(!this->canWrite) return 0;
|
||||
if(this->canSeek)
|
||||
{
|
||||
|
||||
if(this->pos > this->data->file.size())
|
||||
{
|
||||
this->data->file.resize(this->pos+sz);
|
||||
}
|
||||
this->data->file.insert(this->data->file.begin()+this->pos, buff, buff+sz);
|
||||
this->pos+=sz;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
this->data->file.insert(this->data->file.end(), buff, buff+sz);
|
||||
}
|
||||
return sz;
|
||||
}
|
||||
bool MemoryFilesystemStream::CanRead()
|
||||
{
|
||||
return canRead;
|
||||
}
|
||||
bool MemoryFilesystemStream::CanWrite()
|
||||
{
|
||||
return canWrite;
|
||||
}
|
||||
bool MemoryFilesystemStream::CanSeek()
|
||||
{
|
||||
return canSeek;
|
||||
}
|
||||
int64_t MemoryFilesystemStream::GetPosition()
|
||||
{
|
||||
if(!this->canSeek) return (int64_t)this->data->file.size();
|
||||
return pos;
|
||||
}
|
||||
void MemoryFilesystemStream::Flush()
|
||||
{
|
||||
//its already flushed
|
||||
}
|
||||
void MemoryFilesystemStream::Seek(int64_t pos, Streams::SeekOrigin whence)
|
||||
{
|
||||
if(canSeek) return;
|
||||
switch(whence)
|
||||
{
|
||||
case Streams::SeekOrigin::Begin:
|
||||
this->pos = (size_t)pos;
|
||||
break;
|
||||
case Streams::SeekOrigin::Current:
|
||||
this->pos += (size_t)pos;
|
||||
break;
|
||||
case Streams::SeekOrigin::End:
|
||||
this->pos = (size_t)(this->data->file.size() + pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
MemoryFilesystemStream::~MemoryFilesystemStream()
|
||||
{
|
||||
mtx->Lock();
|
||||
if(this->canWrite) this->data->canAccess=true;
|
||||
this->data->readers--;
|
||||
mtx->Unlock();
|
||||
}
|
||||
|
||||
MemoryEntry* MemoryFilesystem::GetEntry(VFSPath path,bool followSymlink)
|
||||
{
|
||||
if(path.relative) return nullptr;
|
||||
if(path.path.empty()) return &this->root;
|
||||
|
||||
auto entry = GetEntry(path.GetParent(),true);
|
||||
if(entry == nullptr) return nullptr;
|
||||
|
||||
auto dir = dynamic_cast<MemoryDirectory*>(entry);
|
||||
if(dir != nullptr)
|
||||
{
|
||||
for(auto item : dir->entries)
|
||||
{
|
||||
if(item->name == path.GetFileName())
|
||||
{
|
||||
auto link = dynamic_cast<MemorySymlink*>(item);
|
||||
if(followSymlink && link != nullptr)
|
||||
{
|
||||
item = GetEntry(link->linkedTo,true);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Streams::Stream* MemoryFilesystem::OpenFile(VFSPath path, std::string mode)
|
||||
{
|
||||
bool canRead=false;
|
||||
bool canWrite=false;
|
||||
bool canSeek=true;
|
||||
bool mustExist=false;
|
||||
bool truncate=false;
|
||||
|
||||
|
||||
if(mode.size() >= 1)
|
||||
{
|
||||
if(mode[0] == 'r')
|
||||
{
|
||||
canRead = true;
|
||||
mustExist=true;
|
||||
}
|
||||
else if(mode[0] == 'w')
|
||||
{
|
||||
canWrite = true;
|
||||
truncate=true;
|
||||
}
|
||||
else if(mode[0] == 'a')
|
||||
{
|
||||
canSeek = false;
|
||||
canWrite = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(((mode.size() >= 2 && mode[1] == '+') || (mode.size() >= 2 && mode[1] == 'b' && mode[2] == '+')))
|
||||
{
|
||||
canRead = true;
|
||||
canWrite = true;
|
||||
}
|
||||
|
||||
mtx->Lock();
|
||||
if(mustExist)
|
||||
{
|
||||
auto file = GetEntry(path,true);
|
||||
|
||||
if(file == nullptr)
|
||||
{
|
||||
mtx->Unlock();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto f = dynamic_cast<MemoryFile*>(file);
|
||||
if(f == nullptr)
|
||||
{
|
||||
mtx->Unlock();
|
||||
return nullptr;
|
||||
}
|
||||
if(!f->data->canAccess)
|
||||
{
|
||||
mtx->Unlock();
|
||||
return nullptr;
|
||||
}
|
||||
if(canWrite && f->data->readers > 0)
|
||||
{
|
||||
mtx->Unlock();
|
||||
return nullptr;
|
||||
}
|
||||
f->data->readers++;
|
||||
if(canWrite) f->data->canAccess=false;
|
||||
|
||||
mtx->Unlock();
|
||||
return new MemoryFilesystemStream(mtx,f->data,canRead,canWrite,canSeek);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto file = dynamic_cast<MemoryFile*>(GetEntry(path,true));
|
||||
|
||||
|
||||
if(file != nullptr)
|
||||
{
|
||||
if(!file->data->canAccess)
|
||||
{
|
||||
mtx->Unlock();
|
||||
return nullptr;
|
||||
}
|
||||
if(file->data->readers > 0)
|
||||
{
|
||||
mtx->Unlock();
|
||||
return nullptr;
|
||||
}
|
||||
file->data->canAccess=false;
|
||||
file->data->readers++;
|
||||
if(truncate) {file->data->file.clear(); file->data->lastWrite=time(NULL);}
|
||||
mtx->Unlock();
|
||||
return new MemoryFilesystemStream(mtx,file->data,canRead,canWrite,canSeek);
|
||||
|
||||
}
|
||||
|
||||
|
||||
auto dir = GetEntry(path.GetParent(),true);
|
||||
|
||||
if(dir == nullptr)
|
||||
{
|
||||
mtx->Unlock();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto myDir = dynamic_cast<MemoryDirectory*>(dir);
|
||||
|
||||
|
||||
if(myDir == nullptr)
|
||||
{
|
||||
mtx->Unlock();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MemoryFile* thefile=nullptr;
|
||||
|
||||
for(auto f : myDir->entries)
|
||||
{
|
||||
if(f->name == path.GetFileName())
|
||||
{
|
||||
auto symlink = dynamic_cast<MemorySymlink*>(f);
|
||||
while(symlink != nullptr)
|
||||
{
|
||||
auto ent = GetEntry(symlink->name,false);
|
||||
auto sym = dynamic_cast<MemorySymlink*>(f);
|
||||
if(sym != nullptr)
|
||||
symlink = sym;
|
||||
else
|
||||
{
|
||||
auto myDir0 = dynamic_cast<MemoryDirectory*>(GetEntry(symlink->linkedTo.GetParent(),true));
|
||||
if(myDir0 != nullptr)
|
||||
{
|
||||
for(auto f2 : myDir0->entries)
|
||||
{
|
||||
if(f2->name == symlink->linkedTo.GetFileName())
|
||||
{
|
||||
auto myFile = dynamic_cast<MemoryFile*>(f2);
|
||||
if(myFile != nullptr)
|
||||
{
|
||||
thefile = myFile;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtx->Unlock();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
myDir = myDir0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtx->Unlock();
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(thefile == nullptr)
|
||||
{
|
||||
|
||||
MemoryFile* f = new MemoryFile();
|
||||
f->name = path.GetFileName();
|
||||
f->data = std::make_shared<MemoryFileData>();
|
||||
f->data->canAccess=false;
|
||||
f->data->readers++;
|
||||
|
||||
myDir->entries.push_back(f);
|
||||
|
||||
mtx->Unlock();
|
||||
return new MemoryFilesystemStream(mtx,f->data,canRead,canWrite,canSeek);
|
||||
}
|
||||
if(thefile != nullptr)
|
||||
{
|
||||
if(!thefile->data->canAccess)
|
||||
{
|
||||
mtx->Unlock();
|
||||
return nullptr;
|
||||
}
|
||||
if(thefile->data->readers > 0)
|
||||
{
|
||||
mtx->Unlock();
|
||||
return nullptr;
|
||||
}
|
||||
thefile->data->canAccess=false;
|
||||
thefile->data->readers++;
|
||||
if(truncate) {thefile->data->file.clear(); thefile->data->lastWrite=time(NULL);}
|
||||
mtx->Unlock();
|
||||
return new MemoryFilesystemStream(mtx,thefile->data,canRead,canWrite,canSeek);
|
||||
}
|
||||
}
|
||||
|
||||
mtx->Unlock();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MemoryFilesystem::CreateDirectory(VFSPath path)
|
||||
{
|
||||
if(path.relative) return;
|
||||
if(path.path.empty()) return;
|
||||
mtx->Lock();
|
||||
MemoryDirectory* dir=&root;
|
||||
for(auto part : path.path)
|
||||
{
|
||||
bool have=false;
|
||||
for(auto dirent : dir->entries)
|
||||
{
|
||||
if(dirent->name == part)
|
||||
{
|
||||
auto symlink = dynamic_cast<MemorySymlink*>(dirent);
|
||||
if(symlink != nullptr)
|
||||
{
|
||||
dirent = GetEntry(symlink->linkedTo,true);
|
||||
}
|
||||
auto dirdirent = dynamic_cast<MemoryDirectory*>(dirent);
|
||||
if(dirdirent != nullptr)
|
||||
{
|
||||
dir = dirdirent;
|
||||
have=true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtx->Unlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!have)
|
||||
{
|
||||
MemoryDirectory* dir2 = new MemoryDirectory();
|
||||
dir2->name = part;
|
||||
|
||||
dir2->lastWrite=time(NULL);
|
||||
|
||||
dir->entries.push_back(dir2);
|
||||
dir->lastWrite=time(NULL);
|
||||
|
||||
dir=dir2;
|
||||
}
|
||||
}
|
||||
mtx->Unlock();
|
||||
}
|
||||
|
||||
void MemoryFilesystem::DeleteFile(VFSPath path)
|
||||
{
|
||||
if(path.relative || path.path.empty()) return;
|
||||
mtx->Lock();
|
||||
MemoryDirectory* dir=&root;
|
||||
if(path.path.size() > 1)
|
||||
{
|
||||
dir = dynamic_cast<MemoryDirectory*>(GetEntry(path.GetParent(),true));
|
||||
}
|
||||
if(dir == nullptr)
|
||||
{
|
||||
mtx->Unlock();
|
||||
return;
|
||||
}
|
||||
std::string fname = path.GetFileName();
|
||||
for(auto index = dir->entries.begin(); index < dir->entries.end(); index++)
|
||||
{
|
||||
auto item = *index;
|
||||
if(item->name == fname)
|
||||
{
|
||||
auto p = dynamic_cast<MemoryDirectory*>(item);
|
||||
if(p == nullptr)
|
||||
{
|
||||
delete item;
|
||||
dir->entries.erase(index);
|
||||
|
||||
dir->lastWrite=time(NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
mtx->Unlock();
|
||||
}
|
||||
|
||||
bool MemoryFilesystem::RegularFileExists(VFSPath path)
|
||||
{
|
||||
|
||||
if(path.relative) return false;
|
||||
if(path.path.empty()) return false;
|
||||
mtx->Lock();
|
||||
auto f = GetEntry(path,false);
|
||||
mtx->Unlock();
|
||||
return dynamic_cast<MemoryFile*>(f) != nullptr;
|
||||
}
|
||||
bool MemoryFilesystem::SymlinkExists(VFSPath path)
|
||||
{
|
||||
|
||||
if(path.relative) return false;
|
||||
if(path.path.empty()) return false;
|
||||
mtx->Lock();
|
||||
auto f = GetEntry(path,false);
|
||||
mtx->Unlock();
|
||||
return dynamic_cast<MemorySymlink*>(f) != nullptr;
|
||||
}
|
||||
bool MemoryFilesystem::DirectoryExists(VFSPath path)
|
||||
{
|
||||
if(path.relative) return false;
|
||||
if(path.path.empty()) return true;
|
||||
mtx->Lock();
|
||||
auto f = GetEntry(path,false);
|
||||
mtx->Unlock();
|
||||
return dynamic_cast<MemoryDirectory*>(f) != nullptr;
|
||||
}
|
||||
|
||||
void MemoryFilesystem::DeleteDirectory(VFSPath path)
|
||||
{
|
||||
if(path.relative || path.path.empty()) return;
|
||||
mtx->Lock();
|
||||
MemoryDirectory* dir=&root;
|
||||
if(path.path.size() > 1)
|
||||
{
|
||||
dir = dynamic_cast<MemoryDirectory*>(GetEntry(path.GetParent(),true));
|
||||
}
|
||||
if(dir == nullptr)
|
||||
{
|
||||
mtx->Unlock();
|
||||
return;
|
||||
}
|
||||
std::string fname = path.GetFileName();
|
||||
for(auto index = dir->entries.begin(); index < dir->entries.end(); index++)
|
||||
{
|
||||
auto item = *index;
|
||||
if(item->name == fname)
|
||||
{
|
||||
auto p = dynamic_cast<MemoryDirectory*>(item);
|
||||
if(p != nullptr)
|
||||
{
|
||||
delete item;
|
||||
dir->entries.erase(index);
|
||||
dir->lastWrite=time(NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
mtx->Unlock();
|
||||
}
|
||||
|
||||
void MemoryFilesystem::CreateSymlink(VFSPath existingFile, VFSPath symlinkFile)
|
||||
{
|
||||
if(existingFile.relative || symlinkFile.relative || symlinkFile.path.empty()) return;
|
||||
mtx->Lock();
|
||||
MemoryDirectory* dir=&root;
|
||||
if(symlinkFile.path.size() > 1)
|
||||
{
|
||||
dir = dynamic_cast<MemoryDirectory*>(GetEntry(symlinkFile.GetParent(),true));
|
||||
}
|
||||
if(dir == nullptr)
|
||||
{
|
||||
mtx->Unlock();
|
||||
return;
|
||||
}
|
||||
std::string fname = symlinkFile.GetFileName();
|
||||
for(auto index = dir->entries.begin(); index < dir->entries.end(); index++)
|
||||
{
|
||||
auto item = *index;
|
||||
if(item->name == fname)
|
||||
{
|
||||
auto p = dynamic_cast<MemorySymlink*>(item);
|
||||
if(p != nullptr)
|
||||
{
|
||||
p->linkedTo = existingFile;
|
||||
p->lastWrite = time(NULL);
|
||||
}
|
||||
mtx->Unlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
MemorySymlink* symlink = new MemorySymlink();
|
||||
symlink->name = fname;
|
||||
symlink->linkedTo = existingFile;
|
||||
symlink->lastWrite = time(NULL);
|
||||
dir->entries.push_back(symlink);
|
||||
dir->lastWrite = time(NULL);
|
||||
|
||||
mtx->Unlock();
|
||||
}
|
||||
VFSPathEnumerator MemoryFilesystem::EnumeratePaths(VFSPath path)
|
||||
{
|
||||
std::pair<size_t,std::vector<std::string>>* paths=new std::pair<size_t,std::vector<std::string>>();
|
||||
paths->first=0;
|
||||
mtx->Lock();
|
||||
auto dir = dynamic_cast<MemoryDirectory*>(GetEntry(path,true));
|
||||
if(dir != nullptr)
|
||||
{
|
||||
for(auto item : dir->entries) paths->second.push_back(item->name);
|
||||
}
|
||||
mtx->Unlock();
|
||||
|
||||
return VFSPathEnumerator([paths,path](VFSPath& _path)->bool{
|
||||
if(paths->first < paths->second.size())
|
||||
{
|
||||
_path = path / paths->second[paths->first++];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},[paths]()->void{
|
||||
delete paths;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void MemoryFilesystem::CreateHardlink(VFSPath existingFile, VFSPath newName)
|
||||
{
|
||||
mtx->Lock();
|
||||
auto existing = dynamic_cast<MemoryFile*>(GetEntry(existingFile,true));
|
||||
if(existing == nullptr)
|
||||
{
|
||||
mtx->Unlock();
|
||||
return;
|
||||
}
|
||||
MemoryDirectory* dir=&root;
|
||||
if(newName.path.size() > 1)
|
||||
{
|
||||
dir = dynamic_cast<MemoryDirectory*>(GetEntry(newName.GetParent(),true));
|
||||
}
|
||||
if(dir == nullptr)
|
||||
{
|
||||
mtx->Unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
std::string fname = newName.GetFileName();
|
||||
for(auto index = dir->entries.begin(); index < dir->entries.end(); index++)
|
||||
{
|
||||
auto item = *index;
|
||||
if(item->name == fname)
|
||||
{
|
||||
|
||||
mtx->Unlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MemoryFile* memFile = new MemoryFile();
|
||||
memFile->name = fname;
|
||||
memFile->data = existing->data;
|
||||
dir->entries.push_back(memFile);
|
||||
dir->lastWrite=time(NULL);
|
||||
|
||||
mtx->Unlock();
|
||||
}
|
||||
void MemoryFilesystem::MoveFile(VFSPath src, VFSPath dest)
|
||||
{
|
||||
DeleteFile(dest);
|
||||
CreateHardlink(src,dest);
|
||||
DeleteFile(src);
|
||||
}
|
||||
void MemoryFilesystem::MoveDirectory(VFSPath src, VFSPath dest)
|
||||
{
|
||||
CreateDirectory(dest);
|
||||
for(auto ent : EnumeratePaths(src))
|
||||
{
|
||||
VFSPath destPath = dest / ent.GetFileName();
|
||||
if(FileExists(ent)) MoveFile(ent,destPath);
|
||||
if(DirectoryExists(ent)) MoveDirectory(ent,destPath);
|
||||
|
||||
}
|
||||
DeleteDirectory(src);
|
||||
}
|
||||
|
||||
VFSPath MemoryFilesystem::ReadLink(VFSPath p)
|
||||
{
|
||||
mtx->Lock();
|
||||
VFSPath p2;
|
||||
auto symlink = dynamic_cast<MemorySymlink*>(GetEntry(p,false));
|
||||
if(symlink != nullptr)
|
||||
{
|
||||
p2 = symlink->linkedTo;
|
||||
}
|
||||
mtx->Unlock();
|
||||
return p2;
|
||||
}
|
||||
std::string MemoryFilesystem::VFSPathToSystem(VFSPath path)
|
||||
{
|
||||
return path.ToString();
|
||||
}
|
||||
VFSPath MemoryFilesystem::SystemToVFSPath(std::string path)
|
||||
{
|
||||
return path;
|
||||
}
|
||||
void MemoryFilesystem::GetDate(VFSPath path, time_t& lastWrite, time_t& lastAccess)
|
||||
{
|
||||
|
||||
mtx->Lock();
|
||||
auto node = GetEntry(path,false);
|
||||
auto dir = dynamic_cast<MemoryDirectory*>(node);
|
||||
|
||||
auto file = dynamic_cast<MemoryFile*>(node);
|
||||
|
||||
auto sym = dynamic_cast<MemorySymlink*>(node);
|
||||
|
||||
if(dir != nullptr) lastWrite = dir->lastWrite;
|
||||
if(file != nullptr) lastWrite = file->data->lastWrite;
|
||||
if(sym != nullptr) lastWrite = sym->lastWrite;
|
||||
mtx->Unlock();
|
||||
lastAccess = lastWrite;
|
||||
}
|
||||
void MemoryFilesystem::SetDate(VFSPath path, time_t lastWrite, time_t lastAccess)
|
||||
{
|
||||
mtx->Lock();
|
||||
auto node = GetEntry(path,false);
|
||||
auto dir = dynamic_cast<MemoryDirectory*>(node);
|
||||
|
||||
auto file = dynamic_cast<MemoryFile*>(node);
|
||||
|
||||
auto sym = dynamic_cast<MemorySymlink*>(node);
|
||||
|
||||
if(dir != nullptr) dir->lastWrite = lastWrite;
|
||||
if(file != nullptr) file->data->lastWrite = lastWrite;
|
||||
if(sym != nullptr) sym->lastWrite = lastWrite;
|
||||
mtx->Unlock();
|
||||
}
|
||||
MemoryFilesystem::~MemoryFilesystem()
|
||||
{
|
||||
|
||||
}
|
||||
MemoryFilesystem::MemoryFilesystem()
|
||||
{
|
||||
mtx = std::make_shared<Threading::Mutex>();
|
||||
}
|
||||
|
||||
MemoryEntry::~MemoryEntry()
|
||||
{
|
||||
|
||||
}
|
||||
MemoryFile::~MemoryFile()
|
||||
{
|
||||
|
||||
}
|
||||
MemoryDirectory::MemoryDirectory()
|
||||
{
|
||||
this->lastWrite = time(NULL);
|
||||
}
|
||||
MemoryDirectory::~MemoryDirectory()
|
||||
{
|
||||
for(auto item : this->entries) delete item;
|
||||
}
|
||||
MemoryFileData::MemoryFileData()
|
||||
{
|
||||
this->lastWrite = time(NULL);
|
||||
this->canAccess=true;
|
||||
this->readers=0;
|
||||
|
||||
}
|
||||
}
|
||||
@ -266,7 +266,9 @@ namespace Tesses::Framework::Filesystem
|
||||
std::vector<std::string> paths;
|
||||
if(this->path.empty()) return VFSPath();
|
||||
paths.insert(paths.begin(), this->path.begin(), this->path.end()-1);
|
||||
return VFSPath(paths);
|
||||
auto res= VFSPath(paths);
|
||||
res.relative = this->relative;
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string VFSPath::GetFileName()
|
||||
|
||||
@ -85,6 +85,16 @@ namespace Tesses::Framework::Http
|
||||
data->currentHeaders.Clear();
|
||||
return 0;
|
||||
}*/
|
||||
std::string ServerContext::GetUrlWithQuery()
|
||||
{
|
||||
if(this->queryParams.kvp.empty()) return this->path;
|
||||
return this->path + "?" + HttpUtils::QueryParamsEncode(this->queryParams);
|
||||
}
|
||||
std::string ServerContext::GetOriginalPathWithQuery()
|
||||
{
|
||||
if(this->queryParams.kvp.empty()) return this->originalPath;
|
||||
return this->originalPath + "?" + HttpUtils::QueryParamsEncode(this->queryParams);
|
||||
}
|
||||
bool ServerContext::NeedToParseFormData()
|
||||
{
|
||||
std::string ct;
|
||||
|
||||
@ -381,7 +381,7 @@ namespace Tesses::Framework::Http {
|
||||
s.push_back(item);
|
||||
else if(item >= '0' && item <= '9')
|
||||
s.push_back(item);
|
||||
else if(item == '-' || item == '_' || item == '.' || item == '~')
|
||||
else if(item == '-' || item == '_' || item == '.' || item == '~' || item == '/')
|
||||
s.push_back(item);
|
||||
else
|
||||
{
|
||||
|
||||
@ -57,16 +57,21 @@ namespace Tesses::Framework::Streams
|
||||
}
|
||||
bool FileStream::CanRead()
|
||||
{
|
||||
return this->canRead;
|
||||
return this->canRead && this->f;
|
||||
}
|
||||
bool FileStream::CanWrite()
|
||||
{
|
||||
return this->canWrite;
|
||||
return this->canWrite && this->f;
|
||||
}
|
||||
bool FileStream::CanSeek()
|
||||
{
|
||||
return this->canSeek;
|
||||
return this->canSeek && this->f;
|
||||
}
|
||||
bool FileStream::EndOfStream()
|
||||
{
|
||||
return feof(this->f);
|
||||
}
|
||||
|
||||
int64_t FileStream::GetPosition()
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
|
||||
@ -15,7 +15,7 @@ namespace Tesses::Framework::Streams
|
||||
{
|
||||
if(this->offset >= this->buffer.size()) return 0;
|
||||
size_t toRead = std::min(sz, this->buffer.size()-this->offset);
|
||||
memcpy(buff, this->buffer.data() + this->offset, sz);
|
||||
memcpy(buff, this->buffer.data() + this->offset, toRead);
|
||||
this->offset += toRead;
|
||||
return toRead;
|
||||
}
|
||||
|
||||
@ -232,6 +232,13 @@ namespace Tesses::Framework::Streams {
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
int on=1;
|
||||
#if defined(SO_REUSEPORT)
|
||||
NETWORK_SETSOCKOPT(this->sock,SOL_SOCKET,SO_REUSEPORT,(const char*)&on, (socklen_t)sizeof(on));
|
||||
#endif
|
||||
#if defined(SO_REUSEADDR)
|
||||
NETWORK_SETSOCKOPT(this->sock,SOL_SOCKET,SO_REUSEADDR,(const char*)&on, (socklen_t)sizeof(on));
|
||||
#endif
|
||||
if(NETWORK_BIND(this->sock, (const sockaddr*)&addr, (socklen_t)sizeof(addr)) != 0)
|
||||
{
|
||||
this->valid = false;
|
||||
@ -432,7 +439,13 @@ namespace Tesses::Framework::Streams {
|
||||
}
|
||||
|
||||
SetPort((struct sockaddr*)&addr, port);
|
||||
|
||||
int on=1;
|
||||
#if defined(SO_REUSEPORT)
|
||||
NETWORK_SETSOCKOPT(this->sock,SOL_SOCKET,SO_REUSEPORT,(const char*)&on, (socklen_t)sizeof(on));
|
||||
#endif
|
||||
#if defined(SO_REUSEADDR)
|
||||
NETWORK_SETSOCKOPT(this->sock,SOL_SOCKET,SO_REUSEADDR,(const char*)&on, (socklen_t)sizeof(on));
|
||||
#endif
|
||||
int r = NETWORK_BIND(this->sock, (struct sockaddr*)&addr, sizeof(addr));
|
||||
if(r != 0)
|
||||
{
|
||||
|
||||
@ -95,7 +95,7 @@ namespace Tesses::Framework::Streams {
|
||||
void Stream::CopyTo(Stream* strm, size_t buffSize)
|
||||
{
|
||||
if(strm != nullptr)
|
||||
strm->CopyTo(*strm, buffSize);
|
||||
this->CopyTo(*strm, buffSize);
|
||||
}
|
||||
void Stream::CopyTo(Stream& strm, size_t buffSize)
|
||||
{
|
||||
|
||||
69
src/Threading/ThreadPool.cpp
Normal file
69
src/Threading/ThreadPool.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
#include "TessesFramework/Threading/ThreadPool.hpp"
|
||||
#if !defined(GEKKO)
|
||||
#include <thread>
|
||||
#endif
|
||||
namespace Tesses::Framework::Threading
|
||||
{
|
||||
size_t ThreadPool::GetNumberOfCores()
|
||||
{
|
||||
#if defined(GEKKO)
|
||||
return 1;
|
||||
#else
|
||||
return (size_t)std::thread::hardware_concurrency();
|
||||
#endif
|
||||
}
|
||||
ThreadPool::ThreadPool(size_t threads)
|
||||
{
|
||||
this->isRunning=true;
|
||||
for(size_t i = 0; i < threads; i++)
|
||||
{
|
||||
this->threads.push_back(new Thread([this]()->void{
|
||||
while(true)
|
||||
{
|
||||
this->mtx.Lock();
|
||||
|
||||
if(!this->isRunning)
|
||||
{
|
||||
this->mtx.Unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
std::function<void()> fn=nullptr;
|
||||
|
||||
if(this->callbacks.empty())
|
||||
{
|
||||
fn=this->callbacks.front();
|
||||
this->callbacks.pop();
|
||||
}
|
||||
this->mtx.Unlock();
|
||||
if(fn)
|
||||
fn();
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
void ThreadPool::Schedule(std::function<void()> cb)
|
||||
{
|
||||
this->mtx.Lock();
|
||||
this->callbacks.push(cb);
|
||||
this->mtx.Unlock();
|
||||
}
|
||||
ThreadPool::~ThreadPool()
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
this->mtx.Lock();
|
||||
auto emp=this->callbacks.empty();
|
||||
if(emp) this->isRunning=false;
|
||||
this->mtx.Unlock();
|
||||
if(emp) break;
|
||||
}
|
||||
|
||||
for(auto item : this->threads)
|
||||
{
|
||||
item->Join();
|
||||
delete item;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
231
src/wrapper.cpp
Normal file
231
src/wrapper.cpp
Normal file
@ -0,0 +1,231 @@
|
||||
|
||||
#include "TessesFramework/TessesFramework.hpp"
|
||||
|
||||
#include "TessesFramework/TessesFramework.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace Tesses::Framework;
|
||||
using namespace Tesses::Framework::Streams;
|
||||
using namespace Tesses::Framework::Filesystem;
|
||||
using namespace Tesses::Framework::Threading;
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
string_t* string_create()
|
||||
{
|
||||
return static_cast<string_t*>(new std::string());
|
||||
}
|
||||
string_t* string_create_from_buff(const void* text, size_t len)
|
||||
{
|
||||
return static_cast<string_t*>(new std::string((const char*)text,len));
|
||||
}
|
||||
string_t* string_create_from_charpointer(const char* text)
|
||||
{
|
||||
return static_cast<string_t*>(new std::string(text));
|
||||
}
|
||||
string_t* string_resize(string_t* str, size_t len)
|
||||
{
|
||||
static_cast<std::string*>(str)->resize(len);
|
||||
return str;
|
||||
}
|
||||
string_t* string_set_char(string_t* str, size_t index, char c)
|
||||
{
|
||||
static_cast<std::string*>(str)->at(index) = c;
|
||||
return str;
|
||||
}
|
||||
char string_get_char(string_t* str,size_t index)
|
||||
{
|
||||
return static_cast<std::string*>(str)->at(index);
|
||||
}
|
||||
string_t* string_append_char(string_t* str, char c)
|
||||
{
|
||||
static_cast<std::string*>(str)->push_back(c);
|
||||
return str;
|
||||
}
|
||||
string_t* string_append_from_buff(string_t* str,const void* text, size_t len)
|
||||
{
|
||||
static_cast<std::string*>(str)->append((const char*)text,len);
|
||||
return str;
|
||||
}
|
||||
string_t* string_append_from_charpointer(string_t* str,const char* text)
|
||||
{
|
||||
static_cast<std::string*>(str)->append(text);
|
||||
return str;
|
||||
}
|
||||
string_t* string_append(string_t* str, string_t* toAppend)
|
||||
{
|
||||
if(str == NULL) return NULL;
|
||||
static_cast<std::string*>(str)->append(*static_cast<std::string*>(str));
|
||||
return str;
|
||||
}
|
||||
string_t* string_append_signed(string_t* str, int64_t num)
|
||||
{
|
||||
static_cast<std::string*>(str)->append(std::to_string(num));
|
||||
return str;
|
||||
}
|
||||
string_t* string_append_unsigned(string_t* str, uint64_t num)
|
||||
{
|
||||
static_cast<std::string*>(str)->append(std::to_string(num));
|
||||
return str;
|
||||
}
|
||||
string_t* string_append_double(string_t* str, double num)
|
||||
{
|
||||
static_cast<std::string*>(str)->append(std::to_string(num));
|
||||
return str;
|
||||
}
|
||||
void string_print(string_t* str)
|
||||
{
|
||||
std::cout << *static_cast<std::string*>(str);
|
||||
}
|
||||
void string_println(string_t* str)
|
||||
{
|
||||
std::cout << *static_cast<std::string*>(str) << std::endl;
|
||||
}
|
||||
size_t string_size(string_t* str)
|
||||
{
|
||||
return static_cast<std::string*>(str)->size();
|
||||
}
|
||||
const char* string_c_str(string_t* str)
|
||||
{
|
||||
return static_cast<std::string*>(str)->c_str();
|
||||
}
|
||||
void string_free(string_t* str)
|
||||
{
|
||||
delete static_cast<std::string*>(str);
|
||||
}
|
||||
|
||||
void tf_init()
|
||||
{
|
||||
TF_Init();
|
||||
}
|
||||
tf_thread_t* tf_create_thread(void* userData, tf_action_user_data_t cb)
|
||||
{
|
||||
Thread* thrd = new Thread([userData,cb]()->void{
|
||||
cb(userData);
|
||||
});
|
||||
return static_cast<tf_thread_t*>(thrd);
|
||||
}
|
||||
void tf_join_thread(tf_thread_t* thrd)
|
||||
{
|
||||
auto thrd2 = static_cast<Thread*>(thrd);
|
||||
if(thrd2 != nullptr)
|
||||
{
|
||||
thrd2->Join();
|
||||
delete thrd2;
|
||||
}
|
||||
}
|
||||
void tf_detach_thread(tf_thread_t* thrd)
|
||||
{
|
||||
auto thrd2 = static_cast<Thread*>(thrd);
|
||||
if(thrd2 != nullptr)
|
||||
{
|
||||
thrd2->Detach();
|
||||
delete thrd2;
|
||||
}
|
||||
}
|
||||
|
||||
tf_mutex_t* tf_mutex_create()
|
||||
{
|
||||
return static_cast<tf_mutex_t*>(new Mutex());
|
||||
}
|
||||
void tf_mutex_lock(tf_mutex_t* mtx)
|
||||
{
|
||||
static_cast<Mutex*>(mtx)->Lock();
|
||||
|
||||
}
|
||||
bool tf_mutex_trylock(tf_mutex_t* mtx)
|
||||
{
|
||||
return static_cast<Mutex*>(mtx)->TryLock();
|
||||
|
||||
}
|
||||
void tf_mutex_unlock(tf_mutex_t* mtx)
|
||||
{
|
||||
static_cast<Mutex*>(mtx)->Unlock();
|
||||
|
||||
}
|
||||
void tf_mutex_free(tf_mutex_t* mtx)
|
||||
{
|
||||
delete static_cast<Mutex*>(mtx);
|
||||
|
||||
}
|
||||
|
||||
bool tf_stream_canread(tf_stream_t* strm)
|
||||
{
|
||||
return static_cast<Stream*>(strm)->CanRead();
|
||||
}
|
||||
bool tf_stream_canwrite(tf_stream_t* strm)
|
||||
{
|
||||
return static_cast<Stream*>(strm)->CanWrite();
|
||||
}
|
||||
bool tf_stream_canseek(tf_stream_t* strm)
|
||||
{
|
||||
return static_cast<Stream*>(strm)->CanSeek();
|
||||
}
|
||||
bool tf_stream_eof(tf_stream_t* strm)
|
||||
{
|
||||
return static_cast<Stream*>(strm)->EndOfStream();
|
||||
}
|
||||
int64_t tf_stream_getlen(tf_stream_t* strm)
|
||||
{
|
||||
return static_cast<Stream*>(strm)->GetLength();
|
||||
}
|
||||
int64_t tf_stream_getpos(tf_stream_t* strm)
|
||||
{
|
||||
return static_cast<Stream*>(strm)->GetPosition();
|
||||
}
|
||||
void tf_stream_seek(tf_stream_t* strm, int64_t pos, TF_WHENCE whence)
|
||||
{
|
||||
static_cast<Stream*>(strm)->Seek(pos,whence == TF_SEEK_BEGIN ? SeekOrigin::Begin : whence == TF_SEEK_CURRENT ? SeekOrigin::Current : SeekOrigin::End);
|
||||
}
|
||||
size_t tf_stream_read(tf_stream_t* strm, uint8_t* buffer, size_t length)
|
||||
{
|
||||
return static_cast<Stream*>(strm)->Read(buffer,length);
|
||||
}
|
||||
size_t tf_stream_write(tf_stream_t* strm, const uint8_t* buffer, size_t length)
|
||||
{
|
||||
return static_cast<Stream*>(strm)->Write(buffer,length);
|
||||
}
|
||||
size_t tf_stream_readblock(tf_stream_t* strm, uint8_t* buffer, size_t length)
|
||||
{
|
||||
return static_cast<Stream*>(strm)->ReadBlock(buffer,length);
|
||||
}
|
||||
void tf_stream_writeblock(tf_stream_t* strm, const uint8_t* buffer, size_t length)
|
||||
{
|
||||
static_cast<Stream*>(strm)->WriteBlock(buffer,length);
|
||||
}
|
||||
void tf_stream_copyto(tf_stream_t* src, tf_stream_t* dest, size_t blockSize)
|
||||
{
|
||||
static_cast<Stream*>(src)->CopyTo(static_cast<Stream*>(dest),blockSize);
|
||||
}
|
||||
void tf_stream_close(tf_stream_t* strm)
|
||||
{
|
||||
delete static_cast<Stream*>(strm);
|
||||
}
|
||||
void tf_stream_flush(tf_stream_t* strm)
|
||||
{
|
||||
static_cast<Stream*>(strm)->Flush();
|
||||
}
|
||||
int32_t tf_stream_readbyte(tf_stream_t* strm)
|
||||
{
|
||||
return static_cast<Stream*>(strm)->ReadByte();
|
||||
}
|
||||
void tf_stream_writebyte(tf_stream_t* strm, uint8_t val)
|
||||
{
|
||||
static_cast<Stream*>(strm)->WriteByte(val);
|
||||
}
|
||||
|
||||
tf_stream_t* tf_stream_fopen(const char* file, const char* mode)
|
||||
{
|
||||
FILE* f = fopen(file,mode);
|
||||
if(f == NULL) return NULL;
|
||||
return static_cast<tf_stream_t*>(new FileStream(f,true,std::string(mode)));
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user