vlc/vlc-3.0 | branch: master | Hugo Beauzée-Luyssen <h...@beauzee.fr> | Fri Apr 6 17:11:19 2018 +0200| [5d8c8d39d83a05f48ba3cf2edd5e531fa0f96a28] | committer: Hugo Beauzée-Luyssen
lua: libs: Provide a basic io module replacement (cherry picked from commit e6d9d25ef9f144ac661453324e1e143048f9e035) Signed-off-by: Hugo Beauzée-Luyssen <h...@beauzee.fr> > http://git.videolan.org/gitweb.cgi/vlc/vlc-3.0.git/?a=commit;h=5d8c8d39d83a05f48ba3cf2edd5e531fa0f96a28 --- modules/lua/libs/io.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) diff --git a/modules/lua/libs/io.c b/modules/lua/libs/io.c index f3bbefe4c0..67b92f36b5 100644 --- a/modules/lua/libs/io.c +++ b/modules/lua/libs/io.c @@ -24,6 +24,7 @@ # include "config.h" #endif +#include <stdio.h> #include <errno.h> #include <vlc_common.h> @@ -32,6 +33,162 @@ #include "../vlc.h" #include "../libs.h" +static int vlclua_io_file_read_line( lua_State *L, FILE* p_file ) +{ + char* psz_line = NULL; + size_t i_buffer; + ssize_t i_len = getline( &psz_line, &i_buffer, p_file ); + if ( i_len == -1 ) + return 0; + if( psz_line[i_len - 1] == '\n' ) + psz_line[--i_len] = 0; + lua_pushstring( L, psz_line ); + free( psz_line ); + return 1; +} + +static int vlclua_io_file_read_number( lua_State *L, FILE* p_file ) +{ + lua_Number num; + if ( fscanf( p_file, LUA_NUMBER_SCAN, &num ) != 1 ) + return 0; + lua_pushnumber( L, num ); + return 1; +} + +static int vlclua_io_file_read_chars( lua_State *L, size_t i_len, FILE* p_file ) +{ + size_t i_toread = LUAL_BUFFERSIZE; + size_t i_read; + luaL_Buffer b; + luaL_buffinit( L, &b ); + do { + char *p = luaL_prepbuffer(&b); + if (i_toread > i_len) + i_toread = i_len; + i_read = fread(p, sizeof(char), i_toread, p_file); + luaL_addsize(&b, i_read); + i_len -= i_read; + } while (i_len > 0 && i_read == i_toread); + luaL_pushresult(&b); + return (i_len == 0 || lua_objlen(L, -1) > 0); +} + +static int vlclua_io_file_read( lua_State *L ) +{ + FILE **pp_file = (FILE**)luaL_checkudata( L, 1, "io_file" ); + if( lua_type( L, 2 ) == LUA_TNUMBER ) + { + return vlclua_io_file_read_chars( L, (size_t)lua_tointeger( L, 2 ), + *pp_file ); + } + const char* psz_mode = luaL_optstring( L, 2, "*l" ); + if ( *psz_mode != '*' ) + return luaL_error( L, "Invalid file:read() format: %s", psz_mode ); + switch ( psz_mode[1] ) + { + case 'l': + return vlclua_io_file_read_line( L, *pp_file ); + case 'n': + return vlclua_io_file_read_number( L, *pp_file ); + case 'a': + return vlclua_io_file_read_chars( L, SIZE_MAX, *pp_file ); + default: + break; + } + return luaL_error( L, "Invalid file:read() format: %s", psz_mode ); +} + +static int vlclua_io_file_write( lua_State *L ) +{ + FILE **pp_file = (FILE**)luaL_checkudata( L, 1, "io_file" ); + int i_nb_args = lua_gettop( L ); + bool b_success = true; + for ( int i = 2; i <= i_nb_args; ++i ) + { + bool i_res; + if ( lua_type( L, i ) == LUA_TNUMBER ) + i_res = fprintf(*pp_file, LUA_NUMBER_FMT, lua_tonumber( L, i ) ) > 0; + else + { + size_t i_len; + const char* psz_value = luaL_checklstring( L, i, &i_len ); + i_res = fwrite(psz_value, sizeof(*psz_value), i_len, *pp_file ) > 0; + } + b_success = b_success && i_res; + } + lua_pushboolean( L, b_success ); + return 1; +} + +static int vlclua_io_file_seek( lua_State *L ) +{ + FILE **pp_file = (FILE**)luaL_checkudata( L, 1, "io_file" ); + const char* psz_mode = luaL_optstring( L, 2, NULL ); + if ( psz_mode != NULL ) + { + long i_offset = luaL_optlong( L, 3, 0 ); + int i_mode; + if ( !strcmp( psz_mode, "set" ) ) + i_mode = SEEK_SET; + else if ( !strcmp( psz_mode, "end" ) ) + i_mode = SEEK_END; + else + i_mode = SEEK_CUR; + if( fseek( *pp_file, i_offset, i_mode ) != 0 ) + return luaL_error( L, "Failed to seek" ); + } + lua_pushinteger( L, ftell( *pp_file ) ); + return 1; +} + +static int vlclua_io_file_flush( lua_State *L ) +{ + FILE **pp_file = (FILE**)luaL_checkudata( L, 1, "io_file" ); + fflush( *pp_file ); + return 0; +} + +static int vlclua_io_file_close( lua_State *L ) +{ + FILE **pp_file = (FILE**)luaL_checkudata( L, 1, "io_file" ); + fclose( *pp_file ); + return 0; +} + +static const luaL_Reg vlclua_io_file_reg[] = { + { "read", vlclua_io_file_read }, + { "write", vlclua_io_file_write }, + { "seek", vlclua_io_file_seek }, + { "flush", vlclua_io_file_flush }, + { NULL, NULL } +}; + +static int vlclua_io_open( lua_State *L ) +{ + if( lua_gettop( L ) < 1 ) + return luaL_error( L, "Usage: vlc.io.open(file_path [, mode])" ); + const char* psz_path = luaL_checkstring( L, 1 ); + const char* psz_mode = luaL_optstring( L, 2, "r" ); + FILE *p_f = vlc_fopen( psz_path, psz_mode ); + if ( p_f == NULL ) + return 0; + + FILE** pp_f = lua_newuserdata( L, sizeof( p_f ) ); + *pp_f = p_f; + + if( luaL_newmetatable( L, "io_file" ) ) + { + lua_newtable( L ); + luaL_register( L, NULL, vlclua_io_file_reg ); + lua_setfield( L, -2, "__index" ); + lua_pushcfunction( L, vlclua_io_file_close ); + lua_setfield( L, -2, "__gc" ); + } + lua_setmetatable( L, -2 ); + return 1; +} + static int vlclua_mkdir( lua_State *L ) { if( lua_gettop( L ) < 2 ) return vlclua_error( L ); @@ -47,6 +204,7 @@ static int vlclua_mkdir( lua_State *L ) static const luaL_Reg vlclua_io_reg[] = { { "mkdir", vlclua_mkdir }, + { "open", vlclua_io_open }, { NULL, NULL } }; _______________________________________________ vlc-commits mailing list vlc-commits@videolan.org https://mailman.videolan.org/listinfo/vlc-commits