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, |
