PageRenderTime 57ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/trunk/IronHells/src/lua/lstrlib.c

#
C | 841 lines | 760 code | 68 blank | 13 comment | 119 complexity | 8ec7d6e798f051ce5f85d0e84d55c448 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, Apache-2.0
  1. /*
  2. ** $Id: lstrlib.c 124 2003-04-09 00:19:02Z 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
  15. str_len(lua_State * L)
  16. {
  17. size_t l;
  18. luaL_check_lstr(L, 1, &l);
  19. lua_pushnumber(L, l);
  20. return 1;
  21. }
  22. static long
  23. posrelat(long pos,
  24. size_t len)
  25. {
  26. /* relative string position: negative means back from end */
  27. return (pos >= 0) ? pos : (long) len + pos + 1;
  28. }
  29. static int
  30. str_sub(lua_State * L)
  31. {
  32. size_t l;
  33. const char *s = luaL_check_lstr(L, 1, &l);
  34. long start = posrelat(luaL_check_long(L, 2), l);
  35. long end = posrelat(luaL_opt_long(L, 3, -1), l);
  36. if(start < 1)
  37. start = 1;
  38. if(end > (long) l)
  39. end = l;
  40. if(start <= end)
  41. lua_pushlstring(L, s + start - 1, end - start + 1);
  42. else
  43. lua_pushstring(L, "");
  44. return 1;
  45. }
  46. static int
  47. str_lower(lua_State * L)
  48. {
  49. size_t l;
  50. size_t i;
  51. luaL_Buffer b;
  52. const char *s = luaL_check_lstr(L, 1, &l);
  53. luaL_buffinit(L, &b);
  54. for(i = 0; i < l; i++)
  55. luaL_putchar(&b, tolower((unsigned char) (s[i])));
  56. luaL_pushresult(&b);
  57. return 1;
  58. }
  59. static int
  60. str_upper(lua_State * L)
  61. {
  62. size_t l;
  63. size_t i;
  64. luaL_Buffer b;
  65. const char *s = luaL_check_lstr(L, 1, &l);
  66. luaL_buffinit(L, &b);
  67. for(i = 0; i < l; i++)
  68. luaL_putchar(&b, toupper((unsigned char) (s[i])));
  69. luaL_pushresult(&b);
  70. return 1;
  71. }
  72. static int
  73. str_rep(lua_State * L)
  74. {
  75. size_t l;
  76. luaL_Buffer b;
  77. const char *s = luaL_check_lstr(L, 1, &l);
  78. int n = luaL_check_int(L, 2);
  79. luaL_buffinit(L, &b);
  80. while(n-- > 0)
  81. luaL_addlstring(&b, s, l);
  82. luaL_pushresult(&b);
  83. return 1;
  84. }
  85. static int
  86. str_byte(lua_State * L)
  87. {
  88. size_t l;
  89. const char *s = luaL_check_lstr(L, 1, &l);
  90. long pos = posrelat(luaL_opt_long(L, 2, 1), l);
  91. luaL_arg_check(L, 0 < pos && (size_t) pos <= l, 2, "out of range");
  92. lua_pushnumber(L, (unsigned char) s[pos - 1]);
  93. return 1;
  94. }
  95. static int
  96. str_char(lua_State * L)
  97. {
  98. int n = lua_gettop(L); /* number of arguments */
  99. int i;
  100. luaL_Buffer b;
  101. luaL_buffinit(L, &b);
  102. for(i = 1; i <= n; i++)
  103. {
  104. int c = luaL_check_int(L, i);
  105. luaL_arg_check(L, (unsigned char) c == c, i, "invalid value");
  106. luaL_putchar(&b, (unsigned char) c);
  107. }
  108. luaL_pushresult(&b);
  109. return 1;
  110. }
  111. /*
  112. ** {======================================================
  113. ** PATTERN MATCHING
  114. ** =======================================================
  115. */
  116. #ifndef MAX_CAPTURES
  117. #define MAX_CAPTURES 32 /* arbitrary limit */
  118. #endif
  119. struct Capture
  120. {
  121. const char *src_end; /* end ('\0') of source string */
  122. int level; /* total number of captures (finished or unfinished) */
  123. struct
  124. {
  125. const char *init;
  126. long len; /* -1 signals unfinished capture */
  127. }
  128. capture[MAX_CAPTURES];
  129. };
  130. #define ESC '%'
  131. #define SPECIALS "^$*+?.([%-"
  132. static int
  133. check_capture(lua_State * L,
  134. int l,
  135. struct Capture *cap)
  136. {
  137. l -= '1';
  138. if(!(0 <= l && l < cap->level && cap->capture[l].len != -1))
  139. lua_error(L, "invalid capture index");
  140. return l;
  141. }
  142. static int
  143. capture_to_close(lua_State * L,
  144. struct Capture *cap)
  145. {
  146. int level = cap->level;
  147. for(level--; level >= 0; level--)
  148. if(cap->capture[level].len == -1)
  149. return level;
  150. lua_error(L, "invalid pattern capture");
  151. return 0; /* to avoid warnings */
  152. }
  153. const char *
  154. luaI_classend(lua_State * L,
  155. const char *p)
  156. {
  157. switch (*p++)
  158. {
  159. case ESC:
  160. if(*p == '\0')
  161. lua_error(L, "malformed pattern (ends with `%')");
  162. return p + 1;
  163. case '[':
  164. if(*p == '^')
  165. p++;
  166. do
  167. { /* look for a ']' */
  168. if(*p == '\0')
  169. lua_error(L, "malformed pattern (missing `]')");
  170. if(*(p++) == ESC && *p != '\0')
  171. p++; /* skip escapes (e.g. '%]') */
  172. } while(*p != ']');
  173. return p + 1;
  174. default:
  175. return p;
  176. }
  177. }
  178. static int
  179. match_class(int c,
  180. int cl)
  181. {
  182. int res;
  183. switch (tolower(cl))
  184. {
  185. case 'a':
  186. res = isalpha(c);
  187. break;
  188. case 'c':
  189. res = iscntrl(c);
  190. break;
  191. case 'd':
  192. res = isdigit(c);
  193. break;
  194. case 'l':
  195. res = islower(c);
  196. break;
  197. case 'p':
  198. res = ispunct(c);
  199. break;
  200. case 's':
  201. res = isspace(c);
  202. break;
  203. case 'u':
  204. res = isupper(c);
  205. break;
  206. case 'w':
  207. res = isalnum(c);
  208. break;
  209. case 'x':
  210. res = isxdigit(c);
  211. break;
  212. case 'z':
  213. res = (c == '\0');
  214. break;
  215. default:
  216. return (cl == c);
  217. }
  218. return (islower(cl) ? res : !res);
  219. }
  220. static int
  221. matchbracketclass(int c,
  222. const char *p,
  223. const char *endclass)
  224. {
  225. int sig = 1;
  226. if(*(p + 1) == '^')
  227. {
  228. sig = 0;
  229. p++; /* skip the '^' */
  230. }
  231. while(++p < endclass)
  232. {
  233. if(*p == ESC)
  234. {
  235. p++;
  236. if(match_class(c, (unsigned char) *p))
  237. return sig;
  238. }
  239. else if((*(p + 1) == '-') && (p + 2 < endclass))
  240. {
  241. p += 2;
  242. if((int) (unsigned char) *(p - 2) <= c &&
  243. c <= (int) (unsigned char) *p)
  244. return sig;
  245. }
  246. else if((int) (unsigned char) *p == c)
  247. return sig;
  248. }
  249. return !sig;
  250. }
  251. int
  252. luaI_singlematch(int c,
  253. const char *p,
  254. const char *ep)
  255. {
  256. switch (*p)
  257. {
  258. case '.': /* matches any char */
  259. return 1;
  260. case ESC:
  261. return match_class(c, (unsigned char) *(p + 1));
  262. case '[':
  263. return matchbracketclass(c, p, ep - 1);
  264. default:
  265. return ((unsigned char) *p == c);
  266. }
  267. }
  268. static const char *match(lua_State * L,
  269. const char *s,
  270. const char *p,
  271. struct Capture *cap);
  272. static const char *
  273. matchbalance(lua_State * L,
  274. const char *s,
  275. const char *p,
  276. struct Capture *cap)
  277. {
  278. if(*p == 0 || *(p + 1) == 0)
  279. lua_error(L, "unbalanced pattern");
  280. if(*s != *p)
  281. return NULL;
  282. else
  283. {
  284. int b = *p;
  285. int e = *(p + 1);
  286. int cont = 1;
  287. while(++s < cap->src_end)
  288. {
  289. if(*s == e)
  290. {
  291. if(--cont == 0)
  292. return s + 1;
  293. }
  294. else if(*s == b)
  295. cont++;
  296. }
  297. }
  298. return NULL; /* string ends out of balance */
  299. }
  300. static const char *
  301. max_expand(lua_State * L,
  302. const char *s,
  303. const char *p,
  304. const char *ep,
  305. struct Capture *cap)
  306. {
  307. long i = 0; /* counts maximum expand for item */
  308. while((s + i) < cap->src_end &&
  309. luaI_singlematch((unsigned char) *(s + i), p, ep))
  310. i++;
  311. /* keeps trying to match with the maximum repetitions */
  312. while(i >= 0)
  313. {
  314. const char *res = match(L, (s + i), ep + 1, cap);
  315. if(res)
  316. return res;
  317. i--; /* else didn't match; reduce 1 repetition to try again */
  318. }
  319. return NULL;
  320. }
  321. static const char *
  322. min_expand(lua_State * L,
  323. const char *s,
  324. const char *p,
  325. const char *ep,
  326. struct Capture *cap)
  327. {
  328. for(;;)
  329. {
  330. const char *res = match(L, s, ep + 1, cap);
  331. if(res != NULL)
  332. return res;
  333. else if(s < cap->src_end &&
  334. luaI_singlematch((unsigned char) *s, p, ep))
  335. s++; /* try with one more repetition */
  336. else
  337. return NULL;
  338. }
  339. }
  340. static const char *
  341. start_capture(lua_State * L,
  342. const char *s,
  343. const char *p,
  344. struct Capture *cap)
  345. {
  346. const char *res;
  347. int level = cap->level;
  348. if(level >= MAX_CAPTURES)
  349. lua_error(L, "too many captures");
  350. cap->capture[level].init = s;
  351. cap->capture[level].len = -1;
  352. cap->level = level + 1;
  353. if((res = match(L, s, p + 1, cap)) == NULL) /* match failed? */
  354. cap->level--; /* undo capture */
  355. return res;
  356. }
  357. static const char *
  358. end_capture(lua_State * L,
  359. const char *s,
  360. const char *p,
  361. struct Capture *cap)
  362. {
  363. int l = capture_to_close(L, cap);
  364. const char *res;
  365. cap->capture[l].len = s - cap->capture[l].init; /* close capture */
  366. if((res = match(L, s, p + 1, cap)) == NULL) /* match failed? */
  367. cap->capture[l].len = -1; /* undo capture */
  368. return res;
  369. }
  370. static const char *
  371. match_capture(lua_State * L,
  372. const char *s,
  373. int level,
  374. struct Capture *cap)
  375. {
  376. int l = check_capture(L, level, cap);
  377. size_t len = cap->capture[l].len;
  378. if((size_t) (cap->src_end - s) >= len &&
  379. memcmp(cap->capture[l].init, s, len) == 0)
  380. return s + len;
  381. else
  382. return NULL;
  383. }
  384. static const char *
  385. match(lua_State * L,
  386. const char *s,
  387. const char *p,
  388. struct Capture *cap)
  389. {
  390. init: /* using goto's to optimize tail recursion */
  391. switch (*p)
  392. {
  393. case '(': /* start capture */
  394. return start_capture(L, s, p, cap);
  395. case ')': /* end capture */
  396. return end_capture(L, s, p, cap);
  397. case ESC: /* may be %[0-9] or %b */
  398. if(isdigit((unsigned char) (*(p + 1))))
  399. { /* capture? */
  400. s = match_capture(L, s, *(p + 1), cap);
  401. if(s == NULL)
  402. return NULL;
  403. p += 2;
  404. goto init; /* else return match(L, s, p+2, cap) */
  405. }
  406. else if(*(p + 1) == 'b')
  407. { /* balanced string? */
  408. s = matchbalance(L, s, p + 2, cap);
  409. if(s == NULL)
  410. return NULL;
  411. p += 4;
  412. goto init; /* else return match(L, s, p+4, cap); */
  413. }
  414. else
  415. goto dflt; /* case default */
  416. case '\0': /* end of pattern */
  417. return s; /* match succeeded */
  418. case '$':
  419. if(*(p + 1) == '\0') /* is the '$' the last char in pattern? */
  420. return (s == cap->src_end) ? s : NULL; /* check end of string */
  421. else
  422. goto dflt;
  423. default:
  424. dflt:{ /* it is a pattern item */
  425. const char *ep = luaI_classend(L, p); /* points to what is next */
  426. int m = s < cap->src_end &&
  427. luaI_singlematch((unsigned char) *s, p, ep);
  428. switch (*ep)
  429. {
  430. case '?':
  431. { /* optional */
  432. const char *res;
  433. if(m &&
  434. ((res =
  435. match(L, s + 1, ep + 1,
  436. cap)) != NULL))
  437. return res;
  438. p = ep + 1;
  439. goto init; /* else return match(L, s, ep+1, cap); */
  440. }
  441. case '*': /* 0 or more repetitions */
  442. return max_expand(L, s, p, ep, cap);
  443. case '+': /* 1 or more repetitions */
  444. return (m ? max_expand(L, s + 1, p, ep, cap)
  445. : NULL);
  446. case '-': /* 0 or more repetitions (minimum) */
  447. return min_expand(L, s, p, ep, cap);
  448. default:
  449. if(!m)
  450. return NULL;
  451. s++;
  452. p = ep;
  453. goto init; /* else return match(L, s+1, ep, cap); */
  454. }
  455. }
  456. }
  457. }
  458. static const char *
  459. lmemfind(const char *s1,
  460. size_t l1,
  461. const char *s2,
  462. size_t l2)
  463. {
  464. if(l2 == 0)
  465. return s1; /* empty strings are everywhere */
  466. else if(l2 > l1)
  467. return NULL; /* avoids a negative `l1' */
  468. else
  469. {
  470. const char *init; /* to search for a `*s2' inside `s1' */
  471. l2--; /* 1st char will be checked by `memchr' */
  472. l1 = l1 - l2; /* `s2' cannot be found after that */
  473. while(l1 > 0 &&
  474. (init = (const char *) memchr(s1, *s2, l1)) != NULL)
  475. {
  476. init++; /* 1st char is already checked */
  477. if(memcmp(init, s2 + 1, l2) == 0)
  478. return init - 1;
  479. else
  480. { /* correct `l1' and `s1' to try again */
  481. l1 -= init - s1;
  482. s1 = init;
  483. }
  484. }
  485. return NULL; /* not found */
  486. }
  487. }
  488. static int
  489. push_captures(lua_State * L,
  490. struct Capture *cap)
  491. {
  492. int i;
  493. luaL_checkstack(L, cap->level, "too many captures");
  494. for(i = 0; i < cap->level; i++)
  495. {
  496. int l = cap->capture[i].len;
  497. if(l == -1)
  498. lua_error(L, "unfinished capture");
  499. lua_pushlstring(L, cap->capture[i].init, l);
  500. }
  501. return cap->level; /* number of strings pushed */
  502. }
  503. static int
  504. str_find(lua_State * L)
  505. {
  506. size_t l1, l2;
  507. const char *s = luaL_check_lstr(L, 1, &l1);
  508. const char *p = luaL_check_lstr(L, 2, &l2);
  509. long init = posrelat(luaL_opt_long(L, 3, 1), l1) - 1;
  510. struct Capture cap;
  511. luaL_arg_check(L, 0 <= init &&
  512. (size_t) init <= l1, 3, "out of range");
  513. if(lua_gettop(L) > 3 || /* extra argument? */
  514. strpbrk(p, SPECIALS) == NULL)
  515. { /* or no special characters? */
  516. const char *s2 = lmemfind(s + init, l1 - init, p, l2);
  517. if(s2)
  518. {
  519. lua_pushnumber(L, s2 - s + 1);
  520. lua_pushnumber(L, s2 - s + l2);
  521. return 2;
  522. }
  523. }
  524. else
  525. {
  526. int anchor = (*p == '^') ? (p++, 1) : 0;
  527. const char *s1 = s + init;
  528. cap.src_end = s + l1;
  529. do
  530. {
  531. const char *res;
  532. cap.level = 0;
  533. if((res = match(L, s1, p, &cap)) != NULL)
  534. {
  535. lua_pushnumber(L, s1 - s + 1); /* start */
  536. lua_pushnumber(L, res - s); /* end */
  537. return push_captures(L, &cap) + 2;
  538. }
  539. } while(s1++ < cap.src_end && !anchor);
  540. }
  541. lua_pushnil(L); /* not found */
  542. return 1;
  543. }
  544. static void
  545. add_s(lua_State * L,
  546. luaL_Buffer * b,
  547. struct Capture *cap)
  548. {
  549. if(lua_isstring(L, 3))
  550. {
  551. const char *news = lua_tostring(L, 3);
  552. size_t l = lua_strlen(L, 3);
  553. size_t i;
  554. for(i = 0; i < l; i++)
  555. {
  556. if(news[i] != ESC)
  557. luaL_putchar(b, news[i]);
  558. else
  559. {
  560. i++; /* skip ESC */
  561. if(!isdigit((unsigned char) news[i]))
  562. luaL_putchar(b, news[i]);
  563. else
  564. {
  565. int level =
  566. check_capture(L, news[i], cap);
  567. luaL_addlstring(b, cap->capture[level].init,
  568. cap->capture[level].len);
  569. }
  570. }
  571. }
  572. }
  573. else
  574. { /* is a function */
  575. int n;
  576. lua_pushvalue(L, 3);
  577. n = push_captures(L, cap);
  578. lua_rawcall(L, n, 1);
  579. if(lua_isstring(L, -1))
  580. luaL_addvalue(b); /* add return to accumulated result */
  581. else
  582. lua_pop(L, 1); /* function result is not a string: pop it */
  583. }
  584. }
  585. static int
  586. str_gsub(lua_State * L)
  587. {
  588. size_t srcl;
  589. const char *src = luaL_check_lstr(L, 1, &srcl);
  590. const char *p = luaL_check_string(L, 2);
  591. int max_s = luaL_opt_int(L, 4, srcl + 1);
  592. int anchor = (*p == '^') ? (p++, 1) : 0;
  593. int n = 0;
  594. struct Capture cap;
  595. luaL_Buffer b;
  596. luaL_arg_check(L,
  597. lua_gettop(L) >= 3 && (lua_isstring(L, 3) ||
  598. lua_isfunction(L, 3)), 3,
  599. "string or function expected");
  600. luaL_buffinit(L, &b);
  601. cap.src_end = src + srcl;
  602. while(n < max_s)
  603. {
  604. const char *e;
  605. cap.level = 0;
  606. e = match(L, src, p, &cap);
  607. if(e)
  608. {
  609. n++;
  610. add_s(L, &b, &cap);
  611. }
  612. if(e && e > src) /* non empty match? */
  613. src = e; /* skip it */
  614. else if(src < cap.src_end)
  615. luaL_putchar(&b, *src++);
  616. else
  617. break;
  618. if(anchor)
  619. break;
  620. }
  621. luaL_addlstring(&b, src, cap.src_end - src);
  622. luaL_pushresult(&b);
  623. lua_pushnumber(L, n); /* number of substitutions */
  624. return 2;
  625. }
  626. /* }====================================================== */
  627. static void
  628. luaI_addquoted(lua_State * L,
  629. luaL_Buffer * b,
  630. int arg)
  631. {
  632. size_t l;
  633. const char *s = luaL_check_lstr(L, arg, &l);
  634. luaL_putchar(b, '"');
  635. while(l--)
  636. {
  637. switch (*s)
  638. {
  639. case '"':
  640. case '\\':
  641. case '\n':
  642. luaL_putchar(b, '\\');
  643. luaL_putchar(b, *s);
  644. break;
  645. case '\0':
  646. luaL_addlstring(b, "\\000", 4);
  647. break;
  648. default:
  649. luaL_putchar(b, *s);
  650. }
  651. s++;
  652. }
  653. luaL_putchar(b, '"');
  654. }
  655. /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
  656. #define MAX_ITEM 512
  657. /* maximum size of each format specification (such as '%-099.99d') */
  658. #define MAX_FORMAT 20
  659. static int
  660. str_format(lua_State * L)
  661. {
  662. int arg = 1;
  663. const char *strfrmt = luaL_check_string(L, arg);
  664. luaL_Buffer b;
  665. luaL_buffinit(L, &b);
  666. while(*strfrmt)
  667. {
  668. if(*strfrmt != '%')
  669. luaL_putchar(&b, *strfrmt++);
  670. else if(*++strfrmt == '%')
  671. luaL_putchar(&b, *strfrmt++); /* %% */
  672. else
  673. { /* format item */
  674. struct Capture cap;
  675. char form[MAX_FORMAT]; /* to store the format ('%...') */
  676. char buff[MAX_ITEM]; /* to store the formatted item */
  677. const char *initf = strfrmt;
  678. form[0] = '%';
  679. if(isdigit((unsigned char) *initf) && *(initf + 1) == '$')
  680. {
  681. arg = *initf - '0';
  682. initf += 2; /* skip the 'n$' */
  683. }
  684. arg++;
  685. cap.src_end = strfrmt + strlen(strfrmt) + 1;
  686. cap.level = 0;
  687. strfrmt = match(L, initf, "[-+ #0]*(%d*)%.?(%d*)", &cap);
  688. if(cap.capture[0].len > 2 || cap.capture[1].len > 2 || /* < 100? */
  689. strfrmt - initf > MAX_FORMAT - 2)
  690. lua_error(L,
  691. "invalid format (width or precision too long)");
  692. strncpy(form + 1, initf, strfrmt - initf + 1); /* +1 to include conversion */
  693. form[strfrmt - initf + 2] = 0;
  694. switch (*strfrmt++)
  695. {
  696. case 'c':
  697. case 'd':
  698. case 'i':
  699. sprintf(buff, form, luaL_check_int(L, arg));
  700. break;
  701. case 'o':
  702. case 'u':
  703. case 'x':
  704. case 'X':
  705. sprintf(buff, form,
  706. (unsigned int) luaL_check_number(L, arg));
  707. break;
  708. case 'e':
  709. case 'E':
  710. case 'f':
  711. case 'g':
  712. case 'G':
  713. sprintf(buff, form, luaL_check_number(L, arg));
  714. break;
  715. case 'q':
  716. luaI_addquoted(L, &b, arg);
  717. continue; /* skip the "addsize" at the end */
  718. case 's':
  719. {
  720. size_t l;
  721. const char *s =
  722. luaL_check_lstr(L, arg, &l);
  723. if(cap.capture[1].len == 0 && l >= 100)
  724. {
  725. /* no precision and string is too long to be formatted;
  726. * keep original string */
  727. lua_pushvalue(L, arg);
  728. luaL_addvalue(&b);
  729. continue; /* skip the "addsize" at the end */
  730. }
  731. else
  732. {
  733. sprintf(buff, form, s);
  734. break;
  735. }
  736. }
  737. default: /* also treat cases 'pnLlh' */
  738. lua_error(L, "invalid option in `format'");
  739. }
  740. luaL_addlstring(&b, buff, strlen(buff));
  741. }
  742. }
  743. luaL_pushresult(&b);
  744. return 1;
  745. }
  746. static const struct luaL_reg strlib[] = {
  747. {"strlen", str_len},
  748. {"strsub", str_sub},
  749. {"strlower", str_lower},
  750. {"strupper", str_upper},
  751. {"strchar", str_char},
  752. {"strrep", str_rep},
  753. {"ascii", str_byte}, /* for compatibility with 3.0 and earlier */
  754. {"strbyte", str_byte},
  755. {"format", str_format},
  756. {"strfind", str_find},
  757. {"gsub", str_gsub}
  758. };
  759. /*
  760. ** Open string library
  761. */
  762. LUALIB_API void
  763. lua_strlibopen(lua_State * L)
  764. {
  765. luaL_openl(L, strlib);
  766. }