1
0
mirror of https://github.com/lua/lua.git synced 2025-01-14 05:43:00 +08:00

"strmap" replaced by "strupper" and "strlower" (that's what people will

use, anyway).
"gsub" aceppts a function to give the replacement string.
This commit is contained in:
Roberto Ierusalimschy 1996-09-16 15:02:40 -03:00
parent 5b9fbfa006
commit c96ad1c945

165
strlib.c
View File

@ -3,7 +3,7 @@
** String library to LUA ** 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 <string.h>
#include <stdio.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" #include "lualib.h"
static char *buffer = NULL; struct lbuff {
static size_t maxbuff = 0; char *b;
static size_t buff_size = 0; size_t max;
size_t size;
};
static struct lbuff lbuffer = {NULL, 0, 0};
static char *lua_strbuffer (unsigned long size) static char *lua_strbuffer (unsigned long size)
{ {
if (size > maxbuff) { if (size > lbuffer.max) {
buffer = (buffer) ? realloc(buffer, maxbuff=size) : malloc(maxbuff=size); /* ANSI "realloc" doesn't need this test, but some machines (Sun!)
if (buffer == NULL) 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"); lua_error("memory overflow");
} }
return buffer; return lbuffer.b;
} }
static char *openspace (unsigned long size) static char *openspace (unsigned long size)
{ {
char *buff = lua_strbuffer(buff_size+size); char *buff = lua_strbuffer(lbuffer.size+size);
return buff+buff_size; return buff+lbuffer.size;
} }
void lua_arg_check(int cond, char *funcname) 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) char *luaI_addchar (int c)
{ {
if (buff_size >= maxbuff) if (lbuffer.size >= lbuffer.max)
lua_strbuffer(maxbuff == 0 ? 100 : maxbuff*2); lua_strbuffer(lbuffer.max == 0 ? 100 : lbuffer.max*2);
buffer[buff_size++] = c; lbuffer.b[lbuffer.size++] = c;
if (c == 0) if (c == 0)
buff_size = 0; /* prepare for next string */ lbuffer.size = 0; /* prepare for next string */
return buffer; return lbuffer.b;
} }
static void addnchar (char *s, int n) static void addnchar (char *s, int n)
{ {
char *b = openspace(n); char *b = openspace(n);
strncpy(b, s, n); strncpy(b, s, n);
buff_size += n; lbuffer.size += n;
} }
static void addstr (char *s)
{
addnchar(s, strlen(s));
}
/* /*
** Interface to strtok ** Interface to strtok
@ -113,8 +124,6 @@ static void str_tok (void)
/* /*
** Return the string length ** Return the string length
** LUA interface:
** n = strlen (string)
*/ */
static void str_len (void) static void str_len (void)
{ {
@ -122,9 +131,7 @@ static void str_len (void)
} }
/* /*
** Return the substring of a string, from start to end ** Return the substring of a string
** LUA interface:
** substring = strsub (string, start, end)
*/ */
static void str_sub (void) 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) static void str_lower (void)
{ {
char *s = lua_check_string(1, "strmap"); char *s = lua_check_string(1, "strlower");
char *from = lua_check_string(2, "strmap"); luaI_addchar(0);
char *to = lua_opt_string(3, "", "strmap"); while (*s)
long len = strlen(to); luaI_addchar(tolower(*s++));
for (luaI_addchar(0); *s; s++) { lua_pushstring(luaI_addchar(0));
char *f = strrchr(from, *s); }
if (f == NULL)
luaI_addchar(*s); /*
else { ** Convert a string to upper case.
long pos = f-from; */
if (pos < len) static void str_upper (void)
luaI_addchar(to[pos]); {
} char *s = lua_check_string(1, "strupper");
} luaI_addchar(0);
while (*s)
luaI_addchar(toupper(*s++));
lua_pushstring(luaI_addchar(0)); 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) static void push_captures (void)
{ {
int i; int i;
luaI_addchar(0);
for (i=0; i<num_captures; i++) { for (i=0; i<num_captures; i++) {
if (capture[i].len == -1) lua_error("unfinished capture"); int l = capture[i].len;
addnchar(capture[i].init, capture[i].len); char *buff = openspace(l+1);
lua_pushstring(luaI_addchar(0)); 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; 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) static int capture_to_close (int level)
{ {
for (level--; level>=0; 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)
{ {
char *src = lua_check_string(1, "s"); if (lua_isstring(newp)) {
char *p = lua_check_string(2, "s"); char *news = lua_getstring(newp);
char *newp = lua_check_string(3, "s"); while (*news) {
int max_s = lua_opt_number(4, strlen(src), "s"); 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, "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 anchor = (*p == '^') ? (p++, 1) : 0;
int n = 0; int n = 0;
luaI_addchar(0); luaI_addchar(0);
@ -390,14 +421,14 @@ static void str_s (void)
if ((e=match(src, p, 0)) == NULL) if ((e=match(src, p, 0)) == NULL)
luaI_addchar(*src++); luaI_addchar(*src++);
else { else {
if (e == src) lua_error("empty pattern in substitution"); /* ??? */ if (e == src) lua_error("empty pattern in substitution");
add_s(newp); add_s(newp);
src = e; src = e;
n++; n++;
} }
if (anchor) break; if (anchor) break;
} }
addnchar(src, strlen(src)); addstr(src);
lua_pushstring(luaI_addchar(0)); lua_pushstring(luaI_addchar(0));
lua_pushnumber(n); /* number of substitutions */ lua_pushnumber(n); /* number of substitutions */
} }
@ -455,16 +486,17 @@ static void str_format (void)
case 's': { case 's': {
char *s = lua_check_string(arg++, "format"); char *s = lua_check_string(arg++, "format");
buff = openspace(strlen(s)); buff = openspace(strlen(s));
buff_size += sprintf(buff, form, s); lbuffer.size += sprintf(buff, form, s);
break; break;
} }
case 'c': case 'd': case 'i': case 'o': case 'c': case 'd': case 'i': case 'o':
case 'u': case 'x': case 'X': case 'u': case 'x': case 'X':
buff_size += sprintf(buff, form, lbuffer.size += sprintf(buff, form,
(int)lua_check_number(arg++, "format")); (int)lua_check_number(arg++, "format"));
break; break;
case 'e': case 'E': case 'f': case 'g': 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; break;
default: /* also treat cases 'pnLlh' */ default: /* also treat cases 'pnLlh' */
lua_error("invalid format option in function `format'"); lua_error("invalid format option in function `format'");
@ -488,11 +520,12 @@ static struct lua_reg strlib[] = {
{"strlen", str_len}, {"strlen", str_len},
{"strsub", str_sub}, {"strsub", str_sub},
{"strset", str_set}, {"strset", str_set},
{"strmap", str_map}, {"strlower", str_lower},
{"strupper", str_upper},
{"ascii", str_ascii}, {"ascii", str_ascii},
{"format", str_format}, {"format", str_format},
{"strfind", str_find}, {"strfind", str_find},
{"gsub", str_s} {"gsub", str_gsub}
}; };