PageRenderTime 27ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/branches/IsengardDev/IronHells/src/client/angband/lua/lstrlib.c

#
C | 621 lines | 536 code | 72 blank | 13 comment | 149 complexity | ebe687db59fd2707e380aa5fa3a4e272 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, Apache-2.0
  1. /*
  2. ** $Id: lstrlib.c 25 2003-02-27 18:06:01Z cipher $
  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 ('\0') 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 == '\0') 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 == '\0') lua_error(L, "malformed pattern (missing `]')");
  130. if (*(p++) == ESC && *p != '\0') 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 == '\0'); 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 '\0': /* end of pattern */
  282. return s; /* match succeeded */
  283. case '$':
  284. if (*(p+1) == '\0') /* 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 '\0': 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. }