summaryrefslogtreecommitdiff
path: root/Source/modules/asura-base/FileSystem
diff options
context:
space:
mode:
Diffstat (limited to 'Source/modules/asura-base/FileSystem')
-rw-r--r--Source/modules/asura-base/FileSystem/Binding/_compressor.cpp0
-rw-r--r--Source/modules/asura-base/FileSystem/Binding/_data_buffer.cpp132
-rw-r--r--Source/modules/asura-base/FileSystem/Binding/_file.cpp223
-rw-r--r--Source/modules/asura-base/FileSystem/Binding/_file_data.cpp60
-rw-r--r--Source/modules/asura-base/FileSystem/Binding/_file_manager.cpp265
-rw-r--r--Source/modules/asura-base/FileSystem/Binding/_io_task.cpp46
-rw-r--r--Source/modules/asura-base/FileSystem/Compressor.cpp11
-rw-r--r--Source/modules/asura-base/FileSystem/Compressor.h28
-rw-r--r--Source/modules/asura-base/FileSystem/DataBuffer.cpp156
-rw-r--r--Source/modules/asura-base/FileSystem/DataBuffer.h87
-rw-r--r--Source/modules/asura-base/FileSystem/DecodedData.h41
-rw-r--r--Source/modules/asura-base/FileSystem/File.cpp294
-rw-r--r--Source/modules/asura-base/FileSystem/File.h146
-rw-r--r--Source/modules/asura-base/FileSystem/FileData.cpp59
-rw-r--r--Source/modules/asura-base/FileSystem/FileData.h69
-rw-r--r--Source/modules/asura-base/FileSystem/FileManager.cpp198
-rw-r--r--Source/modules/asura-base/FileSystem/FileManager.h112
-rw-r--r--Source/modules/asura-base/FileSystem/IOBatchTask.cpp0
-rw-r--r--Source/modules/asura-base/FileSystem/IOBatchTask.h31
-rw-r--r--Source/modules/asura-base/FileSystem/IOTask.cpp61
-rw-r--r--Source/modules/asura-base/FileSystem/IOTask.h56
-rw-r--r--Source/modules/asura-base/FileSystem/Renewable.h27
22 files changed, 2102 insertions, 0 deletions
diff --git a/Source/modules/asura-base/FileSystem/Binding/_compressor.cpp b/Source/modules/asura-base/FileSystem/Binding/_compressor.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/Binding/_compressor.cpp
diff --git a/Source/modules/asura-base/FileSystem/Binding/_data_buffer.cpp b/Source/modules/asura-base/FileSystem/Binding/_data_buffer.cpp
new file mode 100644
index 0000000..ff1f0dc
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/Binding/_data_buffer.cpp
@@ -0,0 +1,132 @@
+#include "../DataBuffer.h"
+
+using namespace Luax;
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ LUAX_REGISTRY(DataBuffer)
+ {
+ LUAX_REGISTER_METHODS(state,
+ { "New", _New },
+ { "GetData", _GetData },
+ { "GetSize", _GetSize },
+ { "GetCapacity", _GetCapacity },
+ { "Refactor", _Refactor },
+ { "Load", _Load },
+ { "Clear", _Clear }
+ );
+ }
+
+ LUAX_POSTPROCESS(DataBuffer)
+ {
+ }
+
+ // databuffer = DataBuffer.New(lstring)
+ // databuffer = DataBuffer.New(capacity)
+ 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 capacity = lua_tonumber(L, 1);
+ DataBuffer* buffer = new DataBuffer(capacity);
+ 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;
+ }
+
+ // capacity = databuffer:GetCapacity()
+ LUAX_IMPL_METHOD(DataBuffer, _GetCapacity)
+ {
+ LUAX_SETUP(L, "U");
+
+ DataBuffer* self = state.GetUserdata<DataBuffer>(1);
+ lua_pushinteger(L, self->GetCapacity());
+ return 1;
+ }
+
+ // databuffer:Refactor(capacity)
+ LUAX_IMPL_METHOD(DataBuffer, _Refactor)
+ {
+ LUAX_PREPARE(L, DataBuffer);
+
+ size_t capacity = state.CheckValue<int>(2);
+ self->Refactor(capacity);
+ 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);
+ buffer->Load(data, size);
+ return 0;
+ }
+ else if(state.IsType(2, LUA_TUSERDATA))
+ {
+ DataBuffer* src = state.CheckUserdata<DataBuffer>(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<DataBuffer>(1);
+ self->Clear();
+ return 0;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Source/modules/asura-base/FileSystem/Binding/_file.cpp b/Source/modules/asura-base/FileSystem/Binding/_file.cpp
new file mode 100644
index 0000000..d19c02a
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/Binding/_file.cpp
@@ -0,0 +1,223 @@
+#include "../file.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ 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/modules/asura-base/FileSystem/Binding/_file_data.cpp b/Source/modules/asura-base/FileSystem/Binding/_file_data.cpp
new file mode 100644
index 0000000..ca872d2
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/Binding/_file_data.cpp
@@ -0,0 +1,60 @@
+#include "../FileData.h"
+
+using namespace std;
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ 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->m_DataRef);
+ return 1;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Source/modules/asura-base/FileSystem/Binding/_file_manager.cpp b/Source/modules/asura-base/FileSystem/Binding/_file_manager.cpp
new file mode 100644
index 0000000..7781d99
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/Binding/_file_manager.cpp
@@ -0,0 +1,265 @@
+#include "../FileManager.h"
+
+using namespace Luax;
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+#define PREPARE(l) \
+ LUAX_STATE(l); \
+ FileManager* fs = FileManager::Get();
+
+ LUAX_REGISTRY(FileManager)
+ {
+ 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(FileManager)
+ {
+ LUAX_REGISTER_ENUM(state, "EFileType",
+ { "FILE", FILE_TYPE_FILE },
+ { "DIRECTORY", FILE_TYPE_DIRECTORY },
+ { "SYMLINK", FILE_TYPE_SYMLINK },
+ { "OTHER", FILE_TYPE_OTHER }
+ );
+ }
+
+ // FileManager.Init(arg0)
+ LUAX_IMPL_METHOD(FileManager, _Init)
+ {
+ PREPARE(L);
+
+ const char* arg0 = state.CheckValue<const char*>(1);
+ fs->Init(arg0);
+ return 0;
+ }
+
+ // successed = FileManager.Mount(path, mountpoint[, prepend = false])
+ // successed = FileManager.Mount(data buffer, archievename, mountpoint[, prepend = false])
+ LUAX_IMPL_METHOD(FileManager, _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 = FileManager.Unmount(path)
+ // successed = FileManager.Unmount(data buffer)
+ LUAX_IMPL_METHOD(FileManager, _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 = FileManager.GetMountPoint(path)
+ LUAX_IMPL_METHOD(FileManager, _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;
+ }
+
+ // FileManager.SetWriteDirectory(dir)
+ LUAX_IMPL_METHOD(FileManager, _SetWriteDirectory)
+ {
+ PREPARE(L);
+
+ cc8* dir = state.CheckValue<cc8*>(1);
+ fs->SetWriteDirectory(dir);
+ return 0;
+ }
+
+ // dir = FileManager.GetWriteDirectory()
+ LUAX_IMPL_METHOD(FileManager, _GetWriteDirectory)
+ {
+ PREPARE(L);
+
+ std::string dir = fs->GetWriteDirectory();
+ state.Push(dir);
+ return 1;
+ }
+
+ // file = FileManager.CreateFile(name)
+ LUAX_IMPL_METHOD(FileManager, _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 = FileManager.CreateDirectory(name)
+ LUAX_IMPL_METHOD(FileManager, _CreateDirectory)
+ {
+ PREPARE(L);
+
+ cc8* path = state.CheckValue<cc8*>(1);
+ state.Push(fs->NewDirectory(path));
+ return 1;
+ }
+
+ // successed = FileManager.Write(path, data buffer)
+ LUAX_IMPL_METHOD(FileManager, _Write)
+ {
+ PREPARE(L);
+
+ cc8* path = state.CheckValue<cc8*>(1);
+ DataBuffer* db = state.CheckUserdata<DataBuffer>(2);
+ state.Push(fs->Write(path, db));
+ return 1;
+ }
+
+ // successed = FileManager.Append(path, data buffer)
+ LUAX_IMPL_METHOD(FileManager, _Append)
+ {
+ PREPARE(L);
+
+ cc8* path = state.CheckValue<cc8*>(1);
+ DataBuffer* db = state.CheckUserdata<DataBuffer>(2);
+ state.Push(fs->Append(path, db));
+ return 1;
+ }
+
+ // successed = FileManager.Remove(path)
+ LUAX_IMPL_METHOD(FileManager, _Remove)
+ {
+ PREPARE(L);
+
+ cc8* path = state.CheckValue<cc8*>(1);
+ state.Push(fs->Remove(path));
+ return 1;
+ }
+
+ // filedata = FileManager.Read(path)
+ LUAX_IMPL_METHOD(FileManager, _Read)
+ {
+ PREPARE(L);
+
+ cc8* path = state.CheckValue<cc8*>(1);
+ FileData* fd = fs->Read(path);
+ if (fd)
+ {
+ fd->m_Data->PushLuaxUserdata(state);
+ fd->SetLuaxMemberRef(state, fd->m_DataRef, -1); // fd->m_DataRef = data buffer
+ state.Pop(1); // data buffer
+ fd->PushLuaxUserdata(state);
+ }
+ else
+ {
+ state.PushNil();
+ }
+ return 1;
+ }
+
+ // fileinfo = FileManager.GetFileInfo(path)
+ LUAX_IMPL_METHOD(FileManager, _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 = FileManager.GetDirectoryItems(path)
+ LUAX_IMPL_METHOD(FileManager, _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/modules/asura-base/FileSystem/Binding/_io_task.cpp b/Source/modules/asura-base/FileSystem/Binding/_io_task.cpp
new file mode 100644
index 0000000..a3d82d5
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/Binding/_io_task.cpp
@@ -0,0 +1,46 @@
+#include "../IOTask.h"
+
+using namespace std;
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ 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->m_BufferRef, 2);
+ if(cbk)
+ task->SetLuaxMemberRef(state, task->m_Callback, 4);
+ task->PushLuaxUserdata(state);
+ return 1;
+ }
+
+ }
+}
diff --git a/Source/modules/asura-base/FileSystem/Compressor.cpp b/Source/modules/asura-base/FileSystem/Compressor.cpp
new file mode 100644
index 0000000..eaa59a2
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/Compressor.cpp
@@ -0,0 +1,11 @@
+#include "Compressor.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+
+
+ }
+} \ No newline at end of file
diff --git a/Source/modules/asura-base/FileSystem/Compressor.h b/Source/modules/asura-base/FileSystem/Compressor.h
new file mode 100644
index 0000000..9fd0808
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/Compressor.h
@@ -0,0 +1,28 @@
+#ifndef _ASURA_COMPRESSOR_H_
+#define _ASURA_COMPRESSOR_H_
+
+#include "../Scripting/Scripting.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ 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/modules/asura-base/FileSystem/DataBuffer.cpp b/Source/modules/asura-base/FileSystem/DataBuffer.cpp
new file mode 100644
index 0000000..71431e1
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/DataBuffer.cpp
@@ -0,0 +1,156 @@
+#include <cstdlib>
+#include <cstring>
+#include "DataBuffer.h"
+
+using namespace AEThreading;
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ DataBuffer::DataBuffer(DataBuffer& src)
+ : m_Size(0)
+ , m_Capacity(0)
+ , m_Bytes(nullptr)
+ {
+ // ʼ
+ lock(m_Mutex)
+ {
+ m_Capacity = src.m_Size;
+ m_Bytes = new byte[m_Capacity];
+ Clear();
+
+ Load(src);
+ }
+ }
+
+ DataBuffer::DataBuffer(std::size_t capacity)
+ : m_Size(0)
+ , m_Capacity(0)
+ , m_Bytes(nullptr)
+ {
+ lock(m_Mutex)
+ {
+ m_Capacity = capacity;
+ m_Bytes = new byte[m_Capacity];
+ Clear();
+ }
+ }
+
+ DataBuffer::DataBuffer(const void* data, std::size_t size)
+ : m_Capacity(0)
+ , m_Size(0)
+ , m_Bytes(nullptr)
+ {
+ lock(m_Mutex)
+ {
+ m_Capacity = size;
+ m_Bytes = new byte[m_Capacity];
+ Clear();
+
+ Load(data, size);
+ }
+ }
+
+ DataBuffer::~DataBuffer()
+ {
+ lock(m_Mutex)
+ {
+ delete[] m_Bytes;
+ }
+ }
+
+ void DataBuffer::Refactor(size_t capacity)
+ {
+ lock(m_Mutex)
+ {
+ if (!m_Bytes || m_Capacity != capacity)
+ {
+ if(m_Bytes)
+ delete[] m_Bytes;
+ m_Capacity = capacity;
+ m_Bytes = new byte[m_Capacity];
+ m_Size = 0;
+ }
+ Clear();
+ }
+ }
+
+ void DataBuffer::Load(DataBuffer& db)
+ {
+ lock(m_Mutex)
+ {
+ Load(db.GetData(), db.GetSize());
+ }
+ }
+
+ void DataBuffer::Load(const void* data, std::size_t size)
+ {
+ lock(m_Mutex)
+ {
+ ASSERT(m_Capacity >= size);
+ memcpy(m_Bytes, data, size);
+ m_Size = size;
+ }
+ }
+
+ void DataBuffer::Move(void* bytes, std::size_t size)
+ {
+ lock(m_Mutex)
+ {
+ if (m_Bytes == bytes)
+ {
+ // sizeֵڶļʱ
+ m_Size = size;
+ }
+ else
+ {
+ if (m_Bytes)
+ delete[] m_Bytes;
+ m_Bytes = (byte*)bytes;
+ m_Size = size;
+ m_Capacity = size;
+ }
+ }
+ }
+
+ byte* DataBuffer::GetData()
+ {
+ return m_Bytes;
+ }
+
+ void DataBuffer::Clear()
+ {
+ lock(m_Mutex)
+ {
+ if (m_Bytes)
+ {
+ memset(m_Bytes, 0, m_Size);
+ m_Size = 0;
+ }
+ }
+ }
+
+ std::size_t DataBuffer::GetSize()
+ {
+ return m_Size;
+ }
+
+ std::size_t DataBuffer::GetCapacity()
+ {
+ return m_Capacity;
+ }
+
+ void DataBuffer::Lock()
+ {
+ m_Mutex.Lock();
+ }
+
+ void DataBuffer::Unlock()
+ {
+ m_Mutex.Unlock();
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Source/modules/asura-base/FileSystem/DataBuffer.h b/Source/modules/asura-base/FileSystem/DataBuffer.h
new file mode 100644
index 0000000..ace372e
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/DataBuffer.h
@@ -0,0 +1,87 @@
+#ifndef _ASURA_ENGINE_DATABUFFER_H_
+#define _ASURA_ENGINE_DATABUFFER_H_
+
+#include <cstdlib>
+
+#include "../Scripting/Scripting.h"
+#include "../Threads/Mutex.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ ///
+ /// ڴݵķװеʹ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 capacity);
+ DataBuffer(const void* bytes, std::size_t size);
+ ~DataBuffer();
+
+ byte* GetData();
+ size_t GetSize();
+ size_t GetCapacity();
+
+ ///
+ /// ޸
+ ///
+ void Refactor(size_t capacity);
+
+ ///
+ /// Դ˻
+ ///
+ void Load(DataBuffer& db);
+ void Load(const void* bytes, std::size_t size);
+
+ ///
+ /// bytesӵȨcapacityΪsize
+ ///
+ void Move(void* bytes, std::size_t size);
+
+ ///
+ ///
+ ///
+ void Clear();
+
+ void Lock();
+ void Unlock();
+
+ private:
+
+ LUAX_DECL_METHOD(_New);
+ LUAX_DECL_METHOD(_GetData);
+ LUAX_DECL_METHOD(_GetSize);
+ LUAX_DECL_METHOD(_GetCapacity);
+ LUAX_DECL_METHOD(_Refactor);
+ LUAX_DECL_METHOD(_Load);
+ LUAX_DECL_METHOD(_Clear);
+
+ ///
+ /// Buffer׵ַݵij
+ ///
+ byte* m_Bytes;
+ size_t m_Size;
+
+ ///
+ /// Buffer
+ ///
+ size_t m_Capacity;
+
+ AEThreading::Mutex m_Mutex;
+
+ };
+
+ }
+}
+
+namespace AEFileSystem = AsuraEngine::FileSystem;
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/FileSystem/DecodedData.h b/Source/modules/asura-base/FileSystem/DecodedData.h
new file mode 100644
index 0000000..1744233
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/DecodedData.h
@@ -0,0 +1,41 @@
+#ifndef _ASURA_ENGINE_DATA_H_
+#define _ASURA_ENGINE_DATA_H_
+
+#include <cstdlib>
+
+#include <asura-base/Threads/Thread.h>
+
+#include "../Scripting/Scripting.h"
+
+#include "DataBuffer.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ ///
+ /// һ̹߳data̳дࡣͼƬݡƵݵȣһ߳нԭ
+ /// ļڲݸʽصȡ
+ ///
+ ASURA_ABSTRACT class DecodedData
+ {
+ public:
+
+ ///
+ /// ڴйdataԷһ߳棬Դϵͳء
+ ///
+ DecodedData() {};
+ virtual ~DecodedData() {};
+
+ ///
+ /// ڴеݲijָʽ档
+ ///
+ virtual void Decode(DataBuffer& buffer) = 0;
+
+ };
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/FileSystem/File.cpp b/Source/modules/asura-base/FileSystem/File.cpp
new file mode 100644
index 0000000..ec8a9bf
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/File.cpp
@@ -0,0 +1,294 @@
+#include <physfs/physfs.h>
+
+#include <asura-base/Exception.h>
+
+#include "File.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ File::File(const std::string& filename)
+ : m_FileName(filename)
+ , m_FileHandle(nullptr)
+ , m_Mode(FILE_MODE_CLOSED)
+ , m_BufferMode(BUFFER_MODE_NONE)
+ , m_BufferSize(0)
+ {
+ size_t dot = filename.rfind('.');
+ if (dot != std::string::npos)
+ {
+ m_Extension = filename.substr(dot + 1);
+ m_Name = filename.substr(0, dot);
+ }
+ else
+ m_Name = filename;
+ }
+
+ File::~File()
+ {
+ if (m_Mode != 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(m_FileName.c_str()))
+ throw Exception("Could NOT open file %s. Does not exist.", m_FileName.c_str());
+
+ if (mode == FILE_MODE_APPEND || mode == FILE_MODE_WRITE)
+ {
+ if (!PHYSFS_getWriteDir())
+ {
+ throw Exception("Could NOT set write directory.");
+ }
+ }
+
+ // Ѿ֮ǰ򿪹Ͳٴµhandle
+ if (m_FileHandle != nullptr)
+ return true;
+
+ PHYSFS_getLastErrorCode();
+
+ PHYSFS_File* handle = nullptr;
+
+ switch (mode)
+ {
+ case FILE_MODE_READ:
+ handle = PHYSFS_openRead(m_FileName.c_str());
+ break;
+ case FILE_MODE_APPEND:
+ handle = PHYSFS_openAppend(m_FileName.c_str());
+ break;
+ case FILE_MODE_WRITE:
+ handle = PHYSFS_openWrite(m_FileName.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)", m_FileName.c_str(), err);
+ }
+
+ m_FileHandle = handle;
+ m_Mode = mode;
+
+ if (m_FileHandle && !SetBuffer(m_BufferMode,m_BufferSize))
+ {
+ m_BufferMode = BUFFER_MODE_NONE;
+ m_BufferSize = 0;
+ }
+
+ return m_FileHandle != nullptr;
+ }
+
+ bool File::Close()
+ {
+ if (m_FileHandle == nullptr || !PHYSFS_close(m_FileHandle))
+ return false;
+ m_Mode = FILE_MODE_CLOSED;
+ m_FileHandle = nullptr;
+ return true;
+ }
+
+ bool File::IsOpen()
+ {
+ return m_Mode != FILE_MODE_CLOSED && m_FileHandle != nullptr;
+ }
+
+ size_t File::GetSize()
+ {
+ if (m_FileHandle == nullptr)
+ {
+ Open(FILE_MODE_READ);
+ size_t size = PHYSFS_fileLength(m_FileHandle);
+ Close();
+ return size;
+ }
+ return PHYSFS_fileLength(m_FileHandle);
+ }
+
+ size_t File::Read(ASURA_OUT DataBuffer* dst, size_t length)
+ {
+ ASSERT(dst);
+
+ if (dst->GetCapacity() < length)
+ throw Exception("Data buffer is too small compares to read length.");
+
+ if (!m_FileHandle || m_Mode != FILE_MODE_READ)
+ throw Exception("File \"%s\" is not opened for reading", m_FileName);
+
+ size_t max = PHYSFS_fileLength(m_FileHandle);
+ length = (length > max) ? max : length;
+
+ if (length < 0)
+ throw Exception("Invalid read size.");
+
+ dst->Lock();
+ size_t size = PHYSFS_readBytes(m_FileHandle, dst->GetData(), length);
+ dst->Unlock();
+ return size;
+ }
+
+ size_t File::ReadAll(ASURA_OUT DataBuffer* dst)
+ {
+ ASSERT(dst);
+
+ if (!m_FileHandle || m_Mode != FILE_MODE_READ)
+ throw Exception("File \"%s\" is not opened for reading", m_FileName);
+
+ size_t length = PHYSFS_fileLength(m_FileHandle);
+
+ if (dst->GetCapacity() < length)
+ throw Exception("Data buffer is too small compares to file length.");
+
+ dst->Lock();
+ byte* data = dst->GetData();
+ size_t size = PHYSFS_readBytes(m_FileHandle, data, length);
+ dst->Move(data, 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 m_FileHandle == nullptr || test_eof(this, m_FileHandle);
+ }
+
+ size_t File::Tell()
+ {
+ if (!m_FileHandle)
+ return - 1;
+
+ return PHYSFS_tell(m_FileHandle);
+ }
+
+ bool File::Seek(size_t pos)
+ {
+ return m_FileHandle != nullptr && PHYSFS_seek(m_FileHandle, pos) != 0;
+ }
+
+ bool File::Write(ASURA_REF DataBuffer* src)
+ {
+ if (!m_FileHandle || (m_Mode != FILE_MODE_APPEND && m_Mode != 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(m_FileHandle, data, size);
+
+ if (written != src->GetSize())
+ return false;
+
+ // л
+ if (m_BufferSize == BUFFER_MODE_LINE && m_BufferSize > size)
+ {
+ if (memchr(data, '\n', size) != nullptr)
+ Flush();
+ }
+
+ return true;
+ }
+
+ bool File::Flush()
+ {
+ if (!m_FileHandle || (m_Mode != FILE_MODE_WRITE && m_Mode != FILE_MODE_APPEND))
+ throw Exception("File is not opened for writing.");
+
+ return PHYSFS_flush(m_FileHandle) != 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())
+ {
+ m_BufferMode = mode;
+ m_BufferSize = size;
+ return true;
+ }
+
+ int ret = 1;
+
+ switch (mode)
+ {
+ case BUFFER_MODE_NONE:
+ default:
+ ret = PHYSFS_setBuffer(m_FileHandle, 0);
+ size = 0;
+ break;
+ case BUFFER_MODE_LINE:
+ case BUFFER_MODE_FULL:
+ ret = PHYSFS_setBuffer(m_FileHandle, size);
+ break;
+ }
+
+ if (ret == 0)
+ return false;
+
+ m_BufferMode = mode;
+ m_BufferSize = size;
+
+ return true;
+ }
+
+ File::BufferMode File::GetBuffer(ASURA_OUT size_t& size)
+ {
+ size = m_BufferSize;
+ return m_BufferMode;
+ }
+
+ const std::string& File::GetFileName()
+ {
+ return m_FileName;
+ }
+
+ const std::string& File::GetName()
+ {
+ return m_Name;
+ }
+
+ const std::string& File::GetExtension()
+ {
+ return m_Extension;
+ }
+
+ File::FileMode File::GetMode()
+ {
+ return m_Mode;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Source/modules/asura-base/FileSystem/File.h b/Source/modules/asura-base/FileSystem/File.h
new file mode 100644
index 0000000..be772e0
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/File.h
@@ -0,0 +1,146 @@
+#ifndef _ASURA_ENGINE_FILE_H_
+#define _ASURA_ENGINE_FILE_H_
+
+#include "physfs/physfs.h"
+
+#include "../Scripting/Scripting.h"
+#include "../Threads/Thread.h"
+
+#include "FileData.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ ///
+ /// ʽļָд㡢Сʹȡʱʹñ࣬ʹ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* m_FileHandle; ///< physfs ļ
+ std::string m_FileName; ///< ļ
+ std::string m_Extension; ///< չ
+ std::string m_Name; ///< չļ
+ FileMode m_Mode; ///< ļģʽ
+ BufferMode m_BufferMode; ///< д뻺ģʽ
+ size_t m_BufferSize; ///< д뻺С
+
+ 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/modules/asura-base/FileSystem/FileData.cpp b/Source/modules/asura-base/FileSystem/FileData.cpp
new file mode 100644
index 0000000..b29a95b
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/FileData.cpp
@@ -0,0 +1,59 @@
+#include "FileData.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ FileData::FileData(const std::string& filename)
+ : m_Data(nullptr)
+ , m_FileName(filename)
+ {
+ size_t dot = filename.rfind('.');
+ if (dot != std::string::npos)
+ {
+ m_Extension = filename.substr(dot + 1);
+ m_Name = filename.substr(0, dot);
+ }
+ else
+ m_Name = filename;
+ }
+
+ FileData::~FileData()
+ {
+ if (m_Data)
+ m_Data->Release();
+ }
+
+ const std::string& FileData::GetFileName()
+ {
+ return m_FileName;
+ }
+
+ const std::string& FileData::GetExtension()
+ {
+ return m_Extension;
+ }
+
+ const std::string& FileData::GetName()
+ {
+ return m_Name;
+ }
+
+ void FileData::BindData(ASURA_MOVE DataBuffer* buffer)
+ {
+ if (!buffer)
+ return;
+ if (m_Data)
+ m_Data->Release();
+ m_Data = buffer;
+ m_Data->Retain();
+ }
+
+ DataBuffer* FileData::GetDataBuffer()
+ {
+ return m_Data;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Source/modules/asura-base/FileSystem/FileData.h b/Source/modules/asura-base/FileSystem/FileData.h
new file mode 100644
index 0000000..d0acd26
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/FileData.h
@@ -0,0 +1,69 @@
+#ifndef _ASURA_ENGINE_FILE_DATA_H_
+#define _ASURA_ENGINE_FILE_DATA_H_
+
+#include <string>
+
+#include <asura-base/Scripting/Scripting.h>
+
+#include "DataBuffer.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ 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 FileManager;
+
+ FileData(const std::string& name);
+
+ ///
+ /// data buffer
+ ///
+ void BindData(ASURA_MOVE DataBuffer* buffer);
+
+ ///
+ /// Data bufferfiledataʱ٣luaüΪ0ʱluaGC١mDataʱһԱá
+ ///
+ ASURA_REF DataBuffer* m_Data;
+ Luax::LuaxMemberRef m_DataRef;
+
+ std::string m_FileName; ///< չļ
+ std::string m_Extension; ///< չ
+ std::string m_Name; ///< ͺ׺ļ
+
+ 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/modules/asura-base/FileSystem/FileManager.cpp b/Source/modules/asura-base/FileSystem/FileManager.cpp
new file mode 100644
index 0000000..bdb4069
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/FileManager.cpp
@@ -0,0 +1,198 @@
+#include <physfs/physfs.h>
+
+#include "../Exception.h"
+
+#include "File.h"
+#include "FileData.h"
+#include "FileManager.h"
+
+using namespace std;
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+#ifdef ASURA_WINDOWS
+ #include <windows.h>
+ #include <direct.h>
+#else
+ #include <sys/param.h>
+ #include <unistd.h>
+#endif
+
+ FileManager::~FileManager()
+ {
+ if (m_Inited) //PHYSFS_isInit
+ PHYSFS_deinit();
+ }
+
+ void FileManager::Init(const char* arg0)
+ {
+ if (!PHYSFS_init(arg0))
+ throw Exception("Failed to initialize filesystem: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
+
+ m_Inited = true;
+ }
+
+ bool FileManager::Mount(const std::string& locpath, const std::string& montpoint/* = "/"*/, bool prepend /*= false*/)
+ {
+ if (!m_Inited)
+ return false;
+
+ return PHYSFS_mount(locpath.c_str(), montpoint.c_str(), !prepend);
+ }
+
+ bool FileManager::Mount(DataBuffer* db, const std::string& archivename, const std::string& mountpoint /*= "/"*/, bool prepend /*= false*/)
+ {
+ if (!m_Inited)
+ return false;
+ if (PHYSFS_mountMemory(db->GetData(), db->GetSize(), nullptr, archivename.c_str(), mountpoint.c_str(), !prepend))
+ {
+ m_MountData[archivename] = db;
+ return true;
+ }
+ return false;
+ }
+
+ bool FileManager::Unmount(const std::string& locpath)
+ {
+ if (!m_Inited)
+ return false;
+
+ // ǹ鵵ӳɾ
+ auto datait = m_MountData.find(locpath);
+ if (datait != m_MountData.end() && PHYSFS_unmount(locpath.c_str()) != 0)
+ {
+ m_MountData.erase(datait);
+ return true;
+ }
+
+ return PHYSFS_unmount(locpath.c_str());
+ }
+
+ bool FileManager::Unmount(DataBuffer* db)
+ {
+ for (const auto& dp : m_MountData)
+ {
+ if (dp.second == db)
+ {
+ std::string archive = dp.first;
+ return Unmount(archive);
+ }
+ }
+ }
+
+ bool FileManager::GetMountPoint(const std::string& locpath, ASURA_OUT std::string& mountpoint)
+ {
+ if (!m_Inited)
+ return false;
+ const char* point = PHYSFS_getMountPoint(locpath.c_str());
+ if (point != nullptr)
+ {
+ mountpoint = point;
+ return true;
+ }
+ return false;
+ }
+
+ void FileManager::SetWriteDirectory(const std::string locpath)
+ {
+ if (!m_Inited)
+ return;
+ if (!PHYSFS_setWriteDir(locpath.c_str()))
+ throw Exception("Failed to set write directory %s", locpath.c_str());
+ }
+
+ std::string FileManager::GetWriteDirectory()
+ {
+ return PHYSFS_getWriteDir();
+ }
+
+ File* FileManager::NewFile(const std::string& name)
+ {
+ return new File(name);
+ }
+
+ bool FileManager::NewDirectory(const std::string& path)
+ {
+ if (!m_Inited)
+ return false;
+ if (!PHYSFS_getWriteDir())
+ return false;
+ if (!PHYSFS_mkdir(path.c_str()))
+ return false;
+ return true;
+ }
+
+ bool FileManager::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 FileManager::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* FileManager::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 FileManager::Remove(const std::string& path)
+ {
+ if (!m_Inited)
+ return false;
+ if (PHYSFS_getWriteDir() == 0)
+ return false;
+
+ if (!PHYSFS_delete(path.c_str()))
+ return false;
+
+ return true;
+ }
+
+ bool FileManager::GetFileInfo(const std::string& filepath, ASURA_OUT FileInfo* info)
+ {
+ if (!m_Inited)
+ 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/modules/asura-base/FileSystem/FileManager.h b/Source/modules/asura-base/FileSystem/FileManager.h
new file mode 100644
index 0000000..ac97da3
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/FileManager.h
@@ -0,0 +1,112 @@
+#ifndef _ASURA_ENGINE_FILESYSTEM_H_
+#define _ASURA_ENGINE_FILESYSTEM_H_
+
+#include <map>
+#include <string>
+
+#include "../Scripting/Scripting.h"
+#include "../Singleton.hpp"
+#include "../Type.h"
+
+#include "FileData.h"
+#include "File.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ 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µġFileManagerʱͱ༭õ࣬AssetDatabaseԴ࣬framework
+ /// ʵ֣߼дFileManagerʵ֣AssetDatabaseṩļݴӦԴķ
+ ///
+ class FileManager ASURA_FINAL
+ : public Singleton<FileManager>
+ , public AEScripting::Portable<FileManager>
+ {
+ public:
+
+ LUAX_DECL_SINGLETON(FileManager);
+
+ ~FileManager();
+
+ 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 m_Inited; ///< Ƿʼɹ
+ std::string m_Cwd; ///< ǰִļĹĿ¼
+ MountDataMap m_MountData; ///< ·ѹĵӳ
+
+ 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 AEFileSystem = AsuraEngine::FileSystem;
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/FileSystem/IOBatchTask.cpp b/Source/modules/asura-base/FileSystem/IOBatchTask.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/IOBatchTask.cpp
diff --git a/Source/modules/asura-base/FileSystem/IOBatchTask.h b/Source/modules/asura-base/FileSystem/IOBatchTask.h
new file mode 100644
index 0000000..8d73e93
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/IOBatchTask.h
@@ -0,0 +1,31 @@
+#ifndef _ASURA_IO_BATCH_TASK_H_
+#define _ASURA_IO_BATCH_TASK_H_
+
+#include "IOTask.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ ///
+ /// дһύһtableδ󷵻ؽ
+ ///
+ class IOBatchTask ASURA_FINAL : public AEThreading::Task
+ {
+ public:
+
+ private:
+
+ ///
+ /// ÿһĽṹ£
+ /// { path = "", }
+ ///
+ Luax::LuaxMemberRef m_Tasks;
+
+ };
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/FileSystem/IOTask.cpp b/Source/modules/asura-base/FileSystem/IOTask.cpp
new file mode 100644
index 0000000..9152a6e
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/IOTask.cpp
@@ -0,0 +1,61 @@
+#include "FileManager.h"
+#include "IOTask.h"
+
+#include <iostream>
+
+using namespace AEScripting;
+using namespace Luax;
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ IOTask::IOTask(const std::string& path, DataBuffer* buffer, IOTaskType type)
+ : m_Path(path)
+ , m_Buffer(buffer)
+ {
+ if (buffer)
+ buffer->Retain();
+ }
+
+ IOTask::~IOTask()
+ {
+ if (m_Buffer)
+ m_Buffer->Release();
+ }
+
+ bool IOTask::Execute()
+ {
+ File file(m_Path);
+ if (m_Type == IOTASK_TYPE_WRITE)
+ {
+
+ }
+ // pathȡݱmBuffer
+ else if (m_Type == IOTASK_TYPE_READ)
+ {
+ if (!m_Buffer)
+ return false;
+ file.Open(File::FILE_MODE_READ);
+ file.ReadAll(m_Buffer);
+ file.Close();
+ }
+ return true;
+ }
+
+ void IOTask::Invoke(lua_State* invokeThreaad)
+ {
+ if (m_Callback)
+ {
+ LuaxScopedState state(invokeThreaad);
+ if (this->PushLuaxMemberRef(state, m_Callback))
+ {
+ this->PushLuaxMemberRef(state, m_BufferRef);
+ state.Call(1, 0);
+ }
+ }
+ }
+
+ }
+}
diff --git a/Source/modules/asura-base/FileSystem/IOTask.h b/Source/modules/asura-base/FileSystem/IOTask.h
new file mode 100644
index 0000000..da54fdc
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/IOTask.h
@@ -0,0 +1,56 @@
+#ifndef _ASURA_IO_TASK_H_
+#define _ASURA_IO_TASK_H_
+
+#include <string>
+
+#include "../Scripting/Scripting.h"
+#include "../Threads/Task.h"
+
+#include "DataBuffer.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ enum IOTaskType
+ {
+ IOTASK_TYPE_READ,
+ IOTASK_TYPE_WRITE,
+ IOTASK_TYPE_APPEND,
+ };
+
+ ///
+ /// ȡļ
+ ///
+ class IOTask ASURA_FINAL
+ : public AEScripting::Portable<IOTask, AEThreading::Task>
+ {
+ 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 m_Path;
+ IOTaskType m_Type;
+
+ DataBuffer* m_Buffer;
+ Luax::LuaxMemberRef m_BufferRef;
+
+ };
+
+ }
+}
+
+#endif \ No newline at end of file
diff --git a/Source/modules/asura-base/FileSystem/Renewable.h b/Source/modules/asura-base/FileSystem/Renewable.h
new file mode 100644
index 0000000..ff44303
--- /dev/null
+++ b/Source/modules/asura-base/FileSystem/Renewable.h
@@ -0,0 +1,27 @@
+#ifndef __ASURA_ENGINE_RENEWABLE_H__
+#define __ASURA_ENGINE_RENEWABLE_H__
+
+#include "DecodedData.h"
+
+namespace AsuraEngine
+{
+ namespace FileSystem
+ {
+
+ ///
+ /// ¹ݽṹͼƬƵ֣ӽݿֱӹڱ༭
+ /// ¹޸handleֵı䲻߱ƻԣڲıhandleԴ
+ ///
+ ASURA_ABSTRACT class Renewable
+ {
+ public:
+ Renewable() {};
+ virtual ~Renewable() {};
+ };
+
+ }
+}
+
+namespace AEFileSystem = AsuraEngine::FileSystem;
+
+#endif \ No newline at end of file