📄 lstrlib.c
字号:
goto dflt; /* case default */ } } } case '\0': { /* end of pattern */ return s; /* match succeeded */ } case '$': { if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ return (s == ms->src_end) ? s : NULL; /* check end of string */ else goto dflt; } default: dflt: { /* it is a pattern item */ const char *ep = luaI_classend(ms, p); /* points to what is next */ int m = s<ms->src_end && luaI_singlematch(uchar(*s), p, ep); switch (*ep) { case '?': { /* optional */ const char *res; if (m && ((res=match(ms, s+1, ep+1)) != NULL)) return res; p=ep+1; goto init; /* else return match(ms, s, ep+1); */ } case '*': { /* 0 or more repetitions */ return max_expand(ms, s, p, ep); } case '+': { /* 1 or more repetitions */ return (m ? max_expand(ms, s+1, p, ep) : NULL); } case '-': { /* 0 or more repetitions (minimum) */ return min_expand(ms, s, p, ep); } default: { if (!m) return NULL; s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ } } } }}static const char *lmemfind (const char *s1, size_t l1, const char *s2, size_t l2) { if (l2 == 0) return s1; /* empty strings are everywhere */ else if (l2 > l1) return NULL; /* avoids a negative `l1' */ else { const char *init; /* to search for a `*s2' inside `s1' */ l2--; /* 1st char will be checked by `memchr' */ l1 = l1-l2; /* `s2' cannot be found after that */ while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { init++; /* 1st char is already checked */ if (memcmp(init, s2+1, l2) == 0) return init-1; else { /* correct `l1' and `s1' to try again */ l1 -= init-s1; s1 = init; } } return NULL; /* not found */ }}static void push_onecapture (MatchState *ms, int i) { int l = ms->capture[i].len; if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); if (l == CAP_POSITION) lua_pushnumber(ms->L, (lua_Number)(ms->capture[i].init - ms->src_init + 1)); else lua_pushlstring(ms->L, ms->capture[i].init, l);}static int push_captures (MatchState *ms, const char *s, const char *e) { int i; luaL_checkstack(ms->L, ms->level, "too many captures"); if (ms->level == 0 && s) { /* no explicit captures? */ lua_pushlstring(ms->L, s, e-s); /* return whole match */ return 1; } else { /* return all captures */ for (i=0; i<ms->level; i++) push_onecapture(ms, i); return ms->level; /* number of strings pushed */ }}static int str_find (lua_State *L) { size_t l1, l2; const char *s = luaL_checklstring(L, 1, &l1); const char *p = luaL_checklstring(L, 2, &l2); sint32 init = posrelat(luaL_optlong(L, 3, 1), l1) - 1; if (init < 0) init = 0; else if ((size_t)(init) > l1) init = (sint32)l1; if (lua_toboolean(L, 4) || /* explicit request? */ strpbrk(p, SPECIALS) == NULL) { /* or no special characters? */ /* do a plain search */ const char *s2 = lmemfind(s+init, l1-init, p, l2); if (s2) { lua_pushnumber(L, (lua_Number)(s2-s+1)); lua_pushnumber(L, (lua_Number)(s2-s+l2)); return 2; } } else { MatchState ms; int anchor = (*p == '^') ? (p++, 1) : 0; const char *s1=s+init; ms.L = L; ms.src_init = s; ms.src_end = s+l1; do { const char *res; ms.level = 0; if ((res=match(&ms, s1, p)) != NULL) { lua_pushnumber(L, (lua_Number)(s1-s+1)); /* start */ lua_pushnumber(L, (lua_Number)(res-s)); /* end */ return push_captures(&ms, NULL, 0) + 2; } } while (s1++<ms.src_end && !anchor); } lua_pushnil(L); /* not found */ return 1;}static int gfind_aux (lua_State *L) { MatchState ms; const char *s = lua_tostring(L, lua_upvalueindex(1)); size_t ls = lua_strlen(L, lua_upvalueindex(1)); const char *p = lua_tostring(L, lua_upvalueindex(2)); const char *src; ms.L = L; ms.src_init = s; ms.src_end = s+ls; for (src = s + (size_t)lua_tonumber(L, lua_upvalueindex(3)); src <= ms.src_end; src++) { const char *e; ms.level = 0; if ((e = match(&ms, src, p)) != NULL) { int newstart = e-s; if (e == src) newstart++; /* empty match? go at least one position */ lua_pushnumber(L, (lua_Number)newstart); lua_replace(L, lua_upvalueindex(3)); return push_captures(&ms, src, e); } } return 0; /* not found */}static int gfind (lua_State *L) { luaL_checkstring(L, 1); luaL_checkstring(L, 2); lua_settop(L, 2); lua_pushnumber(L, 0); lua_pushcclosure(L, gfind_aux, 3); return 1;}static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, const char *e) { lua_State *L = ms->L; if (lua_isstring(L, 3)) { const char *news = lua_tostring(L, 3); size_t l = lua_strlen(L, 3); size_t i; for (i=0; i<l; i++) { if (news[i] != ESC) luaL_putchar(b, news[i]); else { i++; /* skip ESC */ if (!isdigit(uchar(news[i]))) luaL_putchar(b, news[i]); else { int level = check_capture(ms, news[i]); push_onecapture(ms, level); luaL_addvalue(b); /* add capture to accumulated result */ } } } } else { /* is a function */ int n; lua_pushvalue(L, 3); n = push_captures(ms, s, e); lua_call(L, n, 1); if (lua_isstring(L, -1)) luaL_addvalue(b); /* add return to accumulated result */ else lua_pop(L, 1); /* function result is not a string: pop it */ }}static int str_gsub (lua_State *L) { size_t srcl; const char *src = luaL_checklstring(L, 1, &srcl); const char *p = luaL_checkstring(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_isstring(L, 3) || lua_isfunction(L, 3)), 3, "string or function expected"); luaL_buffinit(L, &b); ms.L = L; ms.src_init = src; ms.src_end = src+srcl; while (n < max_s) { const char *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_putchar(&b, *src++); else break; if (anchor) break; } luaL_addlstring(&b, src, ms.src_end-src); luaL_pushresult(&b); lua_pushnumber(L, (lua_Number)n); /* number of substitutions */ return 2;}/* }====================================================== *//* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */#define MAX_ITEM 512/* maximum size of each format specification (such as '%-099.99d') */#define MAX_FORMAT 20static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) { size_t l; const char *s = luaL_checklstring(L, arg, &l); luaL_putchar(b, '"'); while (l--) { switch (*s) { case '"': case '\\': case '\n': { luaL_putchar(b, '\\'); luaL_putchar(b, *s); break; } case '\0': { luaL_addlstring(b, "\\000", 4); break; } default: { luaL_putchar(b, *s); break; } } s++; } luaL_putchar(b, '"');}static const char *scanformat (lua_State *L, const char *strfrmt, char *form, int *hasprecision) { const char *p = strfrmt; while (strchr("-+ #0", *p)) p++; /* skip flags */ if (isdigit(uchar(*p))) p++; /* skip width */ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ if (*p == '.') { p++; *hasprecision = 1; 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)"); if (p-strfrmt+2 > MAX_FORMAT) /* +2 to include `%' and the specifier */ luaL_error(L, "invalid format (too long)"); form[0] = '%'; strncpy(form+1, strfrmt, p-strfrmt+1); form[p-strfrmt+2] = 0; return p;}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 != '%') luaL_putchar(&b, *strfrmt++); else if (*++strfrmt == '%') luaL_putchar(&b, *strfrmt++); /* %% */ else { /* format item */ char form[MAX_FORMAT]; /* to store the format (`%...') */ char buff[MAX_ITEM]; /* to store the formatted item */ int hasprecision = 0; if (isdigit(uchar(*strfrmt)) && *(strfrmt+1) == '$') return luaL_error(L, "obsolete option (d$) to `format'"); arg++; strfrmt = scanformat(L, strfrmt, form, &hasprecision); switch (*strfrmt++) { case 'c': case 'd': case 'i': { sprintf(buff, form, luaL_checkint(L, arg)); break; } case 'o': case 'u': case 'x': case 'X': { sprintf(buff, form, (unsigned int)(luaL_checknumber(L, arg))); break; } case 'e': case 'E': case 'f': case 'g': case 'G': { sprintf(buff, form, luaL_checknumber(L, arg)); break; } case 'q': { luaI_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 (!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 { sprintf(buff, form, s); break; } } default: { /* also treat cases `pnLlh' */ return luaL_error(L, "invalid option to `format'"); } } luaL_addlstring(&b, buff, strlen(buff)); } } luaL_pushresult(&b); return 1;}static const luaL_reg strlib[] = { {"len", str_len}, {"sub", str_sub}, {"lower", str_lower}, {"upper", str_upper}, {"char", str_char}, {"rep", str_rep}, {"byte", str_byte}, {"format", str_format}, {"dump", str_dump}, {"find", str_find}, {"gfind", gfind}, {"gsub", str_gsub}, {NULL, NULL}};/*** Open string library*/LUALIB_API int luaopen_string (lua_State *L) { luaL_openlib(L, LUA_STRLIBNAME, strlib, 0); return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -