浏览代码

"strmap" replaced by "strupper" and "strlower" (that's what people will
use, anyway).
"gsub" aceppts a function to give the replacement string.

Roberto Ierusalimschy 29 年之前
父节点
当前提交
c96ad1c945
共有 1 个文件被更改,包括 100 次插入67 次删除
  1. 100 67
      strlib.c

+ 100 - 67
strlib.c

@@ -3,7 +3,7 @@
 ** String library to LUA
 */
 
-char *rcs_strlib="$Id: strlib.c,v 1.26 1996/08/05 20:55:24 roberto Exp roberto $";
+char *rcs_strlib="$Id: strlib.c,v 1.27 1996/08/09 13:14:11 roberto Exp roberto $";
 
 #include <string.h>
 #include <stdio.h>
@@ -14,25 +14,32 @@ char *rcs_strlib="$Id: strlib.c,v 1.26 1996/08/05 20:55:24 roberto Exp roberto $
 #include "lualib.h"
 
 
-static char *buffer = NULL;
-static size_t maxbuff = 0;
-static size_t buff_size = 0;
+struct lbuff {
+  char *b;
+  size_t max;
+  size_t size;
+};
+
+static struct lbuff lbuffer = {NULL, 0, 0};
 
 
 static char *lua_strbuffer (unsigned long size)
 {
-  if (size > maxbuff) {
-    buffer = (buffer) ? realloc(buffer, maxbuff=size) : malloc(maxbuff=size);
-    if (buffer == NULL)
+  if (size > lbuffer.max) {
+    /* ANSI "realloc" doesn't need this test, but some machines (Sun!)
+       don't follow ANSI */
+    lbuffer.b = (lbuffer.b) ? realloc(lbuffer.b, lbuffer.max=size) :
+                              malloc(lbuffer.max=size);
+    if (lbuffer.b == NULL)
       lua_error("memory overflow");
   }
-  return buffer;
+  return lbuffer.b;
 }
 
 static char *openspace (unsigned long size)
 {
-  char *buff = lua_strbuffer(buff_size+size);
-  return buff+buff_size;
+  char *buff = lua_strbuffer(lbuffer.size+size);
+  return buff+lbuffer.size;
 }
 
 void lua_arg_check(int cond, char *funcname)
@@ -72,21 +79,25 @@ long lua_opt_number (int numArg, long def, char *funcname)
 
 char *luaI_addchar (int c)
 {
-  if (buff_size >= maxbuff)
-    lua_strbuffer(maxbuff == 0 ? 100 : maxbuff*2);
-  buffer[buff_size++] = c;
+  if (lbuffer.size >= lbuffer.max)
+    lua_strbuffer(lbuffer.max == 0 ? 100 : lbuffer.max*2);
+  lbuffer.b[lbuffer.size++] = c;
   if (c == 0)
-    buff_size = 0;  /* prepare for next string */
-  return buffer;
+    lbuffer.size = 0;  /* prepare for next string */
+  return lbuffer.b;
 }
 
 static void addnchar (char *s, int n)
 {
   char *b = openspace(n);
   strncpy(b, s, n);
-  buff_size += n;
+  lbuffer.size += n;
 }
 
+static void addstr (char *s)
+{
+  addnchar(s, strlen(s));
+}
 
 /*
 ** Interface to strtok
@@ -113,8 +124,6 @@ static void str_tok (void)
 
 /*
 ** Return the string length
-** LUA interface:
-**			n = strlen (string)
 */
 static void str_len (void)
 {
@@ -122,9 +131,7 @@ static void str_len (void)
 }
 
 /*
-** Return the substring of a string, from start to end
-** LUA interface:
-**			substring = strsub (string, start, end)
+** Return the substring of a string
 */
 static void str_sub (void)
 {
@@ -140,24 +147,26 @@ static void str_sub (void)
 }
 
 /*
-** Transliterate a string
+** Convert a string to lower case.
 */
-static void str_map (void)
-{
-  char *s = lua_check_string(1, "strmap");
-  char *from = lua_check_string(2, "strmap");
-  char *to = lua_opt_string(3, "", "strmap");
-  long len = strlen(to);
-  for (luaI_addchar(0); *s; s++) {
-    char *f = strrchr(from, *s);
-    if (f == NULL)
-      luaI_addchar(*s);
-    else {
-      long pos = f-from;
-      if (pos < len)
-        luaI_addchar(to[pos]);
-    }
-  }
+static void str_lower (void)
+{
+  char *s = lua_check_string(1, "strlower");
+  luaI_addchar(0);
+  while (*s)
+    luaI_addchar(tolower(*s++));
+  lua_pushstring(luaI_addchar(0));
+}
+
+/*
+** Convert a string to upper case.
+*/
+static void str_upper (void)
+{
+  char *s = lua_check_string(1, "strupper");
+  luaI_addchar(0);
+  while (*s)
+    luaI_addchar(toupper(*s++));
   lua_pushstring(luaI_addchar(0));
 }
 
@@ -255,11 +264,13 @@ static int num_captures;  /* only valid after a sucessful call to match */
 static void push_captures (void)
 {
   int i;
-  luaI_addchar(0);
   for (i=0; i<num_captures; i++) {
-    if (capture[i].len == -1) lua_error("unfinished capture");
-    addnchar(capture[i].init, capture[i].len);
-    lua_pushstring(luaI_addchar(0));
+    int l = capture[i].len;
+    char *buff = openspace(l+1);
+    if (l == -1) lua_error("unfinished capture");
+    strncpy(buff, capture[i].init, l);
+    buff[l] = 0;
+    lua_pushstring(buff);
   }
 }
 
@@ -271,18 +282,6 @@ static int check_cap (int l, int level)
   return l;
 }
 
-static void add_s (char *newp)
-{
-  while (*newp) {
-    if (*newp != ESC || !isdigit(*++newp))
-      luaI_addchar(*newp++);
-    else {
-      int l = check_cap(*newp++, num_captures);
-      addnchar(capture[l].init, capture[l].len);
-    }
-  }
-}
-
 static int capture_to_close (int level)
 {
   for (level--; level>=0; level--)
@@ -376,12 +375,44 @@ static void str_find (void)
   }
 }
 
