• R/O
  • SSH
  • HTTPS

green-candy: Commit


Commit MetaInfo

Revisión13 (tree)
Tiempo2022-01-17 05:05:37
Autorquiret

Log Message

- refactored the Eir FileSystem module for MTA:BLUE to use MTA OOP-style semantics

Cambiar Resumen

Diferencia incremental

--- blueMods/depend/lua/configure.ac (revision 12)
+++ blueMods/depend/lua/configure.ac (nonexistent)
@@ -1,64 +0,0 @@
1-AC_PREREQ(2.59)
2-AC_INIT([Autotoolized Lua], [5.1.3], [], [lua-at])
3-
4-AC_CONFIG_HEADERS([config.h])
5-AC_CONFIG_SRCDIR([src/lapi.c])
6-
7-AM_INIT_AUTOMAKE([1.9 foreign])
8-
9-AC_PROG_CC
10-AC_PROG_LIBTOOL
11-
12-AC_ARG_WITH(
13- [readline],
14- [AC_HELP_STRING([--with-readline], [Use readline for interpreter input [default=yes]])],
15- [use_readline=$withval],
16- [use_readline=yes]
17-)
18-
19-LUA_LIBS="-lm"
20-
21-# Check for readline
22-READLINE_DEFS="#undef LUA_USE_READLINE"
23-if test "x$use_readline" == "xyes"; then
24- AC_CHECK_LIB([readline], [readline], [], [use_readline=no], [-lncurses])
25- AC_CHECK_HEADERS([readline/readline.h readline/history.h], [], [use_readline=no])
26- if test "x$use_readline" == "xno"; then
27- AC_MSG_WARN([readline headers could not be found, disabling readline support])
28- else
29- READLINE_DEFS="#define LUA_USE_READLINE"
30- LUA_LIBS="$LUA_LIBS -lreadline -lncurses"
31- fi
32-fi
33-AC_SUBST(READLINE_DEFS)
34-
35-case "$host" in
36- *-mingw*) use_os=win32 ;;
37- *-darwin*) use_os=macosx ;;
38- *) use_os=posix ;;
39-esac
40-
41-POSIX_DEFS="#undef LUA_USE_POSIX"
42-LUA_DL_DEFS="#undef LUA_USE_DLOPEN"
43-LUA_BUILD_AS_DLL_DEFS="#undef LUA_BUILD_AS_DLL"
44-
45-if test "x$use_os" == "xwin32"; then
46- LUA_BUILD_AS_DLL_DEFS="#define LUA_BUILD_AS_DLL"
47-elif test "x$use_os" == "xmacosx"; then
48- POSIX_DEFS="#define LUA_USE_POSIX"
49- LUA_DL_DEFS="#define LUA_DL_DYLD"
50-elif test "x$use_os" == "xposix"; then
51- POSIX_DEFS="#define LUA_USE_POSIX"
52- LUA_DL_DEFS="#define LUA_DL_DLOPEN"
53- LUA_LIBS="$LUA_LIBS -ldl"
54-fi
55-AC_SUBST(POSIX_DEFS)
56-AC_SUBST(LUA_DL_DEFS)
57-AC_SUBST(LUA_BUILD_AS_DLL_DEFS)
58-
59-AC_SUBST(LUA_LIBS)
60-
61-AC_CONFIG_FILES([Makefile
62- src/Makefile
63- src/luaconf.h.template])
64-AC_OUTPUT
--- blueMods/depend/lua/Makefile.am (revision 12)
+++ blueMods/depend/lua/Makefile.am (nonexistent)
@@ -1,3 +0,0 @@
1-SUBDIRS = src
2-
3-EXTRA_DIST = autogen.sh COPYRIGHT HISTORY INSTALL MANIFEST README
--- blueMods/fileSystem/StdInc.h (revision 12)
+++ blueMods/fileSystem/StdInc.h (revision 13)
@@ -17,17 +17,15 @@
1717 *********************************************************/
1818
1919 /** MODULE SPECIFIC INFORMATION **/
20-#define MODULE_NAME "Eir/GREEN FileSystem"
20+#define MODULE_NAME "Eir FileSystem"
2121 #define MODULE_AUTHOR "The_GTA"
2222 #define MODULE_VERSION 2.0
2323
2424 #pragma warning(disable: 4996)
2525
26-#define NOMINMAX
27-
28-#include "../../Shared/core/Common.h"
2926 #include "Common.h"
3027 #include <CFileSystem.h>
28+#include "luafslib.h"
3129 #include "luaclass.h"
3230 #include "luafile.h"
3331 #include "luafilesystem.h"
--- blueMods/fileSystem/include/ILuaModuleManager.h (revision 12)
+++ blueMods/fileSystem/include/ILuaModuleManager.h (revision 13)
@@ -58,6 +58,10 @@
5858 virtual const char* GetOperatingSystemName ( ) = 0;
5959
6060 virtual lua_State* GetResourceFromName ( const char* szResourceName ) = 0;
61+
62+ // GetResourceName above doesn't work if module and MTA were compiled with different compiler versions
63+ virtual bool GetResourceName(lua_State* luaVM, char* szName, size_t length) = 0;
64+ virtual bool GetResourceFilePath(lua_State* luaVM, const char* fileName, char* path, size_t length) = 0;
6165 };
6266
6367 #endif
--- blueMods/fileSystem/luaclass.cpp (revision 12)
+++ blueMods/fileSystem/luaclass.cpp (revision 13)
@@ -1,10 +1,9 @@
11 /*****************************************************************************
22 *
3-* PROJECT: Lua Interpreter
3+* PROJECT: Eir FileSystem for MTA:BLUE
44 * LICENSE: See LICENSE in the top level directory
55 * FILE: luaclass.cpp
66 * PURPOSE: Lua filesystem access
7-* DEVELOPERS: The_GTA <quiret@gmx.de>
87 *
98 * Multi Theft Auto is available from http://www.multitheftauto.com/
109 *
@@ -12,101 +11,134 @@
1211
1312 #include "StdInc.h"
1413
15-struct _class_internal
14+static int luaclass_destroy( lua_State *L )
1615 {
17- unk *inter;
18- bool destroyed;
19-};
16+ void *obj = luaclass_getpointer( L, 1 );
2017
21-static int lua_iunkcollect( lua_State *L )
22-{
23- _class_internal *inter = (_class_internal*)lua_touserdata( L, 1 );
18+ // TODO: allow clean-up of the given object, we have to support all possible ones.
2419
25- if ( !inter->destroyed )
26- delete (unk*)inter->inter;
20+ if ( fsIsFile( obj ) )
21+ {
22+ fsCleanupFile( (CFile*)obj );
23+ }
24+ else if ( fsIsTranslator( obj ) )
25+ {
26+ fsCleanupTranslator( (CFileTranslator*)obj );
27+ }
2728
2829 return 0;
2930 }
3031
31-static int lua_destrPre( lua_State *L )
32+static const luaL_Reg _common_class_meths[] =
3233 {
33- _class_internal *inter = (_class_internal*)lua_touserdata( L, lua_upvalueindex( 2 ) );
34+ { "destroy", luaclass_destroy },
35+ { nullptr, nullptr }
36+};
3437
35- if ( inter->destroyed )
36- return 0;
37-
38- lua_pushvalue( L, lua_upvalueindex( 1 ) );
39- lua_call( L, 0, 0 );
40-
41- inter->destroyed = true;
42- return 0;
38+void luaclass_makemeta( lua_State *L, int ridx )
39+{
40+ lua_newtable( L );
41+ lua_pushvalue( L, ridx - 1 );
42+ luaL_openlib( L, nullptr, _common_class_meths, 1 );
4343 }
4444
45-static int lua_grk( lua_State *L )
45+void* luaclass_getpointer( lua_State *L, int idx )
4646 {
47- if ( strcmp( lua_tostring( L, 2 ), "destroy" ) == 0 )
47+ luaL_checktype( L, idx, LUA_TUSERDATA );
48+
49+ if ( lua_objlen( L, idx ) < sizeof(void*) )
4850 {
49- lua_rawget( L, lua_upvalueindex( 1 ) );
50- lua_pushvalue( L, lua_upvalueindex( 2 ) );
51- lua_pushcclosure( L, lua_destrPre, 2 );
52- return 1;
51+ lua_pushlstring( L, "invalid userdata", 16 );
52+ lua_error( L );
5353 }
5454
55- lua_rawget( L, lua_upvalueindex( 1 ) );
56- return 1;
55+ void **ptr_class = (void**)lua_touserdata( L, idx );
56+
57+ assert( ptr_class != nullptr );
58+
59+ return *ptr_class;
5760 }
5861
59-void lua_newclass( lua_State *L, unk *inter )
62+static int luaclassmt_index( lua_State *L )
6063 {
61- // Create a function metatable for the constructor.
62- lua_newtable( L );
63- lua_pushvalue( L, -1 );
64- lua_newtable( L );
64+ void *obj = luaclass_getpointer( L, 1 );
6565
66- lua_pushvalue( L, LUA_ENVIRONINDEX );
67- lua_setfield( L, -2, "__index" );
66+ // TODO: return the methods that are appropriate for the given object.
6867
69- lua_pushboolean( L, false );
70- lua_setfield( L, -2, "__metatable" );
68+ if ( fsIsFile( obj ) )
69+ {
70+ lua_getmetatable( L, lua_upvalueindex( 1 ) );
71+ lua_pushlstring( L, "metas", 5 );
72+ lua_rawget( L, -2 );
73+ lua_pushlstring( L, "file", 4 );
74+ lua_rawget( L, -2 );
75+ goto doIndex;
76+ }
77+ else if ( fsIsTranslator( obj ) )
78+ {
79+ lua_getmetatable( L, lua_upvalueindex( 1 ) );
80+ lua_pushlstring( L, "metas", 5 );
81+ lua_rawget( L, -2 );
82+ lua_pushlstring( L, "ftrans", 6 );
83+ lua_rawget( L, -2 );
84+ goto doIndex;
85+ }
7186
72- // Set the metatable.
73- lua_setmetatable( L, -2 );
87+ return 0;
7488
75- // Apply the metatable to the constructor.
76- lua_setfenv( L, -3 );
89+doIndex:
90+ lua_pushvalue( L, 2 );
91+ lua_rawget( L, -2 );
7792
78- // Now only the table is on the stack, that is the constructor's environment.
93+ if ( lua_isnil( L, -1 ) )
94+ {
95+ lua_pop( L, 2 );
7996
80- // Switch positions of constructor with environment.
81- lua_insert( L, -2 );
97+ // Try to index general class methods instead.
98+ lua_pushlstring( L, "class", 5 );
99+ lua_rawget( L, -2 );
100+ lua_pushvalue( L, 2 );
101+ lua_rawget( L, -2 );
102+ }
82103
83- lua_call( L, 0, 0 );
104+ return 1;
105+}
84106
85- // Only thing on top: class environment.
107+static int luaclassmt_gc( lua_State *L )
108+{
109+ return luaclass_destroy( L );
110+}
86111
87- _class_internal *it = (_class_internal*)lua_newuserdata( L, sizeof(_class_internal) );
88- it->inter = inter;
89- it->destroyed = false;
90- lua_insert( L, -2 );
112+static const luaL_Reg _luaclass_metatable[] =
113+{
114+ { "__index", luaclassmt_index },
115+ { "__gc", luaclassmt_gc },
116+ { nullptr, nullptr }
117+};
91118
119+void luaclassmt_make( lua_State *L, int ridx )
120+{
92121 lua_newtable( L );
93- lua_insert( L, -2 );
94- lua_pushvalue( L, -1 );
95- lua_pushvalue( L, -4 );
122+ lua_pushvalue( L, ridx - 1 );
123+ luaL_openlib( L, nullptr, _luaclass_metatable, 1 );
124+}
96125
97- lua_pushcclosure( L, lua_grk, 2 );
98- lua_setfield( L, -3, "__index" );
126+static void luaclassmt_push( lua_State *L )
127+{
128+ assert( lua_type( L, lua_upvalueindex( 1 ) ) == LUA_TUSERDATA );
129+ lua_getmetatable( L, lua_upvalueindex( 1 ) );
130+ assert( lua_type( L, -1 ) == LUA_TTABLE );
131+ lua_pushlstring( L, "classmt", 7 );
132+ lua_rawget( L, -2 );
133+ lua_remove( L, -2 );
134+}
99135
100- lua_pushcclosure( L, lua_iunkcollect, 1 );
101- lua_setfield( L, -2, "__gc" );
136+void luaclass_pushshim( lua_State *L, void *classptr )
137+{
138+ void **ptrud = (void**)lua_newuserdata( L, sizeof(void*) );
102139
103- lua_pushboolean( L, false );
104- lua_setfield( L, -2, "__metatable" );
140+ *ptrud = classptr;
105141
142+ luaclassmt_push( L );
106143 lua_setmetatable( L, -2 );
107-}
108-
109-void* lua_getmethodtrans( lua_State *L )
110-{
111- return lua_touserdata( L, lua_upvalueindex( 1 ) );
112-}
144+}
\ No newline at end of file
--- blueMods/fileSystem/luaclass.h (revision 12)
+++ blueMods/fileSystem/luaclass.h (revision 13)
@@ -1,10 +1,9 @@
11 /*****************************************************************************
22 *
3-* PROJECT: Lua Interpreter
3+* PROJECT: Eir FileSystem for MTA:BLUE
44 * LICENSE: See LICENSE in the top level directory
55 * FILE: luaclass.h
66 * PURPOSE: Lua filesystem access
7-* DEVELOPERS: The_GTA <quiret@gmx.de>
87 *
98 * Multi Theft Auto is available from http://www.multitheftauto.com/
109 *
@@ -13,15 +12,9 @@
1312 #ifndef FU_CLASS
1413 #define FU_CLASS
1514
16-class unk abstract
17-{
18-public:
19- virtual ~unk() = 0;
20-};
15+void luaclass_pushshim( lua_State *L, void *classptr );
16+void* luaclass_getpointer( lua_State *L, int idx );
2117
22-void lua_newclass( lua_State *L, unk *inter );
23-void* lua_getmethodtrans( lua_State *L );
24-
2518 #define LUA_CHECK( val ) if ( !(val) ) { lua_pushboolean( L, false ); return 1; }
2619
2720 #endif //FU_CLASS
--- blueMods/fileSystem/luafile.Utils.hxx (revision 12)
+++ blueMods/fileSystem/luafile.Utils.hxx (revision 13)
@@ -1,10 +1,9 @@
11 /*****************************************************************************
22 *
3-* PROJECT: Lua Interpreter
3+* PROJECT: Eir FileSystem for MTA:BLUE
44 * LICENSE: See LICENSE in the top level directory
55 * FILE: luafile.cpp
66 * PURPOSE: Lua filesystem utils
7-* DEVELOPERS: The_GTA <quiret@gmx.de>
87 *
98 * Multi Theft Auto is available from http://www.multitheftauto.com/
109 *
@@ -29,4 +28,52 @@
2928 lua_setfield( L, top, "size" );
3029 }
3130
31+#define LUAFILE_GUARDFSCALL_BEGIN \
32+ try {
33+#define LUAFILE_GUARDFSCALL_END \
34+ } \
35+ catch( FileSystem::TerminatedObjectException& ) \
36+ { \
37+ lua_pushboolean( L, false ); \
38+ return 1; \
39+ } \
40+ catch( FileSystem::filesystem_exception& except ) \
41+ { \
42+ lua_pushboolean( L, false ); \
43+ FileSystem::eGenExceptCode code = except.get_code(); \
44+ if ( code == FileSystem::eGenExceptCode::RESOURCE_UNAVAILABLE ) \
45+ { \
46+ lua_pushstring( L, "resource unavailable" ); \
47+ } \
48+ else if ( code == FileSystem::eGenExceptCode::MEMORY_INSUFFICIENT ) \
49+ { \
50+ lua_pushstring( L, "memory insufficient" ); \
51+ } \
52+ else if ( code == FileSystem::eGenExceptCode::INVALID_SYSPARAM ) \
53+ { \
54+ lua_pushstring( L, "invalid sysparam" ); \
55+ } \
56+ else if ( code == FileSystem::eGenExceptCode::INVALID_PARAM ) \
57+ { \
58+ lua_pushstring( L, "invalid param" ); \
59+ } \
60+ else if ( code == FileSystem::eGenExceptCode::ILLEGAL_PATHCHAR ) \
61+ { \
62+ lua_pushstring( L, "illegal pathchar" ); \
63+ } \
64+ else if ( code == FileSystem::eGenExceptCode::UNSUPPORTED_OPERATION ) \
65+ { \
66+ lua_pushstring( L, "unsupported operation" ); \
67+ } \
68+ else if ( code == FileSystem::eGenExceptCode::INVALID_OBJECT_STATE ) \
69+ { \
70+ lua_pushstring( L, "invalid object state" ); \
71+ } \
72+ else \
73+ { \
74+ lua_pushstring( L, "unknown fs error" ); \
75+ } \
76+ return 2; \
77+ }
78+
3279 #endif //_LUAFILE_UITLS_
--- blueMods/fileSystem/luafile.cpp (revision 12)
+++ blueMods/fileSystem/luafile.cpp (revision 13)
@@ -1,10 +1,9 @@
11 /*****************************************************************************
22 *
3-* PROJECT: Lua Interpreter
3+* PROJECT: Eir FileSystem for MTA:BLUE
44 * LICENSE: See LICENSE in the top level directory
55 * FILE: luafile.cpp
6-* PURPOSE: Test environment for the filesystem
7-* DEVELOPERS: Martin Turski <quiret@gmx.de>
6+* PURPOSE: Lua implementation of the FileSystem CFile class
87 *
98 * For documentation visit http://wiki.mtasa.com/wiki/MTA:Eir/FileSystem/
109 *
@@ -15,35 +14,13 @@
1514 #include <StdInc.h>
1615 #include "luafile.Utils.hxx"
1716
18-using namespace std;
19-
20-static int luafile_onIndex( lua_State *lua )
21-{
22- lua_pushvalue( lua, 2 );
23- lua_gettable( lua, lua_upvalueindex( 1 ) );
24-
25- if ( lua_type( lua, 3 ) == LUA_TBOOLEAN && lua_toboolean( lua, 3 ) == false )
26- return 0;
27-
28- lua_pop( lua, 1 );
29- lua_gettable( lua, lua_upvalueindex( 2 ) );
30- return 1;
31-}
32-
33-static int luafile_onNewindex( lua_State *lua )
34-{
35- // We do not allow any modification from outside
36- return 0;
37-}
38-
3917 static int luafile_read( lua_State *L )
4018 {
41- luaL_checktype( L, 1, LUA_TNUMBER );
19+ CFile *file = fsLuaGetFile( L, 1 );
20+ luaL_checktype( L, 2, LUA_TNUMBER );
4221
43- CFile *file = (CFile*)lua_getmethodtrans( L );
22+ long byteCount = (long)lua_tonumber( L, 2 );
4423
45- long byteCount = (long)lua_tonumber( L, 1 );
46-
4724 LUA_CHECK( byteCount >= 0 );
4825
4926 size_t bytesRead = (size_t)byteCount;
@@ -54,19 +31,27 @@
5431 return 1;
5532 }
5633
57- std::vector <char> buf( bytesRead );
34+ eir::Vector <char, FileSysCommonAllocator> buf;
5835
59-#ifdef FU_CLASS
60- bytesRead = file->Read( &buf[0], bytesRead );
36+ try
37+ {
38+ buf.Resize( bytesRead );
39+ }
40+ catch( eir::out_of_memory_exception& )
41+ {
42+ lua_pushboolean( L, false );
43+ return 1;
44+ }
6145
46+ LUAFILE_GUARDFSCALL_BEGIN
47+ bytesRead = file->Read( &buf[0], bytesRead );
48+ LUAFILE_GUARDFSCALL_END
49+
6250 if ( bytesRead == 0 )
6351 {
6452 lua_pushlstring( L, "", 0 );
6553 return 1;
6654 }
67-#else
68- bytesRead = file->Read( &buf[0], 1, bytesRead );
69-#endif
7055
7156 lua_pushlstring( L, &buf[0], bytesRead );
7257 return 1;
@@ -109,12 +94,18 @@
10994 template <typename numberType>
11095 AINLINE int _fileReadNumber( lua_State *L )
11196 {
97+ CFile *file = fsLuaGetFile( L, 1 );
98+
11299 numberType out_num;
113100
114- LUA_CHECK(
115- ((CFile*)lua_getmethodtrans( L ))->ReadStruct( out_num )
116- );
101+ bool success;
102+
103+ LUAFILE_GUARDFSCALL_BEGIN
104+ success = file->ReadStruct( out_num );
105+ LUAFILE_GUARDFSCALL_END
117106
107+ LUA_CHECK( success );
108+
118109 lua_pushnumber( L, (lua_Number)out_num );
119110 return 1;
120111 }
@@ -164,10 +155,15 @@
164155
165156 static int luafile_readBoolean( lua_State *L )
166157 {
158+ CFile *file = fsLuaGetFile( L, 1 );
159+
167160 bool out_b;
168161
169- bool successful =
170- ((CFile*)lua_getmethodtrans( L ))->ReadBool( out_b );
162+ bool successful;
163+
164+ LUAFILE_GUARDFSCALL_BEGIN
165+ successful = file->ReadBool( out_b );
166+ LUAFILE_GUARDFSCALL_END
171167
172168 if ( !successful )
173169 lua_pushnil( L );
@@ -180,9 +176,10 @@
180176 template <typename numberType, typename validityChecker>
181177 AINLINE int _writeFileNumber( lua_State *L, const char *methodName )
182178 {
183- luaL_checktype( L, 1, LUA_TNUMBER );
179+ CFile *file = fsLuaGetFile( L, 1 );
180+ luaL_checktype( L, 2, LUA_TNUMBER );
184181
185- lua_Number number = lua_tonumber( L, 1 );
182+ lua_Number number = lua_tonumber( L, 2 );
186183
187184 // Check validity of number.
188185 {
@@ -196,22 +193,31 @@
196193
197194 numberType realNum = (numberType)number;
198195
199- lua_pushnumber( L, ((CFile*)lua_getmethodtrans( L ))->WriteStruct( realNum ) );
196+ size_t numWrite;
197+
198+ LUAFILE_GUARDFSCALL_BEGIN
199+ numWrite = file->WriteStruct( realNum );
200+ LUAFILE_GUARDFSCALL_END
201+
202+ lua_pushnumber( L, numWrite );
200203 return 1;
201204 }
202205
203206 static int luafile_write( lua_State *L )
204207 {
205- luaL_checktype( L, 1, LUA_TSTRING );
208+ CFile *file = fsLuaGetFile( L, 1 );
209+ luaL_checktype( L, 2, LUA_TSTRING );
206210
207211 size_t len;
208- const char *string = lua_tolstring( L, 1, &len );
212+ const char *string = lua_tolstring( L, 2, &len );
209213
210-#ifndef FU_CLASS
211- lua_pushwideinteger( L, ((CFile*)lua_getmethodtrans( L ))->Write( string, len ) );
212-#else
213- lua_pushnumber( L, ((CFile*)lua_getmethodtrans( L ))->Write( string, len ) );
214-#endif
214+ size_t numWrite;
215+
216+ LUAFILE_GUARDFSCALL_BEGIN
217+ numWrite = file->Write( string, len );
218+ LUAFILE_GUARDFSCALL_END
219+
220+ lua_pushnumber( L, numWrite );
215221 return 1;
216222 }
217223
@@ -259,41 +265,63 @@
259265
260266 static int luafile_writeBoolean( lua_State *L )
261267 {
262- luaL_checktype( L, 1, LUA_TBOOLEAN );
263- lua_pushnumber( L,
264- ((CFile*)lua_getmethodtrans( L ))->WriteBool(
265- ( lua_toboolean( L, 1 ) != 0 )
266- )
267- );
268+ CFile *file = fsLuaGetFile( L, 1 );
269+ luaL_checktype( L, 2, LUA_TBOOLEAN );
270+
271+ size_t numWrite;
272+
273+ LUAFILE_GUARDFSCALL_BEGIN
274+ numWrite = file->WriteBool(
275+ ( lua_toboolean( L, 2 ) != 0 )
276+ );
277+ LUAFILE_GUARDFSCALL_END
278+
279+ lua_pushnumber( L, numWrite );
268280 return 1;
269281 }
270282
271283 static int luafile_size( lua_State *L )
272284 {
273- lua_pushnumber( L, ((CFile*)lua_getmethodtrans( L ))->GetSize() );
285+ CFile *file = fsLuaGetFile( L, 1 );
286+
287+ size_t fileSize;
288+
289+ LUAFILE_GUARDFSCALL_BEGIN
290+ fileSize = file->GetSize();
291+ LUAFILE_GUARDFSCALL_END
292+
293+ lua_pushnumber( L, fileSize );
274294 return 1;
275295 }
276296
277297 static int luafile_stat( lua_State *L )
278298 {
299+ CFile *file = fsLuaGetFile( L, 1 );
300+
279301 filesysStats stats;
280302
281- CFile *filePtr = ((CFile*)lua_getmethodtrans( L ));
303+ LUAFILE_GUARDFSCALL_BEGIN
304+ if ( !file->QueryStats( stats ) )
305+ return 0;
282306
283- if ( !filePtr->QueryStats( stats ) )
284- return 0;
307+ fsOffsetNumber_t fileSize = file->GetSizeNative();
285308
286- fsOffsetNumber_t fileSize = filePtr->GetSizeNative();
287-
288- luafile_pushStats( L, fileSize, stats );
289- return 1;
309+ luafile_pushStats( L, fileSize, stats );
310+ return 1;
311+ LUAFILE_GUARDFSCALL_END
290312 }
291313
292314 static int luafile_tell( lua_State *L )
293315 {
316+ CFile *file = fsLuaGetFile( L, 1 );
317+
294318 // (Attempt to) Get a large FileSystem number that stands for the current seek.
295- fsOffsetNumber_t filePosition = ((CFile*)lua_getmethodtrans( L ))->TellNative();
319+ fsOffsetNumber_t filePosition;
296320
321+ LUAFILE_GUARDFSCALL_BEGIN
322+ filePosition = file->TellNative();
323+ LUAFILE_GUARDFSCALL_END
324+
297325 lua_Number num = (lua_Number)filePosition;
298326
299327 lua_pushnumber( L, num );
@@ -302,20 +330,21 @@
302330
303331 static int luafile_seek( lua_State *L )
304332 {
305- luaL_checktype( L, 1, LUA_TNUMBER );
333+ CFile *file = fsLuaGetFile( L, 1 );
334+ luaL_checktype( L, 2, LUA_TNUMBER );
306335
307336 int seekType;
308337
309- switch( lua_type( L, 2 ) )
338+ switch( lua_type( L, 3 ) )
310339 {
311340 case LUA_TNUMBER:
312- if ( (seekType = (int)lua_tonumber( L, 2 )) < 0 || seekType > SEEK_END )
341+ if ( (seekType = (int)lua_tonumber( L, 3 )) < 0 || seekType > SEEK_END )
313342 goto defMethod;
314343
315344 break;
316345 case LUA_TSTRING:
317346 {
318- const char *type = lua_tostring( L, 2 );
347+ const char *type = lua_tostring( L, 3 );
319348
320349 if ( strcmp( type, "cur" ) == 0 )
321350 {
@@ -341,23 +370,42 @@
341370 }
342371
343372 // Convert lua_Number into a large FileSystem number.
344- lua_Number num = lua_tonumber( L, 1 );
373+ lua_Number num = lua_tonumber( L, 2 );
345374
346375 fsOffsetNumber_t seekOffset = (fsOffsetNumber_t)num;
347376
348- lua_pushnumber( L, ((CFile*)lua_getmethodtrans( L ))->SeekNative( seekOffset, seekType ) );
377+ int seekReturn;
378+
379+ LUAFILE_GUARDFSCALL_BEGIN
380+ seekReturn = file->SeekNative( seekOffset, seekType );
381+ LUAFILE_GUARDFSCALL_END
382+
383+ lua_pushnumber( L, seekReturn );
349384 return 1;
350385 }
351386
352387 static int luafile_eof( lua_State *L )
353388 {
354- lua_pushboolean( L, ((CFile*)lua_getmethodtrans( L ))->IsEOF() );
389+ CFile *file = fsLuaGetFile( L, 1 );
390+
391+ bool is_eof;
392+
393+ LUAFILE_GUARDFSCALL_BEGIN
394+ is_eof = file->IsEOF();
395+ LUAFILE_GUARDFSCALL_END
396+
397+ lua_pushboolean( L, is_eof );
355398 return 1;
356399 }
357400
358401 static int luafile_flush( lua_State *L )
359402 {
360- ((CFile*)lua_getmethodtrans( L ))->Flush();
403+ CFile *file = fsLuaGetFile( L, 1 );
404+
405+ LUAFILE_GUARDFSCALL_BEGIN
406+ file->Flush();
407+ LUAFILE_GUARDFSCALL_END
408+
361409 lua_pushboolean( L, true );
362410 return 1;
363411 }
@@ -364,7 +412,12 @@
364412
365413 static int luafile_seekEnd( lua_State *L )
366414 {
367- ((CFile*)lua_getmethodtrans( L ))->SetSeekEnd();
415+ CFile *file = fsLuaGetFile( L, 1 );
416+
417+ LUAFILE_GUARDFSCALL_BEGIN
418+ file->SetSeekEnd();
419+ LUAFILE_GUARDFSCALL_END
420+
368421 lua_pushboolean( L, true );
369422 return 1;
370423 }
@@ -371,36 +424,20 @@
371424
372425 static int luafile_isWritable( lua_State *L )
373426 {
374- lua_pushboolean( L, ((CFile*)lua_getmethodtrans( L ))->IsWriteable() );
427+ CFile *file = fsLuaGetFile( L, 1 );
428+ lua_pushboolean( L, file->IsWriteable() );
375429 return 1;
376430 }
377431
378432 static int luafile_isReadable( lua_State *L )
379433 {
380- lua_pushboolean( L, ((CFile*)lua_getmethodtrans( L ))->IsReadable() );
434+ CFile *file = fsLuaGetFile( L, 1 );
435+ lua_pushboolean( L, file->IsReadable() );
381436 return 1;
382437 }
383438
384-static int luafile_destroy( lua_State *lua )
439+static const luaL_Reg file_methods[] =
385440 {
386- delete (CFile*)lua_touserdata( lua, lua_upvalueindex( 1 ) );
387-
388- return 0;
389-}
390-
391-static const luaL_Reg fileInterface_sys[] =
392-{
393-#ifndef FU_CLASS
394- { "__newindex", luafile_onNewindex },
395-#endif
396- { "destroy", luafile_destroy },
397-#ifndef FU_CLASS
398- { NULL, NULL }
399-};
400-
401-static const luaL_Reg fileInterface[] =
402-{
403-#endif
404441 { "read", luafile_read },
405442 { "readByte", luafile_readByte },
406443 { "readUByte", luafile_readUByte },
@@ -434,48 +471,12 @@
434471 { "seekEnd", luafile_seekEnd },
435472 { "isWritable", luafile_isWritable },
436473 { "isReadable", luafile_isReadable },
437- { NULL, NULL }
474+ { nullptr, nullptr }
438475 };
439476
440-int luaconstructor_file( lua_State *lua )
477+void luafile_makemeta( lua_State *L, int ridx )
441478 {
442-#ifndef FU_CLASS
443- CFile *file = (CFile*)lua_touserdata( lua, lua_upvalueindex( 1 ) );
444-
445- // Register as file
446- ILuaClass *j = lua_refclass( lua, 1 );
447- j->SetTransmit( LUACLASS_FILE, file );
448-
449- lua_basicextend( lua );
450-
451- // Create the illegal access table
452- lua_newtable( lua );
453- lua_pushboolean( lua, false );
454- lua_setfield( lua, 2, "__index" );
455- lua_pushboolean( lua, false );
456- lua_setfield( lua, 2, "__newindex" );
457-
458- // We need the class outer environment
459- j->PushOuterEnvironment( lua );
460-
461- lua_pushcclosure( lua, luafile_onIndex, 2 );
462- lua_setfield( lua, LUA_ENVIRONINDEX, "__index" );
463-
464- lua_pushvalue( lua, lua_upvalueindex( 1 ) );
465- lua_setfield( lua, LUA_ENVIRONINDEX, "ioptr" );
466-
467- j->RegisterInterfaceTrans( lua, fileInterface, 0, LUACLASS_FILE );
468-#endif
469-
470- lua_pushvalue( lua, LUA_ENVIRONINDEX );
471- lua_pushvalue( lua, lua_upvalueindex( 1 ) );
472- luaL_openlib( lua, NULL, fileInterface_sys, 1 );
473-
474- lua_pushlstring( lua, "file", 4 );
475- lua_setfield( lua, LUA_ENVIRONINDEX, "__type" );
476- return 0;
479+ lua_newtable( L );
480+ lua_pushvalue( L, ridx - 1 );
481+ luaL_openlib( L, nullptr, file_methods, 1 );
477482 }
478-
479-void luafile_open( lua_State *lua )
480-{
481-}
--- blueMods/fileSystem/luafile.h (revision 12)
+++ blueMods/fileSystem/luafile.h (revision 13)
@@ -1,10 +1,9 @@
11 /*****************************************************************************
22 *
3-* PROJECT: Lua Interpreter
3+* PROJECT: Eir FileSystem for MTA:BLUE
44 * LICENSE: See LICENSE in the top level directory
55 * FILE: luafile.h
66 * PURPOSE: File environment header
7-* DEVELOPERS: Martin Turski <quiret@gmx.de>
87 *
98 * Multi Theft Auto is available from http://www.multitheftauto.com/
109 *
@@ -15,7 +14,12 @@
1514
1615 #define LUACLASS_FILE 136
1716
18-int luaconstructor_file( lua_State *lua );
19-void luafile_open( lua_State *lua );
17+void luafile_makemeta( lua_State *lua, int ridx );
2018
19+void fsRegisterFile( CFile *obj );
20+bool fsIsFile( void *objptr );
21+void fsCleanupFile( CFile *obj );
22+void fsShutdownFiles( void );
23+CFile* fsLuaGetFile( lua_State *L, int idx );
24+
2125 #endif //_FILELIB_
--- blueMods/fileSystem/luafile.reg.cpp (nonexistent)
+++ blueMods/fileSystem/luafile.reg.cpp (revision 13)
@@ -0,0 +1,56 @@
1+/*****************************************************************************
2+*
3+* PROJECT: Eir FileSystem for MTA:BLUE
4+* LICENSE: See LICENSE in the top level directory
5+* FILE: luafile.reg.cpp
6+* PURPOSE: Pointer registry for CFile
7+*
8+* For documentation visit http://wiki.mtasa.com/wiki/MTA:Eir/FileSystem/
9+*
10+* Multi Theft Auto is available from http://www.multitheftauto.com/
11+*
12+*****************************************************************************/
13+
14+#include <StdInc.h>
15+
16+static eir::Set <CFile*, FileSysCommonAllocator> _reg_files;
17+
18+void fsRegisterFile( CFile *obj )
19+{
20+ _reg_files.Insert( obj );
21+}
22+
23+bool fsIsFile( void *objptr )
24+{
25+ return ( _reg_files.Find( (CFile*)objptr ) != nullptr );
26+}
27+
28+void fsCleanupFile( CFile *obj )
29+{
30+ delete obj;
31+
32+ _reg_files.Remove( obj );
33+}
34+
35+void fsShutdownFiles( void )
36+{
37+ for ( CFile *file : _reg_files )
38+ {
39+ delete file;
40+ }
41+
42+ _reg_files.Clear();
43+}
44+
45+CFile* fsLuaGetFile( lua_State *L, int idx )
46+{
47+ void *obj = luaclass_getpointer( L, idx );
48+
49+ if ( fsIsFile( obj ) == false )
50+ {
51+ lua_pushlstring( L, "not a file", 10 );
52+ lua_error( L );
53+ }
54+
55+ return (CFile*)obj;
56+}
\ No newline at end of file
--- blueMods/fileSystem/luafilesystem.cpp (revision 12)
+++ blueMods/fileSystem/luafilesystem.cpp (revision 13)
@@ -1,10 +1,9 @@
11 /*****************************************************************************
22 *
3-* PROJECT: Lua Interpreter
3+* PROJECT: Eir FileSystem for MTA:BLUE
44 * LICENSE: See LICENSE in the top level directory
55 * FILE: luafilesystem.cpp
6-* PURPOSE: Lua filesystem access
7-* DEVELOPERS: Martin Turski <quiret@gmx.de>
6+* PURPOSE: Lua implementation of the FileSystem CFileTranslator class
87 *
98 * For documentation visit http://wiki.mtasa.com/wiki/MTA:Eir/FileSystem/
109 *
@@ -19,120 +18,223 @@
1918
2019 static int filesystem_open( lua_State *L )
2120 {
22- int theTop = lua_gettop( L );
21+ // TODO: maybe allow access to the full feature-set of Eir FileSystem by enabling
22+ // the non ANSI-C fopen API with struct as open-descriptor.
2323
24- luaL_checktype( L, 1, LUA_TSTRING );
24+ CFileTranslator *trans = fsLuaGetTranslator( L, 1 );
2525 luaL_checktype( L, 2, LUA_TSTRING );
26+ luaL_checktype( L, 3, LUA_TSTRING );
2627
27- lua_settop( L, 2 );
28+ lua_settop( L, 3 );
2829
29- CFile *file = ((CFileTranslator*)lua_getmethodtrans( L ))->Open( lua_tostring( L, 1 ), lua_tostring( L, 2 ) );
30+ CFile *file;
3031
32+ LUAFILE_GUARDFSCALL_BEGIN
33+ file = trans->Open( lua_tostring( L, 2 ), lua_tostring( L, 3 ) );
34+ LUAFILE_GUARDFSCALL_END
35+
3136 if ( !file )
3237 {
3338 lua_pushboolean( L, false );
34- return 1;
39+
40+ eFileOpenFailure open_fail = pubFileSystem->GetLastTranslatorOpenFailure();
41+
42+ if ( open_fail == eFileOpenFailure::NONE )
43+ {
44+ lua_pushlstring( L, "none", 4 );
45+ }
46+ else if ( open_fail == eFileOpenFailure::UNKNOWN_ERROR )
47+ {
48+ lua_pushlstring( L, "unknown error", 13 );
49+ }
50+ else if ( open_fail == eFileOpenFailure::PATH_OUT_OF_SCOPE )
51+ {
52+ lua_pushlstring( L, "path out of scope", 17 );
53+ }
54+ else if ( open_fail == eFileOpenFailure::INVALID_PARAMETERS )
55+ {
56+ lua_pushlstring( L, "invalid parameters", 18 );
57+ }
58+ else if ( open_fail == eFileOpenFailure::RESOURCES_EXHAUSTED )
59+ {
60+ lua_pushlstring( L, "resources exhausted", 19 );
61+ }
62+ else if ( open_fail == eFileOpenFailure::ACCESS_DENIED )
63+ {
64+ lua_pushlstring( L, "access denied", 13 );
65+ }
66+ else if ( open_fail == eFileOpenFailure::NOT_FOUND )
67+ {
68+ lua_pushlstring( L, "not found", 9 );
69+ }
70+ else if ( open_fail == eFileOpenFailure::ALREADY_EXISTS )
71+ {
72+ lua_pushlstring( L, "already exists", 14 );
73+ }
74+ else
75+ {
76+ lua_pushlstring( L, "invalid error mapping (?)", 25 );
77+ }
78+
79+ return 2;
3580 }
3681
37- lua_pushlightuserdata( L, file );
38- lua_pushcclosure( L, luaconstructor_file, 1 );
39-#ifdef FU_CLASS
40- lua_newclass( L, (unk*)file );
41-#else
42- lua_newclass( L );
82+ fslib_config *cfg = fsLuaGetConfig( L );
4383
44- // Register the file
45- lua_getfield( L, 3, "setParent" );
46- lua_getmethodclass( L )->Push( L );
47- lua_call( L, 1, 0 );
48-#endif
84+ if ( cfg->doBufferAllRaw )
85+ {
86+ try
87+ {
88+ file = pubFileSystem->WrapStreamBuffered( file, true );
89+ }
90+ catch( ... )
91+ {}
92+ }
93+
94+ fsRegisterFile( file );
95+ luaclass_pushshim( L, file );
4996 return 1;
5097 }
5198
5299 static int filesystem_exists( lua_State *L )
53100 {
54- luaL_checktype( L, 1, LUA_TSTRING );
55- lua_pushboolean( L, ((CFileTranslator*)lua_getmethodtrans( L ))->Exists( lua_tostring( L, 1 ) ) );
101+ CFileTranslator *trans = fsLuaGetTranslator( L, 1 );
102+ luaL_checktype( L, 2, LUA_TSTRING );
103+
104+ bool exists;
105+
106+ LUAFILE_GUARDFSCALL_BEGIN
107+ exists = trans->Exists( lua_tostring( L, 2 ) );
108+ LUAFILE_GUARDFSCALL_END
109+
110+ lua_pushboolean( L, exists );
56111 return 1;
57112 }
58113
59114 static int filesystem_createDir( lua_State *L )
60115 {
61- luaL_checktype( L, 1, LUA_TSTRING );
62- lua_pushboolean( L, ((CFileTranslator*)lua_getmethodtrans( L ))->CreateDir( lua_tostring( L, 1 ) ) );
116+ CFileTranslator *trans = fsLuaGetTranslator( L, 1 );
117+ luaL_checktype( L, 2, LUA_TSTRING );
118+
119+ bool success;
120+
121+ LUAFILE_GUARDFSCALL_BEGIN
122+ success = trans->CreateDir( lua_tostring( L, 2 ) );
123+ LUAFILE_GUARDFSCALL_END
124+
125+ lua_pushboolean( L, success );
63126 return 1;
64127 }
65128
66129 static int filesystem_chdir( lua_State *L )
67130 {
68- luaL_checktype( L, 1, LUA_TSTRING );
69- lua_pushboolean( L, ((CFileTranslator*)lua_getmethodtrans( L ))->ChangeDirectory( lua_tostring( L, 1 ) ) );
131+ CFileTranslator *trans = fsLuaGetTranslator( L, 1 );
132+ luaL_checktype( L, 2, LUA_TSTRING );
133+
134+ bool success;
135+
136+ LUAFILE_GUARDFSCALL_BEGIN
137+ success = trans->ChangeDirectory( lua_tostring( L, 2 ) );
138+ LUAFILE_GUARDFSCALL_END
139+
140+ lua_pushboolean( L, success );
70141 return 1;
71142 }
72143
73144 static int filesystem_delete( lua_State *L )
74145 {
75- luaL_checktype( L, 1, LUA_TSTRING );
76- lua_pushboolean( L, ((CFileTranslator*)lua_getmethodtrans( L ))->Delete( lua_tostring( L, 1 ) ) );
146+ CFileTranslator *trans = fsLuaGetTranslator( L, 1 );
147+ luaL_checktype( L, 2, LUA_TSTRING );
148+
149+ bool success;
150+
151+ LUAFILE_GUARDFSCALL_BEGIN
152+ success = trans->Delete( lua_tostring( L, 2 ) );
153+ LUAFILE_GUARDFSCALL_END
154+
155+ lua_pushboolean( L, success );
77156 return 1;
78157 }
79158
80159 static int filesystem_copy( lua_State *L )
81160 {
82- luaL_checktype( L, 1, LUA_TSTRING );
161+ CFileTranslator *trans = fsLuaGetTranslator( L, 1 );
83162 luaL_checktype( L, 2, LUA_TSTRING );
84- lua_pushboolean( L, ((CFileTranslator*)lua_getmethodtrans( L ))->Copy( lua_tostring( L, 1 ), lua_tostring( L, 2 ) ) );
163+ luaL_checktype( L, 3, LUA_TSTRING );
164+
165+ bool success;
166+
167+ LUAFILE_GUARDFSCALL_BEGIN
168+ success = trans->Copy( lua_tostring( L, 2 ), lua_tostring( L, 3 ) );
169+ LUAFILE_GUARDFSCALL_END
170+
171+ lua_pushboolean( L, success );
85172 return 1;
86173 }
87174
88175 static int filesystem_rename( lua_State *L )
89176 {
90- luaL_checktype( L, 1, LUA_TSTRING );
177+ CFileTranslator *trans = fsLuaGetTranslator( L, 1 );
91178 luaL_checktype( L, 2, LUA_TSTRING );
92- lua_pushboolean( L, ((CFileTranslator*)lua_getmethodtrans( L ))->Rename( lua_tostring( L, 1 ), lua_tostring( L, 2 ) ) );
179+ luaL_checktype( L, 3, LUA_TSTRING );
180+
181+ bool success;
182+
183+ LUAFILE_GUARDFSCALL_BEGIN
184+ success = trans->Rename( lua_tostring( L, 2 ), lua_tostring( L, 3 ) );
185+ LUAFILE_GUARDFSCALL_END
186+
187+ lua_pushboolean( L, success );
93188 return 1;
94189 }
95190
96191 static int filesystem_size( lua_State *L )
97192 {
98- luaL_checktype( L, 1, LUA_TSTRING );
99-#ifndef FU_CLASS
100- lua_pushwideinteger( L, (lua_WideInteger)((CFileTranslator*)lua_getmethodtrans( L ))->Size( lua_tostring( L, 1 ) ) );
101-#else
102- lua_pushnumber( L, (lua_Number)((CFileTranslator*)lua_getmethodtrans( L ))->Size( lua_tostring( L, 1 ) ) );
103-#endif
193+ CFileTranslator *trans = fsLuaGetTranslator( L, 1 );
194+ luaL_checktype( L, 2, LUA_TSTRING );
195+
196+ size_t fileSize;
197+
198+ LUAFILE_GUARDFSCALL_BEGIN
199+ fileSize = trans->Size( lua_tostring( L, 2 ) );
200+ LUAFILE_GUARDFSCALL_END
201+
202+ lua_pushnumber( L, fileSize );
104203 return 1;
105204 }
106205
107206 static int filesystem_stat( lua_State *L )
108207 {
109- luaL_checktype( L, 1, LUA_TSTRING );
208+ CFileTranslator *trans = fsLuaGetTranslator( L, 1 );
209+ luaL_checktype( L, 2, LUA_TSTRING );
110210
111211 filesysStats stats;
112212
113- CFileTranslator *trans = ((CFileTranslator*)lua_getmethodtrans( L ));
213+ LUAFILE_GUARDFSCALL_BEGIN
214+ if ( !trans->QueryStats( lua_tostring( L, 2 ), stats ) )
215+ {
216+ lua_pushboolean( L, false );
217+ return 1;
218+ }
114219
115- if ( !trans->QueryStats( lua_tostring( L, 1 ), stats ) )
116- {
117- lua_pushboolean( L, false );
220+ size_t fileSize = trans->Size( lua_tostring( L, 2 ) );
221+
222+ luafile_pushStats( L, fileSize, stats );
118223 return 1;
119- }
120-
121- size_t fileSize = trans->Size( lua_tostring( L, 1 ) );
122-
123- luafile_pushStats( L, fileSize, stats );
124- return 1;
224+ LUAFILE_GUARDFSCALL_END
125225 }
126226
127227 static int filesystem_relPath( lua_State *L )
128228 {
129- const char *src = lua_tostring( L, 1 );
229+ CFileTranslator *trans = fsLuaGetTranslator( L, 1 );
230+
231+ const char *src = lua_tostring( L, 2 );
130232 filePath path;
131233
132234 if ( !src )
133235 src = "";
134236
135- if ( !((CFileTranslator*)lua_getmethodtrans( L ))->GetRelativePath( src, true, path ) )
237+ if ( !trans->GetRelativePath( src, true, path ) )
136238 {
137239 lua_pushboolean( L, false );
138240 return 1;
@@ -146,13 +248,15 @@
146248
147249 static int filesystem_relPathRoot( lua_State *L )
148250 {
149- const char *src = lua_tostring( L, 1 );
251+ CFileTranslator *trans = fsLuaGetTranslator( L, 1 );
252+
253+ const char *src = lua_tostring( L, 2 );
150254 filePath path;
151255
152256 if ( !src )
153257 src = "";
154258
155- if ( !((CFileTranslator*)lua_getmethodtrans( L ))->GetRelativePathFromRoot( src, true, path ) )
259+ if ( !trans->GetRelativePathFromRoot( src, true, path ) )
156260 {
157261 lua_pushboolean( L, false );
158262 return 1;
@@ -166,13 +270,15 @@
166270
167271 static int filesystem_absPath( lua_State *L )
168272 {
169- const char *src = lua_tostring( L, 1 );
273+ CFileTranslator *trans = fsLuaGetTranslator( L, 1 );
274+
275+ const char *src = lua_tostring( L, 2 );
170276 filePath path;
171277
172278 if ( !src )
173279 src = "";
174280
175- if ( !((CFileTranslator*)lua_getmethodtrans( L ))->GetFullPath( src, true, path ) )
281+ if ( !trans->GetFullPath( src, true, path ) )
176282 {
177283 lua_pushboolean( L, false );
178284 return 1;
@@ -186,13 +292,15 @@
186292
187293 static int filesystem_absPathRoot( lua_State *L )
188294 {
189- const char *src = lua_tostring( L, 1 );
295+ CFileTranslator *trans = fsLuaGetTranslator( L, 1 );
296+
297+ const char *src = lua_tostring( L, 2 );
190298 filePath path;
191299
192300 if ( !src )
193301 src = "";
194302
195- if ( !((CFileTranslator*)lua_getmethodtrans( L ))->GetFullPathFromRoot( src, true, path ) )
303+ if ( !trans->GetFullPathFromRoot( src, true, path ) )
196304 {
197305 lua_pushboolean( L, false );
198306 return 1;
@@ -212,22 +320,23 @@
212320 luaL_ref( (lua_State*)ud, -2 );
213321 }
214322
215-static int filesystem_scanDir( lua_State *lua )
323+static int filesystem_scanDir( lua_State *L )
216324 {
217- luaL_checktype( lua, 1, LUA_TSTRING );
325+ CFileTranslator *trans = fsLuaGetTranslator( L, 1 );
326+ luaL_checktype( L, 2, LUA_TSTRING );
218327
219- const char *path = lua_tostring( lua, 1 );
328+ const char *path = lua_tostring( L, 2 );
220329 const char *wildcard;
221330 bool recursive;
222331
223- int top = lua_gettop( lua );
332+ int top = lua_gettop( L );
224333
225334 if ( top > 1 )
226335 {
227- wildcard = lua_tostring( lua, 2 );
336+ wildcard = lua_tostring( L, 3 );
228337
229338 if ( top > 2 )
230- recursive = ( lua_toboolean( lua, 3 ) != 0 );
339+ recursive = ( lua_toboolean( L, 4 ) != 0 );
231340 else
232341 recursive = false;
233342 }
@@ -237,28 +346,32 @@
237346 recursive = false;
238347 }
239348
240- lua_newtable( lua );
349+ lua_newtable( L );
241350
242- ((CFileTranslator*)lua_getmethodtrans( lua ))->ScanDirectory( path, wildcard, recursive, lua_findScanCallback, lua_findScanCallback, lua );
351+ LUAFILE_GUARDFSCALL_BEGIN
352+ trans->ScanDirectory( path, wildcard, recursive, lua_findScanCallback, lua_findScanCallback, L );
353+ LUAFILE_GUARDFSCALL_END
354+
243355 return 1;
244356 }
245357
246-static int filesystem_getFiles( lua_State *lua )
358+static int filesystem_getFiles( lua_State *L )
247359 {
248- luaL_checktype( lua, 1, LUA_TSTRING );
360+ CFileTranslator *trans = fsLuaGetTranslator( L, 1 );
361+ luaL_checktype( L, 2, LUA_TSTRING );
249362
250- const char *path = lua_tostring( lua, 1 );
363+ const char *path = lua_tostring( L, 2 );
251364 const char *wildcard;
252365 bool recursive;
253366
254- int top = lua_gettop( lua );
367+ int top = lua_gettop( L );
255368
256369 if ( top > 1 )
257370 {
258- wildcard = lua_tostring( lua, 2 );
371+ wildcard = lua_tostring( L, 3 );
259372
260373 if ( top > 2 )
261- recursive = ( lua_toboolean( lua, 3 ) != 0 );
374+ recursive = ( lua_toboolean( L, 4 ) != 0 );
262375 else
263376 recursive = false;
264377 }
@@ -268,27 +381,34 @@
268381 recursive = false;
269382 }
270383
271- lua_newtable( lua );
384+ lua_newtable( L );
272385
273- ((CFileTranslator*)lua_getmethodtrans( lua ))->ScanDirectory( path, wildcard, recursive, 0, lua_findScanCallback, lua );
386+ LUAFILE_GUARDFSCALL_BEGIN
387+ trans->ScanDirectory( path, wildcard, recursive, nullptr, lua_findScanCallback, L );
388+ LUAFILE_GUARDFSCALL_END
389+
274390 return 1;
275391 }
276392
277-static int filesystem_getDirs( lua_State *lua )
393+static int filesystem_getDirs( lua_State *L )
278394 {
279- luaL_checktype( lua, 1, LUA_TSTRING );
395+ CFileTranslator *trans = fsLuaGetTranslator( L, 1 );
396+ luaL_checktype( L, 2, LUA_TSTRING );
280397
281- const char *path = lua_tostring( lua, 1 );
398+ const char *path = lua_tostring( L, 2 );
282399 bool recursive;
283400
284- if ( lua_gettop( lua ) > 1 )
285- recursive = ( lua_toboolean( lua, 2 ) != 0 );
401+ if ( lua_gettop( L ) > 1 )
402+ recursive = ( lua_toboolean( L, 3 ) != 0 );
286403 else
287404 recursive = false;
288405
289- lua_newtable( lua );
406+ lua_newtable( L );
290407
291- ((CFileTranslator*)lua_getmethodtrans( lua ))->ScanDirectory( path, "*", recursive, lua_findScanCallback, 0, lua );
408+ LUAFILE_GUARDFSCALL_BEGIN
409+ trans->ScanDirectory( path, "*", recursive, lua_findScanCallback, 0, L );
410+ LUAFILE_GUARDFSCALL_END
411+
292412 return 1;
293413 }
294414
@@ -312,367 +432,150 @@
312432 lua_call( L, 1, 0 );
313433 }
314434
315-static int filesystem_scanDirEx( lua_State *lua )
435+static int filesystem_scanDirEx( lua_State *L )
316436 {
317- luaL_checktype( lua, 1, LUA_TSTRING );
318- luaL_checktype( lua, 2, LUA_TSTRING );
437+ CFileTranslator *trans = fsLuaGetTranslator( L, 1 );
438+ luaL_checktype( L, 2, LUA_TSTRING );
439+ luaL_checktype( L, 3, LUA_TSTRING );
319440
320- ((CFileTranslator*)lua_getmethodtrans( lua ))->ScanDirectory(
321- lua_tostring( lua, 1 ),
322- lua_tostring( lua, 2 ),
323- ( lua_toboolean( lua, 5 ) != 0 ),
324- lua_type( lua, 3 ) == LUA_TFUNCTION ? filesystem_exdircb : NULL,
325- lua_type( lua, 4 ) == LUA_TFUNCTION ? filesystem_exfilecb : NULL, lua );
441+ LUAFILE_GUARDFSCALL_BEGIN
442+ trans->ScanDirectory(
443+ lua_tostring( L, 2 ),
444+ lua_tostring( L, 3 ),
445+ ( lua_toboolean( L, 6 ) != 0 ),
446+ lua_type( L, 4 ) == LUA_TFUNCTION ? filesystem_exdircb : nullptr,
447+ lua_type( L, 5 ) == LUA_TFUNCTION ? filesystem_exfilecb : nullptr,
448+ L
449+ );
450+ LUAFILE_GUARDFSCALL_END
326451
327452 return 0;
328453 }
329454
330-static int filesystem_destroy( lua_State *L )
455+int filesystem_setOutbreakEnabled( lua_State *L )
331456 {
332- delete (CFileTranslator*)lua_touserdata( L, lua_upvalueindex( 1 ) );
457+ // This is only secure in the case that we are not on the MTA client.
458+ // Since Lua modules do not exist on the client-side, we are fine.
333459
460+ CFileTranslator *trans = fsLuaGetTranslator( L, 1 );
461+ luaL_checktype( L, 2, LUA_TBOOLEAN );
462+
463+ bool enabled = lua_toboolean( L, 2 );
464+
465+ trans->SetOutbreakEnabled( enabled );
334466 return 0;
335467 }
336468
337-static const luaL_Reg fsys_methods[] =
469+int filesystem_getOutbreakEnabled( lua_State *L )
338470 {
339- { "destroy", filesystem_destroy },
340-#ifndef FU_CLASS
341- { NULL, NULL }
342-};
471+ CFileTranslator *trans = fsLuaGetTranslator( L, 1 );
343472
344-static const luaL_Reg fsys_methods_trans[] =
345-{
346-#endif //FU_CLASS
347- { "open", filesystem_open },
348- { "exists", filesystem_exists },
349- { "createDir", filesystem_createDir },
350- { "chdir", filesystem_chdir },
351- { "delete", filesystem_delete },
352- { "copy", filesystem_copy },
353- { "rename", filesystem_rename },
354- { "size", filesystem_size },
355- { "stat", filesystem_stat },
356- { "relPath", filesystem_relPath },
357- { "relPathRoot", filesystem_relPathRoot },
358- { "absPath", filesystem_absPath },
359- { "absPathRoot", filesystem_absPathRoot },
360- { "scanDir", filesystem_scanDir },
361- { "scanDirEx", filesystem_scanDirEx },
362- { "getDirs", filesystem_getDirs },
363- { "getFiles", filesystem_getFiles },
364- { NULL, NULL }
365-};
473+ bool enabled = trans->IsOutbreakEnabled();
366474
367-int luafsys_constructor( lua_State *L )
368-{
369-#ifndef FU_CLASS
370- CFileTranslator *trans = (CFileTranslator*)lua_touserdata( L, lua_upvalueindex( 1 ) );
371-
372- ILuaClass *j = lua_refclass( L, 1 );
373- j->SetTransmit( LUACLASS_FILETRANSLATOR, trans );
374-
375- j->RegisterInterfaceTrans( L, fsys_methods_trans, 0, LUACLASS_FILETRANSLATOR );
376-#endif //FU_CLASS
377-
378- lua_pushvalue( L, LUA_ENVIRONINDEX );
379- lua_pushvalue( L, lua_upvalueindex( 1 ) );
380- lua_getfield( L, LUA_ENVIRONINDEX, "this" );
381- luaL_openlib( L, NULL, fsys_methods, 2 );
382-
383- lua_pushlstring( L, "filesystem", 10 );
384- lua_setfield( L, LUA_ENVIRONINDEX, "__type" );
385- return 0;
475+ lua_pushboolean( L, enabled );
476+ return 1;
386477 }
387478
388-void luafsys_pushroot( lua_State *L, CFileTranslator *root )
479+int filesystem_setPathProcessMode( lua_State *L )
389480 {
390- lua_pushlightuserdata( L, root );
391- lua_pushcclosure( L, luafsys_constructor, 1 );
392-#ifdef FU_CLASS
393- lua_newclass( L, (unk*)root );
394-#else
395- lua_newclass( L );
396-#endif
397-}
481+ CFileTranslator *trans = fsLuaGetTranslator( L, 1 );
482+ luaL_checktype( L, 2, LUA_TSTRING );
398483
399-int luafsys_createTranslator( lua_State *L )
400-{
401- luaL_checktype( L, 1, LUA_TSTRING );
484+ const char *ppm = lua_tostring( L, 2 );
402485
403- CFileTranslator *root = pubFileSystem->CreateTranslator( lua_tostring( L, 1 ) );
486+ filesysPathProcessMode fs_ppm;
404487
405- if ( !root )
488+ if ( StringEqualToZero( ppm, "distinguished", false ) )
406489 {
490+ fs_ppm = filesysPathProcessMode::DISTINGUISHED;
491+ }
492+ else if ( StringEqualToZero( ppm, "ambivalent_file", false ) )
493+ {
494+ fs_ppm = filesysPathProcessMode::AMBIVALENT_FILE;
495+ }
496+ else
497+ {
407498 lua_pushboolean( L, false );
408499 return 1;
409500 }
410501
411- luafsys_pushroot( L, root );
412- return 1;
413-}
502+ trans->SetPathProcessMode( fs_ppm );
414503
415-#ifndef FU_CLASS
416-static int archive_save( lua_State *L )
417-{
418- ILuaClass *j = lua_refclass( L, lua_upvalueindex( 1 ) );
419-
420- CFile *file;
421-
422- LUA_CHECK( j->GetTransmit( LUACLASS_FILE, (void*&)file ) && file->IsWriteable() );
423-
424- ((CArchiveTranslator*)lua_touserdata( L, lua_upvalueindex( 2 ) ))->Save();
425504 lua_pushboolean( L, true );
426505 return 1;
427506 }
428507
429-static int archive_destroy( lua_State *L )
508+int filesystem_getPathProcessMode( lua_State *L )
430509 {
431- // Decrement the file reference count
432- ILuaClass *j = lua_refclass( L, lua_upvalueindex( 1 ) );
433- j->DecrementMethodStack( L );
510+ CFileTranslator *trans = fsLuaGetTranslator( L, 1 );
434511
435- return 0;
436-}
512+ filesysPathProcessMode fs_ppm = trans->GetPathProcessMode();
437513
438-static const luaL_Reg archiveLib[] =
439-{
440- { "save", archive_save },
441- { "destroy", archive_destroy },
442- { NULL, NULL }
443-};
444-
445-static int archive_constructor( lua_State *L )
446-{
447- lua_pushvalue( L, LUA_ENVIRONINDEX );
448- lua_pushvalue( L, lua_upvalueindex( 1 ) );
449- lua_pushvalue( L, lua_upvalueindex( 2 ) );
450- luaL_openlib( L, NULL, archiveLib, 2 );
451- return 0;
452-}
453-
454-template <typename archiveHandler>
455-static AINLINE int _archiveTranslatorFunctor( lua_State *L, archiveHandler& cb )
456-{
457- luaL_checktype( L, 1, LUA_TCLASS );
458-
459- ILuaClass *j = lua_refclass( L, 1 );
460-
461- // Grab the file interface
462- CFile *file;
463-
464- if ( !j->GetTransmit( LUACLASS_FILE, (void*&)file ) )
465- throw lua_exception( L, LUA_ERRRUN, "expected file at archive creation" );
466-
467- // Attempt to read an archive.
468- CArchiveTranslator *root = cb.CreateTranslator( file );
469-
470- // Check that we actually suceeded in creating the archive
471- LUA_CHECK( root );
472-
473- // Keep the file alive during archive business
474- j->IncrementMethodStack( L );
475-
476- luafsys_pushroot( L, root );
477-
478- // Extend the fileTranslator class
479- lua_pushvalue( L, 1 );
480- lua_pushlightuserdata( L, root );
481- lua_pushcclosure( L, archive_constructor, 2 );
482- luaJ_extend( L, 2, 0 );
483- return 1;
484-}
485-
486-struct archiveTranslatorOpener
487-{
488- AINLINE CArchiveTranslator* CreateTranslator( CFile *file )
514+ if ( fs_ppm == filesysPathProcessMode::DISTINGUISHED )
489515 {
490- return pubFileSystem->OpenArchive( *file );
516+ lua_pushstring( L, "distinguished" );
491517 }
492-};
493-
494-int luafsys_createArchiveTranslator( lua_State *L )
495-{
496- archiveTranslatorOpener opener;
497-
498- return _archiveTranslatorFunctor( L, opener );
499-}
500-
501-struct zipArchiveTranslatorCreator
502-{
503- AINLINE CArchiveTranslator* CreateTranslator( CFile *file )
518+ else if ( fs_ppm == filesysPathProcessMode::AMBIVALENT_FILE )
504519 {
505- return pubFileSystem->CreateZIPArchive( *file );
520+ lua_pushstring( L, "ambivalent_file" );
506521 }
507-};
508-
509-int luafsys_createZIPArchive( lua_State *L )
510-{
511- zipArchiveTranslatorCreator creator;
512-
513- return _archiveTranslatorFunctor( L, creator );
514-}
515-
516-static int luafsys_copyFile( lua_State *L )
517-{
518- CFileTranslator *srcTranslator = lua_readclass <CFileTranslator> ( L, 1, LUACLASS_FILETRANSLATOR );
519- const char *srcPath = lua_tostring( L, 2 );
520- CFileTranslator *dstTranslator = lua_readclass <CFileTranslator> ( L, 3, LUACLASS_FILETRANSLATOR );
521- const char *dstPath = lua_tostring( L, 4 );
522-
523- LUA_CHECK( srcTranslator && srcPath && dstTranslator && dstPath );
524-
525- bool success = FileSystem::FileCopy( srcTranslator, srcPath, dstTranslator, dstPath );
526-
527- lua_pushboolean( L, success );
522+ else
523+ {
524+ lua_pushboolean( L, false );
525+ }
528526 return 1;
529527 }
530528
531-static int luafsys_copyStream( lua_State *L )
529+static const luaL_Reg ftranslator_methods[] =
532530 {
533- CFile *srcStream = lua_readclass <CFile> ( L, 1, LUACLASS_FILE );
534- CFile *dstStream = lua_readclass <CFile> ( L, 2, LUACLASS_FILE );
531+ { "open", filesystem_open },
532+ { "exists", filesystem_exists },
533+ { "createDir", filesystem_createDir },
534+ { "chdir", filesystem_chdir },
535+ { "delete", filesystem_delete },
536+ { "copy", filesystem_copy },
537+ { "rename", filesystem_rename },
538+ { "size", filesystem_size },
539+ { "stat", filesystem_stat },
540+ { "relPath", filesystem_relPath },
541+ { "relPathRoot", filesystem_relPathRoot },
542+ { "absPath", filesystem_absPath },
543+ { "absPathRoot", filesystem_absPathRoot },
544+ { "scanDir", filesystem_scanDir },
545+ { "scanDirEx", filesystem_scanDirEx },
546+ { "getDirs", filesystem_getDirs },
547+ { "getFiles", filesystem_getFiles },
548+ { "setOutbreakEnabled", filesystem_setOutbreakEnabled },
549+ { "getOutbreakEnabled", filesystem_getOutbreakEnabled },
550+ { "setPathProcessMode", filesystem_setPathProcessMode },
551+ { "getPathProcessMode", filesystem_getPathProcessMode },
552+ { nullptr, nullptr }
553+};
535554
536- LUA_CHECK( srcStream && dstStream );
537-
538- FileSystem::StreamCopy( *srcStream, *dstStream );
539-
540- lua_pushboolean( L, true );
541- return 1;
542-}
543-
544-static int luafsys_copyStreamCount( lua_State *L )
555+int luafsys_createTranslator( lua_State *L )
545556 {
546- CFile *srcStream = lua_readclass <CFile> ( L, 1, LUACLASS_FILE );
547- CFile *dstStream = lua_readclass <CFile> ( L, 2, LUACLASS_FILE );
548- int count = (int)lua_tonumber( L, 3 );
549-
550- LUA_CHECK( srcStream && dstStream );
551-
552- LUA_CHECK( count > 0 );
553-
554- FileSystem::StreamCopyCount( *srcStream, *dstStream, count );
555-
556- lua_pushboolean( L, true );
557- return 1;
558-}
559-#endif //FU_CLASS
560-
561-static int luafsys_pathToFilename( lua_State *L )
562-{
563557 luaL_checktype( L, 1, LUA_TSTRING );
564- luaL_checktype( L, 2, LUA_TBOOLEAN );
565558
566- const char *path = lua_tostring( L, 1 );
567- bool includeExtension = ( lua_toboolean( L, 2 ) != 0 );
559+ CFileTranslator *root;
568560
569- filePath directoryOut;
561+ LUAFILE_GUARDFSCALL_BEGIN
562+ root = pubFileSystem->CreateTranslator( lua_tostring( L, 1 ) );
563+ LUAFILE_GUARDFSCALL_END
570564
571- filePath fileName = FileSystem::GetFileNameItem( path, includeExtension, &directoryOut );
572-
573- int iRet = 1;
574-
575- lua_pushlstring( L, fileName.c_str(), fileName.size() );
576-
577- if ( directoryOut.size() != 0 )
565+ if ( !root )
578566 {
579- lua_pushlstring( L, directoryOut.c_str(), directoryOut.size() );
580-
581- iRet++;
567+ lua_pushboolean( L, false );
568+ return 1;
582569 }
583570
584- return iRet;
585-}
586-
587-#ifndef FU_CLASS
588-
589-static int luafsys_streamCompare( lua_State *L )
590-{
591- CFile *srcFile = lua_readclass <CFile> ( L, 1, LUACLASS_FILE );
592- CFile *dstFile = lua_readclass <CFile> ( L, 2, LUACLASS_FILE );
593-
594- LUA_CHECK( srcFile && dstFile );
595-
596- char sourceBuf[2048];
597- char targetBuf[2048];
598-
599- bool isEqual = true;
600-
601- while ( !srcFile->IsEOF() )
602- {
603- size_t sourceReadCount = srcFile->Read( sourceBuf, sizeof( sourceBuf ) );
604- size_t destReadCount = dstFile->Read( targetBuf, sizeof( targetBuf ) );
605-
606- if ( sourceReadCount != destReadCount )
607- {
608- isEqual = false;
609- break;
610- }
611-
612- if ( sourceReadCount != 0 && memcmp( sourceBuf, targetBuf, sourceReadCount ) != 0 )
613- {
614- isEqual = false;
615- break;
616- }
617- }
618-
619- lua_pushboolean( L, isEqual );
571+ fsRegisterTranslator( root );
572+ luaclass_pushshim( L, root );
620573 return 1;
621574 }
622-#endif //FU_CLASS
623575
624-int luafsys_getRoot( lua_State *L )
576+void luaftrans_makemeta( lua_State *L, int ridx )
625577 {
626- lua_pushvalue( L, lua_upvalueindex( 1 ) );
627- return 1;
628-}
629-
630-static const luaL_Reg fsysLib[] =
631-{
632- { "createTranslator", luafsys_createTranslator },
633-#ifndef FU_CLASS
634- { "createArchiveTranslator", luafsys_createArchiveTranslator },
635- { "createZIPArchive", luafsys_createZIPArchive },
636- { "copyFile", luafsys_copyFile },
637- { "copyStream", luafsys_copyStream },
638- { "copyStreamCount", luafsys_copyStreamCount },
639-#endif //FU_CLASS
640- { "pathToFilename", luafsys_pathToFilename },
641-#ifndef FU_CLASS
642- { "streamCompare", luafsys_streamCompare },
643-#endif //FU_CLASS
644- { NULL, NULL }
645-};
646-
647-int luafsys_init( lua_State *L )
648-{
649- // Specify the root fileTranslator
650- CFileTranslator *rootTranslator = pubFileSystem->CreateTranslator( "" ); // use the current directory.
651-
652- // We could fail to obtain the handle to the translator if the directory is handle-locked.
653- // In that case, return false.
654- LUA_CHECK( rootTranslator != NULL );
655-
656- // Return the Lua representation of the root translator.
657- luafsys_pushroot( L, rootTranslator );
658- return 1;
659-}
660-
661-void luafilesystem_open( lua_State *L )
662-{
663578 lua_newtable( L );
664- luaL_openlib( L, NULL, fsysLib, 0 );
665-
666- lua_pushlstring( L, "getRoot", 7 );
667- lua_pushcclosure( L, luafsys_init, 0 );
668- lua_call( L, 0, 1 );
669-
670- lua_pushlstring( L, "root", 4 );
671-
672- lua_pushvalue( L, -2 );
673-
674- lua_rawset( L, -5 );
675-
676- lua_pushcclosure( L, luafsys_getRoot, 1 );
677- lua_rawset( L, -3 );
678-}
579+ lua_pushvalue( L, ridx - 1 );
580+ luaL_openlib( L, nullptr, ftranslator_methods, 1 );
581+}
\ No newline at end of file
--- blueMods/fileSystem/luafilesystem.h (revision 12)
+++ blueMods/fileSystem/luafilesystem.h (revision 13)
@@ -1,10 +1,9 @@
11 /*****************************************************************************
22 *
3-* PROJECT: Lua Interpreter
3+* PROJECT: Eir FileSystem for MTA:BLUE
44 * LICENSE: See LICENSE in the top level directory
55 * FILE: luafilesystem.h
66 * PURPOSE: Lua filesystem access
7-* DEVELOPERS: Martin Turski <quiret@gmx.de>
87 *
98 * Multi Theft Auto is available from http://www.multitheftauto.com/
109 *
@@ -17,7 +16,12 @@
1716
1817 int luafsys_createArchiveTranslator( lua_State *L );
1918 int luafsys_createZIPArchive( lua_State *L );
20-void luafsys_pushroot( lua_State *L, CFileTranslator *root );
2119 void luafilesystem_open( lua_State *L );
2220
21+void fsRegisterTranslator( CFileTranslator *trans );
22+bool fsIsTranslator( void *objptr );
23+void fsCleanupTranslator( CFileTranslator *trans );
24+void fsShutdownTranslators( void );
25+CFileTranslator* fsLuaGetTranslator( lua_State *L, int idx );
26+
2327 #endif //_FILESYSTEMLIB_
--- blueMods/fileSystem/luafilesystem.reg.cpp (nonexistent)
+++ blueMods/fileSystem/luafilesystem.reg.cpp (revision 13)
@@ -0,0 +1,56 @@
1+/*****************************************************************************
2+*
3+* PROJECT: Eir FileSystem for MTA:BLUE
4+* LICENSE: See LICENSE in the top level directory
5+* FILE: luafilesystem.reg.cpp
6+* PURPOSE: Pointer registry for CFileTranslator
7+*
8+* For documentation visit http://wiki.mtasa.com/wiki/MTA:Eir/FileSystem/
9+*
10+* Multi Theft Auto is available from http://www.multitheftauto.com/
11+*
12+*****************************************************************************/
13+
14+#include <StdInc.h>
15+
16+static eir::Set <CFileTranslator*, FileSysCommonAllocator> _reg_ftrans;
17+
18+void fsRegisterTranslator( CFileTranslator *trans )
19+{
20+ _reg_ftrans.Insert( trans );
21+}
22+
23+bool fsIsTranslator( void *objptr )
24+{
25+ return ( _reg_ftrans.Find( (CFileTranslator*)objptr ) != nullptr );
26+}
27+
28+void fsCleanupTranslator( CFileTranslator *trans )
29+{
30+ delete trans;
31+
32+ _reg_ftrans.Remove( trans );
33+}
34+
35+void fsShutdownTranslators( void )
36+{
37+ for ( CFileTranslator *trans : _reg_ftrans )
38+ {
39+ delete trans;
40+ }
41+
42+ _reg_ftrans.Clear();
43+}
44+
45+CFileTranslator* fsLuaGetTranslator( lua_State *L, int idx )
46+{
47+ void *obj = luaclass_getpointer( L, idx );
48+
49+ if ( fsIsTranslator( obj ) == false )
50+ {
51+ lua_pushlstring( L, "not a file-translator", 10 );
52+ lua_error( L );
53+ }
54+
55+ return (CFileTranslator*)obj;
56+}
\ No newline at end of file
--- blueMods/fileSystem/luafslib.cpp (nonexistent)
+++ blueMods/fileSystem/luafslib.cpp (revision 13)
@@ -0,0 +1,527 @@
1+/*****************************************************************************
2+*
3+* PROJECT: Eir FileSystem for MTA:BLUE
4+* LICENSE: See LICENSE in the top level directory
5+* FILE: luafslib.cpp
6+* PURPOSE: Lua Eir FileSystem module main implementation file
7+*
8+* For documentation visit http://wiki.mtasa.com/wiki/MTA:Eir/FileSystem/
9+*
10+* Multi Theft Auto is available from http://www.multitheftauto.com/
11+*
12+*****************************************************************************/
13+
14+#include <StdInc.h>
15+
16+#include "luafile.Utils.hxx"
17+
18+extern CFileSystemInterface *pubFileSystem;
19+
20+#ifndef FU_CLASS
21+static int archive_save( lua_State *L )
22+{
23+ ILuaClass *j = lua_refclass( L, lua_upvalueindex( 1 ) );
24+
25+ CFile *file;
26+
27+ LUA_CHECK( j->GetTransmit( LUACLASS_FILE, (void*&)file ) && file->IsWriteable() );
28+
29+ ((CArchiveTranslator*)lua_touserdata( L, lua_upvalueindex( 2 ) ))->Save();
30+ lua_pushboolean( L, true );
31+ return 1;
32+}
33+
34+static int archive_destroy( lua_State *L )
35+{
36+ // Decrement the file reference count
37+ ILuaClass *j = lua_refclass( L, lua_upvalueindex( 1 ) );
38+ j->DecrementMethodStack( L );
39+
40+ return 0;
41+}
42+
43+static const luaL_Reg archiveLib[] =
44+{
45+ { "save", archive_save },
46+ { "destroy", archive_destroy },
47+ { NULL, NULL }
48+};
49+
50+static int archive_constructor( lua_State *L )
51+{
52+ lua_pushvalue( L, LUA_ENVIRONINDEX );
53+ lua_pushvalue( L, lua_upvalueindex( 1 ) );
54+ lua_pushvalue( L, lua_upvalueindex( 2 ) );
55+ luaL_openlib( L, NULL, archiveLib, 2 );
56+ return 0;
57+}
58+
59+template <typename archiveHandler>
60+static AINLINE int _archiveTranslatorFunctor( lua_State *L, archiveHandler& cb )
61+{
62+ luaL_checktype( L, 1, LUA_TCLASS );
63+
64+ ILuaClass *j = lua_refclass( L, 1 );
65+
66+ // Grab the file interface
67+ CFile *file;
68+
69+ if ( !j->GetTransmit( LUACLASS_FILE, (void*&)file ) )
70+ throw lua_exception( L, LUA_ERRRUN, "expected file at archive creation" );
71+
72+ // Attempt to read an archive.
73+ CArchiveTranslator *root = cb.CreateTranslator( file );
74+
75+ // Check that we actually suceeded in creating the archive
76+ LUA_CHECK( root );
77+
78+ // Keep the file alive during archive business
79+ j->IncrementMethodStack( L );
80+
81+ luafsys_pushroot( L, root );
82+
83+ // Extend the fileTranslator class
84+ lua_pushvalue( L, 1 );
85+ lua_pushlightuserdata( L, root );
86+ lua_pushcclosure( L, archive_constructor, 2 );
87+ luaJ_extend( L, 2, 0 );
88+ return 1;
89+}
90+
91+struct archiveTranslatorOpener
92+{
93+ AINLINE CArchiveTranslator* CreateTranslator( CFile *file )
94+ {
95+ return pubFileSystem->OpenArchive( *file );
96+ }
97+};
98+
99+int luafsys_createArchiveTranslator( lua_State *L )
100+{
101+ archiveTranslatorOpener opener;
102+
103+ return _archiveTranslatorFunctor( L, opener );
104+}
105+
106+struct zipArchiveTranslatorCreator
107+{
108+ AINLINE CArchiveTranslator* CreateTranslator( CFile *file )
109+ {
110+ return pubFileSystem->CreateZIPArchive( *file );
111+ }
112+};
113+
114+int luafsys_createZIPArchive( lua_State *L )
115+{
116+ zipArchiveTranslatorCreator creator;
117+
118+ return _archiveTranslatorFunctor( L, creator );
119+}
120+#endif //FU_CLASS
121+
122+static int luafsys_copyFile( lua_State *L )
123+{
124+ CFileTranslator *srcTranslator = fsLuaGetTranslator( L, 1 );
125+ const char *srcPath = lua_tostring( L, 2 );
126+ CFileTranslator *dstTranslator = fsLuaGetTranslator( L, 3 );
127+ const char *dstPath = lua_tostring( L, 4 );
128+
129+ LUA_CHECK( srcTranslator && srcPath && dstTranslator && dstPath );
130+
131+ bool success;
132+
133+ LUAFILE_GUARDFSCALL_BEGIN
134+ success = FileSystem::FileCopy( srcTranslator, srcPath, dstTranslator, dstPath );
135+ LUAFILE_GUARDFSCALL_END
136+
137+ lua_pushboolean( L, success );
138+ return 1;
139+}
140+
141+static int luafsys_copyStream( lua_State *L )
142+{
143+ CFile *srcStream = fsLuaGetFile( L, 1 );
144+ CFile *dstStream = fsLuaGetFile( L, 2 );
145+
146+ LUA_CHECK( srcStream && dstStream );
147+
148+ LUAFILE_GUARDFSCALL_BEGIN
149+ FileSystem::StreamCopy( *srcStream, *dstStream );
150+ LUAFILE_GUARDFSCALL_END
151+
152+ lua_pushboolean( L, true );
153+ return 1;
154+}
155+
156+static int luafsys_copyStreamCount( lua_State *L )
157+{
158+ CFile *srcStream = fsLuaGetFile( L, 1 );
159+ CFile *dstStream = fsLuaGetFile( L, 2 );
160+ int count = (int)lua_tonumber( L, 3 );
161+
162+ LUA_CHECK( srcStream && dstStream );
163+
164+ LUA_CHECK( count > 0 );
165+
166+ LUAFILE_GUARDFSCALL_BEGIN
167+ FileSystem::StreamCopyCount( *srcStream, *dstStream, count );
168+ LUAFILE_GUARDFSCALL_END
169+
170+ lua_pushboolean( L, true );
171+ return 1;
172+}
173+
174+static int luafsys_pathToFilename( lua_State *L )
175+{
176+ luaL_checktype( L, 1, LUA_TSTRING );
177+ luaL_checktype( L, 2, LUA_TBOOLEAN );
178+
179+ const char *path = lua_tostring( L, 1 );
180+ bool includeExtension = ( lua_toboolean( L, 2 ) != 0 );
181+
182+ filePath directoryOut;
183+
184+ filePath fileName = FileSystem::GetFileNameItem( path, includeExtension, &directoryOut );
185+
186+ int iRet = 1;
187+
188+ lua_pushlstring( L, fileName.c_str(), fileName.size() );
189+
190+ if ( directoryOut.size() != 0 )
191+ {
192+ lua_pushlstring( L, directoryOut.c_str(), directoryOut.size() );
193+
194+ iRet++;
195+ }
196+
197+ return iRet;
198+}
199+
200+static int luafsys_streamCompare( lua_State *L )
201+{
202+ CFile *srcFile = fsLuaGetFile( L, 1 );
203+ CFile *dstFile = fsLuaGetFile( L, 2 );
204+
205+ LUA_CHECK( srcFile && dstFile );
206+
207+ char sourceBuf[2048];
208+ char targetBuf[2048];
209+
210+ bool isEqual = true;
211+
212+ LUAFILE_GUARDFSCALL_BEGIN
213+ while ( !srcFile->IsEOF() )
214+ {
215+ size_t sourceReadCount = srcFile->Read( sourceBuf, sizeof( sourceBuf ) );
216+ size_t destReadCount = dstFile->Read( targetBuf, sizeof( targetBuf ) );
217+
218+ if ( sourceReadCount != destReadCount )
219+ {
220+ isEqual = false;
221+ break;
222+ }
223+
224+ if ( sourceReadCount != 0 && memcmp( sourceBuf, targetBuf, sourceReadCount ) != 0 )
225+ {
226+ isEqual = false;
227+ break;
228+ }
229+ }
230+ LUAFILE_GUARDFSCALL_END
231+
232+ lua_pushboolean( L, isEqual );
233+ return 1;
234+}
235+
236+int luafsys_getRoot( lua_State *L )
237+{
238+ lua_pushvalue( L, lua_upvalueindex( 1 ) );
239+ return 1;
240+}
241+
242+int luafsys_createTranslator( lua_State *L );
243+
244+int luafsys_createRAMDisk( lua_State *L )
245+{
246+ luaL_checktype( L, 1, LUA_TBOOLEAN );
247+
248+ bool case_sensitive = lua_toboolean( L, 1 );
249+
250+ CFileTranslator *ramDisk = pubFileSystem->CreateRamdisk( case_sensitive );
251+
252+ if ( ramDisk == nullptr )
253+ {
254+ lua_pushboolean( L, false );
255+ return 1;
256+ }
257+
258+ fsRegisterTranslator( ramDisk );
259+ luaclass_pushshim( L, ramDisk );
260+ return 1;
261+}
262+
263+int luafsys_createMemoryFile( lua_State *L )
264+{
265+ CFile *memFile = pubFileSystem->CreateMemoryFile();
266+
267+ if ( memFile == nullptr )
268+ {
269+ lua_pushboolean( L, false );
270+ return 1;
271+ }
272+
273+ fsRegisterFile( memFile );
274+ luaclass_pushshim( L, memFile );
275+ return 1;
276+}
277+
278+int luafsys_createFileIterative( lua_State *L )
279+{
280+ CFileTranslator *target = fsLuaGetTranslator( L, 1 );
281+ luaL_checktype( L, 2, LUA_TSTRING );
282+ luaL_checktype( L, 3, LUA_TSTRING );
283+ luaL_checkinteger( L, 4 );
284+
285+ const char *prefix = lua_tostring( L, 2 );
286+ const char *suffix = lua_tostring( L, 3 );
287+ int i_max_dupl = lua_tointeger( L, 4 );
288+
289+ if ( i_max_dupl < 0 )
290+ {
291+ lua_pushboolean( L, false );
292+ return 1;
293+ }
294+
295+ unsigned int max_dupl = (unsigned int)i_max_dupl;
296+
297+ CFile *result;
298+
299+ LUAFILE_GUARDFSCALL_BEGIN
300+ result = pubFileSystem->CreateFileIterative( target, prefix, suffix, max_dupl );
301+ LUAFILE_GUARDFSCALL_END
302+
303+ if ( result == nullptr )
304+ {
305+ lua_pushboolean( L, false );
306+ return 1;
307+ }
308+
309+ fsRegisterFile( result );
310+ luaclass_pushshim( L, result );
311+ return 1;
312+}
313+
314+int luafsys_topointer( lua_State *L )
315+{
316+ void *ptr = luaclass_getpointer( L, 1 );
317+
318+ lua_pushlightuserdata( L, ptr );
319+ return 1;
320+
321+ // TODO: maybe allow conversion from pointer back to object?
322+}
323+
324+int luafsys_type( lua_State *L )
325+{
326+ void *obj = luaclass_getpointer( L, 1 );
327+
328+ if ( fsIsFile( obj ) )
329+ {
330+ lua_pushlstring( L, "file", 4 );
331+ return 1;
332+ }
333+ if ( fsIsTranslator( obj ) )
334+ {
335+ lua_pushlstring( L, "file-translator", 15 );
336+ return 1;
337+ }
338+
339+ lua_pushboolean( L, false );
340+ return 1;
341+}
342+
343+int luafsys_setDoBufferAllRaw( lua_State *L )
344+{
345+ luaL_checktype( L, 1, LUA_TBOOLEAN );
346+
347+ bool enable = lua_toboolean( L, 1 );
348+
349+ fslib_config *cfg = fsLuaGetConfig( L );
350+
351+ cfg->doBufferAllRaw = enable;
352+ return 0;
353+}
354+
355+int luafsys_getDoBufferAllRaw( lua_State *L )
356+{
357+ fslib_config *cfg = fsLuaGetConfig( L );
358+
359+ lua_pushboolean( L, cfg->doBufferAllRaw );
360+ return 1;
361+}
362+
363+static const luaL_Reg fsysLib[] =
364+{
365+ { "createTranslator", luafsys_createTranslator },
366+ { "createRAMDisk", luafsys_createRAMDisk },
367+ { "createMemoryFile", luafsys_createMemoryFile },
368+ { "createFileIterative", luafsys_createFileIterative },
369+#ifndef FU_CLASS
370+ { "createArchiveTranslator", luafsys_createArchiveTranslator },
371+ { "createZIPArchive", luafsys_createZIPArchive },
372+#endif //FU_CLASS
373+ { "copyFile", luafsys_copyFile },
374+ { "copyStream", luafsys_copyStream },
375+ { "copyStreamCount", luafsys_copyStreamCount },
376+ { "pathToFilename", luafsys_pathToFilename },
377+ { "streamCompare", luafsys_streamCompare },
378+ { "topointer", luafsys_topointer },
379+ { "type", luafsys_type },
380+ { "setDoBufferAllRaw", luafsys_setDoBufferAllRaw },
381+ { "getDoBufferAllRaw", luafsys_getDoBufferAllRaw },
382+ { nullptr, nullptr }
383+};
384+
385+int luafsys_init( lua_State *L )
386+{
387+ // Specify the root fileTranslator
388+ CFileTranslator *rootTranslator = pubFileSystem->CreateTranslator( "" ); // use the current directory.
389+
390+ // We could fail to obtain the handle to the translator if the directory is handle-locked.
391+ // In that case, return false.
392+ LUA_CHECK( rootTranslator != nullptr );
393+
394+ // Return the Lua representation of the root translator.
395+ fsRegisterTranslator( rootTranslator );
396+ luaclass_pushshim( L, rootTranslator );
397+ return 1;
398+}
399+
400+void luaclass_makemeta( lua_State *L, int ridx );
401+void luafile_makemeta( lua_State *L, int ridx );
402+void luaftrans_makemeta( lua_State *L, int ridx );
403+void luaimgarch_makemeta( lua_State *L, int ridx );
404+void luaziparch_makemeta( lua_State *L, int ridx );
405+
406+void luaclassmt_make( lua_State *L, int ridx );
407+
408+static int luafilesystem_ongc( lua_State *L )
409+{
410+ void **ptr_cfg = (void**)lua_touserdata( L, lua_upvalueindex( 1 ) );
411+
412+ fslib_config *cfg = (fslib_config*)*ptr_cfg;
413+
414+ delete cfg;
415+
416+ *ptr_cfg = nullptr;
417+
418+ return 0;
419+}
420+
421+fslib_config* fsLuaGetConfig( lua_State *L )
422+{
423+ void **ptr_cfg = (void**)lua_touserdata( L, lua_upvalueindex( 1 ) );
424+
425+ return (fslib_config*)*ptr_cfg;
426+}
427+
428+extern bool _global_doBufferAllRaw;
429+
430+void luafilesystem_open( lua_State *L )
431+{
432+ // We want to store the entire Eir FileSystem Lua implementation state
433+ // as GC-linked userdata upvalue to all C-closures we create.
434+ // This strategy is safely possible because even the "debug.getupvalue" function
435+ // is disallowed from fetching C-closure upvalues.
436+
437+ // The library we will return.
438+ lua_newtable( L );
439+
440+ void **ptr_cfg = (void**)lua_newuserdata( L, sizeof(void*) );
441+ {
442+ fslib_config *cfg = new fslib_config;
443+
444+ cfg->doBufferAllRaw = _global_doBufferAllRaw;
445+
446+ *ptr_cfg = cfg;
447+ }
448+
449+ lua_newtable( L );
450+
451+ // Store as meta-table.
452+ lua_pushvalue( L, -1 );
453+ lua_setmetatable( L, -3 );
454+
455+ // Create a table that should store all meta-tables for Eir FileSystem classes.
456+ lua_newtable( L );
457+
458+ // Store it as "metas" in the maintenance table.
459+ lua_pushlstring( L, "metas", 5 );
460+ lua_pushvalue( L, -2 );
461+ lua_rawset( L, -4 );
462+
463+ // Initialize the class metatable.
464+ lua_pushlstring( L, "class", 5 );
465+ luaclass_makemeta( L, -4 );
466+ lua_rawset( L, -3 );
467+
468+ // Initialize the file metatable.
469+ lua_pushlstring( L, "file", 4 );
470+ luafile_makemeta( L, -4 );
471+ lua_rawset( L, -3 );
472+
473+ // Initialize the file-translator metatable.
474+ lua_pushlstring( L, "ftrans", 6 );
475+ luaftrans_makemeta( L, -4 );
476+ lua_rawset( L, -3 );
477+
478+ // Initialize the img-archive metatable.
479+ lua_pushlstring( L, "imgarch", 7 );
480+ luaimgarch_makemeta( L, -4 );
481+ lua_rawset( L, -3 );
482+
483+ // Initialize the zip-archive metatable.
484+ lua_pushlstring( L, "ziparch", 7 );
485+ luaziparch_makemeta( L, -4 );
486+ lua_rawset( L, -3 );
487+
488+ lua_pop( L, 1 );
489+
490+ // Now all meta-method tables have been initialized.
491+ // Next get the maintenance set-up.
492+ lua_pushlstring( L, "__gc", 4 );
493+ lua_pushvalue( L, -3 );
494+ lua_pushcclosure( L, luafilesystem_ongc, 1 );
495+ lua_rawset( L, -3 );
496+
497+ // Create the shim for all objects.
498+ lua_pushlstring( L, "classmt", 7 );
499+ luaclassmt_make( L, -3 );
500+ lua_rawset( L, -3 );
501+
502+ lua_pop( L, 1 );
503+
504+ // Setup the main Eir FileSystem functions.
505+ lua_pushvalue( L, -2 );
506+ lua_pushvalue( L, -2 );
507+ luaL_openlib( L, nullptr, fsysLib, 1 );
508+ lua_pop( L, 1 );
509+
510+ // Cache the root translator into the lib.
511+ lua_pushvalue( L, -1 );
512+ lua_pushcclosure( L, luafsys_init, 1 );
513+ lua_call( L, 0, 1 );
514+
515+ lua_pushlstring( L, "root", 4 );
516+ lua_pushvalue( L, -2 );
517+ lua_rawset( L, -5 );
518+
519+ lua_pushlstring( L, "getRoot", 7 );
520+ lua_pushvalue( L, -2 );
521+ lua_pushcclosure( L, luafsys_getRoot, 1 );
522+ lua_rawset( L, -5 );
523+
524+ lua_pop( L, 2 );
525+
526+ // At the end we return the table that we created at the top.
527+}
--- blueMods/fileSystem/luafslib.h (nonexistent)
+++ blueMods/fileSystem/luafslib.h (revision 13)
@@ -0,0 +1,24 @@
1+/*****************************************************************************
2+*
3+* PROJECT: Eir FileSystem for MTA:BLUE
4+* LICENSE: See LICENSE in the top level directory
5+* FILE: luafslib.h
6+* PURPOSE: Lua Eir FileSystem module main implementation file
7+*
8+* For documentation visit http://wiki.mtasa.com/wiki/MTA:Eir/FileSystem/
9+*
10+* Multi Theft Auto is available from http://www.multitheftauto.com/
11+*
12+*****************************************************************************/
13+
14+#ifndef _LUA_EIR_FILESYSTEM_FSLIB_HEADER_
15+#define _LUA_EIR_FILESYSTEM_FSLIB_HEADER_
16+
17+struct fslib_config
18+{
19+ bool doBufferAllRaw = false;
20+};
21+
22+fslib_config* fsLuaGetConfig( lua_State *L );
23+
24+#endif //_LUA_EIR_FILESYSTEM_FSLIB_HEADER_
\ No newline at end of file
--- blueMods/fileSystem/luaimgarch.cpp (nonexistent)
+++ blueMods/fileSystem/luaimgarch.cpp (revision 13)
@@ -0,0 +1,28 @@
1+/*****************************************************************************
2+*
3+* PROJECT: Eir FileSystem for MTA:BLUE
4+* LICENSE: See LICENSE in the top level directory
5+* FILE: luaimgarch.cpp
6+* PURPOSE: Lua implementation of the FileSystem CIMGArchiveTranslator class
7+*
8+* For documentation visit http://wiki.mtasa.com/wiki/MTA:Eir/FileSystem/
9+*
10+* Multi Theft Auto is available from http://www.multitheftauto.com/
11+*
12+*****************************************************************************/
13+
14+#include <StdInc.h>
15+
16+extern CFileSystemInterface *pubFileSystem;
17+
18+static const luaL_Reg imgarch_methods[] =
19+{
20+ { nullptr, nullptr }
21+};
22+
23+void luaimgarch_makemeta( lua_State *L, int ridx )
24+{
25+ lua_newtable( L );
26+ lua_pushvalue( L, ridx - 1 );
27+ luaL_openlib( L, nullptr, imgarch_methods, 1 );
28+}
\ No newline at end of file
--- blueMods/fileSystem/luaziparch.cpp (nonexistent)
+++ blueMods/fileSystem/luaziparch.cpp (revision 13)
@@ -0,0 +1,28 @@
1+/*****************************************************************************
2+*
3+* PROJECT: Eir FileSystem for MTA:BLUE
4+* LICENSE: See LICENSE in the top level directory
5+* FILE: luaziparch.cpp
6+* PURPOSE: Lua implementation of the FileSystem CZIPArchiveTranslator class
7+*
8+* For documentation visit http://wiki.mtasa.com/wiki/MTA:Eir/FileSystem/
9+*
10+* Multi Theft Auto is available from http://www.multitheftauto.com/
11+*
12+*****************************************************************************/
13+
14+#include <StdInc.h>
15+
16+extern CFileSystemInterface *pubFileSystem;
17+
18+static const luaL_Reg ziparch_methods[] =
19+{
20+ { nullptr, nullptr }
21+};
22+
23+void luaziparch_makemeta( lua_State *L, int ridx )
24+{
25+ lua_newtable( L );
26+ lua_pushvalue( L, ridx - 1 );
27+ luaL_openlib( L, nullptr, ziparch_methods, 1 );
28+}
\ No newline at end of file
--- blueMods/fileSystem/ml_base.cpp (revision 12)
+++ blueMods/fileSystem/ml_base.cpp (revision 13)
@@ -24,6 +24,8 @@
2424 CFileSystemInterface *pubFileSystem = nullptr;
2525 NativeExecutive::CExecutiveManager *natExecMan = nullptr;
2626
27+bool _global_doBufferAllRaw;
28+
2729 // Initialisation function (module entrypoint)
2830 MTAEXPORT bool InitModule ( ILuaModuleManager10 *pManager, char *szModuleName, char *szAuthor, float *fVersion )
2931 {
@@ -36,6 +38,11 @@
3638 // TODO: anything left to configure for the Eir FileSystem module here?
3739
3840 pubFileSystem = CFileSystem::Create( fsparams );
41+
42+ // Allow per-resource switching of the global file buffering.
43+ _global_doBufferAllRaw = pubFileSystem->GetDoBufferAllRaw();
44+
45+ pubFileSystem->SetDoBufferAllRaw( false );
3946 }
4047 catch( ... )
4148 {
@@ -71,6 +78,10 @@
7178
7279 MTAEXPORT bool ShutdownModule ( void )
7380 {
81+ // Clean-up any remaining handles.
82+ fsShutdownTranslators();
83+ fsShutdownFiles();
84+
7485 if ( pubFileSystem != nullptr )
7586 {
7687 CFileSystem::Destroy( (CFileSystem*)pubFileSystem );
Show on old repository browser