aboutsummaryrefslogtreecommitdiff
path: root/lobject.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2024-10-23 17:16:17 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2024-10-23 17:16:17 -0300
commite3ce88c9e850b7e79751083014699c5eae1bff31 (patch)
treee73392a16c560ed532ef2238132f0e58d2eb23b3 /lobject.c
parent5ffcd458f001fce02e5f20a6130e145c6a3caf53 (diff)
downloadlua-e3ce88c9e850b7e79751083014699c5eae1bff31.tar.gz
lua-e3ce88c9e850b7e79751083014699c5eae1bff31.tar.bz2
lua-e3ce88c9e850b7e79751083014699c5eae1bff31.zip
New function 'lua_numbertostrbuff'
It converts a Lua number to a string in a buffer, without creating a new Lua string.
Diffstat (limited to 'lobject.c')
-rw-r--r--lobject.c44
1 files changed, 23 insertions, 21 deletions
diff --git a/lobject.c b/lobject.c
index ba10189d..97dacaf5 100644
--- a/lobject.c
+++ b/lobject.c
@@ -400,15 +400,17 @@ int luaO_utf8esc (char *buff, unsigned long x) {
400 400
401 401
402/* 402/*
403** Maximum length of the conversion of a number to a string. Must be 403** The size of the buffer for the conversion of a number to a string
404** enough to accommodate both LUA_INTEGER_FMT and LUA_NUMBER_FMT. 404** 'LUA_N2SBUFFSZ' must be enough to accommodate both LUA_INTEGER_FMT
405** For a long long int, this is 19 digits plus a sign and a final '\0', 405** and LUA_NUMBER_FMT. For a long long int, this is 19 digits plus a
406** adding to 21. For a long double, it can go to a sign, the dot, an 406** sign and a final '\0', adding to 21. For a long double, it can go to
407** exponent letter, an exponent sign, 4 exponent digits, the final 407** a sign, the dot, an exponent letter, an exponent sign, 4 exponent
408** '\0', plus the significant digits, which are approximately the *_DIG 408** digits, the final '\0', plus the significant digits, which are
409** attribute. 409** approximately the *_DIG attribute.
410*/ 410*/
411#define MAXNUMBER2STR (20 + l_floatatt(DIG)) 411#if LUA_N2SBUFFSZ < (20 + l_floatatt(DIG))
412#error "invalid value for LUA_N2SBUFFSZ"
413#endif
412 414
413 415
414/* 416/*
@@ -422,12 +424,12 @@ int luaO_utf8esc (char *buff, unsigned long x) {
422*/ 424*/
423static int tostringbuffFloat (lua_Number n, char *buff) { 425static int tostringbuffFloat (lua_Number n, char *buff) {
424 /* first conversion */ 426 /* first conversion */
425 int len = l_sprintf(buff, MAXNUMBER2STR, LUA_NUMBER_FMT, 427 int len = l_sprintf(buff, LUA_N2SBUFFSZ, LUA_NUMBER_FMT,
426 (LUAI_UACNUMBER)n); 428 (LUAI_UACNUMBER)n);
427 lua_Number check = lua_str2number(buff, NULL); /* read it back */ 429 lua_Number check = lua_str2number(buff, NULL); /* read it back */
428 if (check != n) { /* not enough precision? */ 430 if (check != n) { /* not enough precision? */
429 /* convert again with more precision */ 431 /* convert again with more precision */
430 len = l_sprintf(buff, MAXNUMBER2STR, LUA_NUMBER_FMT_N, 432 len = l_sprintf(buff, LUA_N2SBUFFSZ, LUA_NUMBER_FMT_N,
431 (LUAI_UACNUMBER)n); 433 (LUAI_UACNUMBER)n);
432 } 434 }
433 /* looks like an integer? */ 435 /* looks like an integer? */
@@ -442,14 +444,14 @@ static int tostringbuffFloat (lua_Number n, char *buff) {
442/* 444/*
443** Convert a number object to a string, adding it to a buffer. 445** Convert a number object to a string, adding it to a buffer.
444*/ 446*/
445static unsigned tostringbuff (TValue *obj, char *buff) { 447unsigned luaO_tostringbuff (const TValue *obj, char *buff) {
446 int len; 448 int len;
447 lua_assert(ttisnumber(obj)); 449 lua_assert(ttisnumber(obj));
448 if (ttisinteger(obj)) 450 if (ttisinteger(obj))
449 len = lua_integer2str(buff, MAXNUMBER2STR, ivalue(obj)); 451 len = lua_integer2str(buff, LUA_N2SBUFFSZ, ivalue(obj));
450 else 452 else
451 len = tostringbuffFloat(fltvalue(obj), buff); 453 len = tostringbuffFloat(fltvalue(obj), buff);
452 lua_assert(len < MAXNUMBER2STR); 454 lua_assert(len < LUA_N2SBUFFSZ);
453 return cast_uint(len); 455 return cast_uint(len);
454} 456}
455 457
@@ -458,8 +460,8 @@ static unsigned tostringbuff (TValue *obj, char *buff) {
458** Convert a number object to a Lua string, replacing the value at 'obj' 460** Convert a number object to a Lua string, replacing the value at 'obj'
459*/ 461*/
460void luaO_tostring (lua_State *L, TValue *obj) { 462void luaO_tostring (lua_State *L, TValue *obj) {
461 char buff[MAXNUMBER2STR]; 463 char buff[LUA_N2SBUFFSZ];
462 unsigned len = tostringbuff(obj, buff); 464 unsigned len = luaO_tostringbuff(obj, buff);
463 setsvalue(L, obj, luaS_newlstr(L, buff, len)); 465 setsvalue(L, obj, luaS_newlstr(L, buff, len));
464} 466}
465 467
@@ -474,10 +476,10 @@ void luaO_tostring (lua_State *L, TValue *obj) {
474 476
475/* 477/*
476** Size for buffer space used by 'luaO_pushvfstring'. It should be 478** Size for buffer space used by 'luaO_pushvfstring'. It should be
477** (LUA_IDSIZE + MAXNUMBER2STR) + a minimal space for basic messages, 479** (LUA_IDSIZE + LUA_N2SBUFFSZ) + a minimal space for basic messages,
478** so that 'luaG_addinfo' can work directly on the static buffer. 480** so that 'luaG_addinfo' can work directly on the static buffer.
479*/ 481*/
480#define BUFVFS cast_uint(LUA_IDSIZE + MAXNUMBER2STR + 95) 482#define BUFVFS cast_uint(LUA_IDSIZE + LUA_N2SBUFFSZ + 95)
481 483
482/* 484/*
483** Buffer used by 'luaO_pushvfstring'. 'err' signals an error while 485** 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) {
579** Add a numeral to the buffer. 581** Add a numeral to the buffer.
580*/ 582*/
581static void addnum2buff (BuffFS *buff, TValue *num) { 583static void addnum2buff (BuffFS *buff, TValue *num) {
582 char numbuff[MAXNUMBER2STR]; 584 char numbuff[LUA_N2SBUFFSZ];
583 unsigned len = tostringbuff(num, numbuff); /* format number into 'numbuff' */ 585 unsigned len = luaO_tostringbuff(num, numbuff);
584 addstr2buff(buff, numbuff, len); 586 addstr2buff(buff, numbuff, len);
585} 587}
586 588
@@ -626,9 +628,9 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
626 break; 628 break;
627 } 629 }
628 case 'p': { /* a pointer */ 630 case 'p': { /* a pointer */
629 char bf[MAXNUMBER2STR]; /* enough space for '%p' */ 631 char bf[LUA_N2SBUFFSZ]; /* enough space for '%p' */
630 void *p = va_arg(argp, void *); 632 void *p = va_arg(argp, void *);
631 int len = lua_pointer2str(bf, MAXNUMBER2STR, p); 633 int len = lua_pointer2str(bf, LUA_N2SBUFFSZ, p);
632 addstr2buff(&buff, bf, cast_uint(len)); 634 addstr2buff(&buff, bf, cast_uint(len));
633 break; 635 break;
634 } 636 }