vlc | branch: master | Hugo Beauzée-Luyssen <h...@beauzee.fr> | Fri Apr  6 
17:11:19 2018 +0200| [e6d9d25ef9f144ac661453324e1e143048f9e035] | committer: 
Hugo Beauzée-Luyssen

lua: libs: Provide a basic io module replacement

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=e6d9d25ef9f144ac661453324e1e143048f9e035
---

 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

Reply via email to