diff options
Diffstat (limited to 'source/libs/asura-lib-utils')
79 files changed, 5043 insertions, 0 deletions
diff --git a/source/libs/asura-lib-utils/exceptions/exception.cpp b/source/libs/asura-lib-utils/exceptions/exception.cpp new file mode 100644 index 0000000..dbb36ca --- /dev/null +++ b/source/libs/asura-lib-utils/exceptions/exception.cpp @@ -0,0 +1,47 @@ +#include "Exception.h" + +#include <cstdarg> +#include <iostream> + +namespace AsuraEngine +{ + + Exception::Exception(const char *fmt, ...) + { + va_list args; + int size_buffer = 256, size_out; + char *buffer; + while (true) + { + buffer = new char[size_buffer]; + memset(buffer, 0, size_buffer); + + va_start(args, fmt); + size_out = vsnprintf(buffer, size_buffer, fmt, args); + va_end(args); + + // see http://perfec.to/vsnprintf/pasprintf.c + // if size_out ... + // == -1 --> output was truncated + // == size_buffer --> output was truncated + // == size_buffer-1 --> ambiguous, /may/ have been truncated + // > size_buffer --> output was truncated, and size_out + // bytes would have been written + if (size_out == size_buffer || size_out == -1 || size_out == size_buffer - 1) + size_buffer *= 2; + else if (size_out > size_buffer) + size_buffer = size_out + 2; // to avoid the ambiguous case + else + break; + + delete[] buffer; + } + message = std::string(buffer); + delete[] buffer; + } + + Exception::~Exception() throw() + { + } + +} diff --git a/source/libs/asura-lib-utils/exceptions/exception.h b/source/libs/asura-lib-utils/exceptions/exception.h new file mode 100644 index 0000000..57c9ed6 --- /dev/null +++ b/source/libs/asura-lib-utils/exceptions/exception.h @@ -0,0 +1,44 @@ +#ifndef __ASURA_ENGINE_EXCEPTION_H__ +#define __ASURA_ENGINE_EXCEPTION_H__ + +#include <string> +#include <exception> + +namespace AsuraEngine +{ + + /** + * A convenient vararg-enabled exception class. + **/ + class Exception : public std::exception + { + public: + + /** + * Creates a new Exception according to printf-rules. + * + * See: http://www.cplusplus.com/reference/clibrary/cstdio/printf/ + * + * @param fmt The format string (see printf). + **/ + Exception(const char *fmt, ...); + virtual ~Exception() throw(); + + /** + * Returns a string containing reason for the exception. + * @return A description of the exception. + **/ + inline virtual const char *what() const throw() + { + return message.c_str(); + } + + private: + + std::string message; + + }; // Exception + +} + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/io/binding/_compressor.cpp b/source/libs/asura-lib-utils/io/binding/_compressor.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/source/libs/asura-lib-utils/io/binding/_compressor.cpp diff --git a/source/libs/asura-lib-utils/io/binding/_data_buffer.cpp b/source/libs/asura-lib-utils/io/binding/_data_buffer.cpp new file mode 100644 index 0000000..cd73b31 --- /dev/null +++ b/source/libs/asura-lib-utils/io/binding/_data_buffer.cpp @@ -0,0 +1,123 @@ +#include "../data_buffer.h" + +using namespace Luax; + +namespace AsuraEngine +{ + namespace IO + { + + LUAX_REGISTRY(DataBuffer) + { + LUAX_REGISTER_METHODS(state, + { "New", _New }, + { "GetData", _GetData }, + { "GetSize", _GetSize }, + { "Refactor", _Refactor }, + { "Load", _Load }, + { "Clear", _Clear } + ); + } + + LUAX_POSTPROCESS(DataBuffer) + { + } + + // databuffer = DataBuffer.New(lstring) + // databuffer = DataBuffer.New(size) + LUAX_IMPL_METHOD(DataBuffer, _New) + { + LUAX_STATE(L); + + if (state.IsType(1, LUA_TSTRING)) + { + size_t size; + const byte* bytes = lua_tolstring(L, 1, &size); + DataBuffer* buffer = new DataBuffer(bytes, size); + buffer->PushLuaxUserdata(state); + return 1; + } + else if (state.IsType(1, LUA_TNUMBER)) + { + size_t size = lua_tonumber(L, 1); + DataBuffer* buffer = new DataBuffer(size); + buffer->PushLuaxUserdata(state); + return 1; + } + else + { + return state.ErrorType(1, "number or string"); + } + } + + // lsting, len = databuffer:GetData() + LUAX_IMPL_METHOD(DataBuffer, _GetData) + { + LUAX_SETUP(L, "U"); + + DataBuffer* self = state.GetUserdata<DataBuffer>(1); + lua_pushlstring(L, self->GetData(), self->GetSize()); + return 1; + } + + // length = databuffer:GetSize() + LUAX_IMPL_METHOD(DataBuffer, _GetSize) + { + LUAX_SETUP(L, "U"); + + DataBuffer* self = state.GetUserdata<DataBuffer>(1); + lua_pushinteger(L, self->GetSize()); + return 1; + } + + // databuffer:Refactor(size) + LUAX_IMPL_METHOD(DataBuffer, _Refactor) + { + LUAX_PREPARE(L, DataBuffer); + + size_t size = state.CheckValue<int>(2); + self->Refactor(size); + return 0; + } + + // size = databuffer:Load(lstring) + // size = databuffer:Load(src) + LUAX_IMPL_METHOD(DataBuffer, _Load) + { + LUAX_STATE(L); + + DataBuffer* buffer = state.GetUserdata<DataBuffer>(1); + const byte* data; + size_t size; + if (state.IsType(2, LUA_TSTRING)) + { + data = lua_tolstring(L, 2, &size); + size_t len = buffer->Load(data, size); + state.Push(len); + return 1; + } + else if(state.IsType(2, LUA_TUSERDATA)) + { + DataBuffer* src = state.CheckUserdata<DataBuffer>(2); + size_t len = buffer->Load(*src); + state.Push(len); + return 1; + } + else + { + return state.ErrorType(1, "lstring or DataBuffer"); + } + } + + // databuffer:Clear() + LUAX_IMPL_METHOD(DataBuffer, _Clear) + { + LUAX_SETUP(L, "U"); + + DataBuffer* self = state.GetUserdata<DataBuffer>(1); + self->Clear(); + return 0; + } + + } +}
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/io/binding/_file.cpp b/source/libs/asura-lib-utils/io/binding/_file.cpp new file mode 100644 index 0000000..c44bc90 --- /dev/null +++ b/source/libs/asura-lib-utils/io/binding/_file.cpp @@ -0,0 +1,223 @@ +#include "../file.h" + +namespace AsuraEngine +{ + namespace IO + { + + LUAX_REGISTRY(File) + { + LUAX_REGISTER_METHODS(state, + { "New", _New }, + { "Open", _Open }, + { "Close", _Close }, + { "IsOpen", _IsOpen }, + { "GetMode", _GetMode }, + { "GetSize", _GetSize }, + { "Read", _Read }, + { "IsEOF", _IsEOF }, + { "Write", _Write }, + { "Flush", _Flush }, + { "Tell", _Tell }, + { "Seek", _Seek }, + { "SetBuffer", _SetBuffer }, + { "GetBuffer", _GetBuffer }, + { "GetFileName", _GetFileName }, + { "GetExtension", _GetExtension }, + { "GetName", _GetName } + ); + } + + LUAX_POSTPROCESS(File) + { + LUAX_REGISTER_ENUM(state, "EFileMode", + { "CLOSED", FILE_MODE_CLOSED }, + { "READ", FILE_MODE_READ }, + { "WRITE", FILE_MODE_WRITE }, + { "APPEND", FILE_MODE_APPEND } + ); + + LUAX_REGISTER_ENUM(state, "EBufferMode", + { "NONE", BUFFER_MODE_NONE}, + { "LINE", BUFFER_MODE_LINE}, + { "FULL", BUFFER_MODE_FULL} + ); + } + + // file = File.New(name) + LUAX_IMPL_METHOD(File, _New) + { + LUAX_STATE(L); + + cc8* name = state.CheckValue<cc8*>(1); + File* file = new File(name); + file->PushLuaxUserdata(state); + return 1; + } + + // successsed = file:Open(mode) + LUAX_IMPL_METHOD(File, _Open) + { + LUAX_PREPARE(L, File); + + File::FileMode mode = (File::FileMode)state.CheckValue<int>(2); + state.Push(self->Open(mode)); + return 1; + } + + // successed = file:Close() + LUAX_IMPL_METHOD(File, _Close) + { + LUAX_PREPARE(L, File); + + state.Push(self->Close()); + return 1; + } + + // opened = file:IsOpen() + LUAX_IMPL_METHOD(File, _IsOpen) + { + LUAX_PREPARE(L, File); + + state.Push(self->IsOpen()); + return 1; + } + + // mode = file:GetMode() + LUAX_IMPL_METHOD(File, _GetMode) + { + LUAX_PREPARE(L, File); + + File::FileMode mode = self->GetMode(); + state.Push((int)mode); + return 1; + } + + // size = file:GetSize() + LUAX_IMPL_METHOD(File, _GetSize) + { + LUAX_PREPARE(L, File); + + state.Push(self->GetSize()); + return 1; + } + + // size = file:Read(dst, len) + // returns: + // size ʵʶĴС + // params: + // self ļ + // dst Ŀ껺 + // len ĴС + LUAX_IMPL_METHOD(File, _Read) + { + LUAX_PREPARE(L, File); + + DataBuffer* db = state.CheckUserdata<DataBuffer>(2); + if (!db) return state.ErrorType(2, "DataBuffer"); + int len = state.CheckValue<int>(3); + int size = self->Read(db, len); + state.Push(size); + return 1; + } + + // isEOF = file:IsEOF() + LUAX_IMPL_METHOD(File, _IsEOF) + { + LUAX_PREPARE(L, File); + + state.Push(self->IsEOF()); + return 1; + } + + // isWrite = file:Write(data buffer[, size]) + LUAX_IMPL_METHOD(File, _Write) + { + LUAX_PREPARE(L, File); + + DataBuffer* db = state.CheckUserdata<DataBuffer>(2); + if (!db) return state.ErrorType(2, "DataBuffer"); + state.Push(self->Write(db)); + return 1; + } + + // isFlushed = file:Flush() + LUAX_IMPL_METHOD(File, _Flush) + { + LUAX_PREPARE(L, File); + + state.Push(self->Flush()); + return 1; + } + + // pos = file:Tell() + LUAX_IMPL_METHOD(File, _Tell) + { + LUAX_PREPARE(L, File); + + state.Push(self->Tell()); + return 1; + } + + // isSeek = file:Seek(pos) + LUAX_IMPL_METHOD(File, _Seek) + { + LUAX_PREPARE(L, File); + + int pos = state.CheckValue<int>(2); + state.Push(self->Seek(pos)); + return 1; + } + + // isSetted = file:SetBuffer(mode, size) + LUAX_IMPL_METHOD(File, _SetBuffer) + { + LUAX_PREPARE(L, File); + + BufferMode mode = (BufferMode)state.CheckValue<int>(2); + int size = state.CheckValue<int>(3); + state.Push(self->SetBuffer(mode, size)); + return 1; + } + + // size, mode = file:GetBuffer() + LUAX_IMPL_METHOD(File, _GetBuffer) + { + LUAX_PREPARE(L, File); + + size_t size = 0; + BufferMode mode = self->GetBuffer(ASURA_OUT size); + state.Push((int)size); + state.Push((int)mode); + return 2; + } + + // name = file:GetFileName() + LUAX_IMPL_METHOD(File, _GetFileName) + { + LUAX_PREPARE(L, File); + + state.Push(self->GetFileName()); + return 1; + } + + // name = file:GetExtension() + LUAX_IMPL_METHOD(File, _GetExtension) + { + LUAX_PREPARE(L, File); + + state.Push(self->GetExtension()); + return 1; + } + + // name = file:GetName() + LUAX_IMPL_METHOD(File, _GetName) + { + LUAX_PREPARE(L, File); + + state.Push(self->GetName()); + return 1; + } + + } +}
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/io/binding/_file_data.cpp b/source/libs/asura-lib-utils/io/binding/_file_data.cpp new file mode 100644 index 0000000..09a0643 --- /dev/null +++ b/source/libs/asura-lib-utils/io/binding/_file_data.cpp @@ -0,0 +1,60 @@ +#include "../file_data.h" + +using namespace std; + +namespace AsuraEngine +{ + namespace IO + { + + LUAX_REGISTRY(FileData) + { + LUAX_REGISTER_METHODS(state, + { "GetFileName", _GetFileName }, + { "GetExtension", _GetExtension }, + { "GetName", _GetName }, + { "GetDataBuffer", _GetDataBuffer } + ); + } + + LUAX_POSTPROCESS(FileData) + { + } + + // filename = filedata:GetFileName() + LUAX_IMPL_METHOD(FileData, _GetFileName) + { + LUAX_PREPARE(L, FileData); + string filename = self->GetFileName(); + state.Push(filename); + return 1; + } + + // extension = filedata:GetExtension() + LUAX_IMPL_METHOD(FileData, _GetExtension) + { + LUAX_PREPARE(L, FileData); + string extension = self->GetExtension(); + state.Push(extension); + return 1; + } + + // name = filedata:GetName() + LUAX_IMPL_METHOD(FileData, _GetName) + { + LUAX_PREPARE(L, FileData); + string extension = self->GetName(); + state.Push(extension); + return 1; + } + + // databuffer = filedata:GetDataBuffer() + LUAX_IMPL_METHOD(FileData, _GetDataBuffer) + { + LUAX_PREPARE(L, FileData); + self->PushLuaxMemberRef(state, self->mDataRef); + return 1; + } + + } +}
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/io/binding/_file_system.cpp b/source/libs/asura-lib-utils/io/binding/_file_system.cpp new file mode 100644 index 0000000..3843451 --- /dev/null +++ b/source/libs/asura-lib-utils/io/binding/_file_system.cpp @@ -0,0 +1,265 @@ +#include "../file_system.h" + +using namespace Luax; + +namespace AsuraEngine +{ + namespace IO + { + +#define PREPARE(l) \ + LUAX_STATE(l); \ + Filesystem* fs = Filesystem::Get(); + + LUAX_REGISTRY(Filesystem) + { + LUAX_REGISTER_METHODS(state, + { "Init", _Init }, + { "Mount", _Mount }, + { "Unmount", _Unmount }, + { "GetMountPoint", _GetMountPoint }, + { "SetWriteDirectory", _SetWriteDirectory }, + { "GetWriteDirectory", _GetWriteDirectory }, + { "CreateFile", _CreateFile }, + { "CreateDirectory", _CreateDirectory }, + { "Write", _Write }, + { "Append", _Append }, + { "Remove", _Remove }, + { "Read", _Read }, + { "GetFileInfo", _GetFileInfo }, + { "GetDirectoryItems", _GetDirectoryItems } + ); + } + + LUAX_POSTPROCESS(Filesystem) + { + LUAX_REGISTER_ENUM(state, "EFileType", + { "FILE", FILE_TYPE_FILE }, + { "DIRECTORY", FILE_TYPE_DIRECTORY }, + { "SYMLINK", FILE_TYPE_SYMLINK }, + { "OTHER", FILE_TYPE_OTHER } + ); + } + + // Filesystem.Init(arg0) + LUAX_IMPL_METHOD(Filesystem, _Init) + { + PREPARE(L); + + const char* arg0 = state.CheckValue<const char*>(1); + fs->Init(arg0); + return 0; + } + + // successed = Filesystem.Mount(path, mountpoint[, prepend = false]) + // successed = Filesystem.Mount(data buffer, archievename, mountpoint[, prepend = false]) + LUAX_IMPL_METHOD(Filesystem, _Mount) + { + PREPARE(L); + bool mounted = false; + + if (state.IsType(1, LUA_TSTRING)) + { + cc8* path = state.GetValue<cc8*>(1, ""); + cc8* moutpoint = state.GetValue<cc8*>(2, "/"); + bool prepend = state.GetValue<bool>(3, false); + mounted = fs->Mount(path, moutpoint, prepend); + } + else if (state.IsType(1, LUA_TUSERDATA)) + { + DataBuffer* db = state.CheckUserdata<DataBuffer>(1); + if (!db) + return state.ErrorType(1, "Data Buffer"); + cc8* arcname = state.GetValue<cc8*>(2, ""); + cc8* mountpoint = state.GetValue<cc8*>(3, "/"); + bool prepend = state.GetValue<bool>(4, false); + mounted = fs->Mount(db, arcname, mountpoint, prepend); + // retain + fs->LuaxRetain<DataBuffer>(state, db); + } + state.Push(mounted); + return 1; + } + + // successed = Filesystem.Unmount(path) + // successed = Filesystem.Unmount(data buffer) + LUAX_IMPL_METHOD(Filesystem, _Unmount) + { + PREPARE(L); + bool unmounted = false; + + if (state.IsType(1, LUA_TSTRING)) + { + cc8* path = state.GetValue<cc8*>(1, ""); + unmounted = fs->Unmount(path); + } + else if (state.IsType(1, LUA_TUSERDATA)) + { + DataBuffer* db = state.CheckUserdata<DataBuffer>(1); + if (!db) + return state.ErrorType(1, "Data Buffer"); + unmounted = fs->Unmount(db); + if (unmounted) + fs->LuaxRelease<DataBuffer>(state, db); + } + state.Push(unmounted); + return 1; + } + + // moutpoint = Filesystem.GetMountPoint(path) + LUAX_IMPL_METHOD(Filesystem, _GetMountPoint) + { + PREPARE(L); + + cc8* path = state.CheckValue<cc8*>(1); + std::string mp; + if (fs->GetMountPoint(path, ASURA_OUT mp)) + state.Push(mp); + else + state.PushNil(); + + return 1; + } + + // Filesystem.SetWriteDirectory(dir) + LUAX_IMPL_METHOD(Filesystem, _SetWriteDirectory) + { + PREPARE(L); + + cc8* dir = state.CheckValue<cc8*>(1); + fs->SetWriteDirectory(dir); + return 0; + } + + // dir = Filesystem.GetWriteDirectory() + LUAX_IMPL_METHOD(Filesystem, _GetWriteDirectory) + { + PREPARE(L); + + std::string dir = fs->GetWriteDirectory(); + state.Push(dir); + return 1; + } + + // file = Filesystem.CreateFile(name) + LUAX_IMPL_METHOD(Filesystem, _CreateFile) + { + PREPARE(L); + + cc8* name = state.CheckValue<cc8*>(1); + File* file = fs->NewFile(name); + if (file) + file->PushLuaxUserdata(state); + else + state.PushNil(); + return 1; + } + + // successed = Filesystem.CreateDirectory(name) + LUAX_IMPL_METHOD(Filesystem, _CreateDirectory) + { + PREPARE(L); + + cc8* path = state.CheckValue<cc8*>(1); + state.Push(fs->NewDirectory(path)); + return 1; + } + + // successed = Filesystem.Write(path, data buffer) + LUAX_IMPL_METHOD(Filesystem, _Write) + { + PREPARE(L); + + cc8* path = state.CheckValue<cc8*>(1); + DataBuffer* db = state.CheckUserdata<DataBuffer>(2); + state.Push(fs->Write(path, db)); + return 1; + } + + // successed = Filesystem.Append(path, data buffer) + LUAX_IMPL_METHOD(Filesystem, _Append) + { + PREPARE(L); + + cc8* path = state.CheckValue<cc8*>(1); + DataBuffer* db = state.CheckUserdata<DataBuffer>(2); + state.Push(fs->Append(path, db)); + return 1; + } + + // successed = Filesystem.Remove(path) + LUAX_IMPL_METHOD(Filesystem, _Remove) + { + PREPARE(L); + + cc8* path = state.CheckValue<cc8*>(1); + state.Push(fs->Remove(path)); + return 1; + } + + // filedata = Filesystem.Read(path) + LUAX_IMPL_METHOD(Filesystem, _Read) + { + PREPARE(L); + + cc8* path = state.CheckValue<cc8*>(1); + FileData* fd = fs->Read(path); + if (fd) + { + fd->mData->PushLuaxUserdata(state); + fd->SetLuaxMemberRef(state, fd->mDataRef, -1); // fd->mDataRef = data buffer + state.Pop(1); // data buffer + fd->PushLuaxUserdata(state); + } + else + { + state.PushNil(); + } + return 1; + } + + // fileinfo = Filesystem.GetFileInfo(path) + LUAX_IMPL_METHOD(Filesystem, _GetFileInfo) + { + PREPARE(L); + + cc8* path = state.CheckValue<cc8*>(1); + FileInfo info; + if (fs->GetFileInfo(path, &info)) + { + lua_newtable(L); // info table + state.SetField(-1, "size", info.size); + state.SetField(-1, "modtime", info.modtime); + state.SetField(-1, "type", info.type); + } + else + { + state.PushNil(); + } + return 1; + } + + // items = Filesystem.GetDirectoryItems(path) + LUAX_IMPL_METHOD(Filesystem, _GetDirectoryItems) + { + PREPARE(L); + + cc8* path = state.CheckValue<cc8*>(1); + std::vector<std::string> items; + if(fs->GetDirectoryItems(path, ASURA_OUT items)) + { + lua_newtable(L); // item list + for (int i = 0; i < items.size(); ++i) + { + state.SetFieldByIndex(-1, i + 1, items[i]); + } + } + else + { + state.PushNil(); + } + return 1; + } + + } +}
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/io/binding/_io_task.cpp b/source/libs/asura-lib-utils/io/binding/_io_task.cpp new file mode 100644 index 0000000..b3c5988 --- /dev/null +++ b/source/libs/asura-lib-utils/io/binding/_io_task.cpp @@ -0,0 +1,46 @@ +#include "../io_task.h" + +using namespace std; + +namespace AsuraEngine +{ + namespace IO + { + + LUAX_REGISTRY(IOTask) + { + LUAX_REGISTER_METHODS(state, + { "New", _New } + ); + } + + LUAX_POSTPROCESS(IOTask) + { + LUAX_REGISTER_ENUM(state, "EIOTaskType", + { "READ", IOTASK_TYPE_READ }, + { "WRITE", IOTASK_TYPE_WRITE }, + { "APPEND", IOTASK_TYPE_APPEND } + ); + + } + + // task = IOTask.New(path, buffer, type, callback) + LUAX_IMPL_METHOD(IOTask, _New) + { + LUAX_STATE(L); + + cc8* path = state.CheckValue<cc8*>(1); + DataBuffer* db = state.CheckUserdata<DataBuffer>(2); + IOTaskType type = (IOTaskType)state.CheckValue<int>(3); + bool cbk = state.GetTop() >= 4 && state.IsType(4, LUA_TFUNCTION); + + IOTask* task = new IOTask(path, db, type); + task->SetLuaxMemberRef(state, task->mBufferRef, 2); + if(cbk) + task->SetLuaxMemberRef(state, task->mCallback, 4); + task->PushLuaxUserdata(state); + return 1; + } + + } +} diff --git a/source/libs/asura-lib-utils/io/compressor.cpp b/source/libs/asura-lib-utils/io/compressor.cpp new file mode 100644 index 0000000..095eff4 --- /dev/null +++ b/source/libs/asura-lib-utils/io/compressor.cpp @@ -0,0 +1,11 @@ +#include "compressor.h" + +namespace AsuraEngine +{ + namespace IO + { + + + + } +}
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/io/compressor.h b/source/libs/asura-lib-utils/io/compressor.h new file mode 100644 index 0000000..30a074c --- /dev/null +++ b/source/libs/asura-lib-utils/io/compressor.h @@ -0,0 +1,30 @@ +#ifndef __ASURA_COMPRESSOR_H__ +#define __ASURA_COMPRESSOR_H__ + +#include "../scripting/portable.hpp" + +namespace AsuraEngine +{ + namespace IO + { + + class Compressor ASURA_FINAL + : public AEScripting::Portable<Compressor> + { + public: + + LUAX_DECL_SINGLETON(Compressor); + + private: + + LUAX_DECL_METHOD(_Compress); + LUAX_DECL_METHOD(_Decompress); + + + + }; + + } +} + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/io/data_buffer.cpp b/source/libs/asura-lib-utils/io/data_buffer.cpp new file mode 100644 index 0000000..5049b38 --- /dev/null +++ b/source/libs/asura-lib-utils/io/data_buffer.cpp @@ -0,0 +1,102 @@ +#include <cstdlib> +#include <cstring> +#include "data_buffer.h" + +using namespace AEThreading; + +namespace AsuraEngine +{ + namespace IO + { + + DataBuffer::DataBuffer(DataBuffer& src) + { + Load(src); + } + + DataBuffer::DataBuffer(std::size_t size) + : mSize(size) + , mBytes(nullptr) + { + lock(mMutex); + mBytes = new byte[size]; + memset(mBytes, 0, size); + } + + DataBuffer::DataBuffer(const void* data, std::size_t size) + : mSize(size) + , mBytes(nullptr) + { + Load(data, size); + } + + DataBuffer::~DataBuffer() + { + delete[] mBytes; + } + + void DataBuffer::Refactor(size_t size) + { + lock(mMutex); + if (!mBytes || mSize != size) + { + delete[] mBytes; + mBytes = new byte[size]; + mSize = size; + } + memset(mBytes, 0, size * sizeof(byte)); + } + + size_t DataBuffer::Load(DataBuffer& db) + { + return Load(db.GetData(), db.GetSize()); + } + + size_t DataBuffer::Load(const void* data, std::size_t size) + { + lock(mMutex); + size_t len = mSize > size ? size : mSize; + memcpy(mBytes, data, len); + return len; + } + + void DataBuffer::Move(void* bytes, std::size_t size) + { + lock(mMutex); + if (!mBytes) + { + delete[] mBytes; + } + mBytes = (byte*)bytes; + mSize = size; + } + + byte* DataBuffer::GetData() + { + return mBytes; + } + + void DataBuffer::Clear() + { + lock(mMutex); + if (mBytes) + memset(mBytes, 0, mSize); + } + + std::size_t DataBuffer::GetSize() + { + return mSize; + } + + void DataBuffer::Lock() + { + mMutex.Lock(); + } + + void DataBuffer::Unlock() + { + mMutex.Unlock(); + } + + } +}
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/io/data_buffer.h b/source/libs/asura-lib-utils/io/data_buffer.h new file mode 100644 index 0000000..445bdf4 --- /dev/null +++ b/source/libs/asura-lib-utils/io/data_buffer.h @@ -0,0 +1,62 @@ +#ifndef __ASURA_ENGINE_DATABUFFER_H__ +#define __ASURA_ENGINE_DATABUFFER_H__ + +#include <cstdlib> + +#include "../scripting/portable.hpp" +#include "../threading/mutex.h" + +namespace AsuraEngine +{ + namespace IO + { + + /// + /// ڴݵķװеʹData bufferװֱʹconst void*ͨresource managerȡ + /// + class DataBuffer ASURA_FINAL + : public AEScripting::Portable<DataBuffer> + { + public: + + LUAX_DECL_FACTORY(DataBuffer); + + DataBuffer(DataBuffer& src); + DataBuffer(std::size_t size); + DataBuffer(const void* bytes, std::size_t size); + ~DataBuffer(); + + byte* GetData(); + size_t GetSize(); + + void Refactor(size_t size); + size_t Load(DataBuffer& db); + size_t Load(const void* bytes, std::size_t size); + void Move(void* bytes, std::size_t size); + void Clear(); + + void Lock(); + void Unlock(); + + private: + + byte* mBytes; + size_t mSize; + + AEThreading::Mutex mMutex; + + LUAX_DECL_METHOD(_New); + LUAX_DECL_METHOD(_GetData); + LUAX_DECL_METHOD(_GetSize); + LUAX_DECL_METHOD(_Refactor); + LUAX_DECL_METHOD(_Load); + LUAX_DECL_METHOD(_Clear); + + }; + + } +} + +namespace AEIO = AsuraEngine::IO; + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/io/decoded_data.cpp b/source/libs/asura-lib-utils/io/decoded_data.cpp new file mode 100644 index 0000000..358a7a5 --- /dev/null +++ b/source/libs/asura-lib-utils/io/decoded_data.cpp @@ -0,0 +1,21 @@ +#include "../exceptions/exception.h" + +#include "decoded_data.h" + +namespace AsuraEngine +{ + namespace IO + { + + DecodedData::DecodedData(const DataBuffer& databuffer) + { + Decode(databuffer); + } + + DecodedData::~DecodedData() + { + + } + + } +} diff --git a/source/libs/asura-lib-utils/io/decoded_data.h b/source/libs/asura-lib-utils/io/decoded_data.h new file mode 100644 index 0000000..e201e91 --- /dev/null +++ b/source/libs/asura-lib-utils/io/decoded_data.h @@ -0,0 +1,42 @@ +#ifndef __ASURA_ENGINE_DATA_H__ +#define __ASURA_ENGINE_DATA_H__ + +#include <cstdlib> + +#include "../scripting/portable.hpp" + +#include "data_buffer.h" + +namespace AsuraEngine +{ + namespace IO + { + + /// + /// һ̹߳data̳дࡣͼƬݡƵݵȣһ߳нԭļڲݸʽ + /// ȡ + /// + ASURA_ABSTRACT class DecodedData + { + public: + + /// + /// ڴйdataԷһ߳棬Դϵͳء + /// + DecodedData(const DataBuffer& databuffer); + + virtual ~DecodedData(); + + protected: + + /// + /// ڴеݡ + /// + virtual void Decode(const DataBuffer& buffer) = 0; + + }; + + } +} + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/io/file.cpp b/source/libs/asura-lib-utils/io/file.cpp new file mode 100644 index 0000000..0ff8c90 --- /dev/null +++ b/source/libs/asura-lib-utils/io/file.cpp @@ -0,0 +1,292 @@ +#include <physfs/physfs.h> + +#include <asura-lib-utils/exceptions/exception.h> + +#include "file.h" + +namespace AsuraEngine +{ + namespace IO + { + + File::File(const std::string& filename) + : mFileName(filename) + , mFileHandle(nullptr) + , mMode(FILE_MODE_CLOSED) + , mBufferMode(BUFFER_MODE_NONE) + , mBufferSize(0) + { + size_t dot = filename.rfind('.'); + if (dot != std::string::npos) + { + mExtension = filename.substr(dot + 1); + mName = filename.substr(0, dot); + } + else + mName = filename; + } + + File::~File() + { + if (mMode != FILE_MODE_CLOSED) + Close(); + } + + bool File::Open(FileMode mode) + { + if (!PHYSFS_isInit()) + throw Exception("Physfs is NOT initialized."); + + if (mode == FILE_MODE_CLOSED) + return false; + + if (mode == FILE_MODE_READ && !PHYSFS_exists(mFileName.c_str())) + throw Exception("Could NOT open file %s. Does not exist.", mFileName.c_str()); + + if (mode == FILE_MODE_APPEND || mode == FILE_MODE_WRITE) + { + if (!PHYSFS_getWriteDir()) + { + throw Exception("Could NOT set write directory."); + } + } + + // Ѿ֮ǰͲٴµhandle + if (mFileHandle != nullptr) + return true; + + PHYSFS_getLastErrorCode(); + + PHYSFS_File* handle = nullptr; + + switch (mode) + { + case FILE_MODE_READ: + handle = PHYSFS_openRead(mFileName.c_str()); + break; + case FILE_MODE_APPEND: + handle = PHYSFS_openAppend(mFileName.c_str()); + break; + case FILE_MODE_WRITE: + handle = PHYSFS_openWrite(mFileName.c_str()); + break; + } + + if (handle == nullptr) + { + const char *err = PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()); + if (err == nullptr) + err = "unknown error"; + throw Exception("Could not open file %s (%s)", mFileName.c_str(), err); + } + + mFileHandle = handle; + mMode = mode; + + if (mFileHandle && !SetBuffer(mBufferMode,mBufferSize)) + { + mBufferMode = BUFFER_MODE_NONE; + mBufferSize = 0; + } + + return mFileHandle != nullptr; + } + + bool File::Close() + { + if (mFileHandle == nullptr || !PHYSFS_close(mFileHandle)) + return false; + mMode = FILE_MODE_CLOSED; + mFileHandle = nullptr; + return true; + } + + bool File::IsOpen() + { + return mMode != FILE_MODE_CLOSED && mFileHandle != nullptr; + } + + size_t File::GetSize() + { + if (mFileHandle == nullptr) + { + Open(FILE_MODE_READ); + size_t size = PHYSFS_fileLength(mFileHandle); + Close(); + return size; + } + return PHYSFS_fileLength(mFileHandle); + } + + size_t File::Read(ASURA_OUT DataBuffer* dst, size_t length) + { + ASSERT(dst); + + if (dst->GetSize() < length) + throw Exception("Data buffer is too small compares to read length."); + + if (!mFileHandle || mMode != FILE_MODE_READ) + throw Exception("File \"%s\" is not opened for reading", mFileName); + + size_t max = PHYSFS_fileLength(mFileHandle); + length = (length > max) ? max : length; + + if (length < 0) + throw Exception("Invalid read size."); + + dst->Lock(); + size_t size = PHYSFS_readBytes(mFileHandle, dst->GetData(), length); + dst->Unlock(); + return size; + } + + size_t File::ReadAll(ASURA_OUT DataBuffer* dst) + { + ASSERT(dst); + + if (!mFileHandle || mMode != FILE_MODE_READ) + throw Exception("File \"%s\" is not opened for reading", mFileName); + + size_t length = PHYSFS_fileLength(mFileHandle); + + if (dst->GetSize() < length) + throw Exception("Data buffer is too small compares to file length."); + + dst->Lock(); + size_t size = PHYSFS_readBytes(mFileHandle, dst->GetData(), length); + dst->Unlock(); + return size; + } + +#ifdef ASURA_WINDOWS + inline bool test_eof(File *that, PHYSFS_File *) + { + int64 pos = that->Tell(); + int64 size = that->GetSize(); + return pos == -1 || size == -1 || pos >= size; + } +#else + inline bool test_eof(File *, PHYSFS_File *file) + { + return PHYSFS_eof(file); + } +#endif + + bool File::IsEOF() + { + return mFileHandle == nullptr || test_eof(this, mFileHandle); + } + + size_t File::Tell() + { + if (!mFileHandle) + return - 1; + + return PHYSFS_tell(mFileHandle); + } + + bool File::Seek(size_t pos) + { + return mFileHandle != nullptr && PHYSFS_seek(mFileHandle, pos) != 0; + } + + bool File::Write(ASURA_REF DataBuffer* src) + { + if (!mFileHandle || (mMode != FILE_MODE_APPEND && mMode != FILE_MODE_WRITE)) + throw Exception("File is not opened for writing."); + + byte* data = src->GetData(); + int size = src->GetSize(); + + if (size < 0) + throw Exception("Invalid write size."); + + size_t written = PHYSFS_writeBytes(mFileHandle, data, size); + + if (written != src->GetSize()) + return false; + + // л + if (mBufferSize == BUFFER_MODE_LINE && mBufferSize > size) + { + if (memchr(data, '\n', size) != nullptr) + Flush(); + } + + return true; + } + + bool File::Flush() + { + if (!mFileHandle || (mMode != FILE_MODE_WRITE && mMode != FILE_MODE_APPEND)) + throw Exception("File is not opened for writing."); + + return PHYSFS_flush(mFileHandle) != 0; + } + + bool File::SetBuffer(BufferMode mode, size_t size) + { + if (size < 0) + return false; + + // If the file isn't open, we'll make sure the buffer values are set in + // File::open. + if (!IsOpen()) + { + mBufferMode = mode; + mBufferSize = size; + return true; + } + + int ret = 1; + + switch (mode) + { + case BUFFER_MODE_NONE: + default: + ret = PHYSFS_setBuffer(mFileHandle, 0); + size = 0; + break; + case BUFFER_MODE_LINE: + case BUFFER_MODE_FULL: + ret = PHYSFS_setBuffer(mFileHandle, size); + break; + } + + if (ret == 0) + return false; + + mBufferMode = mode; + mBufferSize = size; + + return true; + } + + File::BufferMode File::GetBuffer(ASURA_OUT size_t& size) + { + size = mBufferSize; + return mBufferMode; + } + + const std::string& File::GetFileName() + { + return mFileName; + } + + const std::string& File::GetName() + { + return mName; + } + + const std::string& File::GetExtension() + { + return mExtension; + } + + File::FileMode File::GetMode() + { + return mMode; + } + + } +}
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/io/file.h b/source/libs/asura-lib-utils/io/file.h new file mode 100644 index 0000000..56077e0 --- /dev/null +++ b/source/libs/asura-lib-utils/io/file.h @@ -0,0 +1,146 @@ +#ifndef __ASURA_ENGINE_FILE_H__ +#define __ASURA_ENGINE_FILE_H__ + +#include "physfs/physfs.h" + +#include "../scripting/portable.hpp" +#include "../threading/thread.h" + +#include "file_data.h" + +namespace AsuraEngine +{ + namespace IO + { + + /// + /// ʽļָд㡢Сʹȡʱʹñ࣬ʹFilesystem.read()ֱӶȡļȫ + /// ݣһFileData + /// + class File ASURA_FINAL + : public AEScripting::Portable<File> + { + public: + + LUAX_DECL_FACTORY(File); + + /// + /// ļдģʽ + /// + enum FileMode + { + FILE_MODE_CLOSED, + FILE_MODE_READ, + FILE_MODE_WRITE, + FILE_MODE_APPEND, + }; + + /// + /// ļдʱΪ + /// + enum BufferMode + { + BUFFER_MODE_NONE, ///< ʹû壬дļ + BUFFER_MODE_LINE, ///< л壬зߴﵽСʱдļ + BUFFER_MODE_FULL, ///< ȫ壬ʱдļ + }; + + File(const std::string& filename); + ~File(); + + bool Open(FileMode mode); + bool Close(); + bool IsOpen(); + FileMode GetMode(); + size_t GetSize(); + + /// + /// ȡdata bufferض + /// + size_t Read(ASURA_OUT DataBuffer* dst, size_t length); + size_t ReadAll(ASURA_OUT DataBuffer* dst); + size_t ReadAsync(ASURA_OUT DataBuffer* dst); + + /// + /// Ƿļβ + /// + bool IsEOF(); + + /// + /// data bufferед룬Ƿɹ + /// + bool Write(ASURA_REF DataBuffer* src); + + /// + /// 첽дļдļtaskthreadĶС + /// + bool WriteAsync(ASURA_REF DataBuffer* src, AEThreading::Thread* thread); + + /// + /// ˻壬ǿջдļ + /// + bool Flush(); + + /// + /// صǰдλ + /// + size_t Tell(); + + /// + /// Ӧλ + /// + bool Seek(size_t pos); + + /// + /// ûСģʽ + /// + bool SetBuffer(BufferMode mode, size_t size); + + /// + /// ȡСģʽ + /// + BufferMode GetBuffer(ASURA_OUT size_t& size); + + const std::string& GetFileName(); + const std::string& GetName(); + const std::string& GetExtension(); + + private: + + PHYSFS_File* mFileHandle; ///< physfs ļ + std::string mFileName; ///< ļ + std::string mExtension; ///< չ + std::string mName; ///< չļ + FileMode mMode; ///< ļģʽ + BufferMode mBufferMode; ///< д뻺ģʽ + size_t mBufferSize; ///< д뻺С + + LUAX_DECL_ENUM(FileMode); + LUAX_DECL_ENUM(BufferMode); + + LUAX_DECL_METHOD(_New); + LUAX_DECL_METHOD(_Open); + LUAX_DECL_METHOD(_Close); + LUAX_DECL_METHOD(_IsOpen); + LUAX_DECL_METHOD(_GetMode); + LUAX_DECL_METHOD(_GetSize); + LUAX_DECL_METHOD(_Read); + LUAX_DECL_METHOD(_Write); + LUAX_DECL_METHOD(_ReadAsync); + LUAX_DECL_METHOD(_WriteAsync); + LUAX_DECL_METHOD(_IsEOF); + LUAX_DECL_METHOD(_Flush); + LUAX_DECL_METHOD(_Tell); + LUAX_DECL_METHOD(_Seek); + LUAX_DECL_METHOD(_SetBuffer); + LUAX_DECL_METHOD(_GetBuffer); + LUAX_DECL_METHOD(_GetFileName); + LUAX_DECL_METHOD(_GetExtension); + LUAX_DECL_METHOD(_GetName); + + }; + + } +} + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/io/file_data.cpp b/source/libs/asura-lib-utils/io/file_data.cpp new file mode 100644 index 0000000..92333cf --- /dev/null +++ b/source/libs/asura-lib-utils/io/file_data.cpp @@ -0,0 +1,52 @@ +#include "file_data.h" + +namespace AsuraEngine +{ + namespace IO + { + + FileData::FileData(const std::string& filename) + : mData(nullptr) + , mFileName(filename) + { + size_t dot = filename.rfind('.'); + if (dot != std::string::npos) + { + mExtension = filename.substr(dot + 1); + mName = filename.substr(0, dot); + } + else + mName = filename; + } + + FileData::~FileData() + { + } + + const std::string& FileData::GetFileName() + { + return mFileName; + } + + const std::string& FileData::GetExtension() + { + return mExtension; + } + + const std::string& FileData::GetName() + { + return mName; + } + + void FileData::BindData(ASURA_MOVE DataBuffer* buffer) + { + mData = buffer; + } + + DataBuffer* FileData::GetDataBuffer() + { + return mData; + } + + } +} diff --git a/source/libs/asura-lib-utils/io/file_data.h b/source/libs/asura-lib-utils/io/file_data.h new file mode 100644 index 0000000..9aa0e3b --- /dev/null +++ b/source/libs/asura-lib-utils/io/file_data.h @@ -0,0 +1,69 @@ +#ifndef __ASURA_ENGINE_FILE_DATA_H__ +#define __ASURA_ENGINE_FILE_DATA_H__ + +#include <string> + +#include <asura-lib-utils/scripting/portable.hpp> + +#include "data_buffer.h" + +namespace AsuraEngine +{ + namespace IO + { + + class Filesystem; + + /// + /// filesystemֱӶȡļʱFileDataļݺϢFilesystem + /// + class FileData ASURA_FINAL + : public AEScripting::Portable<FileData> + { + public: + + LUAX_DECL_FACTORY(FileData); + + ~FileData(); + + /// + /// ļݣͨDatabufferݺʹСڲӿڶData bufferΪҲdata buffer + /// + DataBuffer* GetDataBuffer(); + + const std::string& GetFileName(); + const std::string& GetExtension(); + const std::string& GetName(); + + private: + + friend class Filesystem; + + FileData(const std::string& name); + + /// + /// data buffer + /// + void BindData(ASURA_MOVE DataBuffer* buffer); + + /// + /// Data bufferfiledataʱ٣luaüΪ0ʱluaGC١mDataʱһԱá + /// + ASURA_REF DataBuffer* mData; + Luax::LuaxMemberRef mDataRef; + + std::string mFileName; ///< չļ + std::string mExtension; ///< չ + std::string mName; ///< ͺļ + + LUAX_DECL_METHOD(_GetDataBuffer); + LUAX_DECL_METHOD(_GetFileName); + LUAX_DECL_METHOD(_GetExtension); + LUAX_DECL_METHOD(_GetName); + + }; + + } +} + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/io/file_system.cpp b/source/libs/asura-lib-utils/io/file_system.cpp new file mode 100644 index 0000000..20f3cb2 --- /dev/null +++ b/source/libs/asura-lib-utils/io/file_system.cpp @@ -0,0 +1,198 @@ +#include <physfs/physfs.h> + +#include "../exceptions/exception.h" + +#include "file.h" +#include "file_data.h" +#include "file_system.h" + +using namespace std; + +namespace AsuraEngine +{ + namespace IO + { + +#ifdef ASURA_WINDOWS + #include <windows.h> + #include <direct.h> +#else + #include <sys/param.h> + #include <unistd.h> +#endif + + Filesystem::~Filesystem() + { + if (mInited) //PHYSFS_isInit + PHYSFS_deinit(); + } + + void Filesystem::Init(const char* arg0) + { + if (!PHYSFS_init(arg0)) + throw Exception("Failed to initialize filesystem: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode())); + + mInited = true; + } + + bool Filesystem::Mount(const std::string& locpath, const std::string& montpoint/* = "/"*/, bool prepend /*= false*/) + { + if (!mInited) + return false; + + return PHYSFS_mount(locpath.c_str(), montpoint.c_str(), !prepend); + } + + bool Filesystem::Mount(DataBuffer* db, const std::string& archivename, const std::string& mountpoint /*= "/"*/, bool prepend /*= false*/) + { + if (!mInited) + return false; + if (PHYSFS_mountMemory(db->GetData(), db->GetSize(), nullptr, archivename.c_str(), mountpoint.c_str(), !prepend)) + { + mMountData[archivename] = db; + return true; + } + return false; + } + + bool Filesystem::Unmount(const std::string& locpath) + { + if (!mInited) + return false; + + // ǹ鵵ӳɾ + auto datait = mMountData.find(locpath); + if (datait != mMountData.end() && PHYSFS_unmount(locpath.c_str()) != 0) + { + mMountData.erase(datait); + return true; + } + + return PHYSFS_unmount(locpath.c_str()); + } + + bool Filesystem::Unmount(DataBuffer* db) + { + for (const auto& dp : mMountData) + { + if (dp.second == db) + { + std::string archive = dp.first; + return Unmount(archive); + } + } + } + + bool Filesystem::GetMountPoint(const std::string& locpath, ASURA_OUT std::string& mountpoint) + { + if (!mInited) + return false; + const char* point = PHYSFS_getMountPoint(locpath.c_str()); + if (point != nullptr) + { + mountpoint = point; + return true; + } + return false; + } + + void Filesystem::SetWriteDirectory(const std::string locpath) + { + if (!mInited) + return; + if (!PHYSFS_setWriteDir(locpath.c_str())) + throw Exception("Failed to set write directory %s", locpath.c_str()); + } + + std::string Filesystem::GetWriteDirectory() + { + return PHYSFS_getWriteDir(); + } + + File* Filesystem::NewFile(const std::string& name) + { + return new File(name); + } + + bool Filesystem::NewDirectory(const std::string& path) + { + if (!mInited) + return false; + if (!PHYSFS_getWriteDir()) + return false; + if (!PHYSFS_mkdir(path.c_str())) + return false; + return true; + } + + bool Filesystem::Write(const std::string& name, ASURA_REF DataBuffer* buffer) + { + File file(name); + file.Open(File::FILE_MODE_WRITE); + if (!file.Write(buffer)) + throw Exception("Data could not be written."); + } + + bool Filesystem::Append(const std::string& name, ASURA_REF DataBuffer* buffer) + { + File file(name); + file.Open(File::FILE_MODE_APPEND); + if (!file.Write(buffer)) + throw Exception("Data could not be append."); + } + + FileData* Filesystem::Read(const std::string& name) + { + File file = File(name); + file.Open(File::FILE_MODE_READ); + int size = file.GetSize(); + DataBuffer* db = new DataBuffer(size); + if (db) + { + file.ReadAll(db); + FileData* fd = new FileData(name); + fd->BindData(db); + return fd; + } + return nullptr; + } + + bool Filesystem::Remove(const std::string& path) + { + if (!mInited) + return false; + if (PHYSFS_getWriteDir() == 0) + return false; + + if (!PHYSFS_delete(path.c_str())) + return false; + + return true; + } + + bool Filesystem::GetFileInfo(const std::string& filepath, ASURA_OUT FileInfo* info) + { + if (!mInited) + return false; + + PHYSFS_Stat stat = {}; + if (!PHYSFS_stat(filepath.c_str(), &stat)) + return false; + + info->size = (int64)stat.filesize; + info->modtime = (int64)stat.modtime; + + if (stat.filetype == PHYSFS_FILETYPE_REGULAR) + info->type = FILE_TYPE_FILE; + else if (stat.filetype == PHYSFS_FILETYPE_DIRECTORY) + info->type = FILE_TYPE_DIRECTORY; + else if (stat.filetype == PHYSFS_FILETYPE_SYMLINK) + info->type = FILE_TYPE_SYMLINK; + else + info->type = FILE_TYPE_OTHER; + + return true; + } + + } +}
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/io/file_system.h b/source/libs/asura-lib-utils/io/file_system.h new file mode 100644 index 0000000..849cbb6 --- /dev/null +++ b/source/libs/asura-lib-utils/io/file_system.h @@ -0,0 +1,112 @@ +#ifndef __ASURA_ENGINE_FILESYSTEM_H__ +#define __ASURA_ENGINE_FILESYSTEM_H__ + +#include <map> +#include <string> + +#include "../scripting/portable.hpp" +#include "../singleton.hpp" +#include "../type.h" + +#include "file_data.h" +#include "file.h" + +namespace AsuraEngine +{ + namespace IO + { + + enum FileType + { + FILE_TYPE_FILE, ///< ļ + FILE_TYPE_DIRECTORY, ///< ļ + FILE_TYPE_SYMLINK, ///< + FILE_TYPE_OTHER, ///< + }; + + struct FileInfo + { + int64 size; + int64 modtime; + FileType type; + }; + + /// + /// Դء洢ԴָĿ¼ȡ۱༭ʱҪƷʵĻƣûIJϷĿ¼ + /// £file systemµġFilesystemʱͱ༭õ࣬AssetDatabaseԴ࣬framework + /// ʵ֣дFilesystemʵ֣AssetDatabaseṩļݴӦԴķ + /// + class Filesystem ASURA_FINAL + : public Singleton<Filesystem> + , public AEScripting::Portable<Filesystem> + { + public: + + LUAX_DECL_SINGLETON(Filesystem); + + ~Filesystem(); + + void Init(const char* arg0); + + /// + /// ǰִļļ + /// + std::string GetWorkingDirectory(); + + bool Mount(const std::string& locpath, const std::string& montpoint = "/", bool prepend = false); + bool Mount(DataBuffer* db, const std::string& archivename, const std::string& mountpoint = "/", bool prepend = false); + + bool Unmount(const std::string& locpath); + bool Unmount(DataBuffer* db); + + bool GetMountPoint(const std::string& locpath, ASURA_OUT std::string& mountpoint); + + void SetWriteDirectory(const std::string locpath); + std::string GetWriteDirectory(); + File* NewFile(const std::string& name); + bool NewDirectory(const std::string& path); + bool Write(const std::string& path, ASURA_REF DataBuffer* buffer); + bool Append(const std::string& path, ASURA_REF DataBuffer* buffer); + bool Remove(const std::string& path); + + FileData* Read(const std::string& path); + bool GetFileInfo(const std::string& path, ASURA_OUT FileInfo* info); + + bool GetDirectoryItems(const std::string& path, ASURA_OUT std::vector<std::string>& items) { return false; }; + + private: + + typedef std::map<std::string, DataBuffer*> MountDataMap; + + bool mInited; ///< Ƿʼɹ + std::string mCwd; ///< ǰִļĹĿ¼ + MountDataMap mMountData; ///< ·ѹĵӳ + + LUAX_DECL_METHOD(_Init); + LUAX_DECL_METHOD(_Mount); + LUAX_DECL_METHOD(_Unmount); + LUAX_DECL_METHOD(_GetMountPoint); + + LUAX_DECL_METHOD(_SetWriteDirectory); + LUAX_DECL_METHOD(_GetWriteDirectory); + LUAX_DECL_METHOD(_CreateFile); + LUAX_DECL_METHOD(_CreateDirectory); + + LUAX_DECL_METHOD(_Write); + LUAX_DECL_METHOD(_Append); + LUAX_DECL_METHOD(_Remove); + + LUAX_DECL_METHOD(_Read); + + LUAX_DECL_METHOD(_GetFileInfo); + + LUAX_DECL_METHOD(_GetDirectoryItems); + + }; + + } +} + +namespace AEIO = AsuraEngine::IO; + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/io/io_batch_task.cpp b/source/libs/asura-lib-utils/io/io_batch_task.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/source/libs/asura-lib-utils/io/io_batch_task.cpp diff --git a/source/libs/asura-lib-utils/io/io_batch_task.h b/source/libs/asura-lib-utils/io/io_batch_task.h new file mode 100644 index 0000000..c0be921 --- /dev/null +++ b/source/libs/asura-lib-utils/io/io_batch_task.h @@ -0,0 +1,31 @@ +#ifndef __ASURA_IO_BATCH_TASK_H__ +#define __ASURA_IO_BATCH_TASK_H__ + +#include "io_task.h" + +namespace AsuraEngine +{ + namespace IO + { + + /// + /// дһύһtableδؽ + /// + class IOBatchTask ASURA_FINAL : public AEThreading::Task + { + public: + + private: + + /// + /// ÿһĽṹ£ + /// { path = "", } + /// + Luax::LuaxMemberRef mTasks; + + }; + + } +} + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/io/io_task.cpp b/source/libs/asura-lib-utils/io/io_task.cpp new file mode 100644 index 0000000..361b9c5 --- /dev/null +++ b/source/libs/asura-lib-utils/io/io_task.cpp @@ -0,0 +1,55 @@ +#include "file_system.h" +#include "io_task.h" + +#include <iostream> + +using namespace AEScripting; +using namespace Luax; + +namespace AsuraEngine +{ + namespace IO + { + + IOTask::IOTask(const std::string& path, DataBuffer* buffer, IOTaskType type) + : mPath(path) + , mBuffer(buffer) + { + } + + IOTask::~IOTask() + { + } + + bool IOTask::Execute() + { + File file(mPath); + if (mType == IOTASK_TYPE_WRITE) + { + + } + // pathȡݱmBuffer + else if (mType == IOTASK_TYPE_READ) + { + file.Open(File::FILE_MODE_READ); + file.ReadAll(mBuffer); + file.Close(); + } + return true; + } + + void IOTask::Invoke(lua_State* invokeThreaad) + { + if (mCallback) + { + LuaxScopedState state(invokeThreaad); + if (PushLuaxMemberRef(state, mCallback)) + { + PushLuaxMemberRef(state, mBufferRef); + state.Call(1, 0); + } + } + } + + } +} diff --git a/source/libs/asura-lib-utils/io/io_task.h b/source/libs/asura-lib-utils/io/io_task.h new file mode 100644 index 0000000..8f04142 --- /dev/null +++ b/source/libs/asura-lib-utils/io/io_task.h @@ -0,0 +1,57 @@ +#ifndef __ASURA_IO_TASK_H__ +#define __ASURA_IO_TASK_H__ + +#include <string> + +#include "../scripting/portable.hpp" +#include "../threading/task.h" + +#include "data_buffer.h" + +namespace AsuraEngine +{ + namespace IO + { + + enum IOTaskType + { + IOTASK_TYPE_READ, + IOTASK_TYPE_WRITE, + IOTASK_TYPE_APPEND, + }; + + /// + /// ȡļ + /// + class IOTask ASURA_FINAL + : public AEThreading::Task + , public AEScripting::Portable<IOTask> + { + public: + + LUAX_DECL_FACTORY(IOTask); + + IOTask(const std::string& path, DataBuffer* buffer, IOTaskType type); + ~IOTask(); + + bool Execute() override ; + void Invoke(lua_State* invokeThreaad) override; + + private: + + LUAX_DECL_ENUM(IOTaskType); + + LUAX_DECL_METHOD(_New); + + std::string mPath; + IOTaskType mType; + + ASURA_REF DataBuffer* mBuffer; + Luax::LuaxMemberRef mBufferRef; + + }; + + } +} + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/io/reloadable.h b/source/libs/asura-lib-utils/io/reloadable.h new file mode 100644 index 0000000..22a721c --- /dev/null +++ b/source/libs/asura-lib-utils/io/reloadable.h @@ -0,0 +1,29 @@ +#ifndef __ASURA_ENGINE_RELOADABLE_H__ +#define __ASURA_ENGINE_RELOADABLE_H__ + +#include "../scripting/portable.hpp" + +namespace AsuraEngine +{ + namespace IO + { + + /// + /// ¹ݽṹͼƬƵ֣ⲿݿֱӹڱ༭¹ڲıhandleԴ + /// + ASURA_ABSTRACT class Reloadable + { + public: + Reloadable(); + virtual ~Reloadable(); + + // ̳ReloadableҪṩһload + + }; + + } +} + +namespace AEIO = AsuraEngine::IO; + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/manager.hpp b/source/libs/asura-lib-utils/manager.hpp new file mode 100644 index 0000000..7b4e272 --- /dev/null +++ b/source/libs/asura-lib-utils/manager.hpp @@ -0,0 +1,14 @@ +#ifndef __ASURA_ENGINE_MANAGER_H__ +#define __ASURA_ENGINE_MANAGER_H__ + +namespace AsuraEngine +{ + + class Manager + { + + }; + +} + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/math/curve.cpp b/source/libs/asura-lib-utils/math/curve.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/source/libs/asura-lib-utils/math/curve.cpp diff --git a/source/libs/asura-lib-utils/math/curve.h b/source/libs/asura-lib-utils/math/curve.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/source/libs/asura-lib-utils/math/curve.h diff --git a/source/libs/asura-lib-utils/math/functions.cpp b/source/libs/asura-lib-utils/math/functions.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/source/libs/asura-lib-utils/math/functions.cpp diff --git a/source/libs/asura-lib-utils/math/functions.h b/source/libs/asura-lib-utils/math/functions.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/source/libs/asura-lib-utils/math/functions.h diff --git a/source/libs/asura-lib-utils/math/matrix44.cpp b/source/libs/asura-lib-utils/math/matrix44.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/source/libs/asura-lib-utils/math/matrix44.cpp diff --git a/source/libs/asura-lib-utils/math/matrix44.h b/source/libs/asura-lib-utils/math/matrix44.h new file mode 100644 index 0000000..4ab3c0b --- /dev/null +++ b/source/libs/asura-lib-utils/math/matrix44.h @@ -0,0 +1,24 @@ +#ifndef __ASURA_ENGINE_MATRIX44_H__ +#define __ASURA_ENGINE_MATRIX44_H__ + +namespace AsuraEngine +{ + namespace Math + { + + /// + /// 4x4 + /// + class Matrix44 + { + public: + + private: + + + }; + + } +} + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/math/quaternion.cpp b/source/libs/asura-lib-utils/math/quaternion.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/source/libs/asura-lib-utils/math/quaternion.cpp diff --git a/source/libs/asura-lib-utils/math/quaternion.h b/source/libs/asura-lib-utils/math/quaternion.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/source/libs/asura-lib-utils/math/quaternion.h diff --git a/source/libs/asura-lib-utils/math/ranged_value.cpp b/source/libs/asura-lib-utils/math/ranged_value.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/source/libs/asura-lib-utils/math/ranged_value.cpp diff --git a/source/libs/asura-lib-utils/math/ranged_value.h b/source/libs/asura-lib-utils/math/ranged_value.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/source/libs/asura-lib-utils/math/ranged_value.h diff --git a/source/libs/asura-lib-utils/math/rect.hpp b/source/libs/asura-lib-utils/math/rect.hpp new file mode 100644 index 0000000..1751634 --- /dev/null +++ b/source/libs/asura-lib-utils/math/rect.hpp @@ -0,0 +1,47 @@ +#ifndef __ASURA_ENGINE_RECT_H__ +#define __ASURA_ENGINE_RECT_H__ + +namespace AsuraEngine +{ + namespace Math + { + + template<typename T> + struct Rect + { + public: + Rect(); + ~Rect(T x, T y, T w, T h); + + /// + /// x,yǷrectڡ + /// + bool Contain(T x, T y); + + /// + /// Ƿཻཻľ + /// + bool Intersect(const Rect& src, Rect& intersection); + + /// + /// Ƿཻཻľ + /// + static bool Intersect(const Rect<T>& src1, const Rect<T>& src2, Rect<T>& intersection); + + T x, y, w, h; + }; + +#include "Rect.inl" + + // Define the most common types + typedef Rect<int> Recti; + typedef Rect<unsigned int> Rectu; + typedef Rect<float> Rectf; + typedef Rect<long> Reftl; + + } +} + +namespace AEMath = AsuraEngine::Math; + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/math/rect.inl b/source/libs/asura-lib-utils/math/rect.inl new file mode 100644 index 0000000..891a3f8 --- /dev/null +++ b/source/libs/asura-lib-utils/math/rect.inl @@ -0,0 +1,19 @@ +template <typename T> +inline Rect<T>::Rect() + : x(0) + , y(0) + , w(0) + , h(0) +{ + +} + +template <typename T> +inline Rect<T>::Rect(T X, T Y, T W, T H) + : x(X) + , y(Y) + , w(W) + , h(H) +{ + +} diff --git a/source/libs/asura-lib-utils/math/transform.cpp b/source/libs/asura-lib-utils/math/transform.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/source/libs/asura-lib-utils/math/transform.cpp diff --git a/source/libs/asura-lib-utils/math/transform.h b/source/libs/asura-lib-utils/math/transform.h new file mode 100644 index 0000000..be4c850 --- /dev/null +++ b/source/libs/asura-lib-utils/math/transform.h @@ -0,0 +1,30 @@ +#ifndef __ASURA_ENGINE_TRANSFORM_H__ +#define __ASURA_ENGINE_TRANSFORM_H__ + +#include "../scripting/portable.hpp" + +namespace AsuraEngine +{ + namespace Math + { + + class Transform + { + public: + + void Set(float x, float y, float sx, float sy, float ox, float oy, float r); + + void LoadIdentity(); + + void Move(float dx = 0, float dy = 0); + void Rotate(float r); + void Scale(float sx, float sy); + + float m[16]; //4x4 matrix + + }; + + } +} + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/math/vector2.hpp b/source/libs/asura-lib-utils/math/vector2.hpp new file mode 100644 index 0000000..df78255 --- /dev/null +++ b/source/libs/asura-lib-utils/math/vector2.hpp @@ -0,0 +1,70 @@ +#ifndef __ASURA_ENGINE_VECTOR2_H__ +#define __ASURA_ENGINE_VECTOR2_H__ + +namespace AsuraEngine +{ + namespace Math + { + template <typename T> + class Vector2 + { + public: + Vector2(); + Vector2(T X, T Y); + + template <typename U> + explicit Vector2(const Vector2<U>& vector); + + Set(T X, T Y); + + T x; ///< X coordinate of the vector + T y; ///< Y coordinate of the vector + }; + + template <typename T> + Vector2<T> operator -(const Vector2<T>& right); + + template <typename T> + Vector2<T>& operator +=(Vector2<T>& left, const Vector2<T>& right); + + template <typename T> + Vector2<T>& operator -=(Vector2<T>& left, const Vector2<T>& right); + + template <typename T> + Vector2<T> operator +(const Vector2<T>& left, const Vector2<T>& right); + + template <typename T> + Vector2<T> operator -(const Vector2<T>& left, const Vector2<T>& right); + + template <typename T> + Vector2<T> operator *(const Vector2<T>& left, T right); + + template <typename T> + Vector2<T> operator *(T left, const Vector2<T>& right); + + template <typename T> + Vector2<T>& operator *=(Vector2<T>& left, T right); + + template <typename T> + Vector2<T> operator /(const Vector2<T>& left, T right); + + template <typename T> + Vector2<T>& operator /=(Vector2<T>& left, T right); + + template <typename T> + bool operator ==(const Vector2<T>& left, const Vector2<T>& right); + + template <typename T> + bool operator !=(const Vector2<T>& left, const Vector2<T>& right); + +#include "Vector2.inl" + + // Define the most common types + typedef Vector2<int> Vector2i; + typedef Vector2<unsigned int> Vector2u; + typedef Vector2<float> Vector2f; + + } +} + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/math/vector2.inl b/source/libs/asura-lib-utils/math/vector2.inl new file mode 100644 index 0000000..9e131a7 --- /dev/null +++ b/source/libs/asura-lib-utils/math/vector2.inl @@ -0,0 +1,114 @@ +template <typename T> +inline Vector2<T>::Vector2() : + x(0), + y(0) +{ + +} + +template <typename T> +inline Vector2<T>::Vector2(T X, T Y) : + x(X), + y(Y) +{ + +} + +template <typename T> +template <typename U> +inline Vector2<T>::Vector2(const Vector2<U>& vector) : + x(static_cast<T>(vector.x)), + y(static_cast<T>(vector.y)) +{ +} + +template <typename T> +inline Vector2<T>::Set(T X, T Y) +{ + x = X; + y = Y; +} + +template <typename T> +inline Vector2<T> operator -(const Vector2<T>& right) +{ + return Vector2<T>(-right.x, -right.y); +} + +template <typename T> +inline Vector2<T>& operator +=(Vector2<T>& left, const Vector2<T>& right) +{ + left.x += right.x; + left.y += right.y; + + return left; +} + +template <typename T> +inline Vector2<T>& operator -=(Vector2<T>& left, const Vector2<T>& right) +{ + left.x -= right.x; + left.y -= right.y; + + return left; +} + +template <typename T> +inline Vector2<T> operator +(const Vector2<T>& left, const Vector2<T>& right) +{ + return Vector2<T>(left.x + right.x, left.y + right.y); +} + +template <typename T> +inline Vector2<T> operator -(const Vector2<T>& left, const Vector2<T>& right) +{ + return Vector2<T>(left.x - right.x, left.y - right.y); +} + +template <typename T> +inline Vector2<T> operator *(const Vector2<T>& left, T right) +{ + return Vector2<T>(left.x * right, left.y * right); +} + +template <typename T> +inline Vector2<T> operator *(T left, const Vector2<T>& right) +{ + return Vector2<T>(right.x * left, right.y * left); +} + +template <typename T> +inline Vector2<T>& operator *=(Vector2<T>& left, T right) +{ + left.x *= right; + left.y *= right; + + return left; +} + +template <typename T> +inline Vector2<T> operator /(const Vector2<T>& left, T right) +{ + return Vector2<T>(left.x / right, left.y / right); +} + +template <typename T> +inline Vector2<T>& operator /=(Vector2<T>& left, T right) +{ + left.x /= right; + left.y /= right; + + return left; +} + +template <typename T> +inline bool operator ==(const Vector2<T>& left, const Vector2<T>& right) +{ + return (left.x == right.x) && (left.y == right.y); +} + +template <typename T> +inline bool operator !=(const Vector2<T>& left, const Vector2<T>& right) +{ + return (left.x != right.x) || (left.y != right.y); +} diff --git a/source/libs/asura-lib-utils/math/vector3.hpp b/source/libs/asura-lib-utils/math/vector3.hpp new file mode 100644 index 0000000..2b23406 --- /dev/null +++ b/source/libs/asura-lib-utils/math/vector3.hpp @@ -0,0 +1,233 @@ +#ifndef __ASURA_ENGINE_VECTOR3_H__ +#define __ASURA_ENGINE_VECTOR3_H__ + +namespace AsuraEngine +{ + namespace Math + { + template <typename T> + class Vector3 + { + public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates a Vector3(0, 0, 0). + /// + //////////////////////////////////////////////////////////// + Vector3(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vector from its coordinates + /// + /// \param X X coordinate + /// \param Y Y coordinate + /// \param Z Z coordinate + /// + //////////////////////////////////////////////////////////// + Vector3(T X, T Y, T Z); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vector from another type of vector + /// + /// This constructor doesn't replace the copy constructor, + /// it's called only when U != T. + /// A call to this constructor will fail to compile if U + /// is not convertible to T. + /// + /// \param vector Vector to convert + /// + //////////////////////////////////////////////////////////// + template <typename U> + explicit Vector3(const Vector3<U>& vector); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + T x; ///< X coordinate of the vector + T y; ///< Y coordinate of the vector + T z; ///< Z coordinate of the vector + }; + + //////////////////////////////////////////////////////////// + /// \relates Vector3 + /// \brief Overload of unary operator - + /// + /// \param left Vector to negate + /// + /// \return Memberwise opposite of the vector + /// + //////////////////////////////////////////////////////////// + template <typename T> + Vector3<T> operator -(const Vector3<T>& left); + + //////////////////////////////////////////////////////////// + /// \relates Vector3 + /// \brief Overload of binary operator += + /// + /// This operator performs a memberwise addition of both vectors, + /// and assigns the result to \a left. + /// + /// \param left Left operand (a vector) + /// \param right Right operand (a vector) + /// + /// \return Reference to \a left + /// + //////////////////////////////////////////////////////////// + template <typename T> + Vector3<T>& operator +=(Vector3<T>& left, const Vector3<T>& right); + + //////////////////////////////////////////////////////////// + /// \relates Vector3 + /// \brief Overload of binary operator -= + /// + /// This operator performs a memberwise subtraction of both vectors, + /// and assigns the result to \a left. + /// + /// \param left Left operand (a vector) + /// \param right Right operand (a vector) + /// + /// \return Reference to \a left + /// + //////////////////////////////////////////////////////////// + template <typename T> + Vector3<T>& operator -=(Vector3<T>& left, const Vector3<T>& right); + + //////////////////////////////////////////////////////////// + /// \relates Vector3 + /// \brief Overload of binary operator + + /// + /// \param left Left operand (a vector) + /// \param right Right operand (a vector) + /// + /// \return Memberwise addition of both vectors + /// + //////////////////////////////////////////////////////////// + template <typename T> + Vector3<T> operator +(const Vector3<T>& left, const Vector3<T>& right); + + //////////////////////////////////////////////////////////// + /// \relates Vector3 + /// \brief Overload of binary operator - + /// + /// \param left Left operand (a vector) + /// \param right Right operand (a vector) + /// + /// \return Memberwise subtraction of both vectors + /// + //////////////////////////////////////////////////////////// + template <typename T> + Vector3<T> operator -(const Vector3<T>& left, const Vector3<T>& right); + + //////////////////////////////////////////////////////////// + /// \relates Vector3 + /// \brief Overload of binary operator * + /// + /// \param left Left operand (a vector) + /// \param right Right operand (a scalar value) + /// + /// \return Memberwise multiplication by \a right + /// + //////////////////////////////////////////////////////////// + template <typename T> + Vector3<T> operator *(const Vector3<T>& left, T right); + + //////////////////////////////////////////////////////////// + /// \relates Vector3 + /// \brief Overload of binary operator * + /// + /// \param left Left operand (a scalar value) + /// \param right Right operand (a vector) + /// + /// \return Memberwise multiplication by \a left + /// + //////////////////////////////////////////////////////////// + template <typename T> + Vector3<T> operator *(T left, const Vector3<T>& right); + + //////////////////////////////////////////////////////////// + /// \relates Vector3 + /// \brief Overload of binary operator *= + /// + /// This operator performs a memberwise multiplication by \a right, + /// and assigns the result to \a left. + /// + /// \param left Left operand (a vector) + /// \param right Right operand (a scalar value) + /// + /// \return Reference to \a left + /// + //////////////////////////////////////////////////////////// + template <typename T> + Vector3<T>& operator *=(Vector3<T>& left, T right); + + //////////////////////////////////////////////////////////// + /// \relates Vector3 + /// \brief Overload of binary operator / + /// + /// \param left Left operand (a vector) + /// \param right Right operand (a scalar value) + /// + /// \return Memberwise division by \a right + /// + //////////////////////////////////////////////////////////// + template <typename T> + Vector3<T> operator /(const Vector3<T>& left, T right); + + //////////////////////////////////////////////////////////// + /// \relates Vector3 + /// \brief Overload of binary operator /= + /// + /// This operator performs a memberwise division by \a right, + /// and assigns the result to \a left. + /// + /// \param left Left operand (a vector) + /// \param right Right operand (a scalar value) + /// + /// \return Reference to \a left + /// + //////////////////////////////////////////////////////////// + template <typename T> + Vector3<T>& operator /=(Vector3<T>& left, T right); + + //////////////////////////////////////////////////////////// + /// \relates Vector3 + /// \brief Overload of binary operator == + /// + /// This operator compares strict equality between two vectors. + /// + /// \param left Left operand (a vector) + /// \param right Right operand (a vector) + /// + /// \return True if \a left is equal to \a right + /// + //////////////////////////////////////////////////////////// + template <typename T> + bool operator ==(const Vector3<T>& left, const Vector3<T>& right); + + //////////////////////////////////////////////////////////// + /// \relates Vector3 + /// \brief Overload of binary operator != + /// + /// This operator compares strict difference between two vectors. + /// + /// \param left Left operand (a vector) + /// \param right Right operand (a vector) + /// + /// \return True if \a left is not equal to \a right + /// + //////////////////////////////////////////////////////////// + template <typename T> + bool operator !=(const Vector3<T>& left, const Vector3<T>& right); + +#include "Vector3.inl" + + // Define the most common types + typedef Vector3<int> Vector3i; + typedef Vector3<float> Vector3f; + + } +} + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/math/vector3.inl b/source/libs/asura-lib-utils/math/vector3.inl new file mode 100644 index 0000000..3a2aa93 --- /dev/null +++ b/source/libs/asura-lib-utils/math/vector3.inl @@ -0,0 +1,145 @@ + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector3<T>::Vector3() : + x(0), + y(0), + z(0) +{ + +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector3<T>::Vector3(T X, T Y, T Z) : + x(X), + y(Y), + z(Z) +{ + +} + + +//////////////////////////////////////////////////////////// +template <typename T> +template <typename U> +inline Vector3<T>::Vector3(const Vector3<U>& vector) : + x(static_cast<T>(vector.x)), + y(static_cast<T>(vector.y)), + z(static_cast<T>(vector.z)) +{ +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector3<T> operator -(const Vector3<T>& left) +{ + return Vector3<T>(-left.x, -left.y, -left.z); +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector3<T>& operator +=(Vector3<T>& left, const Vector3<T>& right) +{ + left.x += right.x; + left.y += right.y; + left.z += right.z; + + return left; +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector3<T>& operator -=(Vector3<T>& left, const Vector3<T>& right) +{ + left.x -= right.x; + left.y -= right.y; + left.z -= right.z; + + return left; +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector3<T> operator +(const Vector3<T>& left, const Vector3<T>& right) +{ + return Vector3<T>(left.x + right.x, left.y + right.y, left.z + right.z); +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector3<T> operator -(const Vector3<T>& left, const Vector3<T>& right) +{ + return Vector3<T>(left.x - right.x, left.y - right.y, left.z - right.z); +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector3<T> operator *(const Vector3<T>& left, T right) +{ + return Vector3<T>(left.x * right, left.y * right, left.z * right); +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector3<T> operator *(T left, const Vector3<T>& right) +{ + return Vector3<T>(right.x * left, right.y * left, right.z * left); +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector3<T>& operator *=(Vector3<T>& left, T right) +{ + left.x *= right; + left.y *= right; + left.z *= right; + + return left; +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector3<T> operator /(const Vector3<T>& left, T right) +{ + return Vector3<T>(left.x / right, left.y / right, left.z / right); +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector3<T>& operator /=(Vector3<T>& left, T right) +{ + left.x /= right; + left.y /= right; + left.z /= right; + + return left; +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline bool operator ==(const Vector3<T>& left, const Vector3<T>& right) +{ + return (left.x == right.x) && (left.y == right.y) && (left.z == right.z); +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline bool operator !=(const Vector3<T>& left, const Vector3<T>& right) +{ + return (left.x != right.x) || (left.y != right.y) || (left.z != right.z); +} diff --git a/source/libs/asura-lib-utils/math/vector4.h b/source/libs/asura-lib-utils/math/vector4.h new file mode 100644 index 0000000..13a9d8a --- /dev/null +++ b/source/libs/asura-lib-utils/math/vector4.h @@ -0,0 +1,234 @@ +#ifndef __ASURA_ENGINE_VECTOR4_H__ +#define __ASURA_ENGINE_VECTOR4_H__ + +namespace AsuraEngine +{ + namespace Math + { + template <typename T> + class Vector4 + { + public: + + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Creates a Vector4(0, 0, 0). + /// + //////////////////////////////////////////////////////////// + Vector4(); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vector from its coordinates + /// + /// \param X X coordinate + /// \param Y Y coordinate + /// \param Z Z coordinate + /// + //////////////////////////////////////////////////////////// + Vector4(T X, T Y, T Z, T W); + + //////////////////////////////////////////////////////////// + /// \brief Construct the vector from another type of vector + /// + /// This constructor doesn't replace the copy constructor, + /// it's called only when U != T. + /// A call to this constructor will fail to compile if U + /// is not convertible to T. + /// + /// \param vector Vector to convert + /// + //////////////////////////////////////////////////////////// + template <typename U> + explicit Vector4(const Vector4<U>& vector); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + T x; ///< X coordinate of the vector + T y; ///< Y coordinate of the vector + T z; ///< Z coordinate of the vector + T w; ///< W coordinate of the vector + }; + + //////////////////////////////////////////////////////////// + /// \relates Vector4 + /// \brief Overload of unary operator - + /// + /// \param left Vector to negate + /// + /// \return Memberwise opposite of the vector + /// + //////////////////////////////////////////////////////////// + template <typename T> + Vector4<T> operator -(const Vector4<T>& left); + + //////////////////////////////////////////////////////////// + /// \relates Vector4 + /// \brief Overload of binary operator += + /// + /// This operator performs a memberwise addition of both vectors, + /// and assigns the result to \a left. + /// + /// \param left Left operand (a vector) + /// \param right Right operand (a vector) + /// + /// \return Reference to \a left + /// + //////////////////////////////////////////////////////////// + template <typename T> + Vector4<T>& operator +=(Vector4<T>& left, const Vector4<T>& right); + + //////////////////////////////////////////////////////////// + /// \relates Vector4 + /// \brief Overload of binary operator -= + /// + /// This operator performs a memberwise subtraction of both vectors, + /// and assigns the result to \a left. + /// + /// \param left Left operand (a vector) + /// \param right Right operand (a vector) + /// + /// \return Reference to \a left + /// + //////////////////////////////////////////////////////////// + template <typename T> + Vector4<T>& operator -=(Vector4<T>& left, const Vector4<T>& right); + + //////////////////////////////////////////////////////////// + /// \relates Vector4 + /// \brief Overload of binary operator + + /// + /// \param left Left operand (a vector) + /// \param right Right operand (a vector) + /// + /// \return Memberwise addition of both vectors + /// + //////////////////////////////////////////////////////////// + template <typename T> + Vector4<T> operator +(const Vector4<T>& left, const Vector4<T>& right); + + //////////////////////////////////////////////////////////// + /// \relates Vector4 + /// \brief Overload of binary operator - + /// + /// \param left Left operand (a vector) + /// \param right Right operand (a vector) + /// + /// \return Memberwise subtraction of both vectors + /// + //////////////////////////////////////////////////////////// + template <typename T> + Vector4<T> operator -(const Vector4<T>& left, const Vector4<T>& right); + + //////////////////////////////////////////////////////////// + /// \relates Vector4 + /// \brief Overload of binary operator * + /// + /// \param left Left operand (a vector) + /// \param right Right operand (a scalar value) + /// + /// \return Memberwise multiplication by \a right + /// + //////////////////////////////////////////////////////////// + template <typename T> + Vector4<T> operator *(const Vector4<T>& left, T right); + + //////////////////////////////////////////////////////////// + /// \relates Vector4 + /// \brief Overload of binary operator * + /// + /// \param left Left operand (a scalar value) + /// \param right Right operand (a vector) + /// + /// \return Memberwise multiplication by \a left + /// + //////////////////////////////////////////////////////////// + template <typename T> + Vector4<T> operator *(T left, const Vector4<T>& right); + + //////////////////////////////////////////////////////////// + /// \relates Vector4 + /// \brief Overload of binary operator *= + /// + /// This operator performs a memberwise multiplication by \a right, + /// and assigns the result to \a left. + /// + /// \param left Left operand (a vector) + /// \param right Right operand (a scalar value) + /// + /// \return Reference to \a left + /// + //////////////////////////////////////////////////////////// + template <typename T> + Vector4<T>& operator *=(Vector4<T>& left, T right); + + //////////////////////////////////////////////////////////// + /// \relates Vector4 + /// \brief Overload of binary operator / + /// + /// \param left Left operand (a vector) + /// \param right Right operand (a scalar value) + /// + /// \return Memberwise division by \a right + /// + //////////////////////////////////////////////////////////// + template <typename T> + Vector4<T> operator /(const Vector4<T>& left, T right); + + //////////////////////////////////////////////////////////// + /// \relates Vector4 + /// \brief Overload of binary operator /= + /// + /// This operator performs a memberwise division by \a right, + /// and assigns the result to \a left. + /// + /// \param left Left operand (a vector) + /// \param right Right operand (a scalar value) + /// + /// \return Reference to \a left + /// + //////////////////////////////////////////////////////////// + template <typename T> + Vector4<T>& operator /=(Vector4<T>& left, T right); + + //////////////////////////////////////////////////////////// + /// \relates Vector4 + /// \brief Overload of binary operator == + /// + /// This operator compares strict equality between two vectors. + /// + /// \param left Left operand (a vector) + /// \param right Right operand (a vector) + /// + /// \return True if \a left is equal to \a right + /// + //////////////////////////////////////////////////////////// + template <typename T> + bool operator ==(const Vector4<T>& left, const Vector4<T>& right); + + //////////////////////////////////////////////////////////// + /// \relates Vector4 + /// \brief Overload of binary operator != + /// + /// This operator compares strict difference between two vectors. + /// + /// \param left Left operand (a vector) + /// \param right Right operand (a vector) + /// + /// \return True if \a left is not equal to \a right + /// + //////////////////////////////////////////////////////////// + template <typename T> + bool operator !=(const Vector4<T>& left, const Vector4<T>& right); + +#include "Vector4.inl" + + // Define the most common types + typedef Vector4<int> Vector4i; + typedef Vector4<float> Vector4f; + + } +} + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/math/vector4.inl b/source/libs/asura-lib-utils/math/vector4.inl new file mode 100644 index 0000000..025bfcc --- /dev/null +++ b/source/libs/asura-lib-utils/math/vector4.inl @@ -0,0 +1,152 @@ + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector4<T>::Vector4() : + x(0), + y(0), + z(0), + w(0) +{ + +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector4<T>::Vector4(T X, T Y, T Z) : + x(X), + y(Y), + z(Z), + w(0) +{ + +} + + +//////////////////////////////////////////////////////////// +template <typename T> +template <typename U> +inline Vector4<T>::Vector4(const Vector4<U>& vector) : + x(static_cast<T>(vector.x)), + y(static_cast<T>(vector.y)), + z(static_cast<T>(vector.z)) + w(static_cast<T>(vector.w)) +{ +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector4<T> operator -(const Vector4<T>& left) +{ + return Vector4<T>(-left.x, -left.y, -left.z, -left.w); +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector4<T>& operator +=(Vector4<T>& left, const Vector4<T>& right) +{ + left.x += right.x; + left.y += right.y; + left.z += right.z; + left.w += right.w; + + return left; +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector4<T>& operator -=(Vector4<T>& left, const Vector4<T>& right) +{ + left.x -= right.x; + left.y -= right.y; + left.z -= right.z; + left.w -= right.w; + + return left; +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector4<T> operator +(const Vector4<T>& left, const Vector4<T>& right) +{ + return Vector4<T>(left.x + right.x, left.y + right.y, left.z + right.z, left.w + right.w); +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector4<T> operator -(const Vector4<T>& left, const Vector4<T>& right) +{ + return Vector4<T>(left.x - right.x, left.y - right.y, left.z - right.z, left.w - right.w); +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector4<T> operator *(const Vector4<T>& left, T right) +{ + return Vector4<T>(left.x * right, left.y * right, left.z * right, left.w * right); +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector4<T> operator *(T left, const Vector4<T>& right) +{ + return Vector4<T>(right.x * left, right.y * left, right.z * left, right.w * left); +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector4<T>& operator *=(Vector4<T>& left, T right) +{ + left.x *= right; + left.y *= right; + left.z *= right; + left.w *= right; + + return left; +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector4<T> operator /(const Vector4<T>& left, T right) +{ + return Vector4<T>(left.x / right, left.y / right, left.z / right, left.w / right); +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline Vector4<T>& operator /=(Vector4<T>& left, T right) +{ + left.x /= right; + left.y /= right; + left.z /= right; + left.w /= right; + + return left; +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline bool operator ==(const Vector4<T>& left, const Vector4<T>& right) +{ + return (left.x == right.x) && (left.y == right.y) && (left.z == right.z) && (left.w == right.w); +} + + +//////////////////////////////////////////////////////////// +template <typename T> +inline bool operator !=(const Vector4<T>& left, const Vector4<T>& right) +{ + return (left.x != right.x) || (left.y != right.y) || (left.z != right.z) || (left.w != right.w); +} diff --git a/source/libs/asura-lib-utils/module.h b/source/libs/asura-lib-utils/module.h new file mode 100644 index 0000000..b22c68c --- /dev/null +++ b/source/libs/asura-lib-utils/module.h @@ -0,0 +1,32 @@ +#ifndef __ASURA_MODULE_H__ +#define __ASURA_MODULE_H__ + +#include "type.h" +#include "scripting/portable.hpp" + +namespace AsuraEngine +{ + + /// + /// Asura libs Ҫ̳д࣬Կעᡣģа˳Щģ飬Ȼ˳InitializeFinalizeʼ + /// رЩģ顣 + /// + ASURA_ABSTRACT class Module + { + public: + + /// + /// ʼģ顣 + /// + virtual void Initialize(Luax::LuaxState& state) = 0; + + /// + /// رģ顣 + /// + virtual void Finalize(Luax::LuaxState& state) = 0; + + }; + +} + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/scripting/lua_env.h b/source/libs/asura-lib-utils/scripting/lua_env.h new file mode 100644 index 0000000..e2fc4fc --- /dev/null +++ b/source/libs/asura-lib-utils/scripting/lua_env.h @@ -0,0 +1,72 @@ +#ifndef __ASURA_LUA_ENV_H__ +#define __ASURA_LUA_ENV_H__ + +extern "C" +{ +#include <Lua51/lua.h> +#include <Lua51/lauxlib.h> +} +#include <Luax/luax.h> + +#include "../singleton.hpp" + +namespace AsuraEngine +{ + namespace Scripting + { + + /// + /// ͨӿڷlua stateAsura˼ǣ߳άһluaӦ + /// Ҫڴlua߽߳ջ + /// + class LuaEnv ASURA_FINAL : public Singleton<LuaEnv> + { + public: + + LuaEnv() : mVM(0) {}; + ~LuaEnv() {}; + + /// + /// ִջ + /// + inline void Init() + { + ASSERT(!mVM); + mVM = new Luax::LuaxVM(); + ASSERT(mVM); + mVM->Setup(); + }; + + inline lua_State* GetMainThread() + { + return mVM->GetMainThread(); + }; + + inline void Exit() + { + delete mVM; + mVM = nullptr; + } + + private: + + /// + /// ̱߳һluaһAsuraԶֻһִ붼 + /// УֻһΡ߳\ִջӦglobal_Stateģ + /// + /// struct lua_State *mainthread; + /// + /// ʹlua_newstate()ᴴһһglobal_Stateṹһ + /// ߳lua_Stateءglobal_State̹߳˵һ + /// ߳lua_newstate()⣬߳lua_newthread() + /// + Luax::LuaxVM* mVM; + + }; + + } +} + +namespace AEScripting = AsuraEngine::Scripting; + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/scripting/portable.hpp b/source/libs/asura-lib-utils/scripting/portable.hpp new file mode 100644 index 0000000..5badf8d --- /dev/null +++ b/source/libs/asura-lib-utils/scripting/portable.hpp @@ -0,0 +1,29 @@ +#ifndef __ASURA_ENGINE_PORTABLE_H__ +#define __ASURA_ENGINE_PORTABLE_H__ + +#include "../type.h" + +#include "lua_env.h" + +namespace AsuraEngine +{ + namespace Scripting + { + + /// + /// ҪעluanativeҪ̳дģ塣 + /// + template<typename T> + using Portable = Luax::LuaxNativeClass<T>; + + /// + /// ҪΪ࣬userdatamember ref̳д࣬ע̳С + /// + using NativeAccessor = Luax::ILuaxNativeAccessor; + + } +} + +namespace AEScripting = AsuraEngine::Scripting; + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/singleton.hpp b/source/libs/asura-lib-utils/singleton.hpp new file mode 100644 index 0000000..0d2777e --- /dev/null +++ b/source/libs/asura-lib-utils/singleton.hpp @@ -0,0 +1,59 @@ +#ifndef __ASURA_SINGLETON_H__ +#define __ASURA_SINGLETON_H__ + +#include "utils_config.h" + +namespace AsuraEngine +{ + + /// + /// ̳Singletonڵһʵʱʵ֮ٴʵᱨ + /// + template<class T> + class Singleton + { + public: + + static T* Get() + { + // ֮ǰûдһ + if (!instance) instance = new T; + // ʵ + return instance; + } + + static void Destroy() + { + delete instance; + instance = nullptr; + } + + protected: + + Singleton() + { + // instanceζִһʵǴġ + ASSERT(!instance); + // ʵΪʵ + instance = static_cast<T*>(this); + }; + + virtual ~Singleton() {}; + + static T* instance; + + private: + + Singleton(const Singleton& singleton); + + Singleton& operator = (const Singleton& singleton); + + }; + + // ʵʼΪ + template<class T> + T* Singleton<T>::instance = nullptr; + +} + +#endif // __ASURA_SINGLETON_H__
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/stringmap.cpp b/source/libs/asura-lib-utils/stringmap.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/source/libs/asura-lib-utils/stringmap.cpp diff --git a/source/libs/asura-lib-utils/stringmap.hpp b/source/libs/asura-lib-utils/stringmap.hpp new file mode 100644 index 0000000..ddba128 --- /dev/null +++ b/source/libs/asura-lib-utils/stringmap.hpp @@ -0,0 +1,29 @@ +#ifndef __ASURA_ENGINE_STRINGMAP_H__ +#define __ASURA_ENGINE_STRINGMAP_H__ + +#include <string> + +namespace AsuraEngine +{ + + /// + /// һ˫һһӦӳ䣬shader uniformsstatemathine state parameterID + /// + template<typename key_type> + class StringMap + { + public: + + bool ContainsKey(const key_type& key); + + bool ContainsString(const String& str); + + std::string GetStringByKey(const key_type& key); + + key_type GetKeyByString(const String& str); + + }; + +} + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/threading/binding/_coroutine.cpp b/source/libs/asura-lib-utils/threading/binding/_coroutine.cpp new file mode 100644 index 0000000..7f74cca --- /dev/null +++ b/source/libs/asura-lib-utils/threading/binding/_coroutine.cpp @@ -0,0 +1,40 @@ +#include "../coroutine.h" + +using namespace std; + +namespace AsuraEngine +{ + namespace Threading + { + + LUAX_REGISTRY(Coroutine) + { + LUAX_REGISTER_METHODS(state, + { "New", _New }, + { "Run", _Run } + ); + } + + LUAX_POSTPROCESS(Coroutine) + { + + } + + // Coroutine.New() + LUAX_IMPL_METHOD(Coroutine, _New) + { + LUAX_STATE(L); + + return 0; + } + + // coroutine:Run() + LUAX_IMPL_METHOD(Coroutine, _Run) + { + LUAX_PREPARE(L, Coroutine); + + return 0; + } + + } +} diff --git a/source/libs/asura-lib-utils/threading/binding/_thread.cpp b/source/libs/asura-lib-utils/threading/binding/_thread.cpp new file mode 100644 index 0000000..a5aff03 --- /dev/null +++ b/source/libs/asura-lib-utils/threading/binding/_thread.cpp @@ -0,0 +1,210 @@ +#include "../thread.h" + +using namespace std; + +namespace AsuraEngine +{ + namespace Threading + { + + LUAX_REGISTRY(Thread) + { + LUAX_REGISTER_METHODS(state, + { "New", _New }, + { "AddTask", _AddTask }, + { "Start", _Start }, + { "Idle", _Idle }, + { "Pause", _Pause }, + { "Resume", _Resume }, + { "Stop", _Stop }, + { "Join", _Join }, + { "IsRunning", _IsRunning }, + { "IsPaused", _IsPaused }, + { "IsStopped", _IsStopped }, + { "IsCurrent", _IsCurrent }, + { "Sleep", _Sleep }, + { "Post", _Post }, + { "GetName", _GetName }, + { "GetType", _GetType }, + { "GetState", _GetState } + ); + } + + LUAX_POSTPROCESS(Thread) + { + LUAX_REGISTER_ENUM(state, "EThreadType", + { "DEFERRED", THREAD_TYPE_DEFERRED }, + { "IMMEDIATE", THREAD_TYPE_IMMEDIATE } + ); + LUAX_REGISTER_ENUM(state, "EThreadState", + { "READY", THREAD_STATE_IDLE }, + { "RUNNING", THREAD_STATE_RUNNING }, + { "PAUSED", THREAD_STATE_PAUSED }, + { "STOPPED", THREAD_STATE_STOPPED } + ); + } + + // thread = Thread.New(thread_type, sleepTime, name) + LUAX_IMPL_METHOD(Thread, _New) + { + LUAX_STATE(L); + + ThreadType type = (ThreadType)state.GetValue<int>(1, THREAD_TYPE_DEFERRED); + uint sleepTime = state.GetValue<uint>(2,1); + cc8* name = state.GetValue<cc8*>(3, ""); + + Thread* thread = new Thread(state, type, sleepTime, name); + thread->PushLuaxUserdata(state); + + return 1; + } + + // thread:AddTask(task) + LUAX_IMPL_METHOD(Thread, _AddTask) + { + LUAX_PREPARE(L, Thread); + + Task* task = state.GetUserdata<Task>(2); + self->AddTask(task); + self->LuaxRetain<Task>(state, task); + return 0; + } + + // successed = thread:Start(isDeamon, stackSize) + LUAX_IMPL_METHOD(Thread, _Start) + { + LUAX_PREPARE(L, Thread); + + bool isDaemon = state.GetValue(2, true); + uint stackSize = state.GetValue(3, 0); + + state.Push(self->Start(isDaemon, stackSize)); + return 1; + } + + // thread:Idle() + LUAX_IMPL_METHOD(Thread, _Idle) + { + LUAX_PREPARE(L, Thread); + self->Idle(); + return 0; + } + + // thread:Pause() + LUAX_IMPL_METHOD(Thread, _Pause) + { + LUAX_PREPARE(L, Thread); + self->Pause(); + return 0; + } + + // thread:Resume() + LUAX_IMPL_METHOD(Thread, _Resume) + { + LUAX_PREPARE(L, Thread); + self->Resume(); + return 0; + } + + // thread:Stop() + LUAX_IMPL_METHOD(Thread, _Stop) + { + LUAX_PREPARE(L, Thread); + self->Stop(); + return 0; + } + + // thread:Join() + LUAX_IMPL_METHOD(Thread, _Join) + { + LUAX_PREPARE(L, Thread); + self->Join(); + return 0; + } + + // thread:IsRunning() + LUAX_IMPL_METHOD(Thread, _IsRunning) + { + LUAX_PREPARE(L, Thread); + state.Push(self->IsRunning()); + return 1; + } + + // thread:IsPaused() + LUAX_IMPL_METHOD(Thread, _IsPaused) + { + LUAX_PREPARE(L, Thread); + state.Push(self->IsPaused()); + return 1; + } + + // thread:IsStopped() + LUAX_IMPL_METHOD(Thread, _IsStopped) + { + LUAX_PREPARE(L, Thread); + state.Push(self->IsStopped()); + return 1; + } + + // thread:IsCurrent() + LUAX_IMPL_METHOD(Thread, _IsCurrent) + { + LUAX_PREPARE(L, Thread); + state.Push(self->IsCurrent()); + return 1; + } + + // Thread.Sleep(ms) + LUAX_IMPL_METHOD(Thread, _Sleep) + { + LUAX_STATE(L); + uint ms = state.GetValue(1, 0); +#ifdef _WIN32 + ::Sleep(ms); +#endif + return 0; + } + + // thread:Post() + LUAX_IMPL_METHOD(Thread, _Post) + { + LUAX_PREPARE(L, Thread); + self->Post(); + return 0; + } + + // thread:GetName() + LUAX_IMPL_METHOD(Thread, _GetName) + { + LUAX_PREPARE(L, Thread); + state.Push(self->GetName()); + return 1; + } + + // thread:GetType() + LUAX_IMPL_METHOD(Thread, _GetType) + { + LUAX_PREPARE(L, Thread); + state.Push(self->mType); + return 1; + } + + // thread:GetState() + LUAX_IMPL_METHOD(Thread, _GetState) + { + LUAX_PREPARE(L, Thread); + state.Push(self->mState); + return 1; + } + + // thread:SetSleepTime(sleepTime) + LUAX_IMPL_METHOD(Thread, _SetSleepTime) + { + LUAX_PREPARE(L, Thread); + uint time = state.CheckValue<uint>(2); + self->SetSleepTime(time); + return 0; + } + + } +} diff --git a/source/libs/asura-lib-utils/threading/coroutine.cpp b/source/libs/asura-lib-utils/threading/coroutine.cpp new file mode 100644 index 0000000..9f65c5f --- /dev/null +++ b/source/libs/asura-lib-utils/threading/coroutine.cpp @@ -0,0 +1,16 @@ +#include "coroutine.h" + +namespace AsuraEngine +{ + namespace Threading + { +/* + Coroutine::Coroutine() + { + + } +*/ + + + } +} diff --git a/source/libs/asura-lib-utils/threading/coroutine.h b/source/libs/asura-lib-utils/threading/coroutine.h new file mode 100644 index 0000000..01af654 --- /dev/null +++ b/source/libs/asura-lib-utils/threading/coroutine.h @@ -0,0 +1,40 @@ +#ifndef __ASURA_COROUTINE_H__ +#define __ASURA_COROUTINE_H__ + +#include "../scripting/portable.hpp" + +namespace AsuraEngine +{ + namespace Threading + { + + /// + /// luaЭ̣һЩ + /// + class Coroutine ASURA_FINAL + : public AEScripting::Portable<Coroutine> + { + public: + + LUAX_DECL_FACTORY(Coroutine); + + + + private: + + /// + /// ǰЭ̵state + /// + lua_State* mThreadState; + + LUAX_DECL_METHOD(_New); + LUAX_DECL_METHOD(_Run); + + }; + + } +} + +namespace AEThreading = AsuraEngine::Threading; + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/threading/mutex.cpp b/source/libs/asura-lib-utils/threading/mutex.cpp new file mode 100644 index 0000000..663ac28 --- /dev/null +++ b/source/libs/asura-lib-utils/threading/mutex.cpp @@ -0,0 +1,106 @@ +#include <asura-lib-utils/exceptions/exception.h> + +#include "mutex.h" + +namespace AsuraEngine +{ + namespace Threading + { + +#define try_create_mutex(impl)\ + if (!mImpl) \ + { \ + try \ + { \ + mImpl = new impl(); \ + } \ + catch (Exception& e) \ + { \ + mImpl = nullptr; \ + } \ + } + + Mutex::Mutex() + : mImpl(nullptr) + { +#if ASURA_MUTEX_WIN32_CRITICLE_SECTION + try_create_mutex(MutexImplWin32_CS); +#endif +#if ASURA_MUTEX_WIN32_KERNAL_MUTEX + try_create_mutex(MutexImplWin32_KM); +#endif + ASSERT(mImpl); + } + + Mutex::~Mutex() + { + delete mImpl; + } + + void Mutex::Lock() + { + ASSERT(mImpl); + + mImpl->Lock(); + } + + void Mutex::Unlock() + { + ASSERT(mImpl); + + mImpl->Unlock(); + } + +#if ASURA_MUTEX_WIN32_CRITICLE_SECTION + + MutexImplWin32_CS::MutexImplWin32_CS() + { + ::InitializeCriticalSection(&mMutex); + } + + MutexImplWin32_CS::~MutexImplWin32_CS() + { + ::DeleteCriticalSection(&mMutex); + } + + void MutexImplWin32_CS::Lock() + { + ::EnterCriticalSection(&mMutex); + } + + void MutexImplWin32_CS::Unlock() + { + ::LeaveCriticalSection(&mMutex); + } + +#endif // ASURA_MUTEX_WIN32_CRITICLE_SECTION + +#if ASURA_MUTEX_WIN32_KERNAL_MUTEX + + MutexImplWin32_KM::MutexImplWin32_KM() + { + mHandle = ::CreateMutex(NULL, FALSE, NULL); + if (!mHandle) + throw Exception("Cant use win32 mutex."); + } + + MutexImplWin32_KM::~MutexImplWin32_KM() + { + ::CloseHandle(mHandle); + mHandle = NULL; + } + + void MutexImplWin32_KM::Lock() + { + ::WaitForSingleObject(mHandle, INFINITE); + } + + void MutexImplWin32_KM::Unlock() + { + ::ReleaseMutex(mHandle); + } + +#endif // ASURA_MUTEX_WIN32_KERNAL_MUTEX + + } +} diff --git a/source/libs/asura-lib-utils/threading/mutex.h b/source/libs/asura-lib-utils/threading/mutex.h new file mode 100644 index 0000000..7e7d877 --- /dev/null +++ b/source/libs/asura-lib-utils/threading/mutex.h @@ -0,0 +1,126 @@ +#ifndef __ASURA_MUTEX_H__ +#define __ASURA_MUTEX_H__ + +#include <asura-lib-utils/type.h> + +#include "../utils_config.h" + +#if ASURA_THREAD_WIN32 + #include <windows.h> +#endif + +namespace AsuraEngine +{ + namespace Threading + { + + class MutexImpl; + + class Mutex + { + public: + + Mutex(); + ~Mutex(); + + void Lock(); + void Unlock(); + + private: + + MutexImpl* mImpl; + + }; + + class _mutex_locker + { + public: + _mutex_locker(Mutex& mutex) + : m(mutex) + { + m.Lock(); + }; + ~_mutex_locker() + { + m.Unlock(); + } + private: + void* operator new(size_t); + Mutex& m; + }; + +// ڵջӴλÿʼջΪٽ +#define lock(mutex) _mutex_locker _asura_scoped_lock_0x0(mutex) +#define lock2(mutex) _mutex_locker _asura_scoped_lock_0x1(mutex) +#define lock3(mutex) _mutex_locker _asura_scoped_lock_0x2(mutex) +#define lock4(mutex) _mutex_locker _asura_scoped_lock_0x3(mutex) +#define lock5(mutex) _mutex_locker _asura_scoped_lock_0x4(mutex) + + ASURA_ABSTRACT class MutexImpl + { + public: + + MutexImpl() {}; + virtual ~MutexImpl() {}; + + virtual void Lock() = 0; + virtual void Unlock() = 0; + + }; + +#if ASURA_MUTEX_WIN32_CRITICLE_SECTION + + //https://blog.csdn.net/l799623787/article/details/18259949 + class MutexImplWin32_CS ASURA_FINAL : public MutexImpl + { + public: + + MutexImplWin32_CS(); + ~MutexImplWin32_CS(); + + void Lock() override; + void Unlock() override; + + private: + + //HANDLE mHandle; + CRITICAL_SECTION mMutex; + + }; + +#endif // ASURA_MUTEX_WIN32_CRITICLE_SECTION + +#if ASURA_MUTEX_WIN32_KERNAL_MUTEX + + class MutexImplWin32_KM ASURA_FINAL : public MutexImpl + { + public: + + MutexImplWin32_KM(); + ~MutexImplWin32_KM(); + + void Lock() override; + void Unlock() override; + + private: + + HANDLE mHandle; + + }; + +#endif // ASURA_MUTEX_WIN32_KERNAL_MUTEX + +#if ASURA_THREAD_STD + + class MutexImplSTD ASURA_FINAL : public MutexImpl + { + }; + +#endif // ASURA_THREAD_STD + + } +} + +namespace AEThreading = AsuraEngine::Threading; + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/threading/semaphore.cpp b/source/libs/asura-lib-utils/threading/semaphore.cpp new file mode 100644 index 0000000..d59ec78 --- /dev/null +++ b/source/libs/asura-lib-utils/threading/semaphore.cpp @@ -0,0 +1,88 @@ +#include "../exceptions/exception.h" +#include "../type.h" + +#include "semaphore.h" + +namespace AsuraEngine +{ + namespace Threading + { + +#define try_create_semaphore(impl) \ + if (!mImpl) \ + { \ + try \ + { \ + mImpl = new impl(init_count); \ + } \ + catch (Exception& e) \ + { \ + mImpl = nullptr; \ + } \ + } + + Semaphore::Semaphore(unsigned int init_count) + : mImpl(nullptr) + { +#ifdef ASURA_THREAD_WIN32 + try_create_semaphore(SemaphoreWin32); +#endif + ASSERT(mImpl); + } + + Semaphore::~Semaphore() + { + if (mImpl) delete mImpl; + } + + void Semaphore::Signal() + { + ASSERT(mImpl); + mImpl->Signal(); + } + + void Semaphore::Wait(int timeout) + { + ASSERT(mImpl); + mImpl->Wait(timeout); + } + +#if ASURA_THREAD_WIN32 + + SemaphoreWin32::SemaphoreWin32(unsigned int init_value) + : SemaphoreImpl(init_value) + { + mSem = CreateSemaphore(NULL, init_value, UINT_MAX, NULL); + if (!mSem) + throw Exception("Cant use win32 semaphore."); + } + + SemaphoreWin32::~SemaphoreWin32() + { + CloseHandle(mSem); + } + + void SemaphoreWin32::Signal() + { + InterlockedIncrement(&mCount); + if (ReleaseSemaphore(mSem, 1, NULL) == FALSE) + InterlockedDecrement(&mCount); + } + + bool SemaphoreWin32::Wait(int timeout) + { + int result; + result = WaitForSingleObject(mSem, timeout < 0 ? INFINITE : timeout); + if (result == WAIT_OBJECT_0) + { + InterlockedDecrement(&mCount); + return true; + } + else + return false; + } + +#endif // ASURA_THREAD_WIN32 + + } +}
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/threading/semaphore.h b/source/libs/asura-lib-utils/threading/semaphore.h new file mode 100644 index 0000000..80773d8 --- /dev/null +++ b/source/libs/asura-lib-utils/threading/semaphore.h @@ -0,0 +1,70 @@ +#ifndef __ASURA_SEMAPHORE_H__ +#define __ASURA_SEMAPHORE_H__ + +#include "../utils_config.h" + +#if ASURA_THREAD_WIN32 +#include <windows.h> +#endif + +namespace AsuraEngine +{ + namespace Threading + { + + class SemaphoreImpl; + + /// + /// ź + /// + class Semaphore + { + public: + + Semaphore(unsigned int init_count = 1); + ~Semaphore(); + + void Signal(); + void Wait(int timeout = 0); + + private: + SemaphoreImpl* mImpl; + }; + + class SemaphoreImpl + { + public: + SemaphoreImpl(unsigned int init_value) + : mCount(init_value) + { + }; + virtual ~SemaphoreImpl() {}; + virtual void Signal() = 0; + virtual bool Wait(int timeout) = 0; + inline int Current() { return mCount; } + protected: + unsigned int mCount; + }; + +#define wait(sem) sem.Wait(); +#define signal(sem) sem.Signal(); + +#if ASURA_THREAD_WIN32 + + class SemaphoreWin32 : public SemaphoreImpl + { + public: + SemaphoreWin32(unsigned int init_value); + ~SemaphoreWin32(); + void Signal() override; + bool Wait(int timeout) override; + private: + HANDLE mSem; + }; + +#endif // ASURA_THREAD_WIN32 + + } +} + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/threading/task.cpp b/source/libs/asura-lib-utils/threading/task.cpp new file mode 100644 index 0000000..2e84ed4 --- /dev/null +++ b/source/libs/asura-lib-utils/threading/task.cpp @@ -0,0 +1,12 @@ +#include "task.h" +#include "../scripting/lua_env.h" + +using namespace AEScripting; + +namespace AsuraEngine +{ + namespace Threading + { + + } +} diff --git a/source/libs/asura-lib-utils/threading/task.h b/source/libs/asura-lib-utils/threading/task.h new file mode 100644 index 0000000..fb7aa5f --- /dev/null +++ b/source/libs/asura-lib-utils/threading/task.h @@ -0,0 +1,45 @@ +#ifndef __ASURA_THRAD_TASK_H__ +#define __ASURA_THRAD_TASK_H__ + +#include <asura-lib-utils/type.h> +#include <asura-lib-utils/scripting/portable.hpp> + +namespace AsuraEngine +{ + namespace Threading + { + + /// + /// ϣһ̴̳߳TaskдExecute + /// + ASURA_ABSTRACT class Task + : public virtual AEScripting::NativeAccessor + { + public: + + Task() {}; + virtual ~Task() {}; + + /// + /// ִɺtrueûص + /// + virtual bool Execute() = 0; + + /// + /// ûصinvoke threadص + /// + virtual void Invoke(lua_State* invokeThreaad) = 0; + + protected: + + // ȡص + Luax::LuaxMemberRef mCallback; + + }; + + } +} + +namespace AEThreading = AsuraEngine::Threading; + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/threading/thread.cpp b/source/libs/asura-lib-utils/threading/thread.cpp new file mode 100644 index 0000000..0f4f5da --- /dev/null +++ b/source/libs/asura-lib-utils/threading/thread.cpp @@ -0,0 +1,272 @@ +#include "thread.h" + +#include "thread_impl_win32.h" +#include "thread_impl_posix.h" +#include "thread_impl_sdl.h" +#include "thread_impl_std.h" + +namespace AsuraEngine +{ + namespace Threading + { + + Thread::Thread(lua_State* luaThread, ThreadType type /*= THREAD_TYPE_DEFERRED*/, uint sleepTime /*= 0*/, const std::string& name /*= ""*/) + : mName(name) + , mState(THREAD_STATE_IDLE) + , mType(type) + , mLuaThread(luaThread) + , mCallbackThread(nullptr) + , mSleepTime(sleepTime) + { + LUAX_STATE(luaThread); + if (type == THREAD_TYPE_IMMEDIATE) + { + Luax::LuaxVM* vm = state.GetVM(); + ASSERT(vm); + mCallbackThread = vm->CreateThread(); + ASSERT(mCallbackThread); + SetLuaxMemberRef(state, mCallbackThreadRef, -1); + state.Pop(); // callback thread + } + } + + Thread::~Thread() + { + if (mImpl) + { + delete mImpl; + mImpl = nullptr; + } + } + + bool Thread::AddTask(Task* task) + { + lock(mTaskQueueMutex); + mTaskQueue.push(task); + return true; + } + + uint Thread::GetTaskCount() + { + return mTaskQueue.size(); + } + + void Thread::Idle() + { + mState = THREAD_STATE_IDLE; + } + +#define try_start_thread(impl)\ + if (!mImpl) \ + { \ + mImpl = new impl(); \ + if (!mImpl->Start(this, stacksize)) \ + { \ + delete mImpl; \ + mImpl = nullptr; \ + } \ + } + + bool Thread::Start(bool isDaemon /*= true*/, uint32 stacksize /*= 0*/) + { + if (mState != THREAD_STATE_IDLE) + return false; + + // Ѿһ֮ǰģر + if (mImpl) + { + delete mImpl; + mImpl = nullptr; + } + +#if ASURA_THREAD_WIN32 + try_start_thread(ThreadImplWin32); +#endif + + if (!mImpl) + return false; + + mIsDaemon = isDaemon; + mStateMutex.Lock(); + mState = THREAD_STATE_RUNNING; + mStateMutex.Unlock(); + } + + void Thread::Pause() + { + ASSERT(mImpl); + + lock(mStateMutex); + mState = THREAD_STATE_PAUSED; + } + + void Thread::Resume() + { + ASSERT(mImpl); + + lock(mStateMutex); + if(mState == THREAD_STATE_PAUSED) + mState = THREAD_STATE_RUNNING; + } + + void Thread::Stop() + { + ASSERT(mImpl); + + lock(mStateMutex); + mState = THREAD_STATE_STOPPED; + } + + void Thread::PauseSync() + { + Pause(); + wait(mSemPause); + } + + void Thread::ResumeSync() + { + Resume(); + wait(mSemResume); + } + + void Thread::StopSync() + { + Stop(); + wait(mSemStop); + } + + void Thread::Join() + { + ASSERT(mImpl); + mImpl->Join(); + } + + ThreadState Thread::GetState() + { + ThreadState state; + mStateMutex.Lock(); + state = mState; + mStateMutex.Unlock(); + return state; + } + + bool Thread::IsRunning() + { + ASSERT(mImpl); + + return GetState() == THREAD_STATE_RUNNING; + } + + bool Thread::IsPaused() + { + ASSERT(mImpl); + + return GetState() == THREAD_STATE_PAUSED; + } + + bool Thread::IsStopped() + { + ASSERT(mImpl); + + return GetState() == THREAD_STATE_STOPPED; + } + + bool Thread::IsCurrent() + { + ASSERT(mImpl); + + return mImpl->IsCurrent(); + } + + const std::string& Thread::GetName() + { + return mName; + } + + void Thread::Process() + { + LUAX_STATE(mLuaThread); + + do{ + if (IsRunning()) + { + while (!mTaskQueue.empty()) + { + Task* task = mTaskQueue.front(); + if (task && task->Execute()) + { + if (mType == THREAD_TYPE_DEFERRED) + { + mFinishedMutex.Lock(); + mFinishedTasks.push(task); + mFinishedMutex.Unlock(); + } + else if (mType == THREAD_TYPE_IMMEDIATE) + { + task->Invoke(mCallbackThread); + this->LuaxRelease<Task>(state, task); + } + mTaskQueueMutex.Lock(); + mTaskQueue.pop(); + mTaskQueueMutex.Unlock(); + } + } + } + + // ˳ѭ + if (IsStopped()) + break; + + // CPUʹ + Sleep(mSleepTime); + + } while (mIsDaemon); + + // ػ̣߳еstop״̬ + if (!mIsDaemon) + Stop(); + + signal(mSemStop); + + // ״̬ΪIdle + Idle(); + } + + /// + /// ӳģʽص + /// + void Thread::Post() + { + ASSERT(mType == THREAD_TYPE_DEFERRED); + + LUAX_STATE(mLuaThread); + while (!mFinishedTasks.empty()) + { + Task* task = mFinishedTasks.front(); + if (task) + { + task->Invoke(mLuaThread); + this->LuaxRelease<Task>(state, task); + mFinishedMutex.Lock(); + mFinishedTasks.pop(); + mFinishedMutex.Unlock(); + } + } + } + + void Thread::Sleep(uint ms) + { + ASSERT(mImpl); + if (mImpl) + { + mImpl->Sleep(ms); + } + } + + void Thread::SetSleepTime(uint ms) + { + mSleepTime = ms; + } + + } +}
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/threading/thread.h b/source/libs/asura-lib-utils/threading/thread.h new file mode 100644 index 0000000..0e75770 --- /dev/null +++ b/source/libs/asura-lib-utils/threading/thread.h @@ -0,0 +1,221 @@ +#ifndef __ASURA_THREAD_H__ +#define __ASURA_THREAD_H__ + +#include <string> +#include <queue> + +#include <asura-lib-utils/scripting/portable.hpp> + +#include "task.h" +#include "mutex.h" +#include "semaphore.h" + +namespace AsuraEngine +{ + namespace Threading + { + + class ThreadImpl; + + /// + /// ̵߳ļֲͬʵ֣ + /// 1: Deferredӳģʽ߳ϵɺҪ̵ֶ߳Post + /// ̵߳ص첽Ϊͬlua_Stateͻ⡣ + /// 2: Immediateģʽÿһ߳άһlua_newthreadlua_State + /// صڲͬlua_Stateеãⲻ̷ͬ߳ͬһlua_State + /// + enum ThreadType + { + THREAD_TYPE_DEFERRED, + THREAD_TYPE_IMMEDIATE, + }; + + enum ThreadState + { + THREAD_STATE_IDLE, ///< ãδں˶ + THREAD_STATE_RUNNING, ///< ѭ + THREAD_STATE_PAUSED, ///< ѭͣ + THREAD_STATE_STOPPED, ///< ˳ѭ + }; + + /// + /// ߳壬ÿ߳άһtask queue + /// + class Thread ASURA_FINAL + : public AEScripting::Portable<Thread> + { + public: + + LUAX_DECL_FACTORY(Thread); + + Thread(lua_State* luaThread, ThreadType type = THREAD_TYPE_DEFERRED, uint sleepTime = 1, const std::string& name = ""); + ~Thread(); + + bool AddTask(Task* task); + /// + /// õȴ + /// + uint GetTaskCount(); + + void Idle(); + + /// + /// ں˶Сdaemonȴֶstopijʱ̶ɺԶstop + /// + bool Start(bool daemon = true, uint32 stacksize = 0); + + /// + /// ͬ߳̿ƣʵʱġҪ߳ʹIsȷϵָ״̬ + /// + void Pause(); + void Resume(); + void Stop(); + + /// + /// ͬ߳̿ƣȷźźִС̵߳ȴ + /// + void PauseSync(); + void ResumeSync(); + void StopSync(); + + /// + /// ̵߳ȴ߳̽żִС + /// + void Join(); + + ThreadState GetState(); + + /// + /// ߳״̬ + /// 1: IdleУ̴߳Ĭ״̬ʱStart + /// 2: RunningУں˶´Ѿں˵УTask + /// 3: PausedͣȻںУ˶Ĵͣ + /// 4: StoppedֹͣȻںУѾ + /// + bool IsIdle(); + bool IsRunning(); + bool IsPaused(); + bool IsStopped(); + + bool IsCurrent(); + + /// + /// ִС + /// + void Process(); + + const std::string& GetName(); + + /// + /// ص + /// + void Post(); + + /// + /// ߺ + /// + void Sleep(uint ms); + + /// + /// ʱ + /// + void SetSleepTime(uint ms); + + private: + + //----------------------------------------------------------------------------// + + LUAX_DECL_ENUM(ThreadType); + LUAX_DECL_ENUM(ThreadState); + + LUAX_DECL_METHOD(_New); + LUAX_DECL_METHOD(_AddTask); + LUAX_DECL_METHOD(_Start); + LUAX_DECL_METHOD(_Idle); + LUAX_DECL_METHOD(_Pause); + LUAX_DECL_METHOD(_Resume); + LUAX_DECL_METHOD(_Stop); + LUAX_DECL_METHOD(_Join); + LUAX_DECL_METHOD(_IsRunning); + LUAX_DECL_METHOD(_IsPaused); + LUAX_DECL_METHOD(_IsStopped); + LUAX_DECL_METHOD(_IsCurrent); + LUAX_DECL_METHOD(_Sleep); + LUAX_DECL_METHOD(_Post); + LUAX_DECL_METHOD(_GetName); + LUAX_DECL_METHOD(_GetType); + LUAX_DECL_METHOD(_GetState); + LUAX_DECL_METHOD(_SetSleepTime); + + //----------------------------------------------------------------------------// + + /// + /// ˴Ƿػģʽ + /// + bool mIsDaemon; + + lua_State* mLuaThread; + + ThreadImpl* mImpl; + std::string mName; + ThreadType mType; + uint mSleepTime; + + ThreadState mState; + Mutex mStateMutex; + + /// + /// ͬصź + /// + Semaphore mSemPause; + Semaphore mSemResume; + Semaphore mSemStop; + + /// + /// С + /// + std::queue<Task*> mTaskQueue; + Mutex mTaskQueueMutex; + + /// + /// ӳģʽʹ + /// + std::queue<Task*> mFinishedTasks; + Mutex mFinishedMutex; + + /// + /// ģʽʹãصʹõlua߳ + /// + lua_State* mCallbackThread; + Luax::LuaxMemberRef mCallbackThreadRef; + + }; + + /// + /// ̵߳ľʵ֣ûģһֲԣ + /// 1: win32 + /// 2: posix + /// 3: SDL + /// 4: std::thread + /// + ASURA_ABSTRACT class ThreadImpl + { + public: + ThreadImpl() {}; + virtual ~ThreadImpl() {}; + + virtual bool Start(Thread* thread, uint32 stacksize = 0) = 0; + virtual void Join() = 0; + virtual void Kill() = 0; + + virtual void Sleep(uint ms) = 0; + + virtual bool IsRunning() = 0; + virtual bool IsCurrent() = 0; + + }; + + } +} + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/threading/thread_impl_posix.cpp b/source/libs/asura-lib-utils/threading/thread_impl_posix.cpp new file mode 100644 index 0000000..d2ad7af --- /dev/null +++ b/source/libs/asura-lib-utils/threading/thread_impl_posix.cpp @@ -0,0 +1,9 @@ +#include "thread_impl_posix.h" + +namespace AsuraEngine +{ + namespace Threading + { + + } +}
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/threading/thread_impl_posix.h b/source/libs/asura-lib-utils/threading/thread_impl_posix.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/source/libs/asura-lib-utils/threading/thread_impl_posix.h diff --git a/source/libs/asura-lib-utils/threading/thread_impl_sdl.cpp b/source/libs/asura-lib-utils/threading/thread_impl_sdl.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/source/libs/asura-lib-utils/threading/thread_impl_sdl.cpp diff --git a/source/libs/asura-lib-utils/threading/thread_impl_sdl.h b/source/libs/asura-lib-utils/threading/thread_impl_sdl.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/source/libs/asura-lib-utils/threading/thread_impl_sdl.h diff --git a/source/libs/asura-lib-utils/threading/thread_impl_std.cpp b/source/libs/asura-lib-utils/threading/thread_impl_std.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/source/libs/asura-lib-utils/threading/thread_impl_std.cpp diff --git a/source/libs/asura-lib-utils/threading/thread_impl_std.h b/source/libs/asura-lib-utils/threading/thread_impl_std.h new file mode 100644 index 0000000..0e7d3da --- /dev/null +++ b/source/libs/asura-lib-utils/threading/thread_impl_std.h @@ -0,0 +1,43 @@ +#ifndef __ASURA_THREAD_STD_H__ +#define __ASURA_THREAD_STD_H__ + +#include "../utils_config.h" + +#if ASURA_THREAD_STD + +#include <windows.h> + +#include "thread.h" + +namespace AsuraEngine +{ + namespace Threading + { + + /// + /// Threadstd::threadʵ֡ + /// + class ThreadImplSTD : public ThreadImpl + { + public: + + ThreadImplSTD(); + ~ThreadImplSTD(); + + bool Start(Thread* thread, uint32 stacksize) override; + void Join() override; + void Kill() override; + + bool IsRunning() override; + bool IsCurrent() override; + + private: + + }; + + } +} + +#endif // #if ASURA_THREAD_STD + +#endif // __ASURA_THREAD_STD_H__
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/threading/thread_impl_win32.cpp b/source/libs/asura-lib-utils/threading/thread_impl_win32.cpp new file mode 100644 index 0000000..6871c2d --- /dev/null +++ b/source/libs/asura-lib-utils/threading/thread_impl_win32.cpp @@ -0,0 +1,76 @@ +#include "thread_impl_win32.h" +#include "thread.h" + +#include <iostream> + +namespace AsuraEngine +{ + namespace Threading + { + + static DWORD WINAPI _thread_win32_runner(LPVOID param) + { + Thread* thread = (Thread*)param; + thread->Process(); + return 0; + } + + ThreadImplWin32::ThreadImplWin32() + { + } + + ThreadImplWin32::~ThreadImplWin32() + { + if (!mHandle) return; + ::CloseHandle(mHandle); + mHandle = 0; + } + + bool ThreadImplWin32::Start(Thread* thread, uint32 stacksize/*=0*/) + { + assert(!IsRunning()); + mHandle = ::CreateThread( + NULL + , stacksize + , _thread_win32_runner + , thread + , 0 /*е*/ + , NULL); + + return mHandle; + } + + void ThreadImplWin32::Join() + { + // ̵߳ȴ̷߳ + ::WaitForSingleObject(mHandle, INFINITE); + } + + void ThreadImplWin32::Kill() + { + ::TerminateThread(mHandle, FALSE); + } + + void ThreadImplWin32::Sleep(uint ms) + { + ::Sleep(ms); + } + + bool ThreadImplWin32::IsRunning() + { + if (mHandle) { + DWORD exitCode = 0; + // https://blog.csdn.net/yuanmeng567/article/details/19485719 + ::GetExitCodeThread(mHandle, &exitCode); + return exitCode == STILL_ACTIVE; + } + return false; + } + + bool ThreadImplWin32::IsCurrent() + { + return mHandle == ::GetCurrentThread(); + } + + } +}
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/threading/thread_impl_win32.h b/source/libs/asura-lib-utils/threading/thread_impl_win32.h new file mode 100644 index 0000000..a22aeef --- /dev/null +++ b/source/libs/asura-lib-utils/threading/thread_impl_win32.h @@ -0,0 +1,47 @@ +#ifndef __ASURA_THREAD_WIN32_H__ +#define __ASURA_THREAD_WIN32_H__ + +#include "../utils_config.h" + +#if ASURA_THREAD_WIN32 + +#include <windows.h> + +#include "thread.h" + +namespace AsuraEngine +{ + namespace Threading + { + + /// + /// Threadwin32ʵ֡ + /// + class ThreadImplWin32 : public ThreadImpl + { + public: + + ThreadImplWin32(); + ~ThreadImplWin32(); + + bool Start(Thread* thread, uint32 stacksize) override; + void Join() override; + void Kill() override; + + void Sleep(uint ms) override; + + bool IsRunning() override; + bool IsCurrent() override; + + private: + + HANDLE mHandle; + + }; + + } +} + +#endif // #if ASURA_THREAD_WIN32 + +#endif // __ASURA_THREAD_WIN32_H__
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/threading/thread_task.cpp b/source/libs/asura-lib-utils/threading/thread_task.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/source/libs/asura-lib-utils/threading/thread_task.cpp diff --git a/source/libs/asura-lib-utils/threading/thread_task.h b/source/libs/asura-lib-utils/threading/thread_task.h new file mode 100644 index 0000000..1ea0a1a --- /dev/null +++ b/source/libs/asura-lib-utils/threading/thread_task.h @@ -0,0 +1,44 @@ +#ifndef __ASURA_THRAD_TASK_H__ +#define __ASURA_THRAD_TASK_H__ + +#include <asura-lib-utils/type.h> +#include <asura-lib-utils/scripting/portable.hpp> + +namespace AsuraEngine +{ + namespace Threading + { + + /// + /// ϣһ̴̳߳TaskдExecute + /// + ASURA_ABSTRACT class ThreadTask + : virtual public AEScripting::NativeAccessor + { + public: + + ThreadTask(); + virtual ~ThreadTask(); + + /// + /// ִɺtrueûص + /// + virtual bool Execute() = 0; + + /// + /// ûص + /// + virtual void Invoke() = 0; + + protected: + + Luax::LuaxMemberRef mCallback; + + }; + + } +} + +namespace AEThreading = AsuraEngine::Threading; + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/type.h b/source/libs/asura-lib-utils/type.h new file mode 100644 index 0000000..1ed2d42 --- /dev/null +++ b/source/libs/asura-lib-utils/type.h @@ -0,0 +1,85 @@ +#ifndef __ASURA_UTILS_TYPE_H__ +#define __ASURA_UTILS_TYPE_H__ + +#include <cstdlib> +#include <stdint.h> + +namespace AsuraEngine +{ + + //--------------------------------------------------------------------------------// + + typedef int8_t int8; + typedef uint8_t uint8; + //typedef uint8 byte; + typedef char byte; + typedef int16_t int16; + typedef uint16_t uint16; + typedef int32_t int32; + typedef uint32_t uint32; + typedef int64_t int64; + typedef uint64_t uint64; + + typedef uint32_t uint; + typedef int32_t sint; + + typedef std::size_t size_t; + + typedef const char cc8; + + //--------------------------------------------------------------------------------// + +#ifndef ASSERT + #ifdef NDEBUG + #define ASSERT(x) { false ? (void)(x) : (void)0; } + #else + #ifdef _WIN32 + #define ASURA_DEBUG_BREAK() __debugbreak() + #else + #define ASURA_DEBUG_BREAK() raise(SIGTRAP) + #endif + #define ASSERT(x) do { const volatile bool asura_assert_b____ = !(x); if(asura_assert_b____) ASURA_DEBUG_BREAK(); } while (false) + #endif +#endif + + //--------------------------------------------------------------------------------// + +#ifdef _WIN32 + #define ASURA_FINAL final + #define ASURA_LIBRARY_EXPORT __declspec(dllexport) + #define ASURA_LIBRARY_IMPORT __declspec(dllimport) + #define ASURA_FORCE_INLINE __forceinline + #define ASURA_RESTRICT __restrict + #define ASURA_ATTRIBUTE_USED + #define ASURA_ABSTRACT + #define ASURA_API ASURA_LIBRARY_EXPORT + + #define ASURA_WINDOWS 1 +#else + #define ASURA_FINAL final + #define ASURA_LIBRARY_EXPORT __attribute__((visibility("default"))) + #define ASURA_LIBRARY_IMPORT + #define ASURA_FORCE_INLINE __attribute__((always_inline)) inline + #define ASURA_RESTRICT __restrict__ + #define ASURA_ATTRIBUTE_USED __attribute__((used)) + #define ASURA_ABSTRACT + #define ASURA_API ASURA_LIBRARY_EXPORT +#endif + + /// + /// ò + /// +#define ASURA_OUT +#define ASURA_REF + /// + /// ƶָȨ + /// +#define ASURA_MOVE + + //--------------------------------------------------------------------------------// + +#define ASURA_SDL_HOST 1 + +} // namespace AsuraEngine + +#endif // __ASURA_CONFIG_H__
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/utils.h b/source/libs/asura-lib-utils/utils.h new file mode 100644 index 0000000..ce1c6a1 --- /dev/null +++ b/source/libs/asura-lib-utils/utils.h @@ -0,0 +1,6 @@ +#ifndef __ASURA_UTILS_H__ +#define __ASURA_UTILS_H__ + +#include "utils_module.h" + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/utils_config.h b/source/libs/asura-lib-utils/utils_config.h new file mode 100644 index 0000000..02837dc --- /dev/null +++ b/source/libs/asura-lib-utils/utils_config.h @@ -0,0 +1,10 @@ +#ifndef __ASURA_UTILS_CONFIG_H__ +#define __ASURA_UTILS_CONFIG_H__ + +#define ASURA_THREAD_WIN32 1 +#define ASURA_THREAD_STD 1 + +#define ASURA_MUTEX_WIN32_CRITICLE_SECTION 1 +#define ASURA_MUTEX_WIN32_KERNAL_MUTEX 1 + +#endif
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/utils_module.cpp b/source/libs/asura-lib-utils/utils_module.cpp new file mode 100644 index 0000000..61780e6 --- /dev/null +++ b/source/libs/asura-lib-utils/utils_module.cpp @@ -0,0 +1,25 @@ +#include "utils_module.h" + +using namespace AsuraEngine::IO; +using namespace AsuraEngine::Threading; + +namespace AsuraEngine +{ + + void UtilsModule::Initialize(Luax::LuaxState& state) + { + // IO + LUAX_REGISTER_SINGLETON(state, Filesystem); + LUAX_REGISTER_FACTORY(state, DataBuffer); + LUAX_REGISTER_FACTORY(state, FileData); + LUAX_REGISTER_FACTORY(state, File); + LUAX_REGISTER_FACTORY(state, IOTask); + // Threading + LUAX_REGISTER_FACTORY(state, Thread); + } + + void UtilsModule::Finalize(Luax::LuaxState& state) + { + } + +}
\ No newline at end of file diff --git a/source/libs/asura-lib-utils/utils_module.h b/source/libs/asura-lib-utils/utils_module.h new file mode 100644 index 0000000..e802730 --- /dev/null +++ b/source/libs/asura-lib-utils/utils_module.h @@ -0,0 +1,32 @@ +#ifndef __ASURA_LIBS_UTIL_MODULE_H__ +#define __ASURA_LIBS_UTIL_MODULE_H__ + +#include "io/file_system.h" +#include "io/data_buffer.h" +#include "io/file_data.h" +#include "io/file.h" +#include "io/io_task.h" + +#include "threading/thread.h" + +#include "module.h" + +namespace AsuraEngine +{ + + /// + /// Asuraģ + /// + class UtilsModule ASURA_FINAL : public Module + { + public: + + void Initialize(Luax::LuaxState& state) override; + + void Finalize(Luax::LuaxState& state) override; + + }; + +} + +#endif
\ No newline at end of file |