Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/VM/src/lstrlib.cpp
2725 views
1
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
2
// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details
3
#include "lualib.h"
4
5
#include "lstring.h"
6
7
#include <ctype.h>
8
#include <string.h>
9
#include <stdio.h>
10
11
// macro to `unsign' a character
12
#define uchar(c) ((unsigned char)(c))
13
14
static int str_len(lua_State* L)
15
{
16
size_t l;
17
luaL_checklstring(L, 1, &l);
18
lua_pushinteger(L, (int)l);
19
return 1;
20
}
21
22
static int posrelat(int pos, size_t len)
23
{
24
// relative string position: negative means back from end
25
if (pos < 0)
26
pos += (int)len + 1;
27
return (pos >= 0) ? pos : 0;
28
}
29
30
static int str_sub(lua_State* L)
31
{
32
size_t l;
33
const char* s = luaL_checklstring(L, 1, &l);
34
int start = posrelat(luaL_checkinteger(L, 2), l);
35
int end = posrelat(luaL_optinteger(L, 3, -1), l);
36
if (start < 1)
37
start = 1;
38
if (end > (int)l)
39
end = (int)l;
40
if (start <= end)
41
lua_pushlstring(L, s + start - 1, end - start + 1);
42
else
43
lua_pushliteral(L, "");
44
return 1;
45
}
46
47
static int str_reverse(lua_State* L)
48
{
49
size_t l;
50
const char* s = luaL_checklstring(L, 1, &l);
51
luaL_Strbuf b;
52
char* ptr = luaL_buffinitsize(L, &b, l);
53
while (l--)
54
*ptr++ = s[l];
55
luaL_pushresultsize(&b, ptr - b.p);
56
return 1;
57
}
58
59
static int str_lower(lua_State* L)
60
{
61
size_t l;
62
const char* s = luaL_checklstring(L, 1, &l);
63
luaL_Strbuf b;
64
char* ptr = luaL_buffinitsize(L, &b, l);
65
for (size_t i = 0; i < l; i++)
66
*ptr++ = tolower(uchar(s[i]));
67
luaL_pushresultsize(&b, l);
68
return 1;
69
}
70
71
static int str_upper(lua_State* L)
72
{
73
size_t l;
74
const char* s = luaL_checklstring(L, 1, &l);
75
luaL_Strbuf b;
76
char* ptr = luaL_buffinitsize(L, &b, l);
77
for (size_t i = 0; i < l; i++)
78
*ptr++ = toupper(uchar(s[i]));
79
luaL_pushresultsize(&b, l);
80
return 1;
81
}
82
83
static int str_rep(lua_State* L)
84
{
85
size_t l;
86
const char* s = luaL_checklstring(L, 1, &l);
87
int n = luaL_checkinteger(L, 2);
88
89
if (n <= 0)
90
{
91
lua_pushliteral(L, "");
92
return 1;
93
}
94
95
if (l > MAXSSIZE / (size_t)n) // may overflow?
96
luaL_error(L, "resulting string too large");
97
98
luaL_Strbuf b;
99
char* ptr = luaL_buffinitsize(L, &b, l * n);
100
101
const char* start = ptr;
102
103
size_t left = l * n;
104
size_t step = l;
105
106
memcpy(ptr, s, l);
107
ptr += l;
108
left -= l;
109
110
// use the increasing 'pattern' inside our target buffer to fill the next part
111
while (step < left)
112
{
113
memcpy(ptr, start, step);
114
ptr += step;
115
left -= step;
116
step <<= 1;
117
}
118
119
// fill tail
120
memcpy(ptr, start, left);
121
ptr += left;
122
123
luaL_pushresultsize(&b, l * n);
124
125
return 1;
126
}
127
128
static int str_byte(lua_State* L)
129
{
130
size_t l;
131
const char* s = luaL_checklstring(L, 1, &l);
132
int posi = posrelat(luaL_optinteger(L, 2, 1), l);
133
int pose = posrelat(luaL_optinteger(L, 3, posi), l);
134
int n, i;
135
if (posi <= 0)
136
posi = 1;
137
if ((size_t)pose > l)
138
pose = (int)l;
139
if (posi > pose)
140
return 0; // empty interval; return no values
141
n = (int)(pose - posi + 1);
142
if (posi + n <= pose) // overflow?
143
luaL_error(L, "string slice too long");
144
luaL_checkstack(L, n, "string slice too long");
145
for (i = 0; i < n; i++)
146
lua_pushinteger(L, uchar(s[posi + i - 1]));
147
return n;
148
}
149
150
static int str_char(lua_State* L)
151
{
152
int n = lua_gettop(L); // number of arguments
153
154
luaL_Strbuf b;
155
char* ptr = luaL_buffinitsize(L, &b, n);
156
157
for (int i = 1; i <= n; i++)
158
{
159
int c = luaL_checkinteger(L, i);
160
luaL_argcheck(L, uchar(c) == c, i, "invalid value");
161
162
*ptr++ = uchar(c);
163
}
164
luaL_pushresultsize(&b, n);
165
return 1;
166
}
167
168
/*
169
** {======================================================
170
** PATTERN MATCHING
171
** =======================================================
172
*/
173
174
#define CAP_UNFINISHED (-1)
175
#define CAP_POSITION (-2)
176
177
typedef struct MatchState
178
{
179
int matchdepth; // control for recursive depth (to avoid C stack overflow)
180
const char* src_init; // init of source string
181
const char* src_end; // end ('\0') of source string
182
const char* p_end; // end ('\0') of pattern
183
lua_State* L;
184
int level; // total number of captures (finished or unfinished)
185
struct
186
{
187
const char* init;
188
ptrdiff_t len;
189
} capture[LUA_MAXCAPTURES];
190
} MatchState;
191
192
// recursive function
193
static const char* match(MatchState* ms, const char* s, const char* p);
194
195
#define L_ESC '%'
196
#define SPECIALS "^$*+?.([%-"
197
198
static int check_capture(MatchState* ms, int l)
199
{
200
l -= '1';
201
if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED)
202
luaL_error(ms->L, "invalid capture index %%%d", l + 1);
203
return l;
204
}
205
206
static int capture_to_close(MatchState* ms)
207
{
208
int level = ms->level;
209
for (level--; level >= 0; level--)
210
if (ms->capture[level].len == CAP_UNFINISHED)
211
return level;
212
luaL_error(ms->L, "invalid pattern capture");
213
}
214
215
static const char* classend(MatchState* ms, const char* p)
216
{
217
switch (*p++)
218
{
219
case L_ESC:
220
{
221
if (p == ms->p_end)
222
luaL_error(ms->L, "malformed pattern (ends with '%%')");
223
return p + 1;
224
}
225
case '[':
226
{
227
if (*p == '^')
228
p++;
229
do
230
{ // look for a `]'
231
if (p == ms->p_end)
232
luaL_error(ms->L, "malformed pattern (missing ']')");
233
if (*(p++) == L_ESC && p < ms->p_end)
234
p++; // skip escapes (e.g. `%]')
235
} while (*p != ']');
236
return p + 1;
237
}
238
default:
239
{
240
return p;
241
}
242
}
243
}
244
245
static int match_class(int c, int cl)
246
{
247
int res;
248
switch (tolower(cl))
249
{
250
case 'a':
251
res = isalpha(c);
252
break;
253
case 'c':
254
res = iscntrl(c);
255
break;
256
case 'd':
257
res = isdigit(c);
258
break;
259
case 'g':
260
res = isgraph(c);
261
break;
262
case 'l':
263
res = islower(c);
264
break;
265
case 'p':
266
res = ispunct(c);
267
break;
268
case 's':
269
res = isspace(c);
270
break;
271
case 'u':
272
res = isupper(c);
273
break;
274
case 'w':
275
res = isalnum(c);
276
break;
277
case 'x':
278
res = isxdigit(c);
279
break;
280
case 'z':
281
res = (c == 0);
282
break; // deprecated option
283
default:
284
return (cl == c);
285
}
286
return (islower(cl) ? res : !res);
287
}
288
289
static int matchbracketclass(int c, const char* p, const char* ec)
290
{
291
int sig = 1;
292
if (*(p + 1) == '^')
293
{
294
sig = 0;
295
p++; // skip the `^'
296
}
297
while (++p < ec)
298
{
299
if (*p == L_ESC)
300
{
301
p++;
302
if (match_class(c, uchar(*p)))
303
return sig;
304
}
305
else if ((*(p + 1) == '-') && (p + 2 < ec))
306
{
307
p += 2;
308
if (uchar(*(p - 2)) <= c && c <= uchar(*p))
309
return sig;
310
}
311
else if (uchar(*p) == c)
312
return sig;
313
}
314
return !sig;
315
}
316
317
static int singlematch(MatchState* ms, const char* s, const char* p, const char* ep)
318
{
319
if (s >= ms->src_end)
320
return 0;
321
else
322
{
323
int c = uchar(*s);
324
switch (*p)
325
{
326
case '.':
327
return 1; // matches any char
328
case L_ESC:
329
return match_class(c, uchar(*(p + 1)));
330
case '[':
331
return matchbracketclass(c, p, ep - 1);
332
default:
333
return (uchar(*p) == c);
334
}
335
}
336
}
337
338
static const char* matchbalance(MatchState* ms, const char* s, const char* p)
339
{
340
if (p >= ms->p_end - 1)
341
luaL_error(ms->L, "malformed pattern (missing arguments to '%%b')");
342
if (*s != *p)
343
return NULL;
344
else
345
{
346
int b = *p;
347
int e = *(p + 1);
348
int cont = 1;
349
while (++s < ms->src_end)
350
{
351
if (*s == e)
352
{
353
if (--cont == 0)
354
return s + 1;
355
}
356
else if (*s == b)
357
cont++;
358
}
359
}
360
return NULL; // string ends out of balance
361
}
362
363
static const char* max_expand(MatchState* ms, const char* s, const char* p, const char* ep)
364
{
365
ptrdiff_t i = 0; // counts maximum expand for item
366
while (singlematch(ms, s + i, p, ep))
367
i++;
368
// keeps trying to match with the maximum repetitions
369
while (i >= 0)
370
{
371
const char* res = match(ms, (s + i), ep + 1);
372
if (res)
373
return res;
374
i--; // else didn't match; reduce 1 repetition to try again
375
}
376
return NULL;
377
}
378
379
static const char* min_expand(MatchState* ms, const char* s, const char* p, const char* ep)
380
{
381
for (;;)
382
{
383
const char* res = match(ms, s, ep + 1);
384
if (res != NULL)
385
return res;
386
else if (singlematch(ms, s, p, ep))
387
s++; // try with one more repetition
388
else
389
return NULL;
390
}
391
}
392
393
static const char* start_capture(MatchState* ms, const char* s, const char* p, int what)
394
{
395
const char* res;
396
int level = ms->level;
397
if (level >= LUA_MAXCAPTURES)
398
luaL_error(ms->L, "too many captures");
399
ms->capture[level].init = s;
400
ms->capture[level].len = what;
401
ms->level = level + 1;
402
if ((res = match(ms, s, p)) == NULL) // match failed?
403
ms->level--; // undo capture
404
return res;
405
}
406
407
static const char* end_capture(MatchState* ms, const char* s, const char* p)
408
{
409
int l = capture_to_close(ms);
410
const char* res;
411
ms->capture[l].len = s - ms->capture[l].init; // close capture
412
if ((res = match(ms, s, p)) == NULL) // match failed?
413
ms->capture[l].len = CAP_UNFINISHED; // undo capture
414
return res;
415
}
416
417
static const char* match_capture(MatchState* ms, const char* s, int l)
418
{
419
size_t len;
420
l = check_capture(ms, l);
421
len = ms->capture[l].len;
422
if ((size_t)(ms->src_end - s) >= len && memcmp(ms->capture[l].init, s, len) == 0)
423
return s + len;
424
else
425
return NULL;
426
}
427
428
static const char* match(MatchState* ms, const char* s, const char* p)
429
{
430
if (ms->matchdepth-- == 0)
431
luaL_error(ms->L, "pattern too complex");
432
433
lua_State* L = ms->L;
434
void (*interrupt)(lua_State*, int) = L->global->cb.interrupt;
435
436
if (LUAU_UNLIKELY(!!interrupt))
437
{
438
// this interrupt is not yieldable
439
L->nCcalls++;
440
interrupt(L, -1);
441
L->nCcalls--;
442
}
443
444
init: // using goto's to optimize tail recursion
445
if (p != ms->p_end)
446
{ // end of pattern?
447
switch (*p)
448
{
449
case '(':
450
{ // start capture
451
if (*(p + 1) == ')') // position capture?
452
s = start_capture(ms, s, p + 2, CAP_POSITION);
453
else
454
s = start_capture(ms, s, p + 1, CAP_UNFINISHED);
455
break;
456
}
457
case ')':
458
{ // end capture
459
s = end_capture(ms, s, p + 1);
460
break;
461
}
462
case '$':
463
{
464
if ((p + 1) != ms->p_end) // is the `$' the last char in pattern?
465
goto dflt; // no; go to default
466
s = (s == ms->src_end) ? s : NULL; // check end of string
467
break;
468
}
469
case L_ESC:
470
{ // escaped sequences not in the format class[*+?-]?
471
switch (*(p + 1))
472
{
473
case 'b':
474
{ // balanced string?
475
s = matchbalance(ms, s, p + 2);
476
if (s != NULL)
477
{
478
p += 4;
479
goto init; // return match(ms, s, p + 4);
480
} // else fail (s == NULL)
481
break;
482
}
483
case 'f':
484
{ // frontier?
485
const char* ep;
486
char previous;
487
p += 2;
488
if (*p != '[')
489
luaL_error(ms->L, "missing '[' after '%%f' in pattern");
490
ep = classend(ms, p); // points to what is next
491
previous = (s == ms->src_init) ? '\0' : *(s - 1);
492
if (!matchbracketclass(uchar(previous), p, ep - 1) && matchbracketclass(uchar(*s), p, ep - 1))
493
{
494
p = ep;
495
goto init; // return match(ms, s, ep);
496
}
497
s = NULL; // match failed
498
break;
499
}
500
case '0':
501
case '1':
502
case '2':
503
case '3':
504
case '4':
505
case '5':
506
case '6':
507
case '7':
508
case '8':
509
case '9':
510
{ // capture results (%0-%9)?
511
s = match_capture(ms, s, uchar(*(p + 1)));
512
if (s != NULL)
513
{
514
p += 2;
515
goto init; // return match(ms, s, p + 2)
516
}
517
break;
518
}
519
default:
520
goto dflt;
521
}
522
break;
523
}
524
default:
525
dflt:
526
{ // pattern class plus optional suffix
527
const char* ep = classend(ms, p); // points to optional suffix
528
// does not match at least once?
529
if (!singlematch(ms, s, p, ep))
530
{
531
if (*ep == '*' || *ep == '?' || *ep == '-')
532
{ // accept empty?
533
p = ep + 1;
534
goto init; // return match(ms, s, ep + 1);
535
}
536
else // '+' or no suffix
537
s = NULL; // fail
538
}
539
else
540
{ // matched once
541
switch (*ep)
542
{ // handle optional suffix
543
case '?':
544
{ // optional
545
const char* res;
546
if ((res = match(ms, s + 1, ep + 1)) != NULL)
547
s = res;
548
else
549
{
550
p = ep + 1;
551
goto init; // else return match(ms, s, ep + 1);
552
}
553
break;
554
}
555
case '+': // 1 or more repetitions
556
s++; // 1 match already done
557
LUAU_FALLTHROUGH; // go through
558
case '*': // 0 or more repetitions
559
s = max_expand(ms, s, p, ep);
560
break;
561
case '-': // 0 or more repetitions (minimum)
562
s = min_expand(ms, s, p, ep);
563
break;
564
default: // no suffix
565
s++;
566
p = ep;
567
goto init; // return match(ms, s + 1, ep);
568
}
569
}
570
break;
571
}
572
}
573
}
574
ms->matchdepth++;
575
return s;
576
}
577
578
static const char* lmemfind(const char* s1, size_t l1, const char* s2, size_t l2)
579
{
580
if (l2 == 0)
581
return s1; // empty strings are everywhere
582
else if (l2 > l1)
583
return NULL; // avoids a negative `l1'
584
else
585
{
586
const char* init; // to search for a `*s2' inside `s1'
587
l2--; // 1st char will be checked by `memchr'
588
l1 = l1 - l2; // `s2' cannot be found after that
589
while (l1 > 0 && (init = (const char*)memchr(s1, *s2, l1)) != NULL)
590
{
591
init++; // 1st char is already checked
592
if (memcmp(init, s2 + 1, l2) == 0)
593
return init - 1;
594
else
595
{ // correct `l1' and `s1' to try again
596
l1 -= init - s1;
597
s1 = init;
598
}
599
}
600
return NULL; // not found
601
}
602
}
603
604
static void push_onecapture(MatchState* ms, int i, const char* s, const char* e)
605
{
606
if (i >= ms->level)
607
{
608
if (i == 0) // ms->level == 0, too
609
lua_pushlstring(ms->L, s, e - s); // add whole match
610
else
611
luaL_error(ms->L, "invalid capture index");
612
}
613
else
614
{
615
ptrdiff_t l = ms->capture[i].len;
616
if (l == CAP_UNFINISHED)
617
luaL_error(ms->L, "unfinished capture");
618
if (l == CAP_POSITION)
619
lua_pushinteger(ms->L, (int)(ms->capture[i].init - ms->src_init) + 1);
620
else
621
lua_pushlstring(ms->L, ms->capture[i].init, l);
622
}
623
}
624
625
static int push_captures(MatchState* ms, const char* s, const char* e)
626
{
627
int i;
628
int nlevels = (ms->level == 0 && s) ? 1 : ms->level;
629
luaL_checkstack(ms->L, nlevels, "too many captures");
630
for (i = 0; i < nlevels; i++)
631
push_onecapture(ms, i, s, e);
632
return nlevels; // number of strings pushed
633
}
634
635
// check whether pattern has no special characters
636
static int nospecials(const char* p, size_t l)
637
{
638
size_t upto = 0;
639
do
640
{
641
if (strpbrk(p + upto, SPECIALS))
642
return 0; // pattern has a special character
643
upto += strlen(p + upto) + 1; // may have more after \0
644
} while (upto <= l);
645
return 1; // no special chars found
646
}
647
648
static void prepstate(MatchState* ms, lua_State* L, const char* s, size_t ls, const char* p, size_t lp)
649
{
650
ms->L = L;
651
ms->matchdepth = LUAI_MAXCCALLS;
652
ms->src_init = s;
653
ms->src_end = s + ls;
654
ms->p_end = p + lp;
655
}
656
657
static void reprepstate(MatchState* ms)
658
{
659
ms->level = 0;
660
LUAU_ASSERT(ms->matchdepth == LUAI_MAXCCALLS);
661
}
662
663
static int str_find_aux(lua_State* L, int find)
664
{
665
size_t ls, lp;
666
const char* s = luaL_checklstring(L, 1, &ls);
667
const char* p = luaL_checklstring(L, 2, &lp);
668
int init = posrelat(luaL_optinteger(L, 3, 1), ls);
669
if (init < 1)
670
init = 1;
671
else if (init > (int)ls + 1)
672
{ // start after string's end?
673
lua_pushnil(L); // cannot find anything
674
return 1;
675
}
676
// explicit request or no special characters?
677
if (find && (lua_toboolean(L, 4) || nospecials(p, lp)))
678
{
679
// do a plain search
680
const char* s2 = lmemfind(s + init - 1, ls - init + 1, p, lp);
681
if (s2)
682
{
683
lua_pushinteger(L, (int)(s2 - s + 1));
684
lua_pushinteger(L, (int)(s2 - s + lp));
685
return 2;
686
}
687
}
688
else
689
{
690
MatchState ms;
691
const char* s1 = s + init - 1;
692
int anchor = (*p == '^');
693
if (anchor)
694
{
695
p++;
696
lp--; // skip anchor character
697
}
698
prepstate(&ms, L, s, ls, p, lp);
699
do
700
{
701
const char* res;
702
reprepstate(&ms);
703
if ((res = match(&ms, s1, p)) != NULL)
704
{
705
if (find)
706
{
707
lua_pushinteger(L, (int)(s1 - s + 1)); // start
708
lua_pushinteger(L, (int)(res - s)); // end
709
return push_captures(&ms, NULL, 0) + 2;
710
}
711
else
712
return push_captures(&ms, s1, res);
713
}
714
} while (s1++ < ms.src_end && !anchor);
715
}
716
lua_pushnil(L); // not found
717
return 1;
718
}
719
720
static int str_find(lua_State* L)
721
{
722
return str_find_aux(L, 1);
723
}
724
725
static int str_match(lua_State* L)
726
{
727
return str_find_aux(L, 0);
728
}
729
730
static int gmatch_aux(lua_State* L)
731
{
732
MatchState ms;
733
size_t ls, lp;
734
const char* s = lua_tolstring(L, lua_upvalueindex(1), &ls);
735
const char* p = lua_tolstring(L, lua_upvalueindex(2), &lp);
736
const char* src;
737
prepstate(&ms, L, s, ls, p, lp);
738
for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); src <= ms.src_end; src++)
739
{
740
const char* e;
741
reprepstate(&ms);
742
if ((e = match(&ms, src, p)) != NULL)
743
{
744
int newstart = (int)(e - s);
745
if (e == src)
746
newstart++; // empty match? go at least one position
747
lua_pushinteger(L, newstart);
748
lua_replace(L, lua_upvalueindex(3));
749
return push_captures(&ms, src, e);
750
}
751
}
752
return 0; // not found
753
}
754
755
static int gmatch(lua_State* L)
756
{
757
luaL_checkstring(L, 1);
758
luaL_checkstring(L, 2);
759
lua_settop(L, 2);
760
lua_pushinteger(L, 0);
761
lua_pushcclosure(L, gmatch_aux, NULL, 3);
762
return 1;
763
}
764
765
static void add_s(MatchState* ms, luaL_Strbuf* b, const char* s, const char* e)
766
{
767
size_t l, i;
768
const char* news = lua_tolstring(ms->L, 3, &l);
769
770
luaL_prepbuffsize(b, l);
771
772
for (i = 0; i < l; i++)
773
{
774
if (news[i] != L_ESC)
775
luaL_addchar(b, news[i]);
776
else
777
{
778
i++; // skip ESC
779
if (!isdigit(uchar(news[i])))
780
{
781
if (news[i] != L_ESC)
782
luaL_error(ms->L, "invalid use of '%c' in replacement string", L_ESC);
783
luaL_addchar(b, news[i]);
784
}
785
else if (news[i] == '0')
786
luaL_addlstring(b, s, e - s);
787
else
788
{
789
push_onecapture(ms, news[i] - '1', s, e);
790
luaL_addvalue(b); // add capture to accumulated result
791
}
792
}
793
}
794
}
795
796
static void add_value(MatchState* ms, luaL_Strbuf* b, const char* s, const char* e, int tr)
797
{
798
lua_State* L = ms->L;
799
switch (tr)
800
{
801
case LUA_TFUNCTION:
802
{
803
int n;
804
lua_pushvalue(L, 3);
805
n = push_captures(ms, s, e);
806
lua_call(L, n, 1);
807
break;
808
}
809
case LUA_TTABLE:
810
{
811
push_onecapture(ms, 0, s, e);
812
lua_gettable(L, 3);
813
break;
814
}
815
default:
816
{ // LUA_TNUMBER or LUA_TSTRING
817
add_s(ms, b, s, e);
818
return;
819
}
820
}
821
if (!lua_toboolean(L, -1))
822
{ // nil or false?
823
lua_pop(L, 1);
824
lua_pushlstring(L, s, e - s); // keep original text
825
}
826
else if (!lua_isstring(L, -1))
827
luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1));
828
luaL_addvalue(b); // add result to accumulator
829
}
830
831
static int str_gsub(lua_State* L)
832
{
833
size_t srcl, lp;
834
const char* src = luaL_checklstring(L, 1, &srcl);
835
const char* p = luaL_checklstring(L, 2, &lp);
836
int tr = lua_type(L, 3);
837
int max_s = luaL_optinteger(L, 4, (int)srcl + 1);
838
int anchor = (*p == '^');
839
int n = 0;
840
MatchState ms;
841
luaL_Strbuf b;
842
luaL_argexpected(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, "string/function/table");
843
luaL_buffinit(L, &b);
844
if (anchor)
845
{
846
p++;
847
lp--; // skip anchor character
848
}
849
prepstate(&ms, L, src, srcl, p, lp);
850
while (n < max_s)
851
{
852
const char* e;
853
reprepstate(&ms);
854
e = match(&ms, src, p);
855
if (e)
856
{
857
n++;
858
add_value(&ms, &b, src, e, tr);
859
}
860
if (e && e > src) // non empty match?
861
src = e; // skip it
862
else if (src < ms.src_end)
863
luaL_addchar(&b, *src++);
864
else
865
break;
866
if (anchor)
867
break;
868
}
869
luaL_addlstring(&b, src, ms.src_end - src);
870
luaL_pushresult(&b);
871
lua_pushinteger(L, n); // number of substitutions
872
return 2;
873
}
874
875
// }======================================================
876
877
// valid flags in a format specification
878
#define FLAGS "-+ #0"
879
// maximum size of each formatted item (> len(format('%99.99f', -1e308)))
880
#define MAX_ITEM 512
881
// maximum size of each format specification (such as '%-099.99d')
882
#define MAX_FORMAT 32
883
884
static void addquoted(lua_State* L, luaL_Strbuf* b, int arg)
885
{
886
size_t l;
887
const char* s = luaL_checklstring(L, arg, &l);
888
889
luaL_prepbuffsize(b, l + 2);
890
891
luaL_addchar(b, '"');
892
while (l--)
893
{
894
switch (*s)
895
{
896
case '"':
897
case '\\':
898
case '\n':
899
{
900
luaL_addchar(b, '\\');
901
luaL_addchar(b, *s);
902
break;
903
}
904
case '\r':
905
{
906
luaL_addlstring(b, "\\r", 2);
907
break;
908
}
909
case '\0':
910
{
911
luaL_addlstring(b, "\\000", 4);
912
break;
913
}
914
default:
915
{
916
luaL_addchar(b, *s);
917
break;
918
}
919
}
920
s++;
921
}
922
luaL_addchar(b, '"');
923
}
924
925
static const char* scanformat(lua_State* L, const char* strfrmt, char* form, size_t* size)
926
{
927
const char* p = strfrmt;
928
while (*p != '\0' && strchr(FLAGS, *p) != NULL)
929
p++; // skip flags
930
if ((size_t)(p - strfrmt) >= sizeof(FLAGS))
931
luaL_error(L, "invalid format (repeated flags)");
932
if (isdigit(uchar(*p)))
933
p++; // skip width
934
if (isdigit(uchar(*p)))
935
p++; // (2 digits at most)
936
if (*p == '.')
937
{
938
p++;
939
if (isdigit(uchar(*p)))
940
p++; // skip precision
941
if (isdigit(uchar(*p)))
942
p++; // (2 digits at most)
943
}
944
if (isdigit(uchar(*p)))
945
luaL_error(L, "invalid format (width or precision too long)");
946
*(form++) = '%';
947
*size = p - strfrmt + 1;
948
strncpy(form, strfrmt, *size);
949
form += *size;
950
*form = '\0';
951
return p;
952
}
953
954
static void addInt64Format(char form[MAX_FORMAT], char formatIndicator, size_t formatItemSize)
955
{
956
LUAU_ASSERT((formatItemSize + 3) <= MAX_FORMAT);
957
LUAU_ASSERT(form[0] == '%');
958
LUAU_ASSERT(form[formatItemSize] != 0);
959
LUAU_ASSERT(form[formatItemSize + 1] == 0);
960
form[formatItemSize + 0] = 'l';
961
form[formatItemSize + 1] = 'l';
962
form[formatItemSize + 2] = formatIndicator;
963
form[formatItemSize + 3] = 0;
964
}
965
966
static int str_format(lua_State* L)
967
{
968
int top = lua_gettop(L);
969
int arg = 1;
970
size_t sfl;
971
const char* strfrmt = luaL_checklstring(L, arg, &sfl);
972
const char* strfrmt_end = strfrmt + sfl;
973
luaL_Strbuf b;
974
luaL_buffinit(L, &b);
975
while (strfrmt < strfrmt_end)
976
{
977
if (*strfrmt != L_ESC)
978
luaL_addchar(&b, *strfrmt++);
979
else if (*++strfrmt == L_ESC)
980
luaL_addchar(&b, *strfrmt++); // %%
981
else if (*strfrmt == '*')
982
{
983
strfrmt++;
984
if (++arg > top)
985
luaL_error(L, "missing argument #%d", arg);
986
987
luaL_addvalueany(&b, arg);
988
}
989
else
990
{ // format item
991
char form[MAX_FORMAT]; // to store the format (`%...')
992
char buff[MAX_ITEM]; // to store the formatted item
993
if (++arg > top)
994
luaL_error(L, "missing argument #%d", arg);
995
size_t formatItemSize = 0;
996
strfrmt = scanformat(L, strfrmt, form, &formatItemSize);
997
char formatIndicator = *strfrmt++;
998
switch (formatIndicator)
999
{
1000
case 'c':
1001
{
1002
int count = snprintf(buff, sizeof(buff), form, (int)luaL_checknumber(L, arg));
1003
luaL_addlstring(&b, buff, count);
1004
continue; // skip the 'luaL_addlstring' at the end
1005
}
1006
case 'd':
1007
case 'i':
1008
{
1009
long long value = lua_isinteger64(L, arg) ? luaL_checkinteger64(L, arg) : (int64_t)luaL_checknumber(L, arg);
1010
addInt64Format(form, formatIndicator, formatItemSize);
1011
snprintf(buff, sizeof(buff), form, value);
1012
break;
1013
}
1014
case 'o':
1015
case 'u':
1016
case 'x':
1017
case 'X':
1018
{
1019
uint64_t v;
1020
if (lua_isinteger64(L, arg))
1021
{
1022
v = luaL_checkinteger64(L, arg);
1023
}
1024
else
1025
{
1026
double argValue = luaL_checknumber(L, arg);
1027
v = (argValue < 0) ? (unsigned long long)(long long)argValue : (unsigned long long)argValue;
1028
}
1029
addInt64Format(form, formatIndicator, formatItemSize);
1030
snprintf(buff, sizeof(buff), form, v);
1031
break;
1032
}
1033
case 'e':
1034
case 'E':
1035
case 'f':
1036
case 'g':
1037
case 'G':
1038
{
1039
snprintf(buff, sizeof(buff), form, (double)luaL_checknumber(L, arg));
1040
break;
1041
}
1042
case 'q':
1043
{
1044
addquoted(L, &b, arg);
1045
continue; // skip the 'luaL_addlstring' at the end
1046
}
1047
case 's':
1048
{
1049
size_t l;
1050
const char* s = luaL_checklstring(L, arg, &l);
1051
// no precision and string is too long to be formatted, or no format necessary to begin with
1052
if (form[2] == '\0' || (!strchr(form, '.') && l >= 100))
1053
{
1054
luaL_addlstring(&b, s, l);
1055
continue; // skip the `luaL_addlstring' at the end
1056
}
1057
else
1058
{
1059
snprintf(buff, sizeof(buff), form, s);
1060
break;
1061
}
1062
}
1063
case '*':
1064
{
1065
// %* is parsed above, so if we got here we must have %...*
1066
luaL_error(L, "'%%*' does not take a form");
1067
}
1068
default:
1069
{ // also treat cases `pnLlh'
1070
luaL_error(L, "invalid option '%%%c' to 'format'", *(strfrmt - 1));
1071
}
1072
}
1073
luaL_addlstring(&b, buff, strlen(buff));
1074
}
1075
}
1076
luaL_pushresult(&b);
1077
return 1;
1078
}
1079
1080
static int str_split(lua_State* L)
1081
{
1082
size_t haystackLen;
1083
const char* haystack = luaL_checklstring(L, 1, &haystackLen);
1084
size_t needleLen;
1085
const char* needle = luaL_optlstring(L, 2, ",", &needleLen);
1086
1087
const char* begin = haystack;
1088
const char* end = haystack + haystackLen;
1089
const char* spanStart = begin;
1090
int numMatches = 0;
1091
1092
lua_createtable(L, 0, 0);
1093
1094
if (needleLen == 0)
1095
begin++;
1096
1097
// Don't iterate the last needleLen - 1 bytes of the string - they are
1098
// impossible to be splits and would let us memcmp past the end of the
1099
// buffer.
1100
for (const char* iter = begin; iter <= end - needleLen; iter++)
1101
{
1102
// Use of memcmp here instead of strncmp is so that we allow embedded
1103
// nulls to be used in either of the haystack or the needle strings.
1104
// Most Lua string APIs allow embedded nulls, and this should be no
1105
// exception.
1106
if (memcmp(iter, needle, needleLen) == 0)
1107
{
1108
lua_pushinteger(L, ++numMatches);
1109
lua_pushlstring(L, spanStart, iter - spanStart);
1110
lua_settable(L, -3);
1111
1112
spanStart = iter + needleLen;
1113
if (needleLen > 0)
1114
iter += needleLen - 1;
1115
}
1116
}
1117
1118
if (needleLen > 0)
1119
{
1120
lua_pushinteger(L, ++numMatches);
1121
lua_pushlstring(L, spanStart, end - spanStart);
1122
lua_settable(L, -3);
1123
}
1124
1125
return 1;
1126
}
1127
1128
/*
1129
** {======================================================
1130
** PACK/UNPACK
1131
** =======================================================
1132
*/
1133
1134
// value used for padding
1135
#if !defined(LUAL_PACKPADBYTE)
1136
#define LUAL_PACKPADBYTE 0x00
1137
#endif
1138
1139
// maximum size for the binary representation of an integer
1140
#define MAXINTSIZE 16
1141
1142
// number of bits in a character
1143
#define NB CHAR_BIT
1144
1145
// mask for one character (NB 1's)
1146
#define MC ((1 << NB) - 1)
1147
1148
// internal size of integers used for pack/unpack
1149
#define SZINT (int)sizeof(long long)
1150
1151
// dummy union to get native endianness
1152
static const union
1153
{
1154
int dummy;
1155
char little; // true iff machine is little endian
1156
} nativeendian = {1};
1157
1158
// assume we need to align for double & pointers
1159
#define MAXALIGN 8
1160
1161
/*
1162
** Union for serializing floats
1163
*/
1164
typedef union Ftypes
1165
{
1166
float f;
1167
double d;
1168
double n;
1169
char buff[5 * sizeof(double)]; // enough for any float type
1170
} Ftypes;
1171
1172
/*
1173
** information to pack/unpack stuff
1174
*/
1175
typedef struct Header
1176
{
1177
lua_State* L;
1178
int islittle;
1179
int maxalign;
1180
} Header;
1181
1182
/*
1183
** options for pack/unpack
1184
*/
1185
typedef enum KOption
1186
{
1187
Kint, // signed integers
1188
Kuint, // unsigned integers
1189
Kfloat, // floating-point numbers
1190
Kchar, // fixed-length strings
1191
Kstring, // strings with prefixed length
1192
Kzstr, // zero-terminated strings
1193
Kpadding, // padding
1194
Kpaddalign, // padding for alignment
1195
Knop // no-op (configuration or spaces)
1196
} KOption;
1197
1198
/*
1199
** Read an integer numeral from string 'fmt' or return 'df' if
1200
** there is no numeral
1201
*/
1202
static int digit(int c)
1203
{
1204
return '0' <= c && c <= '9';
1205
}
1206
1207
static int getnum(Header* h, const char** fmt, int df)
1208
{
1209
if (!digit(**fmt)) // no number?
1210
return df; // return default value
1211
else
1212
{
1213
int a = 0;
1214
do
1215
{
1216
a = a * 10 + (*((*fmt)++) - '0');
1217
} while (digit(**fmt) && a <= (INT_MAX - 9) / 10);
1218
if (a > MAXSSIZE || digit(**fmt))
1219
luaL_error(h->L, "size specifier is too large");
1220
return a;
1221
}
1222
}
1223
1224
/*
1225
** Read an integer numeral and raises an error if it is larger
1226
** than the maximum size for integers.
1227
*/
1228
static int getnumlimit(Header* h, const char** fmt, int df)
1229
{
1230
int sz = getnum(h, fmt, df);
1231
if (sz > MAXINTSIZE || sz <= 0)
1232
luaL_error(h->L, "integral size (%d) out of limits [1,%d]", sz, MAXINTSIZE);
1233
return sz;
1234
}
1235
1236
/*
1237
** Initialize Header
1238
*/
1239
static void initheader(lua_State* L, Header* h)
1240
{
1241
h->L = L;
1242
h->islittle = nativeendian.little;
1243
h->maxalign = 1;
1244
}
1245
1246
/*
1247
** Read and classify next option. 'size' is filled with option's size.
1248
*/
1249
static KOption getoption(Header* h, const char** fmt, int* size)
1250
{
1251
int opt = *((*fmt)++);
1252
*size = 0; // default
1253
switch (opt)
1254
{
1255
case 'b':
1256
*size = 1;
1257
return Kint;
1258
case 'B':
1259
*size = 1;
1260
return Kuint;
1261
case 'h':
1262
*size = 2;
1263
return Kint;
1264
case 'H':
1265
*size = 2;
1266
return Kuint;
1267
case 'l':
1268
*size = 8;
1269
return Kint;
1270
case 'L':
1271
*size = 8;
1272
return Kuint;
1273
case 'j':
1274
*size = 4;
1275
return Kint;
1276
case 'J':
1277
*size = 4;
1278
return Kuint;
1279
case 'T':
1280
*size = 4;
1281
return Kuint;
1282
case 'f':
1283
*size = 4;
1284
return Kfloat;
1285
case 'd':
1286
*size = 8;
1287
return Kfloat;
1288
case 'n':
1289
*size = 8;
1290
return Kfloat;
1291
case 'i':
1292
*size = getnumlimit(h, fmt, 4);
1293
return Kint;
1294
case 'I':
1295
*size = getnumlimit(h, fmt, 4);
1296
return Kuint;
1297
case 's':
1298
*size = getnumlimit(h, fmt, 4);
1299
return Kstring;
1300
case 'c':
1301
*size = getnum(h, fmt, -1);
1302
if (*size == -1)
1303
luaL_error(h->L, "missing size for format option 'c'");
1304
return Kchar;
1305
case 'z':
1306
return Kzstr;
1307
case 'x':
1308
*size = 1;
1309
return Kpadding;
1310
case 'X':
1311
return Kpaddalign;
1312
case ' ':
1313
break;
1314
case '<':
1315
h->islittle = 1;
1316
break;
1317
case '>':
1318
h->islittle = 0;
1319
break;
1320
case '=':
1321
h->islittle = nativeendian.little;
1322
break;
1323
case '!':
1324
h->maxalign = getnumlimit(h, fmt, MAXALIGN);
1325
break;
1326
default:
1327
luaL_error(h->L, "invalid format option '%c'", opt);
1328
}
1329
return Knop;
1330
}
1331
1332
/*
1333
** Read, classify, and fill other details about the next option.
1334
** 'psize' is filled with option's size, 'notoalign' with its
1335
** alignment requirements.
1336
** Local variable 'size' gets the size to be aligned. (Kpaddalign option
1337
** always gets its full alignment, other options are limited by
1338
** the maximum alignment ('maxalign'). Kchar option needs no alignment
1339
** despite its size.
1340
*/
1341
static KOption getdetails(Header* h, size_t totalsize, const char** fmt, int* psize, int* ntoalign)
1342
{
1343
KOption opt = getoption(h, fmt, psize);
1344
int align = *psize; // usually, alignment follows size
1345
if (opt == Kpaddalign)
1346
{ // 'X' gets alignment from following option
1347
if (**fmt == '\0' || getoption(h, fmt, &align) == Kchar || align == 0)
1348
luaL_argerror(h->L, 1, "invalid next option for option 'X'");
1349
}
1350
if (align <= 1 || opt == Kchar) // need no alignment?
1351
*ntoalign = 0;
1352
else
1353
{
1354
if (align > h->maxalign) // enforce maximum alignment
1355
align = h->maxalign;
1356
if ((align & (align - 1)) != 0) // is 'align' not a power of 2?
1357
luaL_argerror(h->L, 1, "format asks for alignment not power of 2");
1358
*ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1);
1359
}
1360
return opt;
1361
}
1362
1363
/*
1364
** Pack integer 'n' with 'size' bytes and 'islittle' endianness.
1365
** The final 'if' handles the case when 'size' is larger than
1366
** the size of a Lua integer, correcting the extra sign-extension
1367
** bytes if necessary (by default they would be zeros).
1368
*/
1369
static void packint(luaL_Strbuf* b, unsigned long long n, int islittle, int size, int neg)
1370
{
1371
LUAU_ASSERT(size <= MAXINTSIZE);
1372
char buff[MAXINTSIZE];
1373
int i;
1374
buff[islittle ? 0 : size - 1] = (char)(n & MC); // first byte
1375
for (i = 1; i < size; i++)
1376
{
1377
n >>= NB;
1378
buff[islittle ? i : size - 1 - i] = (char)(n & MC);
1379
}
1380
if (neg && size > SZINT)
1381
{ // negative number need sign extension?
1382
for (i = SZINT; i < size; i++) // correct extra bytes
1383
buff[islittle ? i : size - 1 - i] = (char)MC;
1384
}
1385
luaL_addlstring(b, buff, size); // add result to buffer
1386
}
1387
1388
/*
1389
** Copy 'size' bytes from 'src' to 'dest', correcting endianness if
1390
** given 'islittle' is different from native endianness.
1391
*/
1392
static void copywithendian(volatile char* dest, volatile const char* src, int size, int islittle)
1393
{
1394
if (islittle == nativeendian.little)
1395
{
1396
while (size-- != 0)
1397
*(dest++) = *(src++);
1398
}
1399
else
1400
{
1401
dest += size - 1;
1402
while (size-- != 0)
1403
*(dest--) = *(src++);
1404
}
1405
}
1406
1407
static int str_pack(lua_State* L)
1408
{
1409
luaL_Strbuf b;
1410
Header h;
1411
const char* fmt = luaL_checkstring(L, 1); // format string
1412
int arg = 1; // current argument to pack
1413
size_t totalsize = 0; // accumulate total size of result
1414
initheader(L, &h);
1415
lua_pushnil(L); // mark to separate arguments from string buffer
1416
luaL_buffinit(L, &b);
1417
while (*fmt != '\0')
1418
{
1419
int size, ntoalign;
1420
KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
1421
totalsize += ntoalign + size;
1422
while (ntoalign-- > 0)
1423
luaL_addchar(&b, LUAL_PACKPADBYTE); // fill alignment
1424
arg++;
1425
switch (opt)
1426
{
1427
case Kint:
1428
{ // signed integers
1429
long long n = (long long)luaL_checknumber(L, arg);
1430
if (size < SZINT)
1431
{ // need overflow check?
1432
long long lim = (long long)1 << ((size * NB) - 1);
1433
luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow");
1434
}
1435
packint(&b, n, h.islittle, size, (n < 0));
1436
break;
1437
}
1438
case Kuint:
1439
{ // unsigned integers
1440
long long n = (long long)luaL_checknumber(L, arg);
1441
if (size < SZINT) // need overflow check?
1442
luaL_argcheck(L, (unsigned long long)n < ((unsigned long long)1 << (size * NB)), arg, "unsigned overflow");
1443
packint(&b, (unsigned long long)n, h.islittle, size, 0);
1444
break;
1445
}
1446
case Kfloat:
1447
{ // floating-point options
1448
volatile Ftypes u;
1449
char buff[MAXINTSIZE];
1450
double n = luaL_checknumber(L, arg); // get argument
1451
if (size == sizeof(u.f))
1452
u.f = (float)n; // copy it into 'u'
1453
else if (size == sizeof(u.d))
1454
u.d = (double)n;
1455
else
1456
u.n = n;
1457
// move 'u' to final result, correcting endianness if needed
1458
copywithendian(buff, u.buff, size, h.islittle);
1459
luaL_addlstring(&b, buff, size);
1460
break;
1461
}
1462
case Kchar:
1463
{ // fixed-size string
1464
size_t len;
1465
const char* s = luaL_checklstring(L, arg, &len);
1466
luaL_argcheck(L, len <= (size_t)size, arg, "string longer than given size");
1467
luaL_addlstring(&b, s, len); // add string
1468
while (len++ < (size_t)size) // pad extra space
1469
luaL_addchar(&b, LUAL_PACKPADBYTE);
1470
break;
1471
}
1472
case Kstring:
1473
{ // strings with length count
1474
size_t len;
1475
const char* s = luaL_checklstring(L, arg, &len);
1476
luaL_argcheck(L, size >= (int)sizeof(size_t) || len < ((size_t)1 << (size * NB)), arg, "string length does not fit in given size");
1477
packint(&b, len, h.islittle, size, 0); // pack length
1478
luaL_addlstring(&b, s, len);
1479
totalsize += len;
1480
break;
1481
}
1482
case Kzstr:
1483
{ // zero-terminated string
1484
size_t len;
1485
const char* s = luaL_checklstring(L, arg, &len);
1486
luaL_argcheck(L, strlen(s) == len, arg, "string contains zeros");
1487
luaL_addlstring(&b, s, len);
1488
luaL_addchar(&b, '\0'); // add zero at the end
1489
totalsize += len + 1;
1490
break;
1491
}
1492
case Kpadding:
1493
luaL_addchar(&b, LUAL_PACKPADBYTE);
1494
LUAU_FALLTHROUGH;
1495
case Kpaddalign:
1496
case Knop:
1497
arg--; // undo increment
1498
break;
1499
}
1500
}
1501
luaL_pushresult(&b);
1502
return 1;
1503
}
1504
1505
static int str_packsize(lua_State* L)
1506
{
1507
Header h;
1508
const char* fmt = luaL_checkstring(L, 1); // format string
1509
int totalsize = 0; // accumulate total size of result
1510
initheader(L, &h);
1511
while (*fmt != '\0')
1512
{
1513
int size, ntoalign;
1514
KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
1515
luaL_argcheck(L, opt != Kstring && opt != Kzstr, 1, "variable-length format");
1516
size += ntoalign; // total space used by option
1517
luaL_argcheck(L, totalsize <= MAXSSIZE - size, 1, "format result too large");
1518
totalsize += size;
1519
}
1520
lua_pushinteger(L, totalsize);
1521
return 1;
1522
}
1523
1524
/*
1525
** Unpack an integer with 'size' bytes and 'islittle' endianness.
1526
** If size is smaller than the size of a Lua integer and integer
1527
** is signed, must do sign extension (propagating the sign to the
1528
** higher bits); if size is larger than the size of a Lua integer,
1529
** it must check the unread bytes to see whether they do not cause an
1530
** overflow.
1531
*/
1532
static long long unpackint(lua_State* L, const char* str, int islittle, int size, int issigned)
1533
{
1534
unsigned long long res = 0;
1535
int i;
1536
int limit = (size <= SZINT) ? size : SZINT;
1537
for (i = limit - 1; i >= 0; i--)
1538
{
1539
res <<= NB;
1540
res |= (unsigned char)str[islittle ? i : size - 1 - i];
1541
}
1542
if (size < SZINT)
1543
{ // real size smaller than int?
1544
if (issigned)
1545
{ // needs sign extension?
1546
unsigned long long mask = (unsigned long long)1 << (size * NB - 1);
1547
res = ((res ^ mask) - mask); // do sign extension
1548
}
1549
}
1550
else if (size > SZINT)
1551
{ // must check unread bytes
1552
int mask = (!issigned || (long long)res >= 0) ? 0 : MC;
1553
for (i = limit; i < size; i++)
1554
{
1555
if ((unsigned char)str[islittle ? i : size - 1 - i] != mask)
1556
luaL_error(L, "%d-byte integer does not fit into Lua Integer", size);
1557
}
1558
}
1559
return (long long)res;
1560
}
1561
1562
static int str_unpack(lua_State* L)
1563
{
1564
Header h;
1565
const char* fmt = luaL_checkstring(L, 1);
1566
size_t ld;
1567
const char* data = luaL_checklstring(L, 2, &ld);
1568
int pos = posrelat(luaL_optinteger(L, 3, 1), ld) - 1;
1569
if (pos < 0)
1570
pos = 0;
1571
int n = 0; // number of results
1572
luaL_argcheck(L, size_t(pos) <= ld, 3, "initial position out of string");
1573
initheader(L, &h);
1574
while (*fmt != '\0')
1575
{
1576
int size, ntoalign;
1577
KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign);
1578
luaL_argcheck(L, (size_t)ntoalign + size <= ld - pos, 2, "data string too short");
1579
pos += ntoalign; // skip alignment
1580
// stack space for item + next position
1581
luaL_checkstack(L, 2, "too many results");
1582
n++;
1583
switch (opt)
1584
{
1585
case Kint:
1586
{
1587
long long res = unpackint(L, data + pos, h.islittle, size, true);
1588
lua_pushnumber(L, (double)res);
1589
break;
1590
}
1591
case Kuint:
1592
{
1593
unsigned long long res = unpackint(L, data + pos, h.islittle, size, false);
1594
lua_pushnumber(L, (double)res);
1595
break;
1596
}
1597
case Kfloat:
1598
{
1599
volatile Ftypes u;
1600
double num;
1601
copywithendian(u.buff, data + pos, size, h.islittle);
1602
if (size == sizeof(u.f))
1603
num = (double)u.f;
1604
else if (size == sizeof(u.d))
1605
num = (double)u.d;
1606
else
1607
num = u.n;
1608
lua_pushnumber(L, num);
1609
break;
1610
}
1611
case Kchar:
1612
{
1613
lua_pushlstring(L, data + pos, size);
1614
break;
1615
}
1616
case Kstring:
1617
{
1618
size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0);
1619
luaL_argcheck(L, len <= ld - pos - size, 2, "data string too short");
1620
lua_pushlstring(L, data + pos + size, len);
1621
pos += (int)len; // skip string
1622
break;
1623
}
1624
case Kzstr:
1625
{
1626
size_t len = strlen(data + pos);
1627
luaL_argcheck(L, pos + len < ld, 2, "unfinished string for format 'z'");
1628
lua_pushlstring(L, data + pos, len);
1629
pos += (int)len + 1; // skip string plus final '\0'
1630
break;
1631
}
1632
case Kpaddalign:
1633
case Kpadding:
1634
case Knop:
1635
n--; // undo increment
1636
break;
1637
}
1638
pos += size;
1639
}
1640
lua_pushinteger(L, pos + 1); // next position
1641
return n + 1;
1642
}
1643
1644
// }======================================================
1645
1646
static const luaL_Reg strlib[] = {
1647
{"byte", str_byte},
1648
{"char", str_char},
1649
{"find", str_find},
1650
{"format", str_format},
1651
{"gmatch", gmatch},
1652
{"gsub", str_gsub},
1653
{"len", str_len},
1654
{"lower", str_lower},
1655
{"match", str_match},
1656
{"rep", str_rep},
1657
{"reverse", str_reverse},
1658
{"sub", str_sub},
1659
{"upper", str_upper},
1660
{"split", str_split},
1661
{"pack", str_pack},
1662
{"packsize", str_packsize},
1663
{"unpack", str_unpack},
1664
{NULL, NULL},
1665
};
1666
1667
static void createmetatable(lua_State* L)
1668
{
1669
lua_createtable(L, 0, 1); // create metatable for strings
1670
lua_pushliteral(L, ""); // dummy string
1671
lua_pushvalue(L, -2);
1672
lua_setmetatable(L, -2); // set string metatable
1673
lua_pop(L, 1); // pop dummy string
1674
lua_pushvalue(L, -2); // string library...
1675
lua_setfield(L, -2, "__index"); // ...is the __index metamethod
1676
lua_pop(L, 1); // pop metatable
1677
}
1678
1679
/*
1680
** Open string library
1681
*/
1682
int luaopen_string(lua_State* L)
1683
{
1684
luaL_register(L, LUA_STRLIBNAME, strlib);
1685
createmetatable(L);
1686
1687
return 1;
1688
}
1689
1690