mirror of
https://github.com/lua/lua.git
synced 2024-11-23 10:13:50 +08:00
New function 'lua_numbertostrbuff'
It converts a Lua number to a string in a buffer, without creating a new Lua string.
This commit is contained in:
parent
5ffcd458f0
commit
e3ce88c9e8
12
lapi.c
12
lapi.c
@ -368,6 +368,18 @@ LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LUA_API unsigned (lua_numbertostrbuff) (lua_State *L, int idx, char *buff) {
|
||||||
|
const TValue *o = index2value(L, idx);
|
||||||
|
if (ttisnumber(o)) {
|
||||||
|
unsigned len = luaO_tostringbuff(o, buff);
|
||||||
|
buff[len++] = '\0'; /* add final zero */
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) {
|
LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) {
|
||||||
size_t sz = luaO_str2num(s, s2v(L->top.p));
|
size_t sz = luaO_str2num(s, s2v(L->top.p));
|
||||||
if (sz != 0)
|
if (sz != 0)
|
||||||
|
@ -920,10 +920,9 @@ LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
|
|||||||
else {
|
else {
|
||||||
switch (lua_type(L, idx)) {
|
switch (lua_type(L, idx)) {
|
||||||
case LUA_TNUMBER: {
|
case LUA_TNUMBER: {
|
||||||
if (lua_isinteger(L, idx))
|
char buff[LUA_N2SBUFFSZ];
|
||||||
lua_pushfstring(L, "%I", (LUAI_UACINT)lua_tointeger(L, idx));
|
lua_numbertostrbuff(L, idx, buff);
|
||||||
else
|
lua_pushstring(L, buff);
|
||||||
lua_pushfstring(L, "%f", (LUAI_UACNUMBER)lua_tonumber(L, idx));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LUA_TSTRING:
|
case LUA_TSTRING:
|
||||||
|
22
liolib.c
22
liolib.c
@ -665,20 +665,16 @@ static int g_write (lua_State *L, FILE *f, int arg) {
|
|||||||
int status = 1;
|
int status = 1;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
for (; nargs--; arg++) {
|
for (; nargs--; arg++) {
|
||||||
if (lua_type(L, arg) == LUA_TNUMBER) {
|
char buff[LUA_N2SBUFFSZ];
|
||||||
/* optimization: could be done exactly as for strings */
|
const char *s;
|
||||||
int len = lua_isinteger(L, arg)
|
size_t len = lua_numbertostrbuff(L, arg, buff); /* try as a number */
|
||||||
? fprintf(f, LUA_INTEGER_FMT,
|
if (len > 0) { /* did conversion work (value was a number)? */
|
||||||
(LUAI_UACINT)lua_tointeger(L, arg))
|
s = buff;
|
||||||
: fprintf(f, LUA_NUMBER_FMT,
|
len--;
|
||||||
(LUAI_UACNUMBER)lua_tonumber(L, arg));
|
|
||||||
status = status && (len > 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
size_t l;
|
|
||||||
const char *s = luaL_checklstring(L, arg, &l);
|
|
||||||
status = status && (fwrite(s, sizeof(char), l, f) == l);
|
|
||||||
}
|
}
|
||||||
|
else /* must be a string */
|
||||||
|
s = luaL_checklstring(L, arg, &len);
|
||||||
|
status = status && (fwrite(s, sizeof(char), len, f) == len);
|
||||||
}
|
}
|
||||||
if (l_likely(status))
|
if (l_likely(status))
|
||||||
return 1; /* file handle already on stack top */
|
return 1; /* file handle already on stack top */
|
||||||
|
44
lobject.c
44
lobject.c
@ -400,15 +400,17 @@ int luaO_utf8esc (char *buff, unsigned long x) {
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Maximum length of the conversion of a number to a string. Must be
|
** The size of the buffer for the conversion of a number to a string
|
||||||
** enough to accommodate both LUA_INTEGER_FMT and LUA_NUMBER_FMT.
|
** 'LUA_N2SBUFFSZ' must be enough to accommodate both LUA_INTEGER_FMT
|
||||||
** For a long long int, this is 19 digits plus a sign and a final '\0',
|
** and LUA_NUMBER_FMT. For a long long int, this is 19 digits plus a
|
||||||
** adding to 21. For a long double, it can go to a sign, the dot, an
|
** sign and a final '\0', adding to 21. For a long double, it can go to
|
||||||
** exponent letter, an exponent sign, 4 exponent digits, the final
|
** a sign, the dot, an exponent letter, an exponent sign, 4 exponent
|
||||||
** '\0', plus the significant digits, which are approximately the *_DIG
|
** digits, the final '\0', plus the significant digits, which are
|
||||||
** attribute.
|
** approximately the *_DIG attribute.
|
||||||
*/
|
*/
|
||||||
#define MAXNUMBER2STR (20 + l_floatatt(DIG))
|
#if LUA_N2SBUFFSZ < (20 + l_floatatt(DIG))
|
||||||
|
#error "invalid value for LUA_N2SBUFFSZ"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -422,12 +424,12 @@ int luaO_utf8esc (char *buff, unsigned long x) {
|
|||||||
*/
|
*/
|
||||||
static int tostringbuffFloat (lua_Number n, char *buff) {
|
static int tostringbuffFloat (lua_Number n, char *buff) {
|
||||||
/* first conversion */
|
/* first conversion */
|
||||||
int len = l_sprintf(buff, MAXNUMBER2STR, LUA_NUMBER_FMT,
|
int len = l_sprintf(buff, LUA_N2SBUFFSZ, LUA_NUMBER_FMT,
|
||||||
(LUAI_UACNUMBER)n);
|
(LUAI_UACNUMBER)n);
|
||||||
lua_Number check = lua_str2number(buff, NULL); /* read it back */
|
lua_Number check = lua_str2number(buff, NULL); /* read it back */
|
||||||
if (check != n) { /* not enough precision? */
|
if (check != n) { /* not enough precision? */
|
||||||
/* convert again with more precision */
|
/* convert again with more precision */
|
||||||
len = l_sprintf(buff, MAXNUMBER2STR, LUA_NUMBER_FMT_N,
|
len = l_sprintf(buff, LUA_N2SBUFFSZ, LUA_NUMBER_FMT_N,
|
||||||
(LUAI_UACNUMBER)n);
|
(LUAI_UACNUMBER)n);
|
||||||
}
|
}
|
||||||
/* looks like an integer? */
|
/* looks like an integer? */
|
||||||
@ -442,14 +444,14 @@ static int tostringbuffFloat (lua_Number n, char *buff) {
|
|||||||
/*
|
/*
|
||||||
** Convert a number object to a string, adding it to a buffer.
|
** Convert a number object to a string, adding it to a buffer.
|
||||||
*/
|
*/
|
||||||
static unsigned tostringbuff (TValue *obj, char *buff) {
|
unsigned luaO_tostringbuff (const TValue *obj, char *buff) {
|
||||||
int len;
|
int len;
|
||||||
lua_assert(ttisnumber(obj));
|
lua_assert(ttisnumber(obj));
|
||||||
if (ttisinteger(obj))
|
if (ttisinteger(obj))
|
||||||
len = lua_integer2str(buff, MAXNUMBER2STR, ivalue(obj));
|
len = lua_integer2str(buff, LUA_N2SBUFFSZ, ivalue(obj));
|
||||||
else
|
else
|
||||||
len = tostringbuffFloat(fltvalue(obj), buff);
|
len = tostringbuffFloat(fltvalue(obj), buff);
|
||||||
lua_assert(len < MAXNUMBER2STR);
|
lua_assert(len < LUA_N2SBUFFSZ);
|
||||||
return cast_uint(len);
|
return cast_uint(len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -458,8 +460,8 @@ static unsigned tostringbuff (TValue *obj, char *buff) {
|
|||||||
** Convert a number object to a Lua string, replacing the value at 'obj'
|
** Convert a number object to a Lua string, replacing the value at 'obj'
|
||||||
*/
|
*/
|
||||||
void luaO_tostring (lua_State *L, TValue *obj) {
|
void luaO_tostring (lua_State *L, TValue *obj) {
|
||||||
char buff[MAXNUMBER2STR];
|
char buff[LUA_N2SBUFFSZ];
|
||||||
unsigned len = tostringbuff(obj, buff);
|
unsigned len = luaO_tostringbuff(obj, buff);
|
||||||
setsvalue(L, obj, luaS_newlstr(L, buff, len));
|
setsvalue(L, obj, luaS_newlstr(L, buff, len));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -474,10 +476,10 @@ void luaO_tostring (lua_State *L, TValue *obj) {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** Size for buffer space used by 'luaO_pushvfstring'. It should be
|
** Size for buffer space used by 'luaO_pushvfstring'. It should be
|
||||||
** (LUA_IDSIZE + MAXNUMBER2STR) + a minimal space for basic messages,
|
** (LUA_IDSIZE + LUA_N2SBUFFSZ) + a minimal space for basic messages,
|
||||||
** so that 'luaG_addinfo' can work directly on the static buffer.
|
** so that 'luaG_addinfo' can work directly on the static buffer.
|
||||||
*/
|
*/
|
||||||
#define BUFVFS cast_uint(LUA_IDSIZE + MAXNUMBER2STR + 95)
|
#define BUFVFS cast_uint(LUA_IDSIZE + LUA_N2SBUFFSZ + 95)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Buffer used by 'luaO_pushvfstring'. 'err' signals an error while
|
** Buffer used by 'luaO_pushvfstring'. 'err' signals an error while
|
||||||
@ -579,8 +581,8 @@ static void addstr2buff (BuffFS *buff, const char *str, size_t slen) {
|
|||||||
** Add a numeral to the buffer.
|
** Add a numeral to the buffer.
|
||||||
*/
|
*/
|
||||||
static void addnum2buff (BuffFS *buff, TValue *num) {
|
static void addnum2buff (BuffFS *buff, TValue *num) {
|
||||||
char numbuff[MAXNUMBER2STR];
|
char numbuff[LUA_N2SBUFFSZ];
|
||||||
unsigned len = tostringbuff(num, numbuff); /* format number into 'numbuff' */
|
unsigned len = luaO_tostringbuff(num, numbuff);
|
||||||
addstr2buff(buff, numbuff, len);
|
addstr2buff(buff, numbuff, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -626,9 +628,9 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'p': { /* a pointer */
|
case 'p': { /* a pointer */
|
||||||
char bf[MAXNUMBER2STR]; /* enough space for '%p' */
|
char bf[LUA_N2SBUFFSZ]; /* enough space for '%p' */
|
||||||
void *p = va_arg(argp, void *);
|
void *p = va_arg(argp, void *);
|
||||||
int len = lua_pointer2str(bf, MAXNUMBER2STR, p);
|
int len = lua_pointer2str(bf, LUA_N2SBUFFSZ, p);
|
||||||
addstr2buff(&buff, bf, cast_uint(len));
|
addstr2buff(&buff, bf, cast_uint(len));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -845,6 +845,7 @@ LUAI_FUNC int luaO_rawarith (lua_State *L, int op, const TValue *p1,
|
|||||||
LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1,
|
LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1,
|
||||||
const TValue *p2, StkId res);
|
const TValue *p2, StkId res);
|
||||||
LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o);
|
LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o);
|
||||||
|
LUAI_FUNC unsigned luaO_tostringbuff (const TValue *obj, char *buff);
|
||||||
LUAI_FUNC lu_byte luaO_hexavalue (int c);
|
LUAI_FUNC lu_byte luaO_hexavalue (int c);
|
||||||
LUAI_FUNC void luaO_tostring (lua_State *L, TValue *obj);
|
LUAI_FUNC void luaO_tostring (lua_State *L, TValue *obj);
|
||||||
LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
|
LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
|
||||||
|
4
lua.h
4
lua.h
@ -371,7 +371,9 @@ LUA_API int (lua_next) (lua_State *L, int idx);
|
|||||||
LUA_API void (lua_concat) (lua_State *L, int n);
|
LUA_API void (lua_concat) (lua_State *L, int n);
|
||||||
LUA_API void (lua_len) (lua_State *L, int idx);
|
LUA_API void (lua_len) (lua_State *L, int idx);
|
||||||
|
|
||||||
LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s);
|
#define LUA_N2SBUFFSZ 64
|
||||||
|
LUA_API unsigned (lua_numbertostrbuff) (lua_State *L, int idx, char *buff);
|
||||||
|
LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s);
|
||||||
|
|
||||||
LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
|
LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
|
||||||
LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
|
LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
|
||||||
|
@ -675,7 +675,7 @@ approximately @M{n} bytes between steps.
|
|||||||
The garbage-collector step multiplier
|
The garbage-collector step multiplier
|
||||||
controls how much work each incremental step does.
|
controls how much work each incremental step does.
|
||||||
A value of @M{n} means the interpreter will execute
|
A value of @M{n} means the interpreter will execute
|
||||||
@M{n%} @emphx{units of work} for each byte allocated.
|
@M{n%} @emphx{units of work} for each word allocated.
|
||||||
A unit of work corresponds roughly to traversing one slot
|
A unit of work corresponds roughly to traversing one slot
|
||||||
or sweeping one object.
|
or sweeping one object.
|
||||||
Larger values make the collector more aggressive.
|
Larger values make the collector more aggressive.
|
||||||
@ -3829,11 +3829,26 @@ This macro may evaluate its arguments more than once.
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@APIEntry{unsigned (lua_numbertostrbuff) (lua_State *L, int idx,
|
||||||
|
char *buff);|
|
||||||
|
@apii{0,0,-}
|
||||||
|
|
||||||
|
Converts the number at acceptable index @id{idx} to a string
|
||||||
|
and puts the result in @id{buff}.
|
||||||
|
The buffer must have a size of at least @Lid{LUA_N2SBUFFSZ} bytes.
|
||||||
|
The conversion follows a non-specified format @see{coercion}.
|
||||||
|
The function returns the number of bytes written to the buffer
|
||||||
|
(including the final zero),
|
||||||
|
or zero if the value at @id{idx} is not a number.
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@APIEntry{int lua_pcall (lua_State *L, int nargs, int nresults, int msgh);|
|
@APIEntry{int lua_pcall (lua_State *L, int nargs, int nresults, int msgh);|
|
||||||
@apii{nargs + 1,nresults|1,-}
|
@apii{nargs + 1,nresults|1,-}
|
||||||
|
|
||||||
Calls a function (or a callable object) in protected mode.
|
Calls a function (or a callable object) in protected mode.
|
||||||
|
|
||||||
|
|
||||||
Both @id{nargs} and @id{nresults} have the same meaning as
|
Both @id{nargs} and @id{nresults} have the same meaning as
|
||||||
in @Lid{lua_call}.
|
in @Lid{lua_call}.
|
||||||
If there are no errors during the call,
|
If there are no errors during the call,
|
||||||
|
Loading…
Reference in New Issue
Block a user