PageRenderTime 57ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/Assets/LUA/KopiLua/lstrlib.cs

https://bitbucket.org/rusoaica/judgement-day-map-editor
C# | 989 lines | 943 code | 46 blank | 0 comment | 224 complexity | 599e40604a3eab8fdf0d0dab3e2817f0 MD5 | raw file
  1. using System.IO;
  2. namespace KopiLua
  3. {
  4. using lua_Integer = System.Int32;
  5. using LUA_INTFRM_T = System.Int64;
  6. using ptrdiff_t = System.Int32;
  7. using UNSIGNED_LUA_INTFRM_T = System.UInt64;
  8. public partial class Lua
  9. {
  10. public const int CAP_UNFINISHED = (-1);
  11. public const int CAP_POSITION = (-2);
  12. public const int MAX_ITEM = 512;
  13. public const int MAXCCALLS = 200;
  14. public const string FLAGS = "-+ #0";
  15. public const string SPECIALS = "^$*+?.([%-";
  16. public static readonly int MAX_FORMAT = (FLAGS.Length + 1) + (LUA_INTFRMLEN.Length + 1) + 10;
  17. public const char L_ESC = '%';
  18. private static int StrLen(LuaState _l)
  19. {
  20. uint __l;
  21. LuaLCheckLString(_l, 1, out __l);
  22. LuaPushInteger(_l, (int)__l);
  23. return 1;
  24. }
  25. private static ptrdiff_t PosRelat(ptrdiff_t _pos, uint _len)
  26. {
  27. if (_pos < 0) _pos += (ptrdiff_t)_len + 1;
  28. return (_pos >= 0) ? _pos : 0;
  29. }
  30. private static int StrSub(LuaState _l)
  31. {
  32. uint __l;
  33. CharPtr _s = LuaLCheckLString(_l, 1, out __l);
  34. ptrdiff_t _start = PosRelat(LuaLCheckInteger(_l, 2), __l);
  35. ptrdiff_t _end = PosRelat(LuaLOptInteger(_l, 3, -1), __l);
  36. if (_start < 1) _start = 1;
  37. if (_end > (ptrdiff_t)__l) _end = (ptrdiff_t)__l;
  38. if (_start <= _end)
  39. LuaPushLString(_l, _s + _start - 1, (uint)(_end - _start + 1));
  40. else LuaPushLiteral(_l, "");
  41. return 1;
  42. }
  43. private static int StrReverse(LuaState _l)
  44. {
  45. uint __l;
  46. LuaLBuffer _b = new LuaLBuffer();
  47. CharPtr _s = LuaLCheckLString(_l, 1, out __l);
  48. LuaLBuffInit(_l, _b);
  49. while ((__l--) != 0) LuaLAddChar(_b, _s[__l]);
  50. LuaLPushResult(_b);
  51. return 1;
  52. }
  53. private static int StrLower(LuaState _l)
  54. {
  55. uint __l;
  56. uint _i;
  57. LuaLBuffer _b = new LuaLBuffer();
  58. CharPtr _s = LuaLCheckLString(_l, 1, out __l);
  59. LuaLBuffInit(_l, _b);
  60. for (_i = 0; _i < __l; _i++)
  61. LuaLAddChar(_b, ToLower(_s[_i]));
  62. LuaLPushResult(_b);
  63. return 1;
  64. }
  65. private static int StrUpper(LuaState _l)
  66. {
  67. uint __l;
  68. uint _i;
  69. LuaLBuffer _b = new LuaLBuffer();
  70. CharPtr _s = LuaLCheckLString(_l, 1, out __l);
  71. LuaLBuffInit(_l, _b);
  72. for (_i = 0; _i < __l; _i++)
  73. LuaLAddChar(_b, ToUpper(_s[_i]));
  74. LuaLPushResult(_b);
  75. return 1;
  76. }
  77. private static int StrRep(LuaState _l)
  78. {
  79. uint __l;
  80. LuaLBuffer _b = new LuaLBuffer();
  81. CharPtr _s = LuaLCheckLString(_l, 1, out __l);
  82. int _n = LuaLCheckInt(_l, 2);
  83. LuaLBuffInit(_l, _b);
  84. while (_n-- > 0)
  85. LuaLAddLString(_b, _s, __l);
  86. LuaLPushResult(_b);
  87. return 1;
  88. }
  89. private static int StrByte(LuaState _l)
  90. {
  91. uint __l;
  92. CharPtr s = LuaLCheckLString(_l, 1, out __l);
  93. ptrdiff_t _pos_i = PosRelat(LuaLOptInteger(_l, 2, 1), __l);
  94. ptrdiff_t _pos_e = PosRelat(LuaLOptInteger(_l, 3, _pos_i), __l);
  95. int _n, _i;
  96. if (_pos_i <= 0) _pos_i = 1;
  97. if ((uint)_pos_e > __l) _pos_e = (int)__l;
  98. if (_pos_i > _pos_e) return 0;
  99. _n = _pos_e - _pos_i + 1;
  100. if (_pos_i + _n <= _pos_e)
  101. LuaLError(_l, "string slice too long");
  102. LuaLCheckStack(_l, _n, "string slice too long");
  103. for (_i = 0; _i < _n; _i++)
  104. LuaPushInteger(_l, (byte)(s[_pos_i + _i - 1]));
  105. return _n;
  106. }
  107. private static int StrChar(LuaState _l)
  108. {
  109. int _n = LuaGetTop(_l);
  110. int _i;
  111. LuaLBuffer _b = new LuaLBuffer();
  112. LuaLBuffInit(_l, _b);
  113. for (_i = 1; _i <= _n; _i++)
  114. {
  115. int _c = LuaLCheckInt(_l, _i);
  116. LuaLArgCheck(_l, (byte)(_c) == _c, _i, "invalid value");
  117. LuaLAddChar(_b, (char)(byte)_c);
  118. }
  119. LuaLPushResult(_b);
  120. return 1;
  121. }
  122. private static int Writer(LuaState _l, object _b, uint _size, object __b)
  123. {
  124. if (_b.GetType() != typeof(CharPtr))
  125. {
  126. using (MemoryStream _stream = new MemoryStream())
  127. {
  128. }
  129. }
  130. LuaLAddLString((LuaLBuffer)__b, (CharPtr)_b, _size);
  131. return 0;
  132. }
  133. private static int StrDump(LuaState _l)
  134. {
  135. LuaLBuffer _b = new LuaLBuffer();
  136. LuaLCheckType(_l, 1, LUA_TFUNCTION);
  137. LuaSetTop(_l, 1);
  138. LuaLBuffInit(_l, _b);
  139. if (LuaDump(_l, Writer, _b) != 0)
  140. LuaLError(_l, "unable to dump given function");
  141. LuaLPushResult(_b);
  142. return 1;
  143. }
  144. public class MatchState
  145. {
  146. public int matchDepth;
  147. public CharPtr srcInit;
  148. public CharPtr srcEnd;
  149. public LuaState l;
  150. public int level;
  151. public MatchState()
  152. {
  153. for (int i = 0; i < LUA_MAXCAPTURES; i++)
  154. Capture[i] = new capture_();
  155. }
  156. public class capture_
  157. {
  158. public CharPtr init;
  159. public ptrdiff_t len;
  160. };
  161. public capture_[] Capture = new capture_[LUA_MAXCAPTURES];
  162. };
  163. private static int CheckCapture(MatchState _ms, int _l)
  164. {
  165. _l -= '1';
  166. if (_l < 0 || _l >= _ms.level || _ms.Capture[_l].len == CAP_UNFINISHED)
  167. return LuaLError(_ms.l, "invalid capture index %%%d", _l + 1);
  168. return _l;
  169. }
  170. private static int CaptureToClose(MatchState _ms)
  171. {
  172. int _level = _ms.level;
  173. for (_level--; _level >= 0; _level--)
  174. if (_ms.Capture[_level].len == CAP_UNFINISHED) return _level;
  175. return LuaLError(_ms.l, "invalid pattern capture");
  176. }
  177. private static CharPtr ClassEnd(MatchState _ms, CharPtr _p)
  178. {
  179. _p = new CharPtr(_p);
  180. char _c = _p[0];
  181. _p = _p.next();
  182. switch (_c)
  183. {
  184. case L_ESC:
  185. {
  186. if (_p[0] == '\0')
  187. LuaLError(_ms.l, "malformed pattern (ends with " + LUA_QL("%%") + ")");
  188. return _p + 1;
  189. }
  190. case '[':
  191. {
  192. if (_p[0] == '^') _p = _p.next();
  193. do
  194. {
  195. if (_p[0] == '\0')
  196. LuaLError(_ms.l, "malformed pattern (missing " + LUA_QL("]") + ")");
  197. _c = _p[0];
  198. _p = _p.next();
  199. if (_c == L_ESC && _p[0] != '\0')
  200. _p = _p.next();
  201. } while (_p[0] != ']');
  202. return _p + 1;
  203. }
  204. default:
  205. {
  206. return _p;
  207. }
  208. }
  209. }
  210. private static int MatchClass(int _c, int _cl)
  211. {
  212. bool _res;
  213. switch (ToLower(_cl))
  214. {
  215. case 'a': _res = IsAlpha(_c); break;
  216. case 'c': _res = IsCntrl(_c); break;
  217. case 'd': _res = IsDigit(_c); break;
  218. case 'l': _res = IsLower(_c); break;
  219. case 'p': _res = IsPunct(_c); break;
  220. case 's': _res = IsSpace(_c); break;
  221. case 'u': _res = IsUpper(_c); break;
  222. case 'w': _res = IsAlnum(_c); break;
  223. case 'x': _res = IsXDigit((char)_c); break;
  224. case 'z': _res = (_c == 0); break;
  225. default: return (_cl == _c) ? 1 : 0;
  226. }
  227. return (IsLower(_cl) ? (_res ? 1 : 0) : ((!_res) ? 1 : 0));
  228. }
  229. private static int MatchBracketClass(int _c, CharPtr _p, CharPtr _ec)
  230. {
  231. int _sig = 1;
  232. if (_p[1] == '^')
  233. {
  234. _sig = 0;
  235. _p = _p.next();
  236. }
  237. while ((_p = _p.next()) < _ec)
  238. {
  239. if (_p == L_ESC)
  240. {
  241. _p = _p.next();
  242. if (MatchClass(_c, (byte)(_p[0])) != 0)
  243. return _sig;
  244. }
  245. else if ((_p[1] == '-') && (_p + 2 < _ec))
  246. {
  247. _p += 2;
  248. if ((byte)((_p[-2])) <= _c && (_c <= (byte)_p[0]))
  249. return _sig;
  250. }
  251. else if ((byte)(_p[0]) == _c) return _sig;
  252. }
  253. return (_sig == 0) ? 1 : 0;
  254. }
  255. private static int SingleMatch(int _c, CharPtr _p, CharPtr _ep)
  256. {
  257. switch (_p[0])
  258. {
  259. case '.': return 1;
  260. case L_ESC: return MatchClass(_c, (byte)(_p[1]));
  261. case '[': return MatchBracketClass(_c, _p, _ep - 1);
  262. default: return ((byte)(_p[0]) == _c) ? 1 : 0;
  263. }
  264. }
  265. private static CharPtr MatchBalance(MatchState _ms, CharPtr _s, CharPtr _p)
  266. {
  267. if ((_p[0] == 0) || (_p[1] == 0))
  268. LuaLError(_ms.l, "unbalanced pattern");
  269. if (_s[0] != _p[0]) return null;
  270. else
  271. {
  272. int _b = _p[0];
  273. int _e = _p[1];
  274. int _cont = 1;
  275. while ((_s = _s.next()) < _ms.srcEnd)
  276. {
  277. if (_s[0] == _e)
  278. {
  279. if (--_cont == 0) return _s + 1;
  280. }
  281. else if (_s[0] == _b) _cont++;
  282. }
  283. }
  284. return null;
  285. }
  286. private static CharPtr MaxExpand(MatchState _ms, CharPtr _s, CharPtr _p, CharPtr _ep)
  287. {
  288. ptrdiff_t _i = 0;
  289. while ((_s + _i < _ms.srcEnd) && (SingleMatch((byte)(_s[_i]), _p, _ep) != 0))
  290. _i++;
  291. while (_i >= 0)
  292. {
  293. CharPtr _res = Match(_ms, (_s + _i), _ep + 1);
  294. if (_res != null) return _res;
  295. _i--;
  296. }
  297. return null;
  298. }
  299. private static CharPtr MinExpand(MatchState _ms, CharPtr _s, CharPtr _p, CharPtr _ep)
  300. {
  301. for (; ; )
  302. {
  303. CharPtr _res = Match(_ms, _s, _ep + 1);
  304. if (_res != null)
  305. return _res;
  306. else if ((_s < _ms.srcEnd) && (SingleMatch((byte)(_s[0]), _p, _ep) != 0))
  307. _s = _s.next();
  308. else return null;
  309. }
  310. }
  311. private static CharPtr StartCapture(MatchState _ms, CharPtr _s, CharPtr _p, int _what)
  312. {
  313. CharPtr _res;
  314. int _level = _ms.level;
  315. if (_level >= LUA_MAXCAPTURES) LuaLError(_ms.l, "too many captures");
  316. _ms.Capture[_level].init = _s;
  317. _ms.Capture[_level].len = _what;
  318. _ms.level = _level + 1;
  319. if ((_res = Match(_ms, _s, _p)) == null)
  320. _ms.level--;
  321. return _res;
  322. }
  323. private static CharPtr EndCapture(MatchState _ms, CharPtr _s, CharPtr _p)
  324. {
  325. int _l = CaptureToClose(_ms);
  326. CharPtr _res;
  327. _ms.Capture[_l].len = _s - _ms.Capture[_l].init;
  328. if ((_res = Match(_ms, _s, _p)) == null)
  329. _ms.Capture[_l].len = CAP_UNFINISHED;
  330. return _res;
  331. }
  332. private static CharPtr MatchCapture(MatchState _ms, CharPtr _s, int _l)
  333. {
  334. uint _len;
  335. _l = CheckCapture(_ms, _l);
  336. _len = (uint)_ms.Capture[_l].len;
  337. if ((uint)(_ms.srcEnd - _s) >= _len &&
  338. MemCmp(_ms.Capture[_l].init, _s, _len) == 0)
  339. return _s + _len;
  340. else return null;
  341. }
  342. private static CharPtr Match(MatchState _ms, CharPtr _s, CharPtr _p)
  343. {
  344. _s = new CharPtr(_s);
  345. _p = new CharPtr(_p);
  346. if (_ms.matchDepth-- == 0)
  347. LuaLError(_ms.l, "pattern too complex");
  348. init:
  349. switch (_p[0])
  350. {
  351. case '(':
  352. {
  353. if (_p[1] == ')')
  354. return StartCapture(_ms, _s, _p + 2, CAP_POSITION);
  355. else
  356. return StartCapture(_ms, _s, _p + 1, CAP_UNFINISHED);
  357. }
  358. case ')':
  359. {
  360. return EndCapture(_ms, _s, _p + 1);
  361. }
  362. case L_ESC:
  363. {
  364. switch (_p[1])
  365. {
  366. case 'b':
  367. {
  368. _s = MatchBalance(_ms, _s, _p + 2);
  369. if (_s == null) return null;
  370. _p += 4; goto init;
  371. }
  372. case 'f':
  373. {
  374. CharPtr _ep; char previous;
  375. _p += 2;
  376. if (_p[0] != '[')
  377. LuaLError(_ms.l, "missing " + LUA_QL("[") + " after " +
  378. LUA_QL("%%f") + " in pattern");
  379. _ep = ClassEnd(_ms, _p);
  380. previous = (_s == _ms.srcInit) ? '\0' : _s[-1];
  381. if ((MatchBracketClass((byte)(previous), _p, _ep - 1) != 0) ||
  382. (MatchBracketClass((byte)(_s[0]), _p, _ep - 1) == 0)) return null;
  383. _p = _ep; goto init;
  384. }
  385. default:
  386. {
  387. if (IsDigit((byte)(_p[1])))
  388. {
  389. _s = MatchCapture(_ms, _s, (byte)(_p[1]));
  390. if (_s == null) return null;
  391. _p += 2; goto init;
  392. }
  393. {
  394. CharPtr _ep = ClassEnd(_ms, _p);
  395. int _m = (_s < _ms.srcEnd) && (SingleMatch((byte)(_s[0]), _p, _ep) != 0) ? 1 : 0;
  396. switch (_ep[0])
  397. {
  398. case '?':
  399. {
  400. CharPtr _res;
  401. if ((_m != 0) && ((_res = Match(_ms, _s + 1, _ep + 1)) != null))
  402. return _res;
  403. _p = _ep + 1; goto init;
  404. }
  405. case '*':
  406. {
  407. return MaxExpand(_ms, _s, _p, _ep);
  408. }
  409. case '+':
  410. {
  411. return ((_m != 0) ? MaxExpand(_ms, _s + 1, _p, _ep) : null);
  412. }
  413. case '-':
  414. {
  415. return MinExpand(_ms, _s, _p, _ep);
  416. }
  417. default:
  418. {
  419. if (_m == 0) return null;
  420. _s = _s.next(); _p = _ep; goto init;
  421. }
  422. }
  423. }
  424. }
  425. }
  426. }
  427. case '\0':
  428. {
  429. return _s;
  430. }
  431. case '$':
  432. {
  433. if (_p[1] == '\0')
  434. return (_s == _ms.srcEnd) ? _s : null;
  435. else goto dflt;
  436. }
  437. default:
  438. dflt:
  439. {
  440. CharPtr _ep = ClassEnd(_ms, _p);
  441. int _m = (_s < _ms.srcEnd) && (SingleMatch((byte)(_s[0]), _p, _ep) != 0) ? 1 : 0;
  442. switch (_ep[0])
  443. {
  444. case '?':
  445. {
  446. CharPtr _res;
  447. if ((_m != 0) && ((_res = Match(_ms, _s + 1, _ep + 1)) != null))
  448. return _res;
  449. _p = _ep + 1; goto init;
  450. }
  451. case '*':
  452. {
  453. return MaxExpand(_ms, _s, _p, _ep);
  454. }
  455. case '+':
  456. {
  457. return ((_m != 0) ? MaxExpand(_ms, _s + 1, _p, _ep) : null);
  458. }
  459. case '-':
  460. {
  461. return MinExpand(_ms, _s, _p, _ep);
  462. }
  463. default:
  464. {
  465. if (_m == 0) return null;
  466. _s = _s.next(); _p = _ep; goto init;
  467. }
  468. }
  469. }
  470. }
  471. }
  472. private static CharPtr LMemFind(CharPtr _s_1, uint _l_1, CharPtr _s_2, uint _l_2)
  473. {
  474. if (_l_2 == 0) return _s_1;
  475. else if (_l_2 > _l_1) return null;
  476. else
  477. {
  478. CharPtr _init;
  479. _l_2--;
  480. _l_1 = _l_1 - _l_2;
  481. while (_l_1 > 0 && (_init = MemChr(_s_1, _s_2[0], _l_1)) != null)
  482. {
  483. _init = _init.next();
  484. if (MemCmp(_init, _s_2 + 1, _l_2) == 0)
  485. return _init - 1;
  486. else
  487. {
  488. _l_1 -= (uint)(_init - _s_1);
  489. _s_1 = _init;
  490. }
  491. }
  492. return null;
  493. }
  494. }
  495. private static void PushOneCapture(MatchState _ms, int _i, CharPtr _s, CharPtr _e)
  496. {
  497. if (_i >= _ms.level)
  498. {
  499. if (_i == 0)
  500. LuaPushLString(_ms.l, _s, (uint)(_e - _s));
  501. else
  502. LuaLError(_ms.l, "invalid capture index");
  503. }
  504. else
  505. {
  506. ptrdiff_t _l = _ms.Capture[_i].len;
  507. if (_l == CAP_UNFINISHED) LuaLError(_ms.l, "unfinished capture");
  508. if (_l == CAP_POSITION)
  509. LuaPushInteger(_ms.l, _ms.Capture[_i].init - _ms.srcInit + 1);
  510. else
  511. LuaPushLString(_ms.l, _ms.Capture[_i].init, (uint)_l);
  512. }
  513. }
  514. private static int PushCaptures(MatchState _ms, CharPtr _s, CharPtr _e)
  515. {
  516. int _i;
  517. int _n_levels = ((_ms.level == 0) && (_s != null)) ? 1 : _ms.level;
  518. LuaLCheckStack(_ms.l, _n_levels, "too many captures");
  519. for (_i = 0; _i < _n_levels; _i++)
  520. PushOneCapture(_ms, _i, _s, _e);
  521. return _n_levels;
  522. }
  523. private static int StrFindAux(LuaState _l, int _find)
  524. {
  525. uint _l_1, _l_2;
  526. CharPtr _s = LuaLCheckLString(_l, 1, out _l_1);
  527. CharPtr _p = LuaLCheckLString(_l, 2, out _l_2);
  528. ptrdiff_t _init = PosRelat(LuaLOptInteger(_l, 3, 1), _l_1) - 1;
  529. if (_init < 0) _init = 0;
  530. else if ((uint)(_init) > _l_1) _init = (ptrdiff_t)_l_1;
  531. if ((_find != 0) && ((LuaToBoolean(_l, 4) != 0) || StrPbrk(_p, SPECIALS) == null))
  532. {
  533. CharPtr _s_2 = LMemFind(_s + _init, (uint)(_l_1 - _init), _p, (uint)(_l_2));
  534. if (_s_2 != null)
  535. {
  536. LuaPushInteger(_l, _s_2 - _s + 1);
  537. LuaPushInteger(_l, (int)(_s_2 - _s + _l_2));
  538. return 2;
  539. }
  540. }
  541. else
  542. {
  543. MatchState _ms = new MatchState();
  544. int _anchor = 0;
  545. if (_p[0] == '^')
  546. {
  547. _p = _p.next();
  548. _anchor = 1;
  549. }
  550. CharPtr _s_1 = _s + _init;
  551. _ms.l = _l;
  552. _ms.matchDepth = MAXCCALLS;
  553. _ms.srcInit = _s;
  554. _ms.srcEnd = _s + _l_1;
  555. do
  556. {
  557. CharPtr _res;
  558. _ms.level = 0;
  559. LuaAssert(_ms.matchDepth == MAXCCALLS);
  560. if ((_res = Match(_ms, _s_1, _p)) != null)
  561. {
  562. if (_find != 0)
  563. {
  564. LuaPushInteger(_l, _s_1 - _s + 1);
  565. LuaPushInteger(_l, _res - _s);
  566. return PushCaptures(_ms, null, null) + 2;
  567. }
  568. else
  569. return PushCaptures(_ms, _s_1, _res);
  570. }
  571. } while (((_s_1 = _s_1.next()) <= _ms.srcEnd) && (_anchor == 0));
  572. }
  573. LuaPushNil(_l);
  574. return 1;
  575. }
  576. private static int StrFind(LuaState _l)
  577. {
  578. return StrFindAux(_l, 1);
  579. }
  580. private static int StrMatch(LuaState _l)
  581. {
  582. return StrFindAux(_l, 0);
  583. }
  584. private static int GMatchAux(LuaState _l)
  585. {
  586. MatchState _ms = new MatchState();
  587. uint _ls;
  588. CharPtr _s = LuaToLString(_l, LuaUpValueIndex(1), out _ls);
  589. CharPtr _p = LuaToString(_l, LuaUpValueIndex(2));
  590. CharPtr _src;
  591. _ms.l = _l;
  592. _ms.matchDepth = MAXCCALLS;
  593. _ms.srcInit = _s;
  594. _ms.srcEnd = _s + _ls;
  595. for (_src = _s + (uint)LuaToInteger(_l, LuaUpValueIndex(3));
  596. _src <= _ms.srcEnd;
  597. _src = _src.next())
  598. {
  599. CharPtr _e;
  600. _ms.level = 0;
  601. LuaAssert(_ms.matchDepth == MAXCCALLS);
  602. if ((_e = Match(_ms, _src, _p)) != null)
  603. {
  604. lua_Integer _new_start = _e - _s;
  605. if (_e == _src) _new_start++;
  606. LuaPushInteger(_l, _new_start);
  607. LuaReplace(_l, LuaUpValueIndex(3));
  608. return PushCaptures(_ms, _src, _e);
  609. }
  610. }
  611. return 0;
  612. }
  613. private static int GMatch(LuaState _l)
  614. {
  615. LuaLCheckString(_l, 1);
  616. LuaLCheckString(_l, 2);
  617. LuaSetTop(_l, 2);
  618. LuaPushInteger(_l, 0);
  619. LuaPushCClosure(_l, GMatchAux, 3);
  620. return 1;
  621. }
  622. private static int GFindNodeF(LuaState _l)
  623. {
  624. return LuaLError(_l, LUA_QL("string.gfind") + " was renamed to " + LUA_QL("string.gmatch"));
  625. }
  626. private static void AddS(MatchState _ms, LuaLBuffer _b, CharPtr _s, CharPtr _e)
  627. {
  628. uint _l, _i;
  629. CharPtr _news = LuaToLString(_ms.l, 3, out _l);
  630. for (_i = 0; _i < _l; _i++)
  631. {
  632. if (_news[_i] != L_ESC)
  633. LuaLAddChar(_b, _news[_i]);
  634. else
  635. {
  636. _i++;
  637. if (!IsDigit((byte)(_news[_i])))
  638. LuaLAddChar(_b, _news[_i]);
  639. else if (_news[_i] == '0')
  640. LuaLAddLString(_b, _s, (uint)(_e - _s));
  641. else
  642. {
  643. PushOneCapture(_ms, _news[_i] - '1', _s, _e);
  644. LuaLAddValue(_b);
  645. }
  646. }
  647. }
  648. }
  649. private static void AddValue(MatchState _ms, LuaLBuffer _b, CharPtr _s, CharPtr _e)
  650. {
  651. LuaState _l = _ms.l;
  652. switch (LuaType(_l, 3))
  653. {
  654. case LUA_TNUMBER:
  655. case LUA_TSTRING:
  656. {
  657. AddS(_ms, _b, _s, _e);
  658. return;
  659. }
  660. case LUA_TUSERDATA:
  661. case LUA_TFUNCTION:
  662. {
  663. int n;
  664. LuaPushValue(_l, 3);
  665. n = PushCaptures(_ms, _s, _e);
  666. LuaCall(_l, n, 1);
  667. break;
  668. }
  669. case LUA_TTABLE:
  670. {
  671. PushOneCapture(_ms, 0, _s, _e);
  672. LuaGetTable(_l, 3);
  673. break;
  674. }
  675. }
  676. if (LuaToBoolean(_l, -1) == 0)
  677. {
  678. LuaPop(_l, 1);
  679. LuaPushLString(_l, _s, (uint)(_e - _s));
  680. }
  681. else if (LuaIsString(_l, -1) == 0)
  682. LuaLError(_l, "invalid replacement value (a %s)", LuaLTypeName(_l, -1));
  683. LuaLAddValue(_b);
  684. }
  685. private static int StrGSub(LuaState _l)
  686. {
  687. uint _src_l;
  688. CharPtr _src = LuaLCheckLString(_l, 1, out _src_l);
  689. CharPtr _p = LuaLCheckString(_l, 2);
  690. int _tr = LuaType(_l, 3);
  691. int _max_s = LuaLOptInt(_l, 4, (int)(_src_l + 1));
  692. int _anchor = 0;
  693. if (_p[0] == '^')
  694. {
  695. _p = _p.next();
  696. _anchor = 1;
  697. }
  698. int _n = 0;
  699. MatchState _ms = new MatchState();
  700. LuaLBuffer _b = new LuaLBuffer();
  701. LuaLArgCheck(_l, _tr == LUA_TNUMBER || _tr == LUA_TSTRING || _tr == LUA_TFUNCTION || _tr == LUA_TTABLE || _tr == LUA_TUSERDATA, 3, "string/function/table expected");
  702. LuaLBuffInit(_l, _b);
  703. _ms.l = _l;
  704. _ms.matchDepth = MAXCCALLS;
  705. _ms.srcInit = _src;
  706. _ms.srcEnd = _src + _src_l;
  707. while (_n < _max_s)
  708. {
  709. CharPtr _e;
  710. _ms.level = 0;
  711. LuaAssert(_ms.matchDepth == MAXCCALLS);
  712. _e = Match(_ms, _src, _p);
  713. if (_e != null)
  714. {
  715. _n++;
  716. AddValue(_ms, _b, _src, _e);
  717. }
  718. if ((_e != null) && _e > _src)
  719. _src = _e;
  720. else if (_src < _ms.srcEnd)
  721. {
  722. char _c = _src[0];
  723. _src = _src.next();
  724. LuaLAddChar(_b, _c);
  725. }
  726. else break;
  727. if (_anchor != 0) break;
  728. }
  729. LuaLAddLString(_b, _src, (uint)(_ms.srcEnd - _src));
  730. LuaLPushResult(_b);
  731. LuaPushInteger(_l, _n);
  732. return 2;
  733. }
  734. private static void AddQuoted(LuaState _l, LuaLBuffer _b, int _arg)
  735. {
  736. uint __l;
  737. CharPtr _s = LuaLCheckLString(_l, _arg, out __l);
  738. LuaLAddChar(_b, '"');
  739. while ((__l--) != 0)
  740. {
  741. switch (_s[0])
  742. {
  743. case '"':
  744. case '\\':
  745. case '\n':
  746. {
  747. LuaLAddChar(_b, '\\');
  748. LuaLAddChar(_b, _s[0]);
  749. break;
  750. }
  751. case '\r':
  752. {
  753. LuaLAddLString(_b, "\\r", 2);
  754. break;
  755. }
  756. case '\0':
  757. {
  758. LuaLAddLString(_b, "\\000", 4);
  759. break;
  760. }
  761. default:
  762. {
  763. LuaLAddChar(_b, _s[0]);
  764. break;
  765. }
  766. }
  767. _s = _s.next();
  768. }
  769. LuaLAddChar(_b, '"');
  770. }
  771. private static CharPtr ScanFormat(LuaState _l, CharPtr _str_format, CharPtr _form)
  772. {
  773. CharPtr _p = _str_format;
  774. while (_p[0] != '\0' && StrChr(FLAGS, _p[0]) != null) _p = _p.next();
  775. if ((uint)(_p - _str_format) >= (FLAGS.Length + 1))
  776. LuaLError(_l, "invalid format (repeated flags)");
  777. if (IsDigit((byte)(_p[0]))) _p = _p.next();
  778. if (IsDigit((byte)(_p[0]))) _p = _p.next();
  779. if (_p[0] == '.')
  780. {
  781. _p = _p.next();
  782. if (IsDigit((byte)(_p[0]))) _p = _p.next();
  783. if (IsDigit((byte)(_p[0]))) _p = _p.next();
  784. }
  785. if (IsDigit((byte)(_p[0])))
  786. LuaLError(_l, "invalid format (width or precision too long)");
  787. _form[0] = '%';
  788. _form = _form.next();
  789. StrNCpy(_form, _str_format, _p - _str_format + 1);
  790. _form += _p - _str_format + 1;
  791. _form[0] = '\0';
  792. return _p;
  793. }
  794. private static void AddIntLen(CharPtr _form)
  795. {
  796. uint _l = (uint)StrLen(_form);
  797. char _spec = _form[_l - 1];
  798. StrCpy(_form + _l - 1, LUA_INTFRMLEN);
  799. _form[_l + (LUA_INTFRMLEN.Length + 1) - 2] = _spec;
  800. _form[_l + (LUA_INTFRMLEN.Length + 1) - 1] = '\0';
  801. }
  802. private static int StrFormat(LuaState _l)
  803. {
  804. int _top = LuaGetTop(_l);
  805. int _arg = 1;
  806. uint _sfl;
  807. CharPtr _str_format = LuaLCheckLString(_l, _arg, out _sfl);
  808. CharPtr _str_format_end = _str_format + _sfl;
  809. LuaLBuffer _b = new LuaLBuffer();
  810. LuaLBuffInit(_l, _b);
  811. while (_str_format < _str_format_end)
  812. {
  813. if (_str_format[0] != L_ESC)
  814. {
  815. LuaLAddChar(_b, _str_format[0]);
  816. _str_format = _str_format.next();
  817. }
  818. else if (_str_format[1] == L_ESC)
  819. {
  820. LuaLAddChar(_b, _str_format[0]);
  821. _str_format = _str_format + 2;
  822. }
  823. else
  824. {
  825. _str_format = _str_format.next();
  826. CharPtr _form = new char[MAX_FORMAT];
  827. CharPtr _buff = new char[MAX_ITEM];
  828. if (++_arg > _top)
  829. LuaLArgError(_l, _arg, "no value");
  830. _str_format = ScanFormat(_l, _str_format, _form);
  831. char _ch = _str_format[0];
  832. _str_format = _str_format.next();
  833. switch (_ch)
  834. {
  835. case 'c':
  836. {
  837. SPrintF(_buff, _form, (int)LuaLCheckNumber(_l, _arg));
  838. break;
  839. }
  840. case 'd':
  841. case 'i':
  842. {
  843. AddIntLen(_form);
  844. SPrintF(_buff, _form, (LUA_INTFRM_T)LuaLCheckNumber(_l, _arg));
  845. break;
  846. }
  847. case 'o':
  848. case 'u':
  849. case 'x':
  850. case 'X':
  851. {
  852. AddIntLen(_form);
  853. SPrintF(_buff, _form, (UNSIGNED_LUA_INTFRM_T)LuaLCheckNumber(_l, _arg));
  854. break;
  855. }
  856. case 'e':
  857. case 'E':
  858. case 'f':
  859. case 'g':
  860. case 'G':
  861. {
  862. SPrintF(_buff, _form, (double)LuaLCheckNumber(_l, _arg));
  863. break;
  864. }
  865. case 'q':
  866. {
  867. AddQuoted(_l, _b, _arg);
  868. continue;
  869. }
  870. case 's':
  871. {
  872. uint __l;
  873. CharPtr _s = LuaLCheckLString(_l, _arg, out __l);
  874. if ((StrChr(_form, '.') == null) && __l >= 100)
  875. {
  876. LuaPushValue(_l, _arg);
  877. LuaLAddValue(_b);
  878. continue;
  879. }
  880. else
  881. {
  882. SPrintF(_buff, _form, _s);
  883. break;
  884. }
  885. }
  886. default:
  887. {
  888. return LuaLError(_l, "invalid option " + LUA_QL("%%%c") + " to " + LUA_QL("format"), _str_format[-1]);
  889. }
  890. }
  891. LuaLAddLString(_b, _buff, (uint)StrLen(_buff));
  892. }
  893. }
  894. LuaLPushResult(_b);
  895. return 1;
  896. }
  897. private readonly static LuaLReg[] strlib = {
  898. new LuaLReg("byte", StrByte),
  899. new LuaLReg("char", StrChar),
  900. new LuaLReg("dump", StrDump),
  901. new LuaLReg("find", StrFind),
  902. new LuaLReg("format", StrFormat),
  903. new LuaLReg("gfind", GFindNodeF),
  904. new LuaLReg("gmatch", GMatch),
  905. new LuaLReg("gsub", StrGSub),
  906. new LuaLReg("len", StrLen),
  907. new LuaLReg("lower", StrLower),
  908. new LuaLReg("match", StrMatch),
  909. new LuaLReg("rep", StrRep),
  910. new LuaLReg("reverse", StrReverse),
  911. new LuaLReg("sub", StrSub),
  912. new LuaLReg("upper", StrUpper),
  913. new LuaLReg(null, null)
  914. };
  915. private static void CreateMetaTable(LuaState _l)
  916. {
  917. LuaCreateTable(_l, 0, 1);
  918. LuaPushLiteral(_l, "");
  919. LuaPushValue(_l, -2);
  920. LuaSetMetatable(_l, -2);
  921. LuaPop(_l, 1);
  922. LuaPushValue(_l, -2);
  923. LuaSetField(_l, -2, "__index");
  924. LuaPop(_l, 1);
  925. }
  926. public static int LuaOpenString(LuaState _l)
  927. {
  928. LuaLRegister(_l, LUA_STRLIBNAME, strlib);
  929. #if LUA_COMPAT_GFIND
  930. lua_getfield(_l, -1, "gmatch");
  931. lua_setfield(_l, -2, "gfind");
  932. #endif
  933. CreateMetaTable(_l);
  934. return 1;
  935. }
  936. }
  937. }