lstrlib.c
上传用户:dzyhzl
上传日期:2019-04-29
资源大小:56270k
文件大小:18k
源码类别:

模拟服务器

开发平台:

C/C++

  1. /*
  2. ** $Id: lstrlib.c,v 1.56 2000/10/27 16:15:53 roberto Exp $
  3. ** Standard library for string operations and pattern-matching
  4. ** See Copyright Notice in lua.h
  5. */
  6. #include <ctype.h>
  7. #include <stddef.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include "../lua.h"
  12. #include "../lauxlib.h"
  13. #include "../lualib.h"
  14. static int str_len (lua_State *L) {
  15.   size_t l;
  16.   luaL_check_lstr(L, 1, &l);
  17.   lua_pushnumber(L, l);
  18.   return 1;
  19. }
  20. static long posrelat (long pos, size_t len) {
  21.   /* relative string position: negative means back from end */
  22.   return (pos>=0) ? pos : (long)len+pos+1;
  23. }
  24. static int str_sub (lua_State *L) {
  25.   size_t l;
  26.   const char *s = luaL_check_lstr(L, 1, &l);
  27.   long start = posrelat(luaL_check_long(L, 2), l);
  28.   long end = posrelat(luaL_opt_long(L, 3, -1), l);
  29.   if (start < 1) start = 1;
  30.   if (end > (long)l) end = l;
  31.   if (start <= end)
  32.     lua_pushlstring(L, s+start-1, end-start+1);
  33.   else lua_pushstring(L, "");
  34.   return 1;
  35. }
  36. static int str_lower (lua_State *L) {
  37.   size_t l;
  38.   size_t i;
  39.   luaL_Buffer b;
  40.   const char *s = luaL_check_lstr(L, 1, &l);
  41.   luaL_buffinit(L, &b);
  42.   for (i=0; i<l; i++)
  43.     luaL_putchar(&b, tolower((unsigned char)(s[i])));
  44.   luaL_pushresult(&b);
  45.   return 1;
  46. }
  47. static int str_upper (lua_State *L) {
  48.   size_t l;
  49.   size_t i;
  50.   luaL_Buffer b;
  51.   const char *s = luaL_check_lstr(L, 1, &l);
  52.   luaL_buffinit(L, &b);
  53.   for (i=0; i<l; i++)
  54.     luaL_putchar(&b, toupper((unsigned char)(s[i])));
  55.   luaL_pushresult(&b);
  56.   return 1;
  57. }
  58. static int str_rep (lua_State *L) {
  59.   size_t l;
  60.   luaL_Buffer b;
  61.   const char *s = luaL_check_lstr(L, 1, &l);
  62.   int n = luaL_check_int(L, 2);
  63.   luaL_buffinit(L, &b);
  64.   while (n-- > 0)
  65.     luaL_addlstring(&b, s, l);
  66.   luaL_pushresult(&b);
  67.   return 1;
  68. }
  69. static int str_byte (lua_State *L) {
  70.   size_t l;
  71.   const char *s = luaL_check_lstr(L, 1, &l);
  72.   long pos = posrelat(luaL_opt_long(L, 2, 1), l);
  73.   luaL_arg_check(L, 0<pos && (size_t)pos<=l, 2,  "out of range");
  74.   lua_pushnumber(L, (unsigned char)s[pos-1]);
  75.   return 1;
  76. }
  77. static int str_char (lua_State *L) {
  78.   int n = lua_gettop(L);  /* number of arguments */
  79.   int i;
  80.   luaL_Buffer b;
  81.   luaL_buffinit(L, &b);
  82.   for (i=1; i<=n; i++) {
  83.     int c = luaL_check_int(L, i);
  84.     luaL_arg_check(L, (unsigned char)c == c, i, "invalid value");
  85.     luaL_putchar(&b, (unsigned char)c);
  86.   }
  87.   luaL_pushresult(&b);
  88.   return 1;
  89. }
  90. /*
  91. ** {======================================================
  92. ** PATTERN MATCHING
  93. ** =======================================================
  94. */
  95. #ifndef MAX_CAPTURES
  96. #define MAX_CAPTURES 32  /* arbitrary limit */
  97. #endif
  98. struct Capture {
  99.   const char *src_end;  /* end ('') of source string */
  100.   int level;  /* total number of captures (finished or unfinished) */
  101.   struct {
  102.     const char *init;
  103.     long len;  /* -1 signals unfinished capture */
  104.   } capture[MAX_CAPTURES];
  105. };
  106. #define ESC '%'
  107. #define SPECIALS "^$*+?.([%-"
  108. static int check_capture (lua_State *L, int l, struct Capture *cap) {
  109.   l -= '1';
  110.   if (!(0 <= l && l < cap->level && cap->capture[l].len != -1))
  111.     lua_error(L, "invalid capture index");
  112.   return l;
  113. }
  114. static int capture_to_close (lua_State *L, struct Capture *cap) {
  115.   int level = cap->level;
  116.   for (level--; level>=0; level--)
  117.     if (cap->capture[level].len == -1) return level;
  118.   lua_error(L, "invalid pattern capture");
  119.   return 0;  /* to avoid warnings */
  120. }
  121. const char *luaI_classend (lua_State *L, const char *p) {
  122.   switch (*p++) {
  123.     case ESC:
  124.       if (*p == '') lua_error(L, "malformed pattern (ends with `%')");
  125.       return p+1;
  126.     case '[':
  127.       if (*p == '^') p++;
  128.       do {  /* look for a ']' */
  129.         if (*p == '') lua_error(L, "malformed pattern (missing `]')");
  130.         if (*(p++) == ESC && *p != '') p++;  /* skip escapes (e.g. '%]') */
  131.       } while (*p != ']');
  132.       return p+1;
  133.     default:
  134.       return p;
  135.   }
  136. }
  137. static int match_class (int c, int cl) {
  138.   int res;
  139.   switch (tolower(cl)) {
  140.     case 'a' : res = isalpha(c); break;
  141.     case 'c' : res = iscntrl(c); break;
  142.     case 'd' : res = isdigit(c); break;
  143.     case 'l' : res = islower(c); break;
  144.     case 'p' : res = ispunct(c); break;
  145.     case 's' : res = isspace(c); break;
  146.     case 'u' : res = isupper(c); break;
  147.     case 'w' : res = isalnum(c); break;
  148.     case 'x' : res = isxdigit(c); break;
  149.     case 'z' : res = (c == ''); break;
  150.     default: return (cl == c);
  151.   }
  152.   return (islower(cl) ? res : !res);
  153. }
  154. static int matchbracketclass (int c, const char *p, const char *endclass) {
  155.   int sig = 1;
  156.   if (*(p+1) == '^') {
  157.     sig = 0;
  158.     p++;  /* skip the '^' */
  159.   }
  160.   while (++p < endclass) {
  161.     if (*p == ESC) {
  162.       p++;
  163.       if (match_class(c, (unsigned char)*p))
  164.         return sig;
  165.     }
  166.     else if ((*(p+1) == '-') && (p+2 < endclass)) {
  167.       p+=2;
  168.       if ((int)(unsigned char)*(p-2) <= c && c <= (int)(unsigned char)*p)
  169.         return sig;
  170.     }
  171.     else if ((int)(unsigned char)*p == c) return sig;
  172.   }
  173.   return !sig;
  174. }
  175. int luaI_singlematch (int c, const char *p, const char *ep) {
  176.   switch (*p) {
  177.     case '.':  /* matches any char */
  178.       return 1;
  179.     case ESC:
  180.       return match_class(c, (unsigned char)*(p+1));
  181.     case '[':
  182.       return matchbracketclass(c, p, ep-1);
  183.     default:
  184.       return ((unsigned char)*p == c);
  185.   }
  186. }
  187. static const char *match (lua_State *L, const char *s, const char *p,
  188.                           struct Capture *cap);
  189. static const char *matchbalance (lua_State *L, const char *s, const char *p,
  190.                                  struct Capture *cap) {
  191.   if (*p == 0 || *(p+1) == 0)
  192.     lua_error(L, "unbalanced pattern");
  193.   if (*s != *p) return NULL;
  194.   else {
  195.     int b = *p;
  196.     int e = *(p+1);
  197.     int cont = 1;
  198.     while (++s < cap->src_end) {
  199.       if (*s == e) {
  200.         if (--cont == 0) return s+1;
  201.       }
  202.       else if (*s == b) cont++;
  203.     }
  204.   }
  205.   return NULL;  /* string ends out of balance */
  206. }
  207. static const char *max_expand (lua_State *L, const char *s, const char *p,
  208.                                const char *ep, struct Capture *cap) {
  209.   long i = 0;  /* counts maximum expand for item */
  210.   while ((s+i)<cap->src_end && luaI_singlematch((unsigned char)*(s+i), p, ep))
  211.     i++;
  212.   /* keeps trying to match with the maximum repetitions */
  213.   while (i>=0) {
  214.     const char *res = match(L, (s+i), ep+1, cap);
  215.     if (res) return res;
  216.     i--;  /* else didn't match; reduce 1 repetition to try again */
  217.   }
  218.   return NULL;
  219. }
  220. static const char *min_expand (lua_State *L, const char *s, const char *p,
  221.                                const char *ep, struct Capture *cap) {
  222.   for (;;) {
  223.     const char *res = match(L, s, ep+1, cap);
  224.     if (res != NULL)
  225.       return res;
  226.     else if (s<cap->src_end && luaI_singlematch((unsigned char)*s, p, ep))
  227.       s++;  /* try with one more repetition */
  228.     else return NULL;
  229.   }
  230. }
  231. static const char *start_capture (lua_State *L, const char *s, const char *p,
  232.                                   struct Capture *cap) {
  233.   const char *res;
  234.   int level = cap->level;
  235.   if (level >= MAX_CAPTURES) lua_error(L, "too many captures");
  236.   cap->capture[level].init = s;
  237.   cap->capture[level].len = -1;
  238.   cap->level = level+1;
  239.   if ((res=match(L, s, p+1, cap)) == NULL)  /* match failed? */
  240.     cap->level--;  /* undo capture */
  241.   return res;
  242. }
  243. static const char *end_capture (lua_State *L, const char *s, const char *p,
  244.                                 struct Capture *cap) {
  245.   int l = capture_to_close(L, cap);
  246.   const char *res;
  247.   cap->capture[l].len = s - cap->capture[l].init;  /* close capture */
  248.   if ((res = match(L, s, p+1, cap)) == NULL)  /* match failed? */
  249.     cap->capture[l].len = -1;  /* undo capture */
  250.   return res;
  251. }
  252. static const char *match_capture (lua_State *L, const char *s, int level,
  253.                                   struct Capture *cap) {
  254.   int l = check_capture(L, level, cap);
  255.   size_t len = cap->capture[l].len;
  256.   if ((size_t)(cap->src_end-s) >= len &&
  257.       memcmp(cap->capture[l].init, s, len) == 0)
  258.     return s+len;
  259.   else return NULL;
  260. }
  261. static const char *match (lua_State *L, const char *s, const char *p,
  262.                           struct Capture *cap) {
  263.   init: /* using goto's to optimize tail recursion */
  264.   switch (*p) {
  265.     case '(':  /* start capture */
  266.       return start_capture(L, s, p, cap);
  267.     case ')':  /* end capture */
  268.       return end_capture(L, s, p, cap);
  269.     case ESC:  /* may be %[0-9] or %b */
  270.       if (isdigit((unsigned char)(*(p+1)))) {  /* capture? */
  271.         s = match_capture(L, s, *(p+1), cap);
  272.         if (s == NULL) return NULL;
  273.         p+=2; goto init;  /* else return match(L, s, p+2, cap) */
  274.       }
  275.       else if (*(p+1) == 'b') {  /* balanced string? */
  276.         s = matchbalance(L, s, p+2, cap);
  277.         if (s == NULL) return NULL;
  278.         p+=4; goto init;  /* else return match(L, s, p+4, cap); */
  279.       }
  280.       else goto dflt;  /* case default */
  281.     case '':  /* end of pattern */
  282.       return s;  /* match succeeded */
  283.     case '$':
  284.       if (*(p+1) == '')  /* is the '$' the last char in pattern? */
  285.         return (s == cap->src_end) ? s : NULL;  /* check end of string */
  286.       else goto dflt;
  287.     default: dflt: {  /* it is a pattern item */
  288.       const char *ep = luaI_classend(L, p);  /* points to what is next */
  289.       int m = s<cap->src_end && luaI_singlematch((unsigned char)*s, p, ep);
  290.       switch (*ep) {
  291.         case '?': {  /* optional */
  292.           const char *res;
  293.           if (m && ((res=match(L, s+1, ep+1, cap)) != NULL))
  294.             return res;
  295.           p=ep+1; goto init;  /* else return match(L, s, ep+1, cap); */
  296.         }
  297.         case '*':  /* 0 or more repetitions */
  298.           return max_expand(L, s, p, ep, cap);
  299.         case '+':  /* 1 or more repetitions */
  300.           return (m ? max_expand(L, s+1, p, ep, cap) : NULL);
  301.         case '-':  /* 0 or more repetitions (minimum) */
  302.           return min_expand(L, s, p, ep, cap);
  303.         default:
  304.           if (!m) return NULL;
  305.           s++; p=ep; goto init;  /* else return match(L, s+1, ep, cap); */
  306.       }
  307.     }
  308.   }
  309. }
  310. static const char *lmemfind (const char *s1, size_t l1,
  311.                              const char *s2, size_t l2) {
  312.   if (l2 == 0) return s1;  /* empty strings are everywhere */
  313.   else if (l2 > l1) return NULL;  /* avoids a negative `l1' */
  314.   else {
  315.     const char *init;  /* to search for a `*s2' inside `s1' */
  316.     l2--;  /* 1st char will be checked by `memchr' */
  317.     l1 = l1-l2;  /* `s2' cannot be found after that */
  318.     while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {
  319.       init++;   /* 1st char is already checked */
  320.       if (memcmp(init, s2+1, l2) == 0)
  321.         return init-1;
  322.       else {  /* correct `l1' and `s1' to try again */
  323.         l1 -= init-s1;
  324.         s1 = init;
  325.       }
  326.     }
  327.     return NULL;  /* not found */
  328.   }
  329. }
  330. static int push_captures (lua_State *L, struct Capture *cap) {
  331.   int i;
  332.   luaL_checkstack(L, cap->level, "too many captures");
  333.   for (i=0; i<cap->level; i++) {
  334.     int l = cap->capture[i].len;
  335.     if (l == -1) lua_error(L, "unfinished capture");
  336.     lua_pushlstring(L, cap->capture[i].init, l);
  337.   }
  338.   return cap->level;  /* number of strings pushed */
  339. }
  340. static int str_find (lua_State *L) {
  341.   size_t l1, l2;
  342.   const char *s = luaL_check_lstr(L, 1, &l1);
  343.   const char *p = luaL_check_lstr(L, 2, &l2);
  344.   long init = posrelat(luaL_opt_long(L, 3, 1), l1) - 1;
  345.   struct Capture cap;
  346.   luaL_arg_check(L, 0 <= init && (size_t)init <= l1, 3, "out of range");
  347.   if (lua_gettop(L) > 3 ||  /* extra argument? */
  348.       strpbrk(p, SPECIALS) == NULL) {  /* or no special characters? */
  349.     const char *s2 = lmemfind(s+init, l1-init, p, l2);
  350.     if (s2) {
  351.       lua_pushnumber(L, s2-s+1);
  352.       lua_pushnumber(L, s2-s+l2);
  353.       return 2;
  354.     }
  355.   }
  356.   else {
  357.     int anchor = (*p == '^') ? (p++, 1) : 0;
  358.     const char *s1=s+init;
  359.     cap.src_end = s+l1;
  360.     do {
  361.       const char *res;
  362.       cap.level = 0;
  363.       if ((res=match(L, s1, p, &cap)) != NULL) {
  364.         lua_pushnumber(L, s1-s+1);  /* start */
  365.         lua_pushnumber(L, res-s);   /* end */
  366.         return push_captures(L, &cap) + 2;
  367.       }
  368.     } while (s1++<cap.src_end && !anchor);
  369.   }
  370.   lua_pushnil(L);  /* not found */
  371.   return 1;
  372. }
  373. static void add_s (lua_State *L, luaL_Buffer *b, struct Capture *cap) {
  374.   if (lua_isstring(L, 3)) {
  375.     const char *news = lua_tostring(L, 3);
  376.     size_t l = lua_strlen(L, 3);
  377.     size_t i;
  378.     for (i=0; i<l; i++) {
  379.       if (news[i] != ESC)
  380.         luaL_putchar(b, news[i]);
  381.       else {
  382.         i++;  /* skip ESC */
  383.         if (!isdigit((unsigned char)news[i]))
  384.           luaL_putchar(b, news[i]);
  385.         else {
  386.           int level = check_capture(L, news[i], cap);
  387.           luaL_addlstring(b, cap->capture[level].init, cap->capture[level].len);
  388.         }
  389.       }
  390.     }
  391.   }
  392.   else {  /* is a function */
  393.     int n;
  394.     lua_pushvalue(L, 3);
  395.     n = push_captures(L, cap);
  396.     lua_rawcall(L, n, 1);
  397.     if (lua_isstring(L, -1))
  398.       luaL_addvalue(b);  /* add return to accumulated result */
  399.     else
  400.       lua_pop(L, 1);  /* function result is not a string: pop it */
  401.   }
  402. }
  403. static int str_gsub (lua_State *L) {
  404.   size_t srcl;
  405.   const char *src = luaL_check_lstr(L, 1, &srcl);
  406.   const char *p = luaL_check_string(L, 2);
  407.   int max_s = luaL_opt_int(L, 4, srcl+1);
  408.   int anchor = (*p == '^') ? (p++, 1) : 0;
  409.   int n = 0;
  410.   struct Capture cap;
  411.   luaL_Buffer b;
  412.   luaL_arg_check(L,
  413.     lua_gettop(L) >= 3 && (lua_isstring(L, 3) || lua_isfunction(L, 3)),
  414.     3, "string or function expected");
  415.   luaL_buffinit(L, &b);
  416.   cap.src_end = src+srcl;
  417.   while (n < max_s) {
  418.     const char *e;
  419.     cap.level = 0;
  420.     e = match(L, src, p, &cap);
  421.     if (e) {
  422.       n++;
  423.       add_s(L, &b, &cap);
  424.     }
  425.     if (e && e>src) /* non empty match? */
  426.       src = e;  /* skip it */
  427.     else if (src < cap.src_end)
  428.       luaL_putchar(&b, *src++);
  429.     else break;
  430.     if (anchor) break;
  431.   }
  432.   luaL_addlstring(&b, src, cap.src_end-src);
  433.   luaL_pushresult(&b);
  434.   lua_pushnumber(L, n);  /* number of substitutions */
  435.   return 2;
  436. }
  437. /* }====================================================== */
  438. static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) {
  439.   size_t l;
  440.   const char *s = luaL_check_lstr(L, arg, &l);
  441.   luaL_putchar(b, '"');
  442.   while (l--) {
  443.     switch (*s) {
  444.       case '"':  case '\':  case 'n':
  445.         luaL_putchar(b, '\');
  446.         luaL_putchar(b, *s);
  447.         break;
  448.       case '': luaL_addlstring(b, "\000", 4); break;
  449.       default: luaL_putchar(b, *s);
  450.     }
  451.     s++;
  452.   }
  453.   luaL_putchar(b, '"');
  454. }
  455. /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
  456. #define MAX_ITEM 512
  457. /* maximum size of each format specification (such as '%-099.99d') */
  458. #define MAX_FORMAT 20
  459. static int str_format (lua_State *L) {
  460.   int arg = 1;
  461.   const char *strfrmt = luaL_check_string(L, arg);
  462.   luaL_Buffer b;
  463.   luaL_buffinit(L, &b);
  464.   while (*strfrmt) {
  465.     if (*strfrmt != '%')
  466.       luaL_putchar(&b, *strfrmt++);
  467.     else if (*++strfrmt == '%')
  468.       luaL_putchar(&b, *strfrmt++);  /* %% */
  469.     else { /* format item */
  470.       struct Capture cap;
  471.       char form[MAX_FORMAT];  /* to store the format ('%...') */
  472.       char buff[MAX_ITEM];  /* to store the formatted item */
  473.       const char *initf = strfrmt;
  474.       form[0] = '%';
  475.       if (isdigit((unsigned char)*initf) && *(initf+1) == '$') {
  476.         arg = *initf - '0';
  477.         initf += 2;  /* skip the 'n$' */
  478.       }
  479.       arg++;
  480.       cap.src_end = strfrmt+strlen(strfrmt)+1;
  481.       cap.level = 0;
  482.       strfrmt = match(L, initf, "[-+ #0]*(%d*)%.?(%d*)", &cap);
  483.       if (cap.capture[0].len > 2 || cap.capture[1].len > 2 ||  /* < 100? */
  484.           strfrmt-initf > MAX_FORMAT-2)
  485.         lua_error(L, "invalid format (width or precision too long)");
  486.       strncpy(form+1, initf, strfrmt-initf+1); /* +1 to include conversion */
  487.       form[strfrmt-initf+2] = 0;
  488.       switch (*strfrmt++) {
  489.         case 'c':  case 'd':  case 'i':
  490.           sprintf(buff, form, luaL_check_int(L, arg));
  491.           break;
  492.         case 'o':  case 'u':  case 'x':  case 'X':
  493.           sprintf(buff, form, (unsigned int)luaL_check_number(L, arg));
  494.           break;
  495.         case 'e':  case 'E': case 'f': case 'g': case 'G':
  496.           sprintf(buff, form, luaL_check_number(L, arg));
  497.           break;
  498.         case 'q':
  499.           luaI_addquoted(L, &b, arg);
  500.           continue;  /* skip the "addsize" at the end */
  501.         case 's': {
  502.           size_t l;
  503.           const char *s = luaL_check_lstr(L, arg, &l);
  504.           if (cap.capture[1].len == 0 && l >= 100) {
  505.             /* no precision and string is too long to be formatted;
  506.                keep original string */
  507.             lua_pushvalue(L, arg);
  508.             luaL_addvalue(&b);
  509.             continue;  /* skip the "addsize" at the end */
  510.           }
  511.           else {
  512.             sprintf(buff, form, s);
  513.             break;
  514.           }
  515.         }
  516.         default:  /* also treat cases 'pnLlh' */
  517.           lua_error(L, "invalid option in `format'");
  518.       }
  519.       luaL_addlstring(&b, buff, strlen(buff));
  520.     }
  521.   }
  522.   luaL_pushresult(&b);
  523.   return 1;
  524. }
  525. static const struct luaL_reg strlib[] = {
  526. {"strlen", str_len},
  527. {"strsub", str_sub},
  528. {"strlower", str_lower},
  529. {"strupper", str_upper},
  530. {"strchar", str_char},
  531. {"strrep", str_rep},
  532. {"ascii", str_byte},  /* for compatibility with 3.0 and earlier */
  533. {"strbyte", str_byte},
  534. {"format", str_format},
  535. {"strfind", str_find},
  536. {"gsub", str_gsub}
  537. };
  538. /*
  539. ** Open string library
  540. */
  541. LUALIB_API void lua_strlibopen (lua_State *L) {
  542.   luaL_openl(L, strlib);
  543. }