diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-10-23 17:16:17 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-10-23 17:16:17 -0300 |
commit | e3ce88c9e850b7e79751083014699c5eae1bff31 (patch) | |
tree | e73392a16c560ed532ef2238132f0e58d2eb23b3 | |
parent | 5ffcd458f001fce02e5f20a6130e145c6a3caf53 (diff) | |
download | lua-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.
-rw-r--r-- | lapi.c | 12 | ||||
-rw-r--r-- | lauxlib.c | 7 | ||||
-rw-r--r-- | liolib.c | 22 | ||||
-rw-r--r-- | lobject.c | 44 | ||||
-rw-r--r-- | lobject.h | 1 | ||||
-rw-r--r-- | lua.h | 4 | ||||
-rw-r--r-- | manual/manual.of | 17 |
7 files changed, 67 insertions, 40 deletions
@@ -368,6 +368,18 @@ LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { | |||
368 | } | 368 | } |
369 | 369 | ||
370 | 370 | ||
371 | LUA_API unsigned (lua_numbertostrbuff) (lua_State *L, int idx, char *buff) { | ||
372 | const TValue *o = index2value(L, idx); | ||
373 | if (ttisnumber(o)) { | ||
374 | unsigned len = luaO_tostringbuff(o, buff); | ||
375 | buff[len++] = '\0'; /* add final zero */ | ||
376 | return len; | ||
377 | } | ||
378 | else | ||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | |||
371 | LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) { | 383 | LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) { |
372 | size_t sz = luaO_str2num(s, s2v(L->top.p)); | 384 | size_t sz = luaO_str2num(s, s2v(L->top.p)); |
373 | if (sz != 0) | 385 | if (sz != 0) |
@@ -920,10 +920,9 @@ LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { | |||
920 | else { | 920 | else { |
921 | switch (lua_type(L, idx)) { | 921 | switch (lua_type(L, idx)) { |
922 | case LUA_TNUMBER: { | 922 | case LUA_TNUMBER: { |
923 | if (lua_isinteger(L, idx)) | 923 | char buff[LUA_N2SBUFFSZ]; |
924 | lua_pushfstring(L, "%I", (LUAI_UACINT)lua_tointeger(L, idx)); | 924 | lua_numbertostrbuff(L, idx, buff); |
925 | else | 925 | lua_pushstring(L, buff); |
926 | lua_pushfstring(L, "%f", (LUAI_UACNUMBER)lua_tonumber(L, idx)); | ||
927 | break; | 926 | break; |
928 | } | 927 | } |
929 | case LUA_TSTRING: | 928 | case LUA_TSTRING: |
@@ -665,20 +665,16 @@ static int g_write (lua_State *L, FILE *f, int arg) { | |||
665 | int status = 1; | 665 | int status = 1; |
666 | errno = 0; | 666 | errno = 0; |
667 | for (; nargs--; arg++) { | 667 | for (; nargs--; arg++) { |
668 | if (lua_type(L, arg) == LUA_TNUMBER) { | 668 | char buff[LUA_N2SBUFFSZ]; |
669 | /* optimization: could be done exactly as for strings */ | 669 | const char *s; |
670 | int len = lua_isinteger(L, arg) | 670 | size_t len = lua_numbertostrbuff(L, arg, buff); /* try as a number */ |
671 | ? fprintf(f, LUA_INTEGER_FMT, | 671 | if (len > 0) { /* did conversion work (value was a number)? */ |
672 | (LUAI_UACINT)lua_tointeger(L, arg)) | 672 | s = buff; |
673 | : fprintf(f, LUA_NUMBER_FMT, | 673 | len--; |
674 | (LUAI_UACNUMBER)lua_tonumber(L, arg)); | ||
675 | status = status && (len > 0); | ||
676 | } | ||
677 | else { | ||
678 | size_t l; | ||
679 | const char *s = luaL_checklstring(L, arg, &l); | ||
680 | status = status && (fwrite(s, sizeof(char), l, f) == l); | ||
681 | } | 674 | } |
675 | else /* must be a string */ | ||
676 | s = luaL_checklstring(L, arg, &len); | ||
677 | status = status && (fwrite(s, sizeof(char), len, f) == len); | ||
682 | } | 678 | } |
683 | if (l_likely(status)) | 679 | if (l_likely(status)) |
684 | return 1; /* file handle already on stack top */ | 680 | return 1; /* file handle already on stack top */ |
@@ -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 | */ |
423 | static int tostringbuffFloat (lua_Number n, char *buff) { | 425 | static 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 | */ |
445 | static unsigned tostringbuff (TValue *obj, char *buff) { | 447 | unsigned 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 | */ |
460 | void luaO_tostring (lua_State *L, TValue *obj) { | 462 | void 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 | */ |
581 | static void addnum2buff (BuffFS *buff, TValue *num) { | 583 | static 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 | } |
@@ -845,6 +845,7 @@ LUAI_FUNC int luaO_rawarith (lua_State *L, int op, const TValue *p1, | |||
845 | LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1, | 845 | LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1, |
846 | const TValue *p2, StkId res); | 846 | const TValue *p2, StkId res); |
847 | LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o); | 847 | LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o); |
848 | LUAI_FUNC unsigned luaO_tostringbuff (const TValue *obj, char *buff); | ||
848 | LUAI_FUNC lu_byte luaO_hexavalue (int c); | 849 | LUAI_FUNC lu_byte luaO_hexavalue (int c); |
849 | LUAI_FUNC void luaO_tostring (lua_State *L, TValue *obj); | 850 | LUAI_FUNC void luaO_tostring (lua_State *L, TValue *obj); |
850 | LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, | 851 | LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, |
@@ -371,7 +371,9 @@ LUA_API int (lua_next) (lua_State *L, int idx); | |||
371 | LUA_API void (lua_concat) (lua_State *L, int n); | 371 | LUA_API void (lua_concat) (lua_State *L, int n); |
372 | LUA_API void (lua_len) (lua_State *L, int idx); | 372 | LUA_API void (lua_len) (lua_State *L, int idx); |
373 | 373 | ||
374 | LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s); | 374 | #define LUA_N2SBUFFSZ 64 |
375 | LUA_API unsigned (lua_numbertostrbuff) (lua_State *L, int idx, char *buff); | ||
376 | LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s); | ||
375 | 377 | ||
376 | LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); | 378 | LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); |
377 | LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); | 379 | LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); |
diff --git a/manual/manual.of b/manual/manual.of index 6947b2a0..f0b17b4c 100644 --- a/manual/manual.of +++ b/manual/manual.of | |||
@@ -675,7 +675,7 @@ approximately @M{n} bytes between steps. | |||
675 | The garbage-collector step multiplier | 675 | The garbage-collector step multiplier |
676 | controls how much work each incremental step does. | 676 | controls how much work each incremental step does. |
677 | A value of @M{n} means the interpreter will execute | 677 | A value of @M{n} means the interpreter will execute |
678 | @M{n%} @emphx{units of work} for each byte allocated. | 678 | @M{n%} @emphx{units of work} for each word allocated. |
679 | A unit of work corresponds roughly to traversing one slot | 679 | A unit of work corresponds roughly to traversing one slot |
680 | or sweeping one object. | 680 | or sweeping one object. |
681 | Larger values make the collector more aggressive. | 681 | Larger values make the collector more aggressive. |
@@ -3829,11 +3829,26 @@ This macro may evaluate its arguments more than once. | |||
3829 | 3829 | ||
3830 | } | 3830 | } |
3831 | 3831 | ||
3832 | @APIEntry{unsigned (lua_numbertostrbuff) (lua_State *L, int idx, | ||
3833 | char *buff);| | ||
3834 | @apii{0,0,-} | ||
3835 | |||
3836 | Converts the number at acceptable index @id{idx} to a string | ||
3837 | and puts the result in @id{buff}. | ||
3838 | The buffer must have a size of at least @Lid{LUA_N2SBUFFSZ} bytes. | ||
3839 | The conversion follows a non-specified format @see{coercion}. | ||
3840 | The function returns the number of bytes written to the buffer | ||
3841 | (including the final zero), | ||
3842 | or zero if the value at @id{idx} is not a number. | ||
3843 | |||
3844 | } | ||
3845 | |||
3832 | @APIEntry{int lua_pcall (lua_State *L, int nargs, int nresults, int msgh);| | 3846 | @APIEntry{int lua_pcall (lua_State *L, int nargs, int nresults, int msgh);| |
3833 | @apii{nargs + 1,nresults|1,-} | 3847 | @apii{nargs + 1,nresults|1,-} |
3834 | 3848 | ||
3835 | Calls a function (or a callable object) in protected mode. | 3849 | Calls a function (or a callable object) in protected mode. |
3836 | 3850 | ||
3851 | |||
3837 | Both @id{nargs} and @id{nresults} have the same meaning as | 3852 | Both @id{nargs} and @id{nresults} have the same meaning as |
3838 | in @Lid{lua_call}. | 3853 | in @Lid{lua_call}. |
3839 | If there are no errors during the call, | 3854 | If there are no errors during the call, |