-static void str_s (void)
+static void add_s (lua_Object newp)
+{
+  if (lua_isstring(newp)) {
+    char *news = lua_getstring(newp);
+    while (*news) {
+      if (*news != ESC || !isdigit(*++news))
+        luaI_addchar(*news++);
+      else {
+        int l = check_cap(*news++, num_captures);
+        addnchar(capture[l].init, capture[l].len);
+      }
+    }
+  }
+  else if (lua_isfunction(newp)) {
+    lua_Object res;
+    struct lbuff oldbuff;
+    lua_beginblock();
+    push_captures();
+    /* function may use lbuffer, so save it and create a new one */
+    oldbuff = lbuffer;
+    lbuffer.b = NULL; lbuffer.max = lbuffer.size = 0;
+    lua_callfunction(newp);
+    /* restore old buffer */
+    free(lbuffer.b);
+    lbuffer = oldbuff;
+    res = lua_getresult(1);
+    addstr(lua_isstring(res) ? lua_getstring(res) : "");
+    lua_endblock();
+  }
+  else lua_error("incorrect argument to `gsub'");
+}
+
+static void str_gsub (void)
 {
-  char *src = lua_check_string(1, "s");
-  char *p = lua_check_string(2, "s");
-  char *newp = lua_check_string(3, "s");
-  int max_s = lua_opt_number(4, strlen(src), "s");
+  char *src = lua_check_string(1, "gsub");
+  char *p = lua_check_string(2, "gsub");
+  lua_Object newp = lua_getparam(3);
+  int max_s = lua_opt_number(4, strlen(src), "gsub");
   int anchor = (*p == '^') ? (p++, 1) : 0;
   int n = 0;
   luaI_addchar(0);
@@ -390,14 +421,14 @@ static void str_s (void)
     if ((e=match(src, p, 0)) == NULL)
       luaI_addchar(*src++);
     else {
-      if (e == src) lua_error("empty pattern in substitution");  /* ??? */
+      if (e == src) lua_error("empty pattern in substitution");
       add_s(newp);
       src = e;
       n++;
     }
     if (anchor) break;
   }
-  addnchar(src, strlen(src));
+  addstr(src);
   lua_pushstring(luaI_addchar(0));
   lua_pushnumber(n);  /* number of substitutions */
 }
@@ -455,16 +486,17 @@ static void str_format (void)
         case 's': {
           char *s = lua_check_string(arg++, "format");
           buff = openspace(strlen(s));
-          buff_size += sprintf(buff, form, s);
+          lbuffer.size += sprintf(buff, form, s);
           break;
         }
         case 'c':  case 'd':  case 'i': case 'o':
         case 'u':  case 'x':  case 'X':
-          buff_size += sprintf(buff, form,
-                               (int)lua_check_number(arg++, "format"));
+          lbuffer.size += sprintf(buff, form,
+                                  (int)lua_check_number(arg++, "format"));
           break;
         case 'e':  case 'E': case 'f': case 'g':
-          buff_size += sprintf(buff, form, lua_check_number(arg++, "format"));
+          lbuffer.size += sprintf(buff, form,
+                                  lua_check_number(arg++, "format"));
           break;
         default:  /* also treat cases 'pnLlh' */
           lua_error("invalid format option in function `format'");
@@ -488,11 +520,12 @@ static struct lua_reg strlib[] = {
 {"strlen", str_len},
 {"strsub", str_sub},
 {"strset", str_set},
-{"strmap", str_map},
+{"strlower", str_lower},
+{"strupper", str_upper},
 {"ascii", str_ascii},
 {"format", str_format},
 {"strfind", str_find},
-{"gsub",    str_s}
+{"gsub", str_gsub}
 };