From 03b3b8ae80559745f98ef94569b421adddeb441f Mon Sep 17 00:00:00 2001 From: chai Date: Mon, 25 Mar 2019 23:46:59 +0800 Subject: *misc --- .../filesystem/binding/data_buffer.binding.cpp | 110 -------- .../asura-lib-utils/filesystem/data_buffer.cpp | 67 ----- .../libs/asura-lib-utils/filesystem/data_buffer.h | 55 ---- .../asura-lib-utils/filesystem/decoded_data.cpp | 20 -- .../libs/asura-lib-utils/filesystem/decoded_data.h | 42 --- .../libs/asura-lib-utils/filesystem/reloadable.h | 27 -- .../filesystem/resource_manager.cpp | 0 .../asura-lib-utils/filesystem/resource_manager.h | 48 ---- .../asura-lib-utils/io/binding/_compressor.cpp | 0 .../asura-lib-utils/io/binding/_data_buffer.cpp | 110 ++++++++ source/libs/asura-lib-utils/io/binding/_file.cpp | 186 ++++++++++++++ .../libs/asura-lib-utils/io/binding/_file_data.cpp | 64 +++++ .../asura-lib-utils/io/binding/_file_system.cpp | 267 +++++++++++++++++++ source/libs/asura-lib-utils/io/compressor.cpp | 11 + source/libs/asura-lib-utils/io/compressor.h | 30 +++ source/libs/asura-lib-utils/io/data_buffer.cpp | 77 ++++++ source/libs/asura-lib-utils/io/data_buffer.h | 54 ++++ source/libs/asura-lib-utils/io/decoded_data.cpp | 20 ++ source/libs/asura-lib-utils/io/decoded_data.h | 42 +++ source/libs/asura-lib-utils/io/file.cpp | 286 +++++++++++++++++++++ source/libs/asura-lib-utils/io/file.h | 132 ++++++++++ source/libs/asura-lib-utils/io/file_data.cpp | 57 ++++ source/libs/asura-lib-utils/io/file_data.h | 68 +++++ source/libs/asura-lib-utils/io/file_system.cpp | 198 ++++++++++++++ source/libs/asura-lib-utils/io/file_system.h | 110 ++++++++ source/libs/asura-lib-utils/io/reloadable.h | 27 ++ source/libs/asura-lib-utils/manager.hpp | 14 + source/libs/asura-lib-utils/math/rect.hpp | 19 +- source/libs/asura-lib-utils/scripting/portable.hpp | 7 + source/libs/asura-lib-utils/singleton.hpp | 59 +++++ source/libs/asura-lib-utils/stringmap.cpp | 0 source/libs/asura-lib-utils/stringmap.hpp | 29 +++ source/libs/asura-lib-utils/type.h | 14 + source/libs/asura-lib-utils/utils_config.h | 0 34 files changed, 1879 insertions(+), 371 deletions(-) delete mode 100644 source/libs/asura-lib-utils/filesystem/binding/data_buffer.binding.cpp delete mode 100644 source/libs/asura-lib-utils/filesystem/data_buffer.cpp delete mode 100644 source/libs/asura-lib-utils/filesystem/data_buffer.h delete mode 100644 source/libs/asura-lib-utils/filesystem/decoded_data.cpp delete mode 100644 source/libs/asura-lib-utils/filesystem/decoded_data.h delete mode 100644 source/libs/asura-lib-utils/filesystem/reloadable.h delete mode 100644 source/libs/asura-lib-utils/filesystem/resource_manager.cpp delete mode 100644 source/libs/asura-lib-utils/filesystem/resource_manager.h create mode 100644 source/libs/asura-lib-utils/io/binding/_compressor.cpp create mode 100644 source/libs/asura-lib-utils/io/binding/_data_buffer.cpp create mode 100644 source/libs/asura-lib-utils/io/binding/_file.cpp create mode 100644 source/libs/asura-lib-utils/io/binding/_file_data.cpp create mode 100644 source/libs/asura-lib-utils/io/binding/_file_system.cpp create mode 100644 source/libs/asura-lib-utils/io/compressor.cpp create mode 100644 source/libs/asura-lib-utils/io/compressor.h create mode 100644 source/libs/asura-lib-utils/io/data_buffer.cpp create mode 100644 source/libs/asura-lib-utils/io/data_buffer.h create mode 100644 source/libs/asura-lib-utils/io/decoded_data.cpp create mode 100644 source/libs/asura-lib-utils/io/decoded_data.h create mode 100644 source/libs/asura-lib-utils/io/file.cpp create mode 100644 source/libs/asura-lib-utils/io/file.h create mode 100644 source/libs/asura-lib-utils/io/file_data.cpp create mode 100644 source/libs/asura-lib-utils/io/file_data.h create mode 100644 source/libs/asura-lib-utils/io/file_system.cpp create mode 100644 source/libs/asura-lib-utils/io/file_system.h create mode 100644 source/libs/asura-lib-utils/io/reloadable.h create mode 100644 source/libs/asura-lib-utils/manager.hpp create mode 100644 source/libs/asura-lib-utils/singleton.hpp create mode 100644 source/libs/asura-lib-utils/stringmap.cpp create mode 100644 source/libs/asura-lib-utils/stringmap.hpp create mode 100644 source/libs/asura-lib-utils/utils_config.h (limited to 'source/libs/asura-lib-utils') diff --git a/source/libs/asura-lib-utils/filesystem/binding/data_buffer.binding.cpp b/source/libs/asura-lib-utils/filesystem/binding/data_buffer.binding.cpp deleted file mode 100644 index 8e92eee..0000000 --- a/source/libs/asura-lib-utils/filesystem/binding/data_buffer.binding.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include "../data_buffer.h" - -using namespace Luax; - -namespace AsuraEngine -{ - namespace Filesystem - { - - LUAX_REGISTRY(DataBuffer) - { - LUAX_REGISTER_METHODS(state, - { "New", _New }, - { "GetBuffer", _GetBuffer }, - { "GetSize", _GetSize }, - { "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)) - { - byte* bytes; - size_t size; - 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); - } - else - { - return state.ErrorType(1, "number or string"); - } - } - - // lsting, len = databuffer:GetBuffer() - LUAX_IMPL_METHOD(DataBuffer, _GetBuffer) - { - LUAX_SETUP(L, "U"); - - DataBuffer* self = state.GetUserdata(1); - lua_pushlstring(L, self->GetBuffer(), self->GetSize()); - return 2; - } - - // length = databuffer:GetSize() - LUAX_IMPL_METHOD(DataBuffer, _GetSize) - { - LUAX_SETUP(L, "U"); - - DataBuffer* self = state.GetUserdata(1); - lua_pushinteger(L, self->GetSize()); - return 1; - } - - // databuffer:Load(lstring) - // databuffer:Load(src) - LUAX_IMPL_METHOD(DataBuffer, _Load) - { - LUAX_STATE(L); - - DataBuffer* buffer = state.GetUserdata(1); - const byte* data; - size_t size; - if (state.IsType(2, LUA_TSTRING)) - { - data = lua_tolstring(L, 2, &size); - buffer->Load(data, size); - return 0; - } - else if(state.IsType(2, LUA_TUSERDATA)) - { - DataBuffer* src = state.CheckUserdata(2); - buffer->Load(*src); - return 0; - } - else - { - return state.ErrorType(1, "lstring or DataBuffer"); - } - } - - // databuffer:Clear() - LUAX_IMPL_METHOD(DataBuffer, _Clear) - { - LUAX_SETUP(L, "U"); - - DataBuffer* self = state.GetUserdata(1); - self->Clear(); - return 0; - } - - } -} \ No newline at end of file diff --git a/source/libs/asura-lib-utils/filesystem/data_buffer.cpp b/source/libs/asura-lib-utils/filesystem/data_buffer.cpp deleted file mode 100644 index 32a123f..0000000 --- a/source/libs/asura-lib-utils/filesystem/data_buffer.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include -#include "data_buffer.h" - -namespace AsuraEngine -{ - namespace Filesystem - { - - DataBuffer::DataBuffer(DataBuffer& src) - { - Load(src); - } - - DataBuffer::DataBuffer(std::size_t size) - : mSize(size) - , mBytes(nullptr) - { - 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::Load(DataBuffer& db) - { - Load(db.GetBuffer(), db.GetSize()); - } - - void DataBuffer::Load(const void* data, std::size_t size) - { - if (!mBytes || mSize != size) - { - delete[] mBytes; - mBytes = new byte[size]; - } - memcpy(mBytes, data, size); - } - - byte* DataBuffer::GetBuffer() - { - return mBytes; - } - - void DataBuffer::Clear() - { - if (mBytes) - memset(mBytes, 0, mSize); - } - - std::size_t DataBuffer::GetSize() - { - return mSize; - } - - } -} \ No newline at end of file diff --git a/source/libs/asura-lib-utils/filesystem/data_buffer.h b/source/libs/asura-lib-utils/filesystem/data_buffer.h deleted file mode 100644 index 5c80efb..0000000 --- a/source/libs/asura-lib-utils/filesystem/data_buffer.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef __ASURA_ENGINE_DATABUFFER_H__ -#define __ASURA_ENGINE_DATABUFFER_H__ - -#include - -#include "../scripting/portable.hpp" - -namespace AsuraEngine -{ - namespace Filesystem - { - - /// - /// 对内存数据的封装,所有的数据使用Data buffer包装,不直接使用const void*。通过resource manager读取。 - /// - class DataBuffer ASURA_FINAL - : public Scripting::Portable - { - public: - - DataBuffer(DataBuffer& src); - DataBuffer(std::size_t size); - DataBuffer(const void* bytes, std::size_t size); - ~DataBuffer(); - - byte* GetBuffer(); - size_t GetSize(); - - void Load(DataBuffer& db); - void Load(const void* bytes, std::size_t size); - void Clear(); - - private: - - byte* mBytes; - size_t mSize; - - //------------------------------------------------------------------------------------------------------------ - - public: - - LUAX_DECL_FACTORY(DataBuffer); - - LUAX_DECL_METHOD(_New); - LUAX_DECL_METHOD(_GetBuffer); - LUAX_DECL_METHOD(_GetSize); - LUAX_DECL_METHOD(_Load); - LUAX_DECL_METHOD(_Clear); - - }; - - } -} - -#endif \ No newline at end of file diff --git a/source/libs/asura-lib-utils/filesystem/decoded_data.cpp b/source/libs/asura-lib-utils/filesystem/decoded_data.cpp deleted file mode 100644 index 125c652..0000000 --- a/source/libs/asura-lib-utils/filesystem/decoded_data.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "DecodedData.h" -#include "Exceptions/Exception.h" - -namespace AsuraEngine -{ - namespace Filesystem - { - - DecodedData::DecodedData(const DataBuffer* databuffer) - { - Decode(databuffer); - } - - DecodedData::~DecodedData() - { - - } - - } -} diff --git a/source/libs/asura-lib-utils/filesystem/decoded_data.h b/source/libs/asura-lib-utils/filesystem/decoded_data.h deleted file mode 100644 index 49b5815..0000000 --- a/source/libs/asura-lib-utils/filesystem/decoded_data.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef __ASURA_ENGINE_DATA_H__ -#define __ASURA_ENGINE_DATA_H__ - -#include - -#include "../scripting/portable.hpp" - -#include "data_buffer.h" - -namespace AsuraEngine -{ - namespace Filesystem - { - - /// - /// 可以在另一个线程构建的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/filesystem/reloadable.h b/source/libs/asura-lib-utils/filesystem/reloadable.h deleted file mode 100644 index 7c4ea52..0000000 --- a/source/libs/asura-lib-utils/filesystem/reloadable.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __ASURA_ENGINE_RELOADABLE_H__ -#define __ASURA_ENGINE_RELOADABLE_H__ - -#include "../scripting/portable.hpp" - -namespace AsuraEngine -{ - namespace Filesystem - { - - /// - /// 可以重新构建的数据结构。比如图片、音频这种,从外部数据可以直接构建,可以在编辑器内重新构建,适用于不改变handle的资源。 - /// - ASURA_ABSTRACT class Reloadable - { - public: - Reloadable(); - virtual ~Reloadable(); - - // 继承Reloadable的需要提供一个load方法 - - }; - - } -} - -#endif \ No newline at end of file diff --git a/source/libs/asura-lib-utils/filesystem/resource_manager.cpp b/source/libs/asura-lib-utils/filesystem/resource_manager.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/source/libs/asura-lib-utils/filesystem/resource_manager.h b/source/libs/asura-lib-utils/filesystem/resource_manager.h deleted file mode 100644 index 36d46cf..0000000 --- a/source/libs/asura-lib-utils/filesystem/resource_manager.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef __ASURA_ENGINE_RESOURCE_MANAGER_H__ -#define __ASURA_ENGINE_RESOURCE_MANAGER_H__ - -#include - -#include "../scripting/portable.hpp" -#include "data_buffer.h" - -namespace AsuraEngine -{ - namespace Filesystem - { - - /// - /// 资源管理,负责加载、存储资源,指定根目录等。 - /// - class ResourceManager ASURA_FINAL - { - public: - - ResourceManager(); - ~ResourceManager(); - - /// - /// 装载根目录 - /// - void Mount(const std::string& root); - - /// - /// 读取文件并返回一个data buffer,注意如果要确保正确回收内存,在调用处使用unique_ptr - /// - DataBuffer* LoadFile(const std::string& path); - - /// - /// 保存data buffer里的数据 - /// - void SaveFile(const std::string& path, const DataBuffer* buffer); - - //---------------------------------------------------------------------------------------------------------- - - LUAX_DECL_SINGLETON(ResourceManager); - - }; - - } -} - -#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 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..d9eca36 --- /dev/null +++ b/source/libs/asura-lib-utils/io/binding/_data_buffer.cpp @@ -0,0 +1,110 @@ +#include "../data_buffer.h" + +using namespace Luax; + +namespace AsuraEngine +{ + namespace IO + { + + LUAX_REGISTRY(DataBuffer) + { + LUAX_REGISTER_METHODS(state, + { "New", _New }, + { "GetBuffer", _GetData }, + { "GetSize", _GetSize }, + { "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)) + { + byte* bytes; + size_t size; + 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); + } + else + { + return state.ErrorType(1, "number or string"); + } + } + + // lsting, len = databuffer:GetBuffer() + LUAX_IMPL_METHOD(DataBuffer, _GetData) + { + LUAX_SETUP(L, "U"); + + DataBuffer* self = state.GetUserdata(1); + lua_pushlstring(L, self->GetData(), self->GetSize()); + return 2; + } + + // length = databuffer:GetSize() + LUAX_IMPL_METHOD(DataBuffer, _GetSize) + { + LUAX_SETUP(L, "U"); + + DataBuffer* self = state.GetUserdata(1); + lua_pushinteger(L, self->GetSize()); + return 1; + } + + // databuffer:Load(lstring) + // databuffer:Load(src) + LUAX_IMPL_METHOD(DataBuffer, _Load) + { + LUAX_STATE(L); + + DataBuffer* buffer = state.GetUserdata(1); + const byte* data; + size_t size; + if (state.IsType(2, LUA_TSTRING)) + { + data = lua_tolstring(L, 2, &size); + buffer->Load(data, size); + return 0; + } + else if(state.IsType(2, LUA_TUSERDATA)) + { + DataBuffer* src = state.CheckUserdata(2); + buffer->Load(*src); + return 0; + } + else + { + return state.ErrorType(1, "lstring or DataBuffer"); + } + } + + // databuffer:Clear() + LUAX_IMPL_METHOD(DataBuffer, _Clear) + { + LUAX_SETUP(L, "U"); + + DataBuffer* self = state.GetUserdata(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..4120258 --- /dev/null +++ b/source/libs/asura-lib-utils/io/binding/_file.cpp @@ -0,0 +1,186 @@ +#include "../file.h" + +namespace AsuraEngine +{ + namespace IO + { + + LUAX_REGISTRY(File) + { + } + + 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.CheckParam(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.CheckParam(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(2); + if (!db) return state.ErrorType(2, "DataBuffer"); + int len = state.CheckParam(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) + LUAX_IMPL_METHOD(File, _Write) + { + LUAX_PREPARE(L, File); + + DataBuffer* db = state.CheckUserdata(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.CheckParam(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.CheckParam(2); + int size = state.CheckParam(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; + } + + } +} \ 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..56f65f7 --- /dev/null +++ b/source/libs/asura-lib-utils/io/binding/_file_data.cpp @@ -0,0 +1,64 @@ +#include "../file_data.h" + +using namespace std; + +namespace AsuraEngine +{ + namespace IO + { + +#define PREPARE(L) \ + LUAX_STATE(L); \ + FileData* self = state.GetUserdata(1); + + 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) + { + PREPARE(L); + string filename = self->GetFileName(); + state.Push(filename); + return 1; + } + + // extension = filedata:GetExtension() + LUAX_IMPL_METHOD(FileData, _GetExtension) + { + PREPARE(L); + string extension = self->GetExtension(); + state.Push(extension); + return 1; + } + + // name = filedata:GetName() + LUAX_IMPL_METHOD(FileData, _GetName) + { + PREPARE(L); + string extension = self->GetName(); + state.Push(extension); + return 1; + } + + // databuffer = filedata:GetDataBuffer() + LUAX_IMPL_METHOD(FileData, _GetDataBuffer) + { + PREPARE(L); + self->PushLuaxMemberRef(state, self->mDataRef); + return 1; + } + + } +} 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..8cb60bc --- /dev/null +++ b/source/libs/asura-lib-utils/io/binding/_file_system.cpp @@ -0,0 +1,267 @@ +#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.CheckParam(1); + fs->Init(arg0); + return 0; + } + + // successed = Filesystem.Mount(path, mountpoint, prepend) + // successed = Filesystem.Mount(data buffer, archievename, mountpoint, prepend) + LUAX_IMPL_METHOD(Filesystem, _Mount) + { + PREPARE(L); + bool mounted = false; + + if (state.IsType(1, LUA_TSTRING)) + { + cc8* path = state.GetValue(1, ""); + cc8* moutpoint = state.GetValue(2, "/"); + bool prepend = state.GetValue(3, false); + mounted = fs->Mount(path, moutpoint, prepend); + } + else if (state.IsType(1, LUA_TUSERDATA)) + { + DataBuffer* db = state.CheckUserdata(1); + if (!db) + return state.ErrorType(1, "Data Buffer"); + cc8* arcname = state.GetValue(2, ""); + cc8* mountpoint = state.GetValue(3, "/"); + bool prepend = state.GetValue(4, false); + mounted = fs->Mount(db, arcname, mountpoint, prepend); + // retain + fs->LuaxRetain(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(1, ""); + unmounted = fs->Unmount(path); + } + else if (state.IsType(1, LUA_TUSERDATA)) + { + DataBuffer* db = state.CheckUserdata(1); + if (!db) + return state.ErrorType(1, "Data Buffer"); + unmounted = fs->Unmount(db); + if (unmounted) + fs->LuaxRelease(state, db); + } + state.Push(unmounted); + return 1; + } + + // moutpoint = Filesystem.GetMountPoint(path) + LUAX_IMPL_METHOD(Filesystem, _GetMountPoint) + { + PREPARE(L); + + cc8* path = state.CheckParam(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.CheckParam(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.CheckParam(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.CheckParam(1); + state.Push(fs->NewDirectory(path)); + return 1; + } + + // successed = Filesystem.Write(path, data buffer) + LUAX_IMPL_METHOD(Filesystem, _Write) + { + PREPARE(L); + + cc8* path = state.CheckParam(1); + DataBuffer* db = state.CheckUserdata(2); + state.Push(fs->Write(path, db)); + return 1; + } + + // successed = Filesystem.Append(path, data buffer) + LUAX_IMPL_METHOD(Filesystem, _Write) + { + PREPARE(L); + + cc8* path = state.CheckParam(1); + DataBuffer* db = state.CheckUserdata(2); + state.Push(fs->Append(path, db)); + return 1; + } + + // successed = Filesystem.Remove(path) + LUAX_IMPL_METHOD(Filesystem, _Remove) + { + PREPARE(L); + + cc8* path = state.CheckParam(1); + state.Push(fs->Remove(path)); + return 1; + } + + // filedata = Filesystem.Read(path) + LUAX_IMPL_METHOD(Filesystem, _Read) + { + PREPARE(L); + + cc8* path = state.CheckParam(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) + // fileinfo的格式如下: + // {size = , modtime = , type =} + LUAX_IMPL_METHOD(Filesystem, _GetFileInfo) + { + PREPARE(L); + + cc8* path = state.CheckParam(1); + FileInfo info; + if (fs->GetFileInfo(path, &info)) + { + lua_newtable(L); // info table + state.SetField(-1, "size", info.size); + state.SetField(-1, "modetime", 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.CheckParam(1); + std::vector 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; + } + + } +} 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 + { + 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..98675e9 --- /dev/null +++ b/source/libs/asura-lib-utils/io/data_buffer.cpp @@ -0,0 +1,77 @@ +#include +#include +#include "data_buffer.h" + +namespace AsuraEngine +{ + namespace IO + { + + DataBuffer::DataBuffer(DataBuffer& src) + { + Load(src); + } + + DataBuffer::DataBuffer(std::size_t size) + : mSize(size) + , mBytes(nullptr) + { + 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::Load(DataBuffer& db) + { + Load(db.GetData(), db.GetSize()); + } + + void DataBuffer::Load(const void* data, std::size_t size) + { + if (!mBytes || mSize != size) + { + delete[] mBytes; + mBytes = new byte[size]; + } + memcpy(mBytes, data, size); + } + + void DataBuffer::Move(void* bytes, std::size_t size) + { + if (!mBytes) + { + delete[] mBytes; + } + mBytes = (byte*)bytes; + mSize = size; + } + + byte* DataBuffer::GetData() + { + return mBytes; + } + + void DataBuffer::Clear() + { + if (mBytes) + memset(mBytes, 0, mSize); + } + + std::size_t DataBuffer::GetSize() + { + return mSize; + } + + } +} \ 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..c7383fa --- /dev/null +++ b/source/libs/asura-lib-utils/io/data_buffer.h @@ -0,0 +1,54 @@ +#ifndef __ASURA_ENGINE_DATABUFFER_H__ +#define __ASURA_ENGINE_DATABUFFER_H__ + +#include + +#include "../scripting/portable.hpp" + +namespace AsuraEngine +{ + namespace IO + { + + /// + /// 对内存数据的封装,所有的数据使用Data buffer包装,不直接使用const void*。通过resource manager读取。 + /// + class DataBuffer ASURA_FINAL + : public AEScripting::Portable + { + 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 Load(DataBuffer& db); + void Load(const void* bytes, std::size_t size); + void Move(void* bytes, std::size_t size); + void Clear(); + + private: + + byte* mBytes; + size_t mSize; + + LUAX_DECL_METHOD(_New); + LUAX_DECL_METHOD(_GetData); + LUAX_DECL_METHOD(_GetSize); + 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..b208455 --- /dev/null +++ b/source/libs/asura-lib-utils/io/decoded_data.cpp @@ -0,0 +1,20 @@ +#include "DecodedData.h" +#include "Exceptions/Exception.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 + +#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..092a90d --- /dev/null +++ b/source/libs/asura-lib-utils/io/file.cpp @@ -0,0 +1,286 @@ +#include + +#include + +#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; + + 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; + + 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 != nullptr && !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."); + + return PHYSFS_readBytes(mFileHandle, dst->GetData(), length); + } + + 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."); + + return PHYSFS_readBytes(mFileHandle, dst->GetData(), length); + } + +#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..e8f676e --- /dev/null +++ b/source/libs/asura-lib-utils/io/file.h @@ -0,0 +1,132 @@ +#ifndef __ASURA_ENGINE_FILE_H__ +#define __ASURA_ENGINE_FILE_H__ + +#include "physfs/physfs.h" + +#include "../scripting/portable.hpp" + +#include "file_data.h" + +namespace AsuraEngine +{ + namespace IO + { + + /// + /// 以流的形式打开文件,可以指定读写起点、大小。在期望使用流读取时使用本类,否则使用Filesystem.read()直接读取文件全部 + /// 内容,并返回一个FileData对象。 + /// + class File ASURA_FINAL + : public AEScripting::Portable + { + 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); + + /// + /// 是否读到了文件结尾 + /// + bool IsEOF(); + + /// + /// 将data buffer中的内容写入,并返回是否成功 + /// + bool Write(ASURA_REF DataBuffer* src); + + /// + /// 如果开启了缓冲,强制清空缓冲区,写入文件。 + /// + 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_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(_IsEOF); + LUAX_DECL_METHOD(_Write); + LUAX_DECL_METHOD(_Flush); + LUAX_DECL_METHOD(_Tell); + LUAX_DECL_METHOD(_Seek); + LUAX_DECL_METHOD(_SetBuffer); + LUAX_DECL_METHOD(_GetBuffer); + LUAX_DECL_METHOD(_GetFileName); + + }; + + } +} + +#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..47d9095 --- /dev/null +++ b/source/libs/asura-lib-utils/io/file_data.cpp @@ -0,0 +1,57 @@ +#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() + { + } + + void FileData::BindData(DataBuffer* buffer) + { + mData = buffer; + } + + 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..e20f41b --- /dev/null +++ b/source/libs/asura-lib-utils/io/file_data.h @@ -0,0 +1,68 @@ +#ifndef __ASURA_ENGINE_FILE_DATA_H__ +#define __ASURA_ENGINE_FILE_DATA_H__ + +#include + +#include + +#include "data_buffer.h" + +namespace AsuraEngine +{ + namespace IO + { + + class Filesystem; + + /// + /// 当从filesystem直接读取整个文件时,返回FileData对象描述文件内容和其他信息。由Filesystem创建。 + /// + class FileData ASURA_FINAL + : public AEScripting::Portable + { + public: + + LUAX_DECL_FACTORY(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); + ~FileData(); + + /// + /// 绑定data buffer。 + /// + void BindData(ASURA_MOVE DataBuffer* buffer); + + /// + /// Data buffer不会再filedata析构时销毁,当lua引用计数为0时由lua调用GC销毁。创建mData时会添加一个成员引用。 + /// + ASURA_REF DataBuffer* mData; + Luax::LuaxMemberRef mDataRef; + + std::string mFileName; ///< 包含扩展名的文件名 + std::string mExtension; ///< 不包含点的扩展名 + std::string mName; ///< 不包含点和后缀的文件名 + + LUAX_DECL_METHOD(_GetFileName); + LUAX_DECL_METHOD(_GetExtension); + LUAX_DECL_METHOD(_GetName); + LUAX_DECL_METHOD(_GetDataBuffer); + + }; + + } +} + +#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 + +#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 + #include +#else + #include + #include +#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..1af0292 --- /dev/null +++ b/source/libs/asura-lib-utils/io/file_system.h @@ -0,0 +1,110 @@ +#ifndef __ASURA_ENGINE_FILESYSTEM_H__ +#define __ASURA_ENGINE_FILESYSTEM_H__ + +#include +#include + +#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; + }; + + /// + /// 资源管理,负责加载、存储资源,指定根目录等。无论编辑器还是运行时,都需要限制访问的机制,将用户的操作限制在游戏目录 + /// 下,file system就是做这件事的。Filesystem是运行时和编辑器共用的类,AssetDatabase是用来管理资源的类,在framework + /// 里实现,单纯是逻辑处理,读写还是用Filesystem实现,AssetDatabase提供根据文件内容创建对应资源的方法。 + /// + class Filesystem ASURA_FINAL + : public Singleton + , public AEScripting::Portable + { + public: + + LUAX_DECL_SINGLETON(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& items); + + private: + + typedef std::map 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/reloadable.h b/source/libs/asura-lib-utils/io/reloadable.h new file mode 100644 index 0000000..cf30296 --- /dev/null +++ b/source/libs/asura-lib-utils/io/reloadable.h @@ -0,0 +1,27 @@ +#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方法 + + }; + + } +} + +#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/rect.hpp b/source/libs/asura-lib-utils/math/rect.hpp index f635007..1751634 100644 --- a/source/libs/asura-lib-utils/math/rect.hpp +++ b/source/libs/asura-lib-utils/math/rect.hpp @@ -13,8 +13,20 @@ namespace AsuraEngine Rect(); ~Rect(T x, T y, T w, T h); - template - explicit Rect(const Rect& rect); + /// + /// x,y是否落在rect内。 + /// + bool Contain(T x, T y); + + /// + /// 两个矩形是否相交,并返回相交的矩形 + /// + bool Intersect(const Rect& src, Rect& intersection); + + /// + /// 两个矩形是否相交,并返回相交的矩形 + /// + static bool Intersect(const Rect& src1, const Rect& src2, Rect& intersection); T x, y, w, h; }; @@ -25,8 +37,11 @@ namespace AsuraEngine typedef Rect Recti; typedef Rect Rectu; typedef Rect Rectf; + typedef Rect Reftl; } } +namespace AEMath = AsuraEngine::Math; + #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 index 00ede90..097a9fe 100644 --- a/source/libs/asura-lib-utils/scripting/portable.hpp +++ b/source/libs/asura-lib-utils/scripting/portable.hpp @@ -21,7 +21,14 @@ namespace AsuraEngine template using Portable = Luax::LuaxNativeClass; + /// + /// 需要作为基类,访问userdata和member 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..756209a --- /dev/null +++ b/source/libs/asura-lib-utils/singleton.hpp @@ -0,0 +1,59 @@ +#ifndef __ASURA_SINGLETON_H__ +#define __ASURA_SINGLETON_H__ + +#include "Config.h" + +namespace AsuraEngine +{ + + /// + /// 继承Singleton的类在第一次实例化时保存实例,之后如果再次实例化会报错。 + /// + template + 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(this); + }; + + virtual ~Singleton() {}; + + static T* instance; + + private: + + Singleton(const Singleton& singleton); + + Singleton& operator = (const Singleton& singleton); + + }; + + // 实例初始化为空 + template + T* Singleton::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 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 + +namespace AsuraEngine +{ + + /// + /// 一个双向一一对应的映射,用来储存shader uniforms、statemathine state parameter的ID。 + /// + template + 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/type.h b/source/libs/asura-lib-utils/type.h index 72ed8cc..aa00108 100644 --- a/source/libs/asura-lib-utils/type.h +++ b/source/libs/asura-lib-utils/type.h @@ -25,6 +25,8 @@ namespace AsuraEngine typedef std::size_t size_t; + typedef const char cc8; + //---------------------------------------------------------------------------------------------------------------- #ifndef ASSERT @@ -51,6 +53,8 @@ namespace AsuraEngine #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"))) @@ -61,6 +65,16 @@ namespace AsuraEngine #define ASURA_ABSTRACT #define ASURA_API ASURA_LIBRARY_EXPORT #endif + + /// + /// 表明输出和引用参数 + /// +#define ASURA_OUT +#define ASURA_REF + /// + /// 表明移动指针所有权 + /// +#define ASURA_MOVE //---------------------------------------------------------------------------------------------------------------- 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..e69de29 -- cgit v1.1-26-g67d0