New function 'lua_numbertostrbuff'
It converts a Lua number to a string in a buffer, without creating
a new Lua string.
diff --git a/lapi.c b/lapi.c
index fffd7d2..631cf44 100644
--- a/lapi.c
+++ b/lapi.c
@@ -368,6 +368,18 @@
}
+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) {
size_t sz = luaO_str2num(s, s2v(L->top.p));
if (sz != 0)
diff --git a/lauxlib.c b/lauxlib.c
index a36655f..e4b1258 100644
--- a/lauxlib.c
+++ b/lauxlib.c
@@ -920,10 +920,9 @@
else {
switch (lua_type(L, idx)) {
case LUA_TNUMBER: {
- if (lua_isinteger(L, idx))
- lua_pushfstring(L, "%I", (LUAI_UACINT)lua_tointeger(L, idx));
- else
- lua_pushfstring(L, "%f", (LUAI_UACNUMBER)lua_tonumber(L, idx));
+ char buff[LUA_N2SBUFFSZ];
+ lua_numbertostrbuff(L, idx, buff);
+ lua_pushstring(L, buff);
break;
}
case LUA_TSTRING:
diff --git a/liolib.c b/liolib.c
index 17522bb..98ff3d0 100644
--- a/liolib.c
+++ b/liolib.c
@@ -665,20 +665,16 @@
int status = 1;
errno = 0;
for (; nargs--; arg++) {
- if (lua_type(L, arg) == LUA_TNUMBER) {
- /* optimization: could be done exactly as for strings */
- int len = lua_isinteger(L, arg)
- ? fprintf(f, LUA_INTEGER_FMT,
- (LUAI_UACINT)lua_tointeger(L, arg))
- : fprintf(f, LUA_NUMBER_FMT,
- (LUAI_UACNUMBER)lua_tonumber(L, arg));
- status = status && (len > 0);
+ char buff[LUA_N2SBUFFSZ];
+ const char *s;
+ size_t len = lua_numbertostrbuff(L, arg, buff); /* try as a number */
+ if (len > 0) { /* did conversion work (value was a number)? */
+ s = buff;
+ len--;
}
- 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))
return 1; /* file handle already on stack top */
diff --git a/lobject.c b/lobject.c
index ba10189..97dacaf 100644
--- a/lobject.c
+++ b/lobject.c
@@ -400,15 +400,17 @@
/*
-** Maximum length of the conversion of a number to a string. Must be
-** enough to accommodate both LUA_INTEGER_FMT and LUA_NUMBER_FMT.
-** For a long long int, this is 19 digits plus a sign and a final '\0',
-** adding to 21. For a long double, it can go to a sign, the dot, an
-** exponent letter, an exponent sign, 4 exponent digits, the final
-** '\0', plus the significant digits, which are approximately the *_DIG
-** attribute.
+** The size of the buffer for the conversion of a number to a string
+** 'LUA_N2SBUFFSZ' must be enough to accommodate both LUA_INTEGER_FMT
+** and LUA_NUMBER_FMT. For a long long int, this is 19 digits plus a
+** sign and a final '\0', adding to 21. For a long double, it can go to
+** a sign, the dot, an exponent letter, an exponent sign, 4 exponent
+** digits, the final '\0', plus the significant digits, which are
+** 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 @@
*/
static int tostringbuffFloat (lua_Number n, char *buff) {
/* first conversion */
- int len = l_sprintf(buff, MAXNUMBER2STR, LUA_NUMBER_FMT,
+ int len = l_sprintf(buff, LUA_N2SBUFFSZ, LUA_NUMBER_FMT,
(LUAI_UACNUMBER)n);
lua_Number check = lua_str2number(buff, NULL); /* read it back */
if (check != n) { /* not enough 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);
}
/* looks like an integer? */
@@ -442,14 +444,14 @@
/*
** 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;
lua_assert(ttisnumber(obj));
if (ttisinteger(obj))
- len = lua_integer2str(buff, MAXNUMBER2STR, ivalue(obj));
+ len = lua_integer2str(buff, LUA_N2SBUFFSZ, ivalue(obj));
else
len = tostringbuffFloat(fltvalue(obj), buff);
- lua_assert(len < MAXNUMBER2STR);
+ lua_assert(len < LUA_N2SBUFFSZ);
return cast_uint(len);
}
@@ -458,8 +460,8 @@
** Convert a number object to a Lua string, replacing the value at 'obj'
*/
void luaO_tostring (lua_State *L, TValue *obj) {
- char buff[MAXNUMBER2STR];
- unsigned len = tostringbuff(obj, buff);
+ char buff[LUA_N2SBUFFSZ];
+ unsigned len = luaO_tostringbuff(obj, buff);
setsvalue(L, obj, luaS_newlstr(L, buff, len));
}
@@ -474,10 +476,10 @@
/*
** 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.
*/
-#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
@@ -579,8 +581,8 @@
** Add a numeral to the buffer.
*/
static void addnum2buff (BuffFS *buff, TValue *num) {
- char numbuff[MAXNUMBER2STR];
- unsigned len = tostringbuff(num, numbuff); /* format number into 'numbuff' */
+ char numbuff[LUA_N2SBUFFSZ];
+ unsigned len = luaO_tostringbuff(num, numbuff);
addstr2buff(buff, numbuff, len);
}
@@ -626,9 +628,9 @@
break;
}
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 *);
- int len = lua_pointer2str(bf, MAXNUMBER2STR, p);
+ int len = lua_pointer2str(bf, LUA_N2SBUFFSZ, p);
addstr2buff(&buff, bf, cast_uint(len));
break;
}
diff --git a/lobject.h b/lobject.h
index 2411410..b1407b7 100644
--- a/lobject.h
+++ b/lobject.h
@@ -845,6 +845,7 @@
LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1,
const TValue *p2, StkId res);
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 void luaO_tostring (lua_State *L, TValue *obj);
LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
diff --git a/lua.h b/lua.h
index dcf4926..5fbc9d3 100644
--- a/lua.h
+++ b/lua.h
@@ -371,7 +371,9 @@
LUA_API void (lua_concat) (lua_State *L, int n);
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 void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
diff --git a/manual/manual.of b/manual/manual.of
index 6947b2a..f0b17b4 100644
--- a/manual/manual.of
+++ b/manual/manual.of
@@ -675,7 +675,7 @@
The garbage-collector step multiplier
controls how much work each incremental step does.
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
or sweeping one object.
Larger values make the collector more aggressive.
@@ -3829,11 +3829,26 @@
}
+@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);|
@apii{nargs + 1,nresults|1,-}
Calls a function (or a callable object) in protected mode.
+
Both @id{nargs} and @id{nresults} have the same meaning as
in @Lid{lua_call}.
If there are no errors during the call,