1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2007-2018 the VideoLAN team
6 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
31 #include <vlc_common.h>
37 #ifndef LUA_NUMBER_SCAN
38 /* Lua 5.3 only provides str<>long macros */
39 #define LUA_NUMBER_SCAN "%lf"
42 static int vlclua_io_file_read_line( lua_State
*L
, FILE* p_file
)
44 char* psz_line
= NULL
;
46 ssize_t i_len
= getline( &psz_line
, &i_buffer
, p_file
);
49 if( psz_line
[i_len
- 1] == '\n' )
50 psz_line
[--i_len
] = 0;
51 lua_pushstring( L
, psz_line
);
56 static int vlclua_io_file_read_number( lua_State
*L
, FILE* p_file
)
59 if ( fscanf( p_file
, LUA_NUMBER_SCAN
, &num
) != 1 )
61 lua_pushnumber( L
, num
);
65 static int vlclua_io_file_read_chars( lua_State
*L
, size_t i_len
, FILE* p_file
)
67 size_t i_toread
= LUAL_BUFFERSIZE
;
70 luaL_buffinit( L
, &b
);
72 char *p
= luaL_prepbuffer(&b
);
75 i_read
= fread(p
, sizeof(char), i_toread
, p_file
);
76 luaL_addsize(&b
, i_read
);
78 } while (i_len
> 0 && i_read
== i_toread
);
80 return (i_len
== 0 || lua_objlen(L
, -1) > 0);
83 static int vlclua_io_file_read( lua_State
*L
)
85 FILE **pp_file
= (FILE**)luaL_checkudata( L
, 1, "io_file" );
87 return luaL_error( L
, "Attempt to use a closed file" );
88 if( lua_type( L
, 2 ) == LUA_TNUMBER
)
90 return vlclua_io_file_read_chars( L
, (size_t)lua_tointeger( L
, 2 ),
93 const char* psz_mode
= luaL_optstring( L
, 2, "*l" );
94 if ( *psz_mode
!= '*' )
95 return luaL_error( L
, "Invalid file:read() format: %s", psz_mode
);
96 switch ( psz_mode
[1] )
99 return vlclua_io_file_read_line( L
, *pp_file
);
101 return vlclua_io_file_read_number( L
, *pp_file
);
103 return vlclua_io_file_read_chars( L
, SIZE_MAX
, *pp_file
);
107 return luaL_error( L
, "Invalid file:read() format: %s", psz_mode
);
110 static int vlclua_io_file_write( lua_State
*L
)
112 FILE **pp_file
= (FILE**)luaL_checkudata( L
, 1, "io_file" );
114 return luaL_error( L
, "Attempt to use a closed file" );
115 int i_nb_args
= lua_gettop( L
);
116 bool b_success
= true;
117 for ( int i
= 2; i
<= i_nb_args
; ++i
)
120 if ( lua_type( L
, i
) == LUA_TNUMBER
)
121 i_res
= fprintf(*pp_file
, LUA_NUMBER_FMT
, lua_tonumber( L
, i
) ) > 0;
125 const char* psz_value
= luaL_checklstring( L
, i
, &i_len
);
126 i_res
= fwrite(psz_value
, sizeof(*psz_value
), i_len
, *pp_file
) > 0;
128 b_success
= b_success
&& i_res
;
130 lua_pushboolean( L
, b_success
);
134 static int vlclua_io_file_seek( lua_State
*L
)
136 FILE **pp_file
= (FILE**)luaL_checkudata( L
, 1, "io_file" );
138 return luaL_error( L
, "Attempt to use a closed file" );
139 const char* psz_mode
= luaL_optstring( L
, 2, NULL
);
140 if ( psz_mode
!= NULL
)
142 long i_offset
= luaL_optlong( L
, 3, 0 );
144 if ( !strcmp( psz_mode
, "set" ) )
146 else if ( !strcmp( psz_mode
, "end" ) )
150 if( fseek( *pp_file
, i_offset
, i_mode
) != 0 )
151 return luaL_error( L
, "Failed to seek" );
153 lua_pushinteger( L
, ftell( *pp_file
) );
157 static int vlclua_io_file_flush( lua_State
*L
)
159 FILE **pp_file
= (FILE**)luaL_checkudata( L
, 1, "io_file" );
161 return luaL_error( L
, "Attempt to use a closed file" );
166 static int vlclua_io_file_close( lua_State
*L
)
168 FILE **pp_file
= (FILE**)luaL_checkudata( L
, 1, "io_file" );
177 static const luaL_Reg vlclua_io_file_reg
[] = {
178 { "read", vlclua_io_file_read
},
179 { "write", vlclua_io_file_write
},
180 { "seek", vlclua_io_file_seek
},
181 { "flush", vlclua_io_file_flush
},
182 { "close", vlclua_io_file_close
},
186 static int vlclua_io_open( lua_State
*L
)
188 if( lua_gettop( L
) < 1 )
189 return luaL_error( L
, "Usage: vlc.io.open(file_path [, mode])" );
190 const char* psz_path
= luaL_checkstring( L
, 1 );
191 const char* psz_mode
= luaL_optstring( L
, 2, "r" );
192 FILE *p_f
= vlc_fopen( psz_path
, psz_mode
);
196 FILE** pp_f
= lua_newuserdata( L
, sizeof( p_f
) );
199 if( luaL_newmetatable( L
, "io_file" ) )
202 luaL_register( L
, NULL
, vlclua_io_file_reg
);
203 lua_setfield( L
, -2, "__index" );
204 lua_pushcfunction( L
, vlclua_io_file_close
);
205 lua_setfield( L
, -2, "__gc" );
207 lua_setmetatable( L
, -2 );
211 static int vlclua_io_readdir( lua_State
*L
)
213 if( lua_gettop( L
) < 1 )
214 return luaL_error( L
, "Usage: vlc.io.readdir(name)" );
215 const char* psz_path
= luaL_checkstring( L
, 1 );
216 DIR* p_dir
= vlc_opendir( psz_path
);
221 const char* psz_entry
;
223 while ( ( psz_entry
= vlc_readdir( p_dir
) ) != NULL
)
225 lua_pushstring( L
, psz_entry
);
226 lua_rawseti( L
, -2, idx
);
233 static int vlclua_io_unlink( lua_State
*L
)
235 if( lua_gettop( L
) < 1 )
236 return luaL_error( L
, "Usage: vlc.io.unlink(path)" );
237 const char* psz_path
= luaL_checkstring( L
, 1 );
238 int i_res
= vlc_unlink( psz_path
);
239 int i_err
= i_res
!= 0 ? errno
: 0;
240 lua_pushinteger( L
, i_res
);
241 lua_pushinteger( L
, i_err
);
245 static int vlclua_mkdir( lua_State
*L
)
247 if( lua_gettop( L
) < 2 ) return vlclua_error( L
);
249 const char* psz_dir
= luaL_checkstring( L
, 1 );
250 const char* psz_mode
= luaL_checkstring( L
, 2 );
251 if ( !psz_dir
|| !psz_mode
)
252 return vlclua_error( L
);
253 int i_res
= vlc_mkdir( psz_dir
, strtoul( psz_mode
, NULL
, 0 ) );
254 int i_err
= i_res
!= 0 ? errno
: 0;
255 lua_pushinteger( L
, i_res
);
256 lua_pushinteger( L
, i_err
);
260 static const luaL_Reg vlclua_io_reg
[] = {
261 { "mkdir", vlclua_mkdir
},
262 { "open", vlclua_io_open
},
263 { "readdir", vlclua_io_readdir
},
264 { "unlink", vlclua_io_unlink
},
269 void luaopen_vlcio( lua_State
*L
)
272 luaL_register( L
, NULL
, vlclua_io_reg
);
273 lua_setfield( L
, -2, "io" );