[vlc-devel] [vlc-commits] lua: libs: Provide a basic io module replacement

Hugo Beauzée-Luyssen hugo at beauzee.fr
Mon Apr 9 18:24:59 CEST 2018


On Mon, Apr 9, 2018, at 5:02 PM, Hugo Beauzée-Luyssen wrote:
> vlc | branch: master | Hugo Beauzée-Luyssen <hugo at 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 at videolan.org
> https://mailman.videolan.org/listinfo/vlc-commits

Hi,

This commit (along with the related serie) fixes quite a few issues for VLSub. Mainly, it wouldn't have worked properly if you'd have any non-ascii character in your name.
We have a lot of reports related to that, and I'd like to backport this to the 3.0 branch.
I agree that it adds a few function to a public API and that it's usually not a good idea to do so in a stable branch, but I'm not entirely sure how to fix this properly otherwise.

Opinions are welcome!

Regards,

-- 
  Hugo Beauzée-Luyssen
  hugo at beauzee.fr


More information about the vlc-devel mailing list