lua-users home
lua-l archive

Re: Problem with string.format in lua 5.0 & 5.1

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


> Is this will be available in 5.0?
No... This is not a bug, but an improvement.
> And where I can get the code from?
Follows the significant part from lstrlib.c (for 5.1). (luaconf.h should
change according to previous message.)
-- Roberto
/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
#define MAX_ITEM	512
/* valid flags in a format specification */
#define FLAGS	"-+ #0"
/*
** maximum size of each format specification (such as '%-099.99d')
** (+10 accounts for %99.99x plus margin of error)
*/
#define MAX_FORMAT	(sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
 size_t l;
 const char *s = luaL_checklstring(L, arg, &l);
 luaL_addchar(b, '"');
 while (l--) {
 switch (*s) {
 case '"': case '\\': case '\n': {
 luaL_addchar(b, '\\');
 luaL_addchar(b, *s);
 break;
 }
 case '0円': {
 luaL_addlstring(b, "\000円", 4);
 break;
 }
 default: {
 luaL_addchar(b, *s);
 break;
 }
 }
 s++;
 }
 luaL_addchar(b, '"');
}
static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
 const char *p = strfrmt;
 while (strchr(FLAGS, *p)) p++; /* skip flags */
 if ((size_t)(p - strfrmt) >= sizeof(FLAGS))
 luaL_error(L, "invalid format (repeated flags)");
 if (isdigit(uchar(*p))) p++; /* skip width */
 if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
 if (*p == '.') {
 p++;
 if (isdigit(uchar(*p))) p++; /* skip precision */
 if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
 }
 if (isdigit(uchar(*p)))
 luaL_error(L, "invalid format (width or precision too long)");
 *(form++) = '%';
 strncpy(form, strfrmt, p - strfrmt + 1);
 form += p - strfrmt + 1;
 *form = '0円';
 return p;
}
static void addintlen (char *form) {
 int l = strlen(form);
 char spec = form[l - 1];
 strcpy(form + l - 1, LUA_INTFRMLEN);
 form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;
 form[l + sizeof(LUA_INTFRMLEN) - 1] = '0円';
}
static int str_format (lua_State *L) {
 int arg = 1;
 size_t sfl;
 const char *strfrmt = luaL_checklstring(L, arg, &sfl);
 const char *strfrmt_end = strfrmt+sfl;
 luaL_Buffer b;
 luaL_buffinit(L, &b);
 while (strfrmt < strfrmt_end) {
 if (*strfrmt != L_ESC)
 luaL_addchar(&b, *strfrmt++);
 else if (*++strfrmt == L_ESC)
 luaL_addchar(&b, *strfrmt++); /* %% */
 else { /* format item */
 char form[MAX_FORMAT]; /* to store the format (`%...') */
 char buff[MAX_ITEM]; /* to store the formatted item */
 arg++;
 strfrmt = scanformat(L, strfrmt, form);
 switch (*strfrmt++) {
 case 'c': {
 sprintf(buff, form, (int)luaL_checknumber(L, arg));
 break;
 }
 case 'd': case 'i': {
 addintlen(form);
 sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));
 break;
 }
 case 'o': case 'u': case 'x': case 'X': {
 addintlen(form);
 sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
 break;
 }
 case 'e': case 'E': case 'f':
 case 'g': case 'G': {
 sprintf(buff, form, (double)luaL_checknumber(L, arg));
 break;
 }
 case 'q': {
 addquoted(L, &b, arg);
 continue; /* skip the 'addsize' at the end */
 }
 case 's': {
 size_t l;
 const char *s = luaL_checklstring(L, arg, &l);
 if (!strchr(form, '.') && l >= 100) {
 /* no precision and string is too long to be formatted;
 keep original string */
 lua_pushvalue(L, arg);
 luaL_addvalue(&b);
 continue; /* skip the `addsize' at the end */
 }
 else {
 sprintf(buff, form, s);
 break;
 }
 }
 default: { /* also treat cases `pnLlh' */
 return luaL_error(L, "invalid option to " LUA_QL("format"));
 }
 }
 luaL_addlstring(&b, buff, strlen(buff));
 }
 }
 luaL_pushresult(&b);
 return 1;
}

AltStyle によって変換されたページ (->オリジナル) /