static void luaI_waddquoted (lua_State *L, luaL_Buffer *b, int arg) { size_t l; const lua_WChar *s = luaL_checklwstring(L, arg, &l); luaL_addwchar(b, '"'); while (l--) { switch (*s) { case '"': case '\\': case '\n': { luaL_addwchar(b, '\\'); luaL_addwchar(b, *s); break; } case '\r': { luaL_addlstring(b, "\\r", 2); break; } case '\0': { luaL_addlwstring(b, (const lua_WChar*)L"\\000", 4); break; } default: { luaL_addwchar(b, *s); break; } } s++; } luaL_addwchar(b, '"'); }
static int wstr_gsub (lua_State *L) { size_t srcl; const lua_WChar *src = luaL_checklwstring(L, 1, &srcl); const lua_WChar *p = luaL_checkwstring(L, 2); int max_s = luaL_optint(L, 4, srcl+1); int anchor = (*p == '^') ? (p++, 1) : 0; int n = 0; WMatchState ms; luaL_Buffer b; luaL_wbuffinit(L, &b); ms.L = L; ms.src_init = src; ms.src_end = src+srcl; while (n < max_s) { const lua_WChar *e; ms.level = 0; e = wmatch(&ms, src, p); if (e) { n++; wadd_value(&ms, &b, src, e); } if (e && e>src) /* non empty wmatch? */ src = e; /* skip it */ else if (src < ms.src_end) luaL_addwchar(&b, *src++); else break; if (anchor) break; } luaL_addlwstring(&b, src, ms.src_end-src); luaL_pushresult(&b); lua_pushinteger(L, n); /* number of substitutions */ return 2; }
static int str_byte (lua_State *L) { size_t l; const lua_WChar *s = luaL_checklwstring(L, 1, &l); sint32 pos = posrelat(luaL_optlong(L, 2, 1), l); luaL_argcheck(L, 0 < pos && (size_t)(pos) <= l, 2, "out of range"); lua_pushnumber(L, s[pos-1]); return 1; }
static int wstr_reverse (lua_State *L) { size_t l; luaL_Buffer b; const lua_WChar *s = luaL_checklwstring(L, 1, &l); luaL_wbuffinit(L, &b); while (l--) luaL_addwchar(&b, s[l]); luaL_pushresult(&b); return 1; }
static int str_upper (lua_State *L) { size_t l; size_t i; luaL_Buffer b; const lua_WChar *s = luaL_checklwstring(L, 1, &l); luaL_wbuffinit(L, &b); for (i=0; i<l; i++) luaL_putwchar(&b, toupper(s[i])); luaL_pushresult(&b); return 1; }
static int str_rep (lua_State *L) { size_t l; luaL_Buffer b; const lua_WChar *s = luaL_checklwstring(L, 1, &l); int n = luaL_checkint(L, 2); luaL_wbuffinit(L, &b); while (n-- > 0) luaL_addlwstring(&b, s, l); luaL_pushresult(&b); return 1; }
static int wstr_find_aux (lua_State *L, int find) { size_t l1, l2; const lua_WChar *s = luaL_checklwstring(L, 1, &l1); const lua_WChar *p = luaL_checklwstring(L, 2, &l2); ptrdiff_t init = wstr_posrelat(luaL_optinteger(L, 3, 1), l1) - 1; if (init < 0) init = 0; else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; if (find && (lua_toboolean(L, 4) || /* explicit request? */ lua_WChar_pbrk(p, WSPECIALS) == NULL)) { /* or no special characters? */ /* do a plain search */ const lua_WChar *s2 = wlmemfind(s+init, l1-init, p, l2); if (s2) { lua_pushinteger(L, s2-s+1); lua_pushinteger(L, s2-s+l2); return 2; } } else { WMatchState ms; int anchor = (*p == '^') ? (p++, 1) : 0; const lua_WChar *s1=s+init; ms.L = L; ms.src_init = s; ms.src_end = s+l1; do { const lua_WChar *res; ms.level = 0; if ((res=wmatch(&ms, s1, p)) != NULL) { if (find) { lua_pushinteger(L, s1-s+1); /* start */ lua_pushinteger(L, res-s); /* end */ return wpush_captures(&ms, NULL, 0) + 2; } else return wpush_captures(&ms, s1, res); } } while (s1++ < ms.src_end && !anchor); } lua_pushnil(L); /* not found */ return 1; }
static int str_sub (lua_State *L) { size_t l; const lua_WChar *s = luaL_checklwstring(L, 1, &l); sint32 start = posrelat(luaL_checklong(L, 2), l); sint32 end = posrelat(luaL_optlong(L, 3, -1), l); if (start < 1) start = 1; if (end > (sint32)l) end = l; if (start <= end) lua_pushlwstring(L, s+start-1, end-start+1); else lua_pushwliteral(L, L""); return 1; }
static int wstr_sub (lua_State *L) { size_t l; const lua_WChar *s = luaL_checklwstring(L, 1, &l); ptrdiff_t start = wstr_posrelat(luaL_checkinteger(L, 2), l); ptrdiff_t end = wstr_posrelat(luaL_optinteger(L, 3, -1), l); if (start < 1) start = 1; if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; if (start <= end) lua_pushlwstring(L, s+start-1, end-start+1); else lua_pushwliteral(L, L""); return 1; }
static int str_find (lua_State *L) { size_t l1, l2; const lua_WChar *s = luaL_checklwstring(L, 1, &l1); const lua_WChar *p = luaL_checklwstring(L, 2, &l2); sint32 init = posrelat(luaL_optlong(L, 3, 1), l1) - 1; luaL_argcheck(L, 0 <= init && (size_t)(init) <= l1, 3, "out of range"); if (lua_toboolean(L, 4) || /* explicit request? */ lua_WChar_pbrk(p, SPECIALS) == NULL) { /* or no special characters? */ /* do a plain search */ const lua_WChar *s2 = lmemfind(s+init, l1-init, p, l2); if (s2) { lua_pushnumber(L, s2-s+1); lua_pushnumber(L, s2-s+l2); return 2; } } else { MatchState ms; int anchor = (*p == '^') ? (p++, 1) : 0; const lua_WChar *s1=s+init; ms.L = L; ms.src_init = s; ms.src_end = s+l1; do { const lua_WChar *res; ms.level = 0; if ((res=match(&ms, s1, p)) != NULL) { lua_pushnumber(L, s1-s+1); /* start */ lua_pushnumber(L, res-s); /* end */ return push_captures(&ms, NULL, 0) + 2; } } while (s1++<ms.src_end && !anchor); } lua_pushnil(L); /* not found */ return 1; }
static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) { size_t l; const lua_WChar *s = luaL_checklwstring(L, arg, &l); luaL_putwchar(b, '"'); while (l--) { switch (*s) { case '"': case '\\': case '\n': luaL_putwchar(b, '\\'); luaL_putwchar(b, *s); break; case '\0': luaL_addlwstring(b, L"\\000", 4); break; default: luaL_putwchar(b, *s); } s++; } luaL_putwchar(b, '"'); }
static int wstr_byte (lua_State *L) { size_t l; const lua_WChar *s = luaL_checklwstring(L, 1, &l); ptrdiff_t posi = wstr_posrelat(luaL_optinteger(L, 2, 1), l); ptrdiff_t pose = wstr_posrelat(luaL_optinteger(L, 3, posi), l); int n, i; if (posi <= 0) posi = 1; if ((size_t)pose > l) pose = l; if (posi > pose) return 0; /* empty interval; return no values */ n = (int)(pose - posi + 1); if (posi + n <= pose) /* overflow? */ luaL_error(L, "string slice too long"); luaL_checkstack(L, n, "string slice too long"); for (i=0; i<n; i++) lua_pushinteger(L, (lua_WChar)s[posi+i-1]); return n; }
static int g_write (lua_State *L, FILE *f, int arg) { int nargs = lua_gettop(L) - 1; int status = 1; for (; nargs--; arg++) { if (lua_type(L, arg) == LUA_TNUMBER) { /* optimization: could be done exactly as for strings */ status = status && fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; } else if (lua_type(L, arg) == LUA_TSTRING) { size_t l; const char *s = luaL_checklstring(L, arg, &l); status = status && (fwrite(s, sizeof(char), l, f) == l); } else if (lua_type(L, arg) == LUA_TWSTRING) { size_t l; const lua_WChar *s = luaL_checklwstring(L, arg, &l); status = status && (fwrite(s, sizeof(lua_WChar), l, f) == l); } } return pushresult(L, status, NULL); }
static int str_gsub (lua_State *L) { size_t srcl; const lua_WChar *src = luaL_checklwstring(L, 1, &srcl); const lua_WChar *p = luaL_checkwstring(L, 2); int max_s = luaL_optint(L, 4, srcl+1); int anchor = (*p == '^') ? (p++, 1) : 0; int n = 0; MatchState ms; luaL_Buffer b; luaL_argcheck(L, lua_gettop(L) >= 3 && (lua_iswstring(L, 3) || lua_isfunction(L, 3)), 3, "string or function expected"); luaL_wbuffinit(L, &b); ms.L = L; ms.src_init = src; ms.src_end = src+srcl; while (n < max_s) { const lua_WChar *e; ms.level = 0; e = match(&ms, src, p); if (e) { n++; add_s(&ms, &b, src, e); } if (e && e>src) /* non empty match? */ src = e; /* skip it */ else if (src < ms.src_end) luaL_putwchar(&b, *src++); else break; if (anchor) break; } luaL_addlwstring(&b, src, ms.src_end-src); luaL_pushresult(&b); lua_pushnumber(L, n); /* number of substitutions */ return 2; }
int wstr_format_helper (luaL_Buffer* b, lua_State *L, int arg) { size_t sfl; const lua_WChar *strfrmt = luaL_checklwstring(L, arg, &sfl); const lua_WChar *strfrmt_end = strfrmt+sfl; luaL_wbuffinit(L, b); while (strfrmt < strfrmt_end) { if (*strfrmt != '%') luaL_putwchar(b, *strfrmt++); else if (*++strfrmt == '%') luaL_putwchar(b, *strfrmt++); /* %% */ else { /* format item */ lua_WChar form[MAX_FORMAT]; /* to store the format (`%...') */ lua_WChar buff[MAX_ITEM]; /* to store the formatted item */ int hasprecision = 0; if (iswdigit(*strfrmt) && *(strfrmt+1) == '$') return luaL_error(L, "obsolete `format' option (d$)"); arg++; strfrmt = scanformat(L, strfrmt, form, &hasprecision); switch (*strfrmt++) { case 'b': { buff[1] = buff[2] = buff[3] = buff[4] = buff[5] = buff[6] = buff[7] = buff[8] = 0; switch (*strfrmt++) { case 'b': { unsigned int num = (unsigned int)luaL_checkint(L, arg); buff[0] = (unsigned char)num; luaL_addlwstring(b, buff, 1); break; } case 'd': { unsigned int num = (unsigned int)luaL_checkint(L, arg); *(unsigned int*)(&buff) = num; luaL_addlwstring(b, buff, 4); break; } case 'w': { unsigned int num = (unsigned int)luaL_checkint(L, arg); *(unsigned short*)(&buff) = (unsigned short)num; luaL_addlwstring(b, buff, 2); break; } case 'f': { float numF = (float)luaL_checknumber(L, arg); *(float*)(&buff) = numF; luaL_addlwstring(b, buff, 4); break; } case 'F': { double numD = (double)luaL_checknumber(L, arg); *(double*)(&buff) = numD; luaL_addlwstring(b, buff, 8); break; } default: break; } buff[0] = 0; break; } case 'c': case 'd': case 'i': swprintf(buff, form, luaL_checkint(L, arg)); break; case 'o': case 'u': case 'x': case 'X': //?? How should this be for integers? swprintf(buff, form, (unsigned int)(luaL_checknumber(L, arg))); break; case 'e': case 'E': case 'f': case 'g': case 'G': swprintf(buff, form, luaL_checknumber(L, arg)); break; case 'q': luaI_addquoted(L, b, arg); continue; /* skip the `addsize' at the end */ case 'Q': luaI_addquotedbinary(L, b, arg); continue; /* skip the `addsize' at the end */ case 's': { size_t l; const lua_WChar *s = luaL_checklwstring(L, arg, &l); if (!hasprecision && 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 { swprintf(buff, form, s); break; } } default: /* also treat cases `pnLlh' */ luaL_error(L, "invalid option in `format'"); } luaL_addlwstring(b, buff, lua_WChar_len(buff)); } } return 1; }
static void luaI_addquotedbinary (lua_State *L, luaL_Buffer *b, int arg) { size_t l; if (lua_type(L, arg) == LUA_TWSTRING) { const lua_WChar *s = luaL_checklwstring(L, arg, &l); luaL_putwchar(b, 'L'); luaL_putwchar(b, '"'); while (l--) { switch (*s) { case '"': case '\\': luaL_putwchar(b, '\\'); luaL_putwchar(b, *s); break; case '\a': luaL_putwchar(b, '\\'); luaL_putwchar(b, 'a'); break; case '\b': luaL_putwchar(b, '\\'); luaL_putwchar(b, 'b'); break; case '\f': luaL_putwchar(b, '\\'); luaL_putwchar(b, 'f'); break; case '\n': luaL_putwchar(b, '\\'); luaL_putwchar(b, 'n'); break; case '\r': luaL_putwchar(b, '\\'); luaL_putwchar(b, 'r'); break; case '\t': luaL_putwchar(b, '\\'); luaL_putwchar(b, 't'); break; case '\v': luaL_putwchar(b, '\\'); luaL_putwchar(b, 'v'); break; default: if (*s < 256 && isprint((unsigned char)*s)) { luaL_putwchar(b, *s); } else { lua_WChar str[10]; swprintf(str, L"\\x%04x", (unsigned long)*s); luaL_addwstring(b, str); } } s++; } luaL_putwchar(b, '"'); } else { const char *s = luaL_checklstring(L, arg, &l); luaL_putwchar(b, '"'); while (l--) { switch (*s) { case '"': case '\\': luaL_putwchar(b, '\\'); luaL_putwchar(b, *s); break; case '\a': luaL_putwchar(b, '\\'); luaL_putwchar(b, 'a'); break; case '\b': luaL_putwchar(b, '\\'); luaL_putwchar(b, 'b'); break; case '\f': luaL_putwchar(b, '\\'); luaL_putwchar(b, 'f'); break; case '\n': luaL_putwchar(b, '\\'); luaL_putwchar(b, 'n'); break; case '\r': luaL_putwchar(b, '\\'); luaL_putwchar(b, 'r'); break; case '\t': luaL_putwchar(b, '\\'); luaL_putwchar(b, 't'); break; case '\v': luaL_putwchar(b, '\\'); luaL_putwchar(b, 'v'); break; default: if (isprint((unsigned char)*s)) { luaL_putwchar(b, *s); } else { lua_WChar str[10]; swprintf(str, L"\\x%02x", (unsigned long)(unsigned char)*s); luaL_addwstring(b, str); } } s++; } luaL_putwchar(b, '"'); /* const char *s = luaL_checklstring(L, arg, &l); luaL_putchar(b, '"'); while (l--) { switch (*s) { case '"': case '\\': luaL_putchar(b, '\\'); luaL_putchar(b, *s); break; case '\0': luaL_addlstring(b, "\\000", 4); break; default: if (isprint(*s) && *s != 13 && *s != 10) luaL_putchar(b, *s); else { char buf[5]; sprintf(buf, "\\%03d", *s); luaL_addlstring(b, buf, 4); } } s++; } luaL_putchar(b, '"'); */ } }
static int str_lualex(lua_State *L) { size_t l = 0; const lua_WChar *str = luaL_checklwstring(L, 1, &l); int isWide = luaL_checkint(L, 2) != 0; size_t i; luaL_Buffer b; luaL_wbuffinit(L, &b); for (i = 0; i < l; ++i) { // int needUnicodeZero = 1; switch (str[i]) { case '\\': ++i; switch (str[i]) { case 'a': luaL_putwchar(&b, '\a'); break; case 'b': luaL_putwchar(&b, '\b'); break; case 'f': luaL_putwchar(&b, '\f'); break; case 'n': luaL_putwchar(&b, '\n'); break; case 'r': luaL_putwchar(&b, '\r'); break; case 't': luaL_putwchar(&b, '\t'); break; case 'v': luaL_putwchar(&b, '\v'); break; case 'x': { int ch; ++i; ch = tolower(str[i]); if (!isdigit(ch) && !(ch >= 'a' && ch <= 'f') ) { --i; luaL_putwchar(&b, 'x'); } else { /* \xxx */ int c = 0; int i = 0; int numDigits = isWide ? 4 : 2; do { ch = towlower(str[i]); if (iswdigit((wint_t)ch)) c = 16*c + (ch-'0'); else if (ch >= 'a' && ch <= 'f') c = 16*c + (ch-'a') + 10; ++i; ch = towlower(str[i]); } while (++i<numDigits && iswdigit((wint_t)ch) || (ch >= 'a' && ch <= 'f')); luaL_putwchar(&b, c); // needUnicodeZero = 0; } break; } default: { if (!iswdigit(str[i])) luaL_putwchar(&b, str[i]); else { /* \xxx */ int c = 0; int count = 0; do { c = 10*c + (str[i]-'0'); ++i; } while (++count<3 && iswdigit(str[i])); luaL_putwchar(&b, c); } } } break; default: luaL_putwchar(&b, str[i]); } if (isWide) // && needUnicodeZero) luaL_putwchar(&b, str[i]); } luaL_pushresult(&b); return 1; }
int wwstr_format_helper (luaL_Buffer* b, lua_State *L, int arg) { size_t sfl; const lua_WChar *strfrmt = luaL_checklwstring(L, arg, &sfl); const lua_WChar *strfrmt_end = strfrmt+sfl; luaL_wbuffinit(L, b); while (strfrmt < strfrmt_end) { if (*strfrmt != WL_ESC) luaL_addwchar(b, *strfrmt++); else if (*++strfrmt == WL_ESC) luaL_addwchar(b, *strfrmt++); /* %% */ else { /* format item */ lua_WChar form[MAX_FORMAT]; /* to store the format (`%...') */ lua_WChar buff[MAX_ITEM]; /* to store the formatted item */ char _form[MAX_FORMAT]; char _buff[MAX_ITEM]; if (iswdigit(*strfrmt) && *(strfrmt+1) == '$') return luaL_error(L, "obsolete `format' option (d$)"); arg++; strfrmt = wscanformat(L, strfrmt, form); switch (*strfrmt++) { case 'c': { translate_wide_to_single(form, _form); sprintf(_buff, _form, luaL_checkint(L, arg)); translate_single_to_wide(_buff, buff); break; } case 'd': case 'i': { waddintlen(form); translate_wide_to_single(form, _form); sprintf(_buff, _form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); translate_single_to_wide(_buff, buff); break; } case 'o': case 'u': case 'x': case 'X': { //?? How should this be for integers? translate_wide_to_single(form, _form); sprintf(_buff, _form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); translate_single_to_wide(_buff, buff); break; } case 'e': case 'E': case 'f': case 'g': case 'G': { translate_wide_to_single(form, _form); sprintf(_buff, _form, luaL_checknumber(L, arg)); translate_single_to_wide(_buff, buff); break; } case 'q': { luaI_waddquoted(L, b, arg); continue; /* skip the 'addsize' at the end */ } case 's': { size_t l; const lua_WChar *s = luaL_checklwstring(L, arg, &l); (void)s; if (!lua_WChar_chr(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 { assert(0); // swprintf((wchar_t*)buff, (wchar_t*)form, s); break; } } case 'b': { buff[1] = buff[2] = buff[3] = buff[4] = buff[5] = buff[6] = buff[7] = buff[8] = 0; switch (*strfrmt++) { case 'b': { unsigned int num = (unsigned int)luaL_checkint(L, arg); buff[0] = (unsigned char)num; luaL_addlwstring(b, buff, 1); break; } case 'd': { unsigned int num = (unsigned int)luaL_checkint(L, arg); *(unsigned int*)(&buff) = num; luaL_addlwstring(b, buff, 4); break; } case 'w': { unsigned int num = (unsigned int)luaL_checkint(L, arg); *(unsigned short*)(&buff) = (unsigned short)num; luaL_addlwstring(b, buff, 2); break; } case 'f': { float numF = (float)luaL_checknumber(L, arg); *(float*)(&buff) = numF; luaL_addlwstring(b, buff, 4); break; } case 'F': { double numD = (double)luaL_checknumber(L, arg); *(double*)(&buff) = numD; luaL_addlwstring(b, buff, 8); break; } default: break; } buff[0] = 0; break; } } luaL_addlwstring(b, buff, lua_WChar_len(buff)); } } return 1; }
static int str_len (lua_State *L) { size_t l; luaL_checklwstring(L, 1, &l); lua_pushnumber(L, l); return 1; }
static void luaI_addquotedbinary (lua_State *L, luaL_Buffer *b, int arg) { size_t l; if (lua_type(L, arg) == LUA_TWSTRING) { const lua_WChar *s = luaL_checklwstring(L, arg, &l); luaL_addwchar(b, 'L'); luaL_addwchar(b, '"'); while (l--) { switch (*s) { case '"': case '\\': luaL_addwchar(b, '\\'); luaL_addwchar(b, *s); break; case '\a': luaL_addwchar(b, '\\'); luaL_addwchar(b, 'a'); break; case '\b': luaL_addwchar(b, '\\'); luaL_addwchar(b, 'b'); break; case '\f': luaL_addwchar(b, '\\'); luaL_addwchar(b, 'f'); break; case '\n': luaL_addwchar(b, '\\'); luaL_addwchar(b, 'n'); break; case '\r': luaL_addwchar(b, '\\'); luaL_addwchar(b, 'r'); break; case '\t': luaL_addwchar(b, '\\'); luaL_addwchar(b, 't'); break; case '\v': luaL_addwchar(b, '\\'); luaL_addwchar(b, 'v'); break; default: if (*s < 256 && isprint((unsigned char)*s)) { luaL_addwchar(b, *s); } else { char str[10]; lua_WChar wstr[10]; sprintf(str, "\\x%04x", (unsigned long)*s); translate_single_to_wide(str, wstr); luaL_addwstring(b, wstr); } } s++; } luaL_addwchar(b, '"'); } else { const char *s = luaL_checklstring(L, arg, &l); luaL_addwchar(b, '"'); while (l--) { switch (*s) { case '"': case '\\': luaL_addwchar(b, '\\'); luaL_addwchar(b, *s); break; case '\a': luaL_addwchar(b, '\\'); luaL_addwchar(b, 'a'); break; case '\b': luaL_addwchar(b, '\\'); luaL_addwchar(b, 'b'); break; case '\f': luaL_addwchar(b, '\\'); luaL_addwchar(b, 'f'); break; case '\n': luaL_addwchar(b, '\\'); luaL_addwchar(b, 'n'); break; case '\r': luaL_addwchar(b, '\\'); luaL_addwchar(b, 'r'); break; case '\t': luaL_addwchar(b, '\\'); luaL_addwchar(b, 't'); break; case '\v': luaL_addwchar(b, '\\'); luaL_addwchar(b, 'v'); break; default: if (isprint((unsigned char)*s)) { luaL_addwchar(b, *s); } else { char str[10]; lua_WChar wstr[10]; sprintf(str, "\\x%02x", (unsigned int)*s); translate_single_to_wide(str, wstr); luaL_addwstring(b, wstr); } } s++; } luaL_addwchar(b, '"'); } }