forked from len0rd/rockbox
Lua replace fscanf
Rocklua was using the full fscanf implementation to simply read %ld for the file:read("*n") function wasting 1k on unneeded/unused functionality Instead, I've implemented a filetol function to duplicate it without the extra overhead using strtol which as an added bonus ERANGE errors now resolve to LONG_MIN and LONGMAX instead of integer overflow filetol() reads long int from an open file, skips preceding whitespaces returns -1 if error, 1 on success. *num set to LONG_MAX or LONG_MIN on overflow. If number of digits is > than LUAI_MAXNUMBER2STR filepointer will continue till the next non digit but buffer will stop being filled with characters. Preceding zero is ignored. Change-Id: Ia42d0f73c63a894625bca4581e9b7e1cc7387fd2
This commit is contained in:
parent
cc0a4c632a
commit
eab73b3dee
6 changed files with 66 additions and 295 deletions
|
@ -30,7 +30,6 @@ rockaux.c
|
||||||
rocklib.c
|
rocklib.c
|
||||||
rocklib_img.c
|
rocklib_img.c
|
||||||
tlsf_helper.c
|
tlsf_helper.c
|
||||||
fscanf.c
|
|
||||||
strftime.c
|
strftime.c
|
||||||
strpbrk.c
|
strpbrk.c
|
||||||
strtoul.c
|
strtoul.c
|
||||||
|
|
|
@ -1,291 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
* __________ __ ___.
|
|
||||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
||||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
||||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
||||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
||||||
* \/ \/ \/ \/ \/
|
|
||||||
* $Id$
|
|
||||||
*
|
|
||||||
* Copied from firmware/common/sscanf.c
|
|
||||||
* Original author: Tomasz Malesinski
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 Maurus Cuelenaere
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
||||||
* KIND, either express or implied.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#include "rocklibc.h"
|
|
||||||
|
|
||||||
static int parse_dec(int (*peek)(void *userp),
|
|
||||||
void (*pop)(void *userp),
|
|
||||||
void *userp,
|
|
||||||
long *vp)
|
|
||||||
{
|
|
||||||
long v = 0;
|
|
||||||
int n = 0;
|
|
||||||
int minus = 0;
|
|
||||||
char ch;
|
|
||||||
|
|
||||||
if ((*peek)(userp) == '-')
|
|
||||||
{
|
|
||||||
(*pop)(userp);
|
|
||||||
n++;
|
|
||||||
minus = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ch = (*peek)(userp);
|
|
||||||
if (!isdigit(ch))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
v = v * 10 + ch - '0';
|
|
||||||
(*pop)(userp);
|
|
||||||
n++;
|
|
||||||
ch = (*peek)(userp);
|
|
||||||
} while (isdigit(ch));
|
|
||||||
|
|
||||||
*vp = minus ? -v : v;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int parse_chars(int (*peek)(void *userp),
|
|
||||||
void (*pop)(void *userp),
|
|
||||||
void *userp,
|
|
||||||
char *vp,
|
|
||||||
bool fake)
|
|
||||||
{
|
|
||||||
int n = 0;
|
|
||||||
|
|
||||||
char *pt=vp;
|
|
||||||
|
|
||||||
while (!isspace((*peek)(userp)))
|
|
||||||
{
|
|
||||||
if(fake==false)
|
|
||||||
*(pt++) = (*peek)(userp);
|
|
||||||
|
|
||||||
n++;
|
|
||||||
(*pop)(userp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(fake==false)
|
|
||||||
(*pt)='\0';
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int parse_hex(int (*peek)(void *userp),
|
|
||||||
void (*pop)(void *userp),
|
|
||||||
void *userp,
|
|
||||||
unsigned long *vp)
|
|
||||||
{
|
|
||||||
unsigned long v = 0;
|
|
||||||
int n = 0;
|
|
||||||
char ch;
|
|
||||||
|
|
||||||
ch = (*peek)(userp);
|
|
||||||
if (!isxdigit(ch))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (ch >= 'a')
|
|
||||||
ch = ch - 'a' + 10;
|
|
||||||
else if (ch >= 'A')
|
|
||||||
ch = ch - 'A' + 10;
|
|
||||||
else
|
|
||||||
ch = ch - '0';
|
|
||||||
v = v * 16 + ch;
|
|
||||||
(*pop)(userp);
|
|
||||||
n++;
|
|
||||||
ch = (*peek)(userp);
|
|
||||||
} while (isxdigit(ch));
|
|
||||||
|
|
||||||
*vp = v;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int skip_spaces(int (*peek)(void *userp),
|
|
||||||
void (*pop)(void *userp),
|
|
||||||
void *userp)
|
|
||||||
{
|
|
||||||
int n = 0;
|
|
||||||
while (isspace((*peek)(userp))) {
|
|
||||||
n++;
|
|
||||||
(*pop)(userp);
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int scan(int (*peek)(void *userp),
|
|
||||||
void (*pop)(void *userp),
|
|
||||||
void *userp,
|
|
||||||
const char *fmt,
|
|
||||||
va_list ap)
|
|
||||||
{
|
|
||||||
char ch;
|
|
||||||
int n = 0;
|
|
||||||
int n_chars = 0;
|
|
||||||
int r;
|
|
||||||
long lval;
|
|
||||||
bool skip=false;
|
|
||||||
unsigned long ulval;
|
|
||||||
|
|
||||||
while ((ch = *fmt++) != '\0')
|
|
||||||
{
|
|
||||||
bool literal = false;
|
|
||||||
|
|
||||||
if (ch == '%')
|
|
||||||
{
|
|
||||||
ch = *fmt++;
|
|
||||||
|
|
||||||
if(ch== '*') /* We should process this, but not store it in an argument */
|
|
||||||
{
|
|
||||||
ch=*fmt++;
|
|
||||||
skip=true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
skip=false;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ch)
|
|
||||||
{
|
|
||||||
case 'x':
|
|
||||||
n_chars += skip_spaces(peek, pop, userp);
|
|
||||||
if ((r = parse_hex(peek, pop, userp, &ulval)) >= 0)
|
|
||||||
{
|
|
||||||
if(skip==false)
|
|
||||||
{
|
|
||||||
*(va_arg(ap, unsigned int *)) = ulval;
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
n_chars += r;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return n;
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
n_chars += skip_spaces(peek, pop, userp);
|
|
||||||
if ((r = parse_dec(peek, pop, userp, &lval)) >= 0)
|
|
||||||
{
|
|
||||||
if(skip==false)
|
|
||||||
{
|
|
||||||
*(va_arg(ap, int *)) = lval;
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
n_chars += r;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return n;
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
if(skip==false)
|
|
||||||
{
|
|
||||||
*(va_arg(ap, int *)) = n_chars;
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
n_chars += skip_spaces(peek, pop, userp);
|
|
||||||
ch = *fmt++;
|
|
||||||
switch (ch)
|
|
||||||
{
|
|
||||||
case 'x':
|
|
||||||
if ((r = parse_hex(peek, pop, userp, &ulval)) >= 0)
|
|
||||||
{
|
|
||||||
if(skip==false)
|
|
||||||
{
|
|
||||||
*(va_arg(ap, unsigned long *)) = ulval;
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
n_chars += r;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return n;
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
if ((r = parse_dec(peek, pop, userp, &lval)) >= 0)
|
|
||||||
{
|
|
||||||
if(skip==false)
|
|
||||||
{
|
|
||||||
*(va_arg(ap, long *)) = lval;
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
n_chars += r;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return n;
|
|
||||||
break;
|
|
||||||
case '\0':
|
|
||||||
return n;
|
|
||||||
default:
|
|
||||||
literal = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
n_chars += skip_spaces(peek, pop, userp);
|
|
||||||
n_chars += parse_chars(peek,pop, userp,skip?0:va_arg(ap, char *), skip );
|
|
||||||
if(skip==false)
|
|
||||||
{
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '\0':
|
|
||||||
return n;
|
|
||||||
default:
|
|
||||||
literal = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
literal = true;
|
|
||||||
|
|
||||||
if (literal)
|
|
||||||
{
|
|
||||||
n_chars += skip_spaces(peek, pop, userp);
|
|
||||||
if ((*peek)(userp) != ch)
|
|
||||||
continue;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
(*pop)(userp);
|
|
||||||
n_chars++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int fspeek(void *userp)
|
|
||||||
{
|
|
||||||
int fd = *((int*) userp);
|
|
||||||
char buf = 0;
|
|
||||||
if(rb->read(fd, &buf, 1) == 1)
|
|
||||||
rb->lseek(fd, -1, SEEK_CUR);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fspop(void *userp)
|
|
||||||
{
|
|
||||||
int fd = *((int*) userp);
|
|
||||||
rb->lseek(fd, 1, SEEK_CUR);
|
|
||||||
}
|
|
||||||
|
|
||||||
int PREFIX(fscanf)(int fd, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
r = scan(fspeek, fspop, &fd, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
return r;
|
|
||||||
}
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "lauxlib.h"
|
#include "lauxlib.h"
|
||||||
#include "lualib.h"
|
#include "lualib.h"
|
||||||
#include "rocklibc.h"
|
#include "rocklibc.h"
|
||||||
|
#include "rocklib.h"
|
||||||
|
|
||||||
#include "llimits.h"
|
#include "llimits.h"
|
||||||
|
|
||||||
|
@ -247,7 +248,7 @@ static int io_lines (lua_State *L) {
|
||||||
|
|
||||||
static int read_number (lua_State *L, int *f) {
|
static int read_number (lua_State *L, int *f) {
|
||||||
lua_Number d;
|
lua_Number d;
|
||||||
if (PREFIX(fscanf)(*f, LUA_NUMBER_SCAN, &d) == 1) {
|
if (filetol(*f, &d) == 1) { /* was fscanf(f, LUA_NUMBER_SCAN, &d)*/
|
||||||
lua_pushnumber(L, d);
|
lua_pushnumber(L, d);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
* $Id$
|
* $Id$
|
||||||
*
|
*
|
||||||
* Copyright (C) 2008 Dan Everton (safetydan)
|
* Copyright (C) 2008 Dan Everton (safetydan)
|
||||||
|
* Copyright (C) 2018 William Wilgus
|
||||||
* String function implementations taken from dietlibc 0.31 (GPLv2 License)
|
* String function implementations taken from dietlibc 0.31 (GPLv2 License)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
|
@ -24,6 +25,8 @@
|
||||||
#define _ROCKCONF_H_ /* Protect against unwanted include */
|
#define _ROCKCONF_H_ /* Protect against unwanted include */
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
||||||
|
extern long strtol(const char *nptr, char **endptr, int base);
|
||||||
|
|
||||||
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
|
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
|
||||||
int errno = 0;
|
int errno = 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -101,3 +104,63 @@ int get_current_path(lua_State *L, int level)
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* filetol()
|
||||||
|
reads long int from an open file, skips preceding
|
||||||
|
whitespaces returns -1 if error, 1 on success.
|
||||||
|
*num set to LONG_MAX or LONG_MIN on overflow.
|
||||||
|
If number of digits is > than LUAI_MAXNUMBER2STR
|
||||||
|
filepointer will continue till the next non digit
|
||||||
|
but buffer will stop being filled with characters.
|
||||||
|
Preceding zero is ignored
|
||||||
|
*/
|
||||||
|
int filetol(int fd, long *num)
|
||||||
|
{
|
||||||
|
static char buffer[LUAI_MAXNUMBER2STR];
|
||||||
|
int retn = -1;
|
||||||
|
char chbuf = 0;
|
||||||
|
size_t count = 0;
|
||||||
|
bool neg = false;
|
||||||
|
long val;
|
||||||
|
|
||||||
|
while (rb->read(fd, &chbuf, 1) == 1)
|
||||||
|
{
|
||||||
|
if(!isspace(chbuf) || retn == 1)
|
||||||
|
{
|
||||||
|
if(chbuf == '0') /* strip preceeding zeros */
|
||||||
|
{
|
||||||
|
*num = 0;
|
||||||
|
retn = 1;
|
||||||
|
}
|
||||||
|
else if(chbuf == '-' && retn != 1)
|
||||||
|
neg = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rb->lseek(fd, -1, SEEK_CUR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (rb->read(fd, &chbuf, 1) == 1)
|
||||||
|
{
|
||||||
|
if(!isdigit(chbuf))
|
||||||
|
{
|
||||||
|
rb->lseek(fd, -1, SEEK_CUR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (count < LUAI_MAXNUMBER2STR - 2)
|
||||||
|
buffer[count++] = chbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(count)
|
||||||
|
{
|
||||||
|
buffer[count] = '\0';
|
||||||
|
val = strtol(buffer, NULL, 10);
|
||||||
|
*num = (neg)? -val:val;
|
||||||
|
retn = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ struct lua_str_reg {
|
||||||
|
|
||||||
LUALIB_API int (luaopen_rock) (lua_State *L);
|
LUALIB_API int (luaopen_rock) (lua_State *L);
|
||||||
int get_current_path(lua_State *L, int level);
|
int get_current_path(lua_State *L, int level);
|
||||||
|
int filetol(int fd, long *num);
|
||||||
|
|
||||||
#endif /* _ROCKLIB_H_ */
|
#endif /* _ROCKLIB_H_ */
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,5 @@ extern int errno;
|
||||||
#define memcmp rb->memcmp
|
#define memcmp rb->memcmp
|
||||||
#define strlen rb->strlen
|
#define strlen rb->strlen
|
||||||
|
|
||||||
extern int PREFIX(fscanf)(int fd, const char *fmt, ...);
|
|
||||||
|
|
||||||
#endif /* _ROCKLIBC_H_ */
|
#endif /* _ROCKLIBC_H_ */
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue