Public Git Hosting - luajit-2.0.git/blob - src/lib_string.c
git
repo.or.cz
/
luajit-2.0.git
/
blob
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
log
|
graphiclog1
|
graphiclog2
|
commit
|
commitdiff
|
tree
|
refs
|
edit
|
fork
blame
|
history
|
raw
|
HEAD
FFI: Don't propagate qualifiers into subtypes of complex.
[luajit-2.0.git]
/
src
/
lib_string.c
blob c6168edbb67ad9e0d27a59cb7bdc7c124267896c
1
/*
2
** String library.
3
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
4
**
5
** Major portions taken verbatim or adapted from the Lua interpreter.
6
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
7
*/
8
9
#include <stdio.h>
10
11
#define lib_string_c
12
#define LUA_LIB
13
14
#include
"lua.h"
15
#include
"lauxlib.h"
16
#include
"lualib.h"
17
18
#include
"lj_obj.h"
19
#include
"lj_gc.h"
20
#include
"lj_err.h"
21
#include
"lj_str.h"
22
#include
"lj_tab.h"
23
#include
"lj_meta.h"
24
#include
"lj_state.h"
25
#include
"lj_ff.h"
26
#include
"lj_bcdump.h"
27
#include
"lj_char.h"
28
#include
"lj_lib.h"
29
30
/* ------------------------------------------------------------------------ */
31
32
#define LJLIB_MODULE_string
33
34
LJLIB_ASM
(
string_len
)
LJLIB_REC
(.)
35
{
36
lj_lib_checkstr
(
L
,
1
);
37
return
FFH_RETRY
;
38
}
39
40
LJLIB_ASM
(
string_byte
)
LJLIB_REC
(
string_range
0
)
41
{
42
GCstr
*
s
=
lj_lib_checkstr
(
L
,
1
);
43
int32_t
len
= (
int32_t
)
s
->
len
;
44
int32_t
start
=
lj_lib_optint
(
L
,
2
,
1
);
45
int32_t
stop
=
lj_lib_optint
(
L
,
3
,
start
);
46
int32_t
n
,
i
;
47
const unsigned char
*
p
;
48
if
(
stop
<
0
)
stop
+=
len
+
1
;
49
if
(
start
<
0
)
start
+=
len
+
1
;
50
if
(
start
<=
0
)
start
=
1
;
51
if
(
stop
>
len
)
stop
=
len
;
52
if
(
start
>
stop
)
return
FFH_RES
(
0
);
/* Empty interval: return no results. */
53
start
--;
54
n
=
stop
-
start
;
55
if
((
uint32_t
)
n
>
LUAI_MAXCSTACK
)
56
lj_err_caller
(
L
,
LJ_ERR_STRSLC
);
57
lj_state_checkstack
(
L
, (
MSize
)
n
);
58
p
= (
const unsigned char
*)
strdata
(
s
) +
start
;
59
for
(
i
=
0
;
i
<
n
;
i
++)
60
setintV
(
L
->
base
+
i
-
1
,
p
[
i
]);
61
return
FFH_RES
(
n
);
62
}
63
64
LJLIB_ASM
(
string_char
)
65
{
66
int
i
,
nargs
= (
int
)(
L
->
top
-
L
->
base
);
67
char
*
buf
=
lj_str_needbuf
(
L
, &
G
(
L
)->
tmpbuf
, (
MSize
)
nargs
);
68
for
(
i
=
1
;
i
<=
nargs
;
i
++) {
69
int32_t
k
=
lj_lib_checkint
(
L
,
i
);
70
if
(!
checku8
(
k
))
71
lj_err_arg
(
L
,
i
,
LJ_ERR_BADVAL
);
72
buf
[
i
-
1
] = (
char
)
k
;
73
}
74
setstrV
(
L
,
L
->
base
-
1
,
lj_str_new
(
L
,
buf
, (
size_t
)
nargs
));
75
return
FFH_RES
(
1
);
76
}
77
78
LJLIB_ASM
(
string_sub
)
LJLIB_REC
(
string_range
1
)
79
{
80
lj_lib_checkstr
(
L
,
1
);
81
lj_lib_checkint
(
L
,
2
);
82
setintV
(
L
->
base
+
2
,
lj_lib_optint
(
L
,
3
, -
1
));
83
return
FFH_RETRY
;
84
}
85
86
LJLIB_ASM
(
string_rep
)
87
{
88
GCstr
*
s
=
lj_lib_checkstr
(
L
,
1
);
89
int32_t
k
=
lj_lib_checkint
(
L
,
2
);
90
GCstr
*
sep
=
lj_lib_optstr
(
L
,
3
);
91
int32_t
len
= (
int32_t
)
s
->
len
;
92
global_State
*
g
=
G
(
L
);
93
int64_t
tlen
;
94
const char
*
src
;
95
char
*
buf
;
96
if
(
k
<=
0
) {
97
empty
:
98
setstrV
(
L
,
L
->
base
-
1
, &
g
->
strempty
);
99
return
FFH_RES
(
1
);
100
}
101
if
(
sep
) {
102
tlen
= (
int64_t
)
len
+
sep
->
len
;
103
if
(
tlen
>
LJ_MAX_STR
)
104
lj_err_caller
(
L
,
LJ_ERR_STROV
);
105
tlen
*=
k
;
106
if
(
tlen
>
LJ_MAX_STR
)
107
lj_err_caller
(
L
,
LJ_ERR_STROV
);
108
}
else
{
109
tlen
= (
int64_t
)
k
*
len
;
110
if
(
tlen
>
LJ_MAX_STR
)
111
lj_err_caller
(
L
,
LJ_ERR_STROV
);
112
}
113
if
(
tlen
==
0
)
goto
empty
;
114
buf
=
lj_str_needbuf
(
L
, &
g
->
tmpbuf
, (
MSize
)
tlen
);
115
src
=
strdata
(
s
);
116
if
(
sep
) {
117
tlen
-=
sep
->
len
;
/* Ignore trailing separator. */
118
if
(
k
>
1
) {
/* Paste one string and one separator. */
119
int32_t
i
;
120
i
=
0
;
while
(
i
<
len
) *
buf
++ =
src
[
i
++];
121
src
=
strdata
(
sep
);
len
=
sep
->
len
;
122
i
=
0
;
while
(
i
<
len
) *
buf
++ =
src
[
i
++];
123
src
=
g
->
tmpbuf
.
buf
;
len
+=
s
->
len
;
k
--;
/* Now copy that k-1 times. */
124
}
125
}
126
do
{
127
int32_t
i
=
0
;
128
do
{ *
buf
++ =
src
[
i
++]; }
while
(
i
<
len
);
129
}
while
(--
k
>
0
);
130
setstrV
(
L
,
L
->
base
-
1
,
lj_str_new
(
L
,
g
->
tmpbuf
.
buf
, (
size_t
)
tlen
));
131
return
FFH_RES
(
1
);
132
}
133
134
LJLIB_ASM
(
string_reverse
)
135
{
136
GCstr
*
s
=
lj_lib_checkstr
(
L
,
1
);
137
lj_str_needbuf
(
L
, &
G
(
L
)->
tmpbuf
,
s
->
len
);
138
return
FFH_RETRY
;
139
}
140
LJLIB_ASM_
(
string_lower
)
141
LJLIB_ASM_
(
string_upper
)
142
143
/* ------------------------------------------------------------------------ */
144
145
static int
writer_buf
(
lua_State
*
L
,
const void
*
p
,
size_t
size
,
void
*
b
)
146
{
147
luaL_addlstring
((
luaL_Buffer
*)
b
, (
const char
*)
p
,
size
);
148
UNUSED
(
L
);
149
return
0
;
150
}
151
152
LJLIB_CF
(
string_dump
)
153
{
154
GCfunc
*
fn
=
lj_lib_checkfunc
(
L
,
1
);
155
int
strip
=
L
->
base
+
1
<
L
->
top
&&
tvistruecond
(
L
->
base
+
1
);
156
luaL_Buffer b
;
157
L
->
top
=
L
->
base
+
1
;
158
luaL_buffinit
(
L
, &
b
);
159
if
(!
isluafunc
(
fn
) ||
lj_bcwrite
(
L
,
funcproto
(
fn
),
writer_buf
, &
b
,
strip
))
160
lj_err_caller
(
L
,
LJ_ERR_STRDUMP
);
161
luaL_pushresult
(&
b
);
162
return
1
;
163
}
164
165
/* ------------------------------------------------------------------------ */
166
167
/* macro to `unsign' a character */
168
#define uchar(c) ((unsigned char)(c))
169
170
#define CAP_UNFINISHED (-1)
171
#define CAP_POSITION (-2)
172
173
typedef
struct
MatchState
{
174
const char
*
src_init
;
/* init of source string */
175
const char
*
src_end
;
/* end (`0円') of source string */
176
lua_State
*
L
;
177
int
level
;
/* total number of captures (finished or unfinished) */
178
int
depth
;
179
struct
{
180
const char
*
init
;
181
ptrdiff_t
len
;
182
}
capture
[
LUA_MAXCAPTURES
];
183
}
MatchState
;
184
185
#define L_ESC
'%'
186
#define SPECIALS
"^$*+?.([%-"
187
188
static int
check_capture
(
MatchState
*
ms
,
int
l
)
189
{
190
l
-=
'1'
;
191
if
(
l
<
0
||
l
>=
ms
->
level
||
ms
->
capture
[
l
].
len
==
CAP_UNFINISHED
)
192
lj_err_caller
(
ms
->
L
,
LJ_ERR_STRCAPI
);
193
return
l
;
194
}
195
196
static int
capture_to_close
(
MatchState
*
ms
)
197
{
198
int
level
=
ms
->
level
;
199
for
(
level
--;
level
>=
0
;
level
--)
200
if
(
ms
->
capture
[
level
].
len
==
CAP_UNFINISHED
)
return
level
;
201
lj_err_caller
(
ms
->
L
,
LJ_ERR_STRPATC
);
202
return
0
;
/* unreachable */
203
}
204
205
static const char
*
classend
(
MatchState
*
ms
,
const char
*
p
)
206
{
207
switch
(*
p
++) {
208
case
L_ESC
:
209
if
(*
p
==
'0円'
)
210
lj_err_caller
(
ms
->
L
,
LJ_ERR_STRPATE
);
211
return
p
+
1
;
212
case
'['
:
213
if
(*
p
==
'^'
)
p
++;
214
do
{
/* look for a `]' */
215
if
(*
p
==
'0円'
)
216
lj_err_caller
(
ms
->
L
,
LJ_ERR_STRPATM
);
217
if
(*(
p
++) ==
L_ESC
&& *
p
!=
'0円'
)
218
p
++;
/* skip escapes (e.g. `%]') */
219
}
while
(*
p
!=
']'
);
220
return
p
+
1
;
221
default
:
222
return
p
;
223
}
224
}
225
226
static const unsigned char
match_class_map
[
32
] = {
227
0
,
LJ_CHAR_ALPHA
,
0
,
LJ_CHAR_CNTRL
,
LJ_CHAR_DIGIT
,
0
,
0
,
LJ_CHAR_GRAPH
,
0
,
0
,
0
,
0
,
228
LJ_CHAR_LOWER
,
0
,
0
,
0
,
LJ_CHAR_PUNCT
,
0
,
0
,
LJ_CHAR_SPACE
,
0
,
229
LJ_CHAR_UPPER
,
0
,
LJ_CHAR_ALNUM
,
LJ_CHAR_XDIGIT
,
0
,
0
,
0
,
0
,
0
,
0
,
0
230
};
231
232
static int
match_class
(
int
c
,
int
cl
)
233
{
234
if
((
cl
&
0xc0
) ==
0x40
) {
235
int
t
=
match_class_map
[(
cl
&
0x1f
)];
236
if
(
t
) {
237
t
=
lj_char_isa
(
c
,
t
);
238
return
(
cl
&
0x20
) ?
t
: !
t
;
239
}
240
if
(
cl
==
'z'
)
return
c
==
0
;
241
if
(
cl
==
'Z'
)
return
c
!=
0
;
242
}
243
return
(
cl
==
c
);
244
}
245
246
static int
matchbracketclass
(
int
c
,
const char
*
p
,
const char
*
ec
)
247
{
248
int
sig
=
1
;
249
if
(*(
p
+
1
) ==
'^'
) {
250
sig
=
0
;
251
p
++;
/* skip the `^' */
252
}
253
while
(++
p
<
ec
) {
254
if
(*
p
==
L_ESC
) {
255
p
++;
256
if
(
match_class
(
c
,
uchar
(*
p
)))
257
return
sig
;
258
}
259
else if
((*(
p
+
1
) ==
'-'
) && (
p
+
2
<
ec
)) {
260
p
+=
2
;
261
if
(
uchar
(*(
p
-
2
)) <=
c
&&
c
<=
uchar
(*
p
))
262
return
sig
;
263
}
264
else if
(
uchar
(*
p
) ==
c
)
return
sig
;
265
}
266
return
!
sig
;
267
}
268
269
static int
singlematch
(
int
c
,
const char
*
p
,
const char
*
ep
)
270
{
271
switch
(*
p
) {
272
case
'.'
:
return
1
;
/* matches any char */
273
case
L_ESC
:
return
match_class
(
c
,
uchar
(*(
p
+
1
)));
274
case
'['
:
return
matchbracketclass
(
c
,
p
,
ep
-
1
);
275
default
:
return
(
uchar
(*
p
) ==
c
);
276
}
277
}
278
279
static const char
*
match
(
MatchState
*
ms
,
const char
*
s
,
const char
*
p
);
280
281
static const char
*
matchbalance
(
MatchState
*
ms
,
const char
*
s
,
const char
*
p
)
282
{
283
if
(*
p
==
0
|| *(
p
+
1
) ==
0
)
284
lj_err_caller
(
ms
->
L
,
LJ_ERR_STRPATU
);
285
if
(*
s
!= *
p
) {
286
return
NULL
;
287
}
else
{
288
int
b
= *
p
;
289
int
e
= *(
p
+
1
);
290
int
cont
=
1
;
291
while
(++
s
<
ms
->
src_end
) {
292
if
(*
s
==
e
) {
293
if
(--
cont
==
0
)
return
s
+
1
;
294
}
else if
(*
s
==
b
) {
295
cont
++;
296
}
297
}
298
}
299
return
NULL
;
/* string ends out of balance */
300
}
301
302
static const char
*
max_expand
(
MatchState
*
ms
,
const char
*
s
,
303
const char
*
p
,
const char
*
ep
)
304
{
305
ptrdiff_t
i
=
0
;
/* counts maximum expand for item */
306
while
((
s
+
i
)<
ms
->
src_end
&&
singlematch
(
uchar
(*(
s
+
i
)),
p
,
ep
))
307
i
++;
308
/* keeps trying to match with the maximum repetitions */
309
while
(
i
>=
0
) {
310
const char
*
res
=
match
(
ms
, (
s
+
i
),
ep
+
1
);
311
if
(
res
)
return
res
;
312
i
--;
/* else didn't match; reduce 1 repetition to try again */
313
}
314
return
NULL
;
315
}
316
317
static const char
*
min_expand
(
MatchState
*
ms
,
const char
*
s
,
318
const char
*
p
,
const char
*
ep
)
319
{
320
for
(;;) {
321
const char
*
res
=
match
(
ms
,
s
,
ep
+
1
);
322
if
(
res
!=
NULL
)
323
return
res
;
324
else if
(
s
<
ms
->
src_end
&&
singlematch
(
uchar
(*
s
),
p
,
ep
))
325
s
++;
/* try with one more repetition */
326
else
327
return
NULL
;
328
}
329
}
330
331
static const char
*
start_capture
(
MatchState
*
ms
,
const char
*
s
,
332
const char
*
p
,
int
what
)
333
{
334
const char
*
res
;
335
int
level
=
ms
->
level
;
336
if
(
level
>=
LUA_MAXCAPTURES
)
lj_err_caller
(
ms
->
L
,
LJ_ERR_STRCAPN
);
337
ms
->
capture
[
level
].
init
=
s
;
338
ms
->
capture
[
level
].
len
=
what
;
339
ms
->
level
=
level
+
1
;
340
if
((
res
=
match
(
ms
,
s
,
p
)) ==
NULL
)
/* match failed? */
341
ms
->
level
--;
/* undo capture */
342
return
res
;
343
}
344
345
static const char
*
end_capture
(
MatchState
*
ms
,
const char
*
s
,
346
const char
*
p
)
347
{
348
int
l
=
capture_to_close
(
ms
);
349
const char
*
res
;
350
ms
->
capture
[
l
].
len
=
s
-
ms
->
capture
[
l
].
init
;
/* close capture */
351
if
((
res
=
match
(
ms
,
s
,
p
)) ==
NULL
)
/* match failed? */
352
ms
->
capture
[
l
].
len
=
CAP_UNFINISHED
;
/* undo capture */
353
return
res
;
354
}
355
356
static const char
*
match_capture
(
MatchState
*
ms
,
const char
*
s
,
int
l
)
357
{
358
size_t
len
;
359
l
=
check_capture
(
ms
,
l
);
360
len
= (
size_t
)
ms
->
capture
[
l
].
len
;
361
if
((
size_t
)(
ms
->
src_end
-
s
) >=
len
&&
362
memcmp
(
ms
->
capture
[
l
].
init
,
s
,
len
) ==
0
)
363
return
s
+
len
;
364
else
365
return
NULL
;
366
}
367
368
static const char
*
match
(
MatchState
*
ms
,
const char
*
s
,
const char
*
p
)
369
{
370
if
(++
ms
->
depth
>
LJ_MAX_XLEVEL
)
371
lj_err_caller
(
ms
->
L
,
LJ_ERR_STRPATX
);
372
init
:
/* using goto's to optimize tail recursion */
373
switch
(*
p
) {
374
case
'('
:
/* start capture */
375
if
(*(
p
+
1
) ==
')'
)
/* position capture? */
376
s
=
start_capture
(
ms
,
s
,
p
+
2
,
CAP_POSITION
);
377
else
378
s
=
start_capture
(
ms
,
s
,
p
+
1
,
CAP_UNFINISHED
);
379
break
;
380
case
')'
:
/* end capture */
381
s
=
end_capture
(
ms
,
s
,
p
+
1
);
382
break
;
383
case
L_ESC
:
384
switch
(*(
p
+
1
)) {
385
case
'b'
:
/* balanced string? */
386
s
=
matchbalance
(
ms
,
s
,
p
+
2
);
387
if
(
s
==
NULL
)
break
;
388
p
+=
4
;
389
goto
init
;
/* else s = match(ms, s, p+4); */
390
case
'f'
: {
/* frontier? */
391
const char
*
ep
;
char
previous
;
392
p
+=
2
;
393
if
(*
p
!=
'['
)
394
lj_err_caller
(
ms
->
L
,
LJ_ERR_STRPATB
);
395
ep
=
classend
(
ms
,
p
);
/* points to what is next */
396
previous
= (
s
==
ms
->
src_init
) ?
'0円'
: *(
s
-
1
);
397
if
(
matchbracketclass
(
uchar
(
previous
),
p
,
ep
-
1
) ||
398
!
matchbracketclass
(
uchar
(*
s
),
p
,
ep
-
1
)) {
s
=
NULL
;
break
; }
399
p
=
ep
;
400
goto
init
;
/* else s = match(ms, s, ep); */
401
}
402
default
:
403
if
(
lj_char_isdigit
(
uchar
(*(
p
+
1
)))) {
/* capture results (%0-%9)? */
404
s
=
match_capture
(
ms
,
s
,
uchar
(*(
p
+
1
)));
405
if
(
s
==
NULL
)
break
;
406
p
+=
2
;
407
goto
init
;
/* else s = match(ms, s, p+2) */
408
}
409
goto
dflt
;
/* case default */
410
}
411
break
;
412
case
'0円'
:
/* end of pattern */
413
break
;
/* match succeeded */
414
case
'$'
:
415
/* is the `$' the last char in pattern? */
416
if
(*(
p
+
1
) !=
'0円'
)
goto
dflt
;
417
if
(
s
!=
ms
->
src_end
)
s
=
NULL
;
/* check end of string */
418
break
;
419
default
:
dflt
: {
/* it is a pattern item */
420
const char
*
ep
=
classend
(
ms
,
p
);
/* points to what is next */
421
int
m
=
s
<
ms
->
src_end
&&
singlematch
(
uchar
(*
s
),
p
,
ep
);
422
switch
(*
ep
) {
423
case
'?'
: {
/* optional */
424
const char
*
res
;
425
if
(
m
&& ((
res
=
match
(
ms
,
s
+
1
,
ep
+
1
)) !=
NULL
)) {
426
s
=
res
;
427
break
;
428
}
429
p
=
ep
+
1
;
430
goto
init
;
/* else s = match(ms, s, ep+1); */
431
}
432
case
'*'
:
/* 0 or more repetitions */
433
s
=
max_expand
(
ms
,
s
,
p
,
ep
);
434
break
;
435
case
'+'
:
/* 1 or more repetitions */
436
s
= (
m
?
max_expand
(
ms
,
s
+
1
,
p
,
ep
) :
NULL
);
437
break
;
438
case
'-'
:
/* 0 or more repetitions (minimum) */
439
s
=
min_expand
(
ms
,
s
,
p
,
ep
);
440
break
;
441
default
:
442
if
(
m
) {
s
++;
p
=
ep
;
goto
init
; }
/* else s = match(ms, s+1, ep); */
443
s
=
NULL
;
444
break
;
445
}
446
break
;
447
}
448
}
449
ms
->
depth
--;
450
return
s
;
451
}
452
453
static const char
*
lmemfind
(
const char
*
s1
,
size_t
l1
,
454
const char
*
s2
,
size_t
l2
)
455
{
456
if
(
l2
==
0
) {
457
return
s1
;
/* empty strings are everywhere */
458
}
else if
(
l2
>
l1
) {
459
return
NULL
;
/* avoids a negative `l1' */
460
}
else
{
461
const char
*
init
;
/* to search for a `*s2' inside `s1' */
462
l2
--;
/* 1st char will be checked by `memchr' */
463
l1
=
l1
-
l2
;
/* `s2' cannot be found after that */
464
while
(
l1
>
0
&& (
init
= (
const char
*)
memchr
(
s1
, *
s2
,
l1
)) !=
NULL
) {
465
init
++;
/* 1st char is already checked */
466
if
(
memcmp
(
init
,
s2
+
1
,
l2
) ==
0
) {
467
return
init
-
1
;
468
}
else
{
/* correct `l1' and `s1' to try again */
469
l1
-= (
size_t
)(
init
-
s1
);
470
s1
=
init
;
471
}
472
}
473
return
NULL
;
/* not found */
474
}
475
}
476
477
static void
push_onecapture
(
MatchState
*
ms
,
int
i
,
const char
*
s
,
const char
*
e
)
478
{
479
if
(
i
>=
ms
->
level
) {
480
if
(
i
==
0
)
/* ms->level == 0, too */
481
lua_pushlstring
(
ms
->
L
,
s
, (
size_t
)(
e
-
s
));
/* add whole match */
482
else
483
lj_err_caller
(
ms
->
L
,
LJ_ERR_STRCAPI
);
484
}
else
{
485
ptrdiff_t
l
=
ms
->
capture
[
i
].
len
;
486
if
(
l
==
CAP_UNFINISHED
)
lj_err_caller
(
ms
->
L
,
LJ_ERR_STRCAPU
);
487
if
(
l
==
CAP_POSITION
)
488
lua_pushinteger
(
ms
->
L
,
ms
->
capture
[
i
].
init
-
ms
->
src_init
+
1
);
489
else
490
lua_pushlstring
(
ms
->
L
,
ms
->
capture
[
i
].
init
, (
size_t
)
l
);
491
}
492
}
493
494
static int
push_captures
(
MatchState
*
ms
,
const char
*
s
,
const char
*
e
)
495
{
496
int
i
;
497
int
nlevels
= (
ms
->
level
==
0
&&
s
) ?
1
:
ms
->
level
;
498
luaL_checkstack
(
ms
->
L
,
nlevels
,
"too many captures"
);
499
for
(
i
=
0
;
i
<
nlevels
;
i
++)
500
push_onecapture
(
ms
,
i
,
s
,
e
);
501
return
nlevels
;
/* number of strings pushed */
502
}
503
504
static ptrdiff_t
posrelat
(
ptrdiff_t
pos
,
size_t
len
)
505
{
506
/* relative string position: negative means back from end */
507
if
(
pos
<
0
)
pos
+= (
ptrdiff_t
)
len
+
1
;
508
return
(
pos
>=
0
) ?
pos
:
0
;
509
}
510
511
static int
str_find_aux
(
lua_State
*
L
,
int
find
)
512
{
513
size_t
l1
,
l2
;
514
const char
*
s
=
luaL_checklstring
(
L
,
1
, &
l1
);
515
const char
*
p
=
luaL_checklstring
(
L
,
2
, &
l2
);
516
ptrdiff_t
init
=
posrelat
(
luaL_optinteger
(
L
,
3
,
1
),
l1
) -
1
;
517
if
(
init
<
0
) {
518
init
=
0
;
519
}
else if
((
size_t
)(
init
) >
l1
) {
520
#if LJ_52
521
setnilV
(
L
->
top
-
1
);
522
return
1
;
523
#else
524
init
= (
ptrdiff_t
)
l1
;
525
#endif
526
}
527
if
(
find
&& (
lua_toboolean
(
L
,
4
) ||
/* explicit request? */
528
strpbrk
(
p
,
SPECIALS
) ==
NULL
)) {
/* or no special characters? */
529
/* do a plain search */
530
const char
*
s2
=
lmemfind
(
s
+
init
,
l1
-(
size_t
)
init
,
p
,
l2
);
531
if
(
s2
) {
532
lua_pushinteger
(
L
,
s2
-
s
+
1
);
533
lua_pushinteger
(
L
,
s2
-
s
+(
ptrdiff_t
)
l2
);
534
return
2
;
535
}
536
}
else
{
537
MatchState ms
;
538
int
anchor
= (*
p
==
'^'
) ? (
p
++,
1
) :
0
;
539
const char
*
s1
=
s
+
init
;
540
ms
.
L
=
L
;
541
ms
.
src_init
=
s
;
542
ms
.
src_end
=
s
+
l1
;
543
do
{
544
const char
*
res
;
545
ms
.
level
=
ms
.
depth
=
0
;
546
if
((
res
=
match
(&
ms
,
s1
,
p
)) !=
NULL
) {
547
if
(
find
) {
548
lua_pushinteger
(
L
,
s1
-
s
+
1
);
/* start */
549
lua_pushinteger
(
L
,
res
-
s
);
/* end */
550
return
push_captures
(&
ms
,
NULL
,
0
) +
2
;
551
}
else
{
552
return
push_captures
(&
ms
,
s1
,
res
);
553
}
554
}
555
}
while
(
s1
++ <
ms
.
src_end
&& !
anchor
);
556
}
557
lua_pushnil
(
L
);
/* not found */
558
return
1
;
559
}
560
561
LJLIB_CF
(
string_find
)
562
{
563
return
str_find_aux
(
L
,
1
);
564
}
565
566
LJLIB_CF
(
string_match
)
567
{
568
return
str_find_aux
(
L
,
0
);
569
}
570
571
LJLIB_NOREG
LJLIB_CF
(
string_gmatch_aux
)
572
{
573
const char
*
p
=
strVdata
(
lj_lib_upvalue
(
L
,
2
));
574
GCstr
*
str
=
strV
(
lj_lib_upvalue
(
L
,
1
));
575
const char
*
s
=
strdata
(
str
);
576
TValue
*
tvpos
=
lj_lib_upvalue
(
L
,
3
);
577
const char
*
src
=
s
+
tvpos
->
u32
.
lo
;
578
MatchState ms
;
579
ms
.
L
=
L
;
580
ms
.
src_init
=
s
;
581
ms
.
src_end
=
s
+
str
->
len
;
582
for
(;
src
<=
ms
.
src_end
;
src
++) {
583
const char
*
e
;
584
ms
.
level
=
ms
.
depth
=
0
;
585
if
((
e
=
match
(&
ms
,
src
,
p
)) !=
NULL
) {
586
int32_t
pos
= (
int32_t
)(
e
-
s
);
587
if
(
e
==
src
)
pos
++;
/* Ensure progress for empty match. */
588
tvpos
->
u32
.
lo
= (
uint32_t
)
pos
;
589
return
push_captures
(&
ms
,
src
,
e
);
590
}
591
}
592
return
0
;
/* not found */
593
}
594
595
LJLIB_CF
(
string_gmatch
)
596
{
597
lj_lib_checkstr
(
L
,
1
);
598
lj_lib_checkstr
(
L
,
2
);
599
L
->
top
=
L
->
base
+
3
;
600
(
L
->
top
-
1
)->
u64
=
0
;
601
lj_lib_pushcc
(
L
,
lj_cf_string_gmatch_aux
,
FF_string_gmatch_aux
,
3
);
602
return
1
;
603
}
604
605
static void
add_s
(
MatchState
*
ms
,
luaL_Buffer
*
b
,
const char
*
s
,
const char
*
e
)
606
{
607
size_t
l
,
i
;
608
const char
*
news
=
lua_tolstring
(
ms
->
L
,
3
, &
l
);
609
for
(
i
=
0
;
i
<
l
;
i
++) {
610
if
(
news
[
i
] !=
L_ESC
) {
611
luaL_addchar
(
b
,
news
[
i
]);
612
}
else
{
613
i
++;
/* skip ESC */
614
if
(!
lj_char_isdigit
(
uchar
(
news
[
i
]))) {
615
luaL_addchar
(
b
,
news
[
i
]);
616
}
else if
(
news
[
i
] ==
'0'
) {
617
luaL_addlstring
(
b
,
s
, (
size_t
)(
e
-
s
));
618
}
else
{
619
push_onecapture
(
ms
,
news
[
i
] -
'1'
,
s
,
e
);
620
luaL_addvalue
(
b
);
/* add capture to accumulated result */
621
}
622
}
623
}
624
}
625
626
static void
add_value
(
MatchState
*
ms
,
luaL_Buffer
*
b
,
627
const char
*
s
,
const char
*
e
)
628
{
629
lua_State
*
L
=
ms
->
L
;
630
switch
(
lua_type
(
L
,
3
)) {
631
case
LUA_TNUMBER
:
632
case
LUA_TSTRING
: {
633
add_s
(
ms
,
b
,
s
,
e
);
634
return
;
635
}
636
case
LUA_TFUNCTION
: {
637
int
n
;
638
lua_pushvalue
(
L
,
3
);
639
n
=
push_captures
(
ms
,
s
,
e
);
640
lua_call
(
L
,
n
,
1
);
641
break
;
642
}
643
case
LUA_TTABLE
: {
644
push_onecapture
(
ms
,
0
,
s
,
e
);
645
lua_gettable
(
L
,
3
);
646
break
;
647
}
648
}
649
if
(!
lua_toboolean
(
L
, -
1
)) {
/* nil or false? */
650
lua_pop
(
L
,
1
);
651
lua_pushlstring
(
L
,
s
, (
size_t
)(
e
-
s
));
/* keep original text */
652
}
else if
(!
lua_isstring
(
L
, -
1
)) {
653
lj_err_callerv
(
L
,
LJ_ERR_STRGSRV
,
luaL_typename
(
L
, -
1
));
654
}
655
luaL_addvalue
(
b
);
/* add result to accumulator */
656
}
657
658
LJLIB_CF
(
string_gsub
)
659
{
660
size_t
srcl
;
661
const char
*
src
=
luaL_checklstring
(
L
,
1
, &
srcl
);
662
const char
*
p
=
luaL_checkstring
(
L
,
2
);
663
int
tr
=
lua_type
(
L
,
3
);
664
int
max_s
=
luaL_optint
(
L
,
4
, (
int
)(
srcl
+
1
));
665
int
anchor
= (*
p
==
'^'
) ? (
p
++,
1
) :
0
;
666
int
n
=
0
;
667
MatchState ms
;
668
luaL_Buffer b
;
669
if
(!(
tr
==
LUA_TNUMBER
||
tr
==
LUA_TSTRING
||
670
tr
==
LUA_TFUNCTION
||
tr
==
LUA_TTABLE
))
671
lj_err_arg
(
L
,
3
,
LJ_ERR_NOSFT
);
672
luaL_buffinit
(
L
, &
b
);
673
ms
.
L
=
L
;
674
ms
.
src_init
=
src
;
675
ms
.
src_end
=
src
+
srcl
;
676
while
(
n
<
max_s
) {
677
const char
*
e
;
678
ms
.
level
=
ms
.
depth
=
0
;
679
e
=
match
(&
ms
,
src
,
p
);
680
if
(
e
) {
681
n
++;
682
add_value
(&
ms
, &
b
,
src
,
e
);
683
}
684
if
(
e
&&
e
>
src
)
/* non empty match? */
685
src
=
e
;
/* skip it */
686
else if
(
src
<
ms
.
src_end
)
687
luaL_addchar
(&
b
, *
src
++);
688
else
689
break
;
690
if
(
anchor
)
691
break
;
692
}
693
luaL_addlstring
(&
b
,
src
, (
size_t
)(
ms
.
src_end
-
src
));
694
luaL_pushresult
(&
b
);
695
lua_pushinteger
(
L
,
n
);
/* number of substitutions */
696
return
2
;
697
}
698
699
/* ------------------------------------------------------------------------ */
700
701
/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
702
#define MAX_FMTITEM 512
703
/* valid flags in a format specification */
704
#define FMT_FLAGS
"-+ #0"
705
/*
706
** maximum size of each format specification (such as '%-099.99d')
707
** (+10 accounts for %99.99x plus margin of error)
708
*/
709
#define MAX_FMTSPEC (sizeof(FMT_FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
710
711
static void
addquoted
(
lua_State
*
L
,
luaL_Buffer
*
b
,
int
arg
)
712
{
713
GCstr
*
str
=
lj_lib_checkstr
(
L
,
arg
);
714
int32_t
len
= (
int32_t
)
str
->
len
;
715
const char
*
s
=
strdata
(
str
);
716
luaL_addchar
(
b
,
'"'
);
717
while
(
len
--) {
718
uint32_t
c
=
uchar
(*
s
);
719
if
(
c
==
'"'
||
c
==
'
\\
'
||
c
==
'
\n
'
) {
720
luaL_addchar
(
b
,
'
\\
'
);
721
}
else if
(
lj_char_iscntrl
(
c
)) {
/* This can only be 0-31 or 127. */
722
uint32_t
d
;
723
luaL_addchar
(
b
,
'
\\
'
);
724
if
(
c
>=
100
||
lj_char_isdigit
(
uchar
(
s
[
1
]))) {
725
luaL_addchar
(
b
,
'0'
+(
c
>=
100
));
if
(
c
>=
100
)
c
-=
100
;
726
goto
tens
;
727
}
else if
(
c
>=
10
) {
728
tens
:
729
d
= (
c
*
205
) >>
11
;
c
-=
d
*
10
;
luaL_addchar
(
b
,
'0'
+
d
);
730
}
731
c
+=
'0'
;
732
}
733
luaL_addchar
(
b
,
c
);
734
s
++;
735
}
736
luaL_addchar
(
b
,
'"'
);
737
}
738
739
static const char
*
scanformat
(
lua_State
*
L
,
const char
*
strfrmt
,
char
*
form
)
740
{
741
const char
*
p
=
strfrmt
;
742
while
(*
p
!=
'0円'
&&
strchr
(
FMT_FLAGS
, *
p
) !=
NULL
)
p
++;
/* skip flags */
743
if
((
size_t
)(
p
-
strfrmt
) >=
sizeof
(
FMT_FLAGS
))
744
lj_err_caller
(
L
,
LJ_ERR_STRFMTR
);
745
if
(
lj_char_isdigit
(
uchar
(*
p
)))
p
++;
/* skip width */
746
if
(
lj_char_isdigit
(
uchar
(*
p
)))
p
++;
/* (2 digits at most) */
747
if
(*
p
==
'.'
) {
748
p
++;
749
if
(
lj_char_isdigit
(
uchar
(*
p
)))
p
++;
/* skip precision */
750
if
(
lj_char_isdigit
(
uchar
(*
p
)))
p
++;
/* (2 digits at most) */
751
}
752
if
(
lj_char_isdigit
(
uchar
(*
p
)))
753
lj_err_caller
(
L
,
LJ_ERR_STRFMTW
);
754
*(
form
++) =
'%'
;
755
strncpy
(
form
,
strfrmt
, (
size_t
)(
p
-
strfrmt
+
1
));
756
form
+=
p
-
strfrmt
+
1
;
757
*
form
=
'0円'
;
758
return
p
;
759
}
760
761
static void
addintlen
(
char
*
form
)
762
{
763
size_t
l
=
strlen
(
form
);
764
char
spec
=
form
[
l
-
1
];
765
strcpy
(
form
+
l
-
1
,
LUA_INTFRMLEN
);
766
form
[
l
+
sizeof
(
LUA_INTFRMLEN
) -
2
] =
spec
;
767
form
[
l
+
sizeof
(
LUA_INTFRMLEN
) -
1
] =
'0円'
;
768
}
769
770
static unsigned
LUA_INTFRM_T
num2intfrm
(
lua_State
*
L
,
int
arg
)
771
{
772
if
(
sizeof
(
LUA_INTFRM_T
) ==
4
) {
773
return
(
LUA_INTFRM_T
)
lj_lib_checkbit
(
L
,
arg
);
774
}
else
{
775
cTValue
*
o
;
776
lj_lib_checknumber
(
L
,
arg
);
777
o
=
L
->
base
+
arg
-
1
;
778
if
(
tvisint
(
o
))
779
return
(
LUA_INTFRM_T
)
intV
(
o
);
780
else
781
return
(
LUA_INTFRM_T
)
numV
(
o
);
782
}
783
}
784
785
static unsigned
LUA_INTFRM_T
num2uintfrm
(
lua_State
*
L
,
int
arg
)
786
{
787
if
(
sizeof
(
LUA_INTFRM_T
) ==
4
) {
788
return
(
unsigned
LUA_INTFRM_T
)
lj_lib_checkbit
(
L
,
arg
);
789
}
else
{
790
cTValue
*
o
;
791
lj_lib_checknumber
(
L
,
arg
);
792
o
=
L
->
base
+
arg
-
1
;
793
if
(
tvisint
(
o
))
794
return
(
unsigned
LUA_INTFRM_T
)
intV
(
o
);
795
else if
((
int32_t
)
o
->
u32
.
hi
<
0
)
796
return
(
unsigned
LUA_INTFRM_T
)(
LUA_INTFRM_T
)
numV
(
o
);
797
else
798
return
(
unsigned
LUA_INTFRM_T
)
numV
(
o
);
799
}
800
}
801
802
static
GCstr
*
meta_tostring
(
lua_State
*
L
,
int
arg
)
803
{
804
TValue
*
o
=
L
->
base
+
arg
-
1
;
805
cTValue
*
mo
;
806
lua_assert
(
o
<
L
->
top
);
/* Caller already checks for existence. */
807
if
(
LJ_LIKELY
(
tvisstr
(
o
)))
808
return
strV
(
o
);
809
if
(!
tvisnil
(
mo
=
lj_meta_lookup
(
L
,
o
,
MM_tostring
))) {
810
copyTV
(
L
,
L
->
top
++,
mo
);
811
copyTV
(
L
,
L
->
top
++,
o
);
812
lua_call
(
L
,
1
,
1
);
813
L
->
top
--;
814
if
(
tvisstr
(
L
->
top
))
815
return
strV
(
L
->
top
);
816
o
=
L
->
base
+
arg
-
1
;
817
copyTV
(
L
,
o
,
L
->
top
);
818
}
819
if
(
tvisnumber
(
o
)) {
820
return
lj_str_fromnumber
(
L
,
o
);
821
}
else if
(
tvisnil
(
o
)) {
822
return
lj_str_newlit
(
L
,
"nil"
);
823
}
else if
(
tvisfalse
(
o
)) {
824
return
lj_str_newlit
(
L
,
"false"
);
825
}
else if
(
tvistrue
(
o
)) {
826
return
lj_str_newlit
(
L
,
"true"
);
827
}
else
{
828
if
(
tvisfunc
(
o
) &&
isffunc
(
funcV
(
o
)))
829
lj_str_pushf
(
L
,
"function: builtin#%d"
,
funcV
(
o
)->
c
.
ffid
);
830
else
831
lj_str_pushf
(
L
,
"%s: %p"
,
lj_typename
(
o
),
lua_topointer
(
L
,
arg
));
832
L
->
top
--;
833
return
strV
(
L
->
top
);
834
}
835
}
836
837
LJLIB_CF
(
string_format
)
838
{
839
int
arg
=
1
,
top
= (
int
)(
L
->
top
-
L
->
base
);
840
GCstr
*
fmt
=
lj_lib_checkstr
(
L
,
arg
);
841
const char
*
strfrmt
=
strdata
(
fmt
);
842
const char
*
strfrmt_end
=
strfrmt
+
fmt
->
len
;
843
luaL_Buffer b
;
844
luaL_buffinit
(
L
, &
b
);
845
while
(
strfrmt
<
strfrmt_end
) {
846
if
(*
strfrmt
!=
L_ESC
) {
847
luaL_addchar
(&
b
, *
strfrmt
++);
848
}
else if
(*++
strfrmt
==
L_ESC
) {
849
luaL_addchar
(&
b
, *
strfrmt
++);
/* %% */
850
}
else
{
/* format item */
851
char
form
[
MAX_FMTSPEC
];
/* to store the format (`%...') */
852
char
buff
[
MAX_FMTITEM
];
/* to store the formatted item */
853
if
(++
arg
>
top
)
854
luaL_argerror
(
L
,
arg
,
lj_obj_typename
[
0
]);
855
strfrmt
=
scanformat
(
L
,
strfrmt
,
form
);
856
switch
(*
strfrmt
++) {
857
case
'c'
:
858
sprintf
(
buff
,
form
,
lj_lib_checkint
(
L
,
arg
));
859
break
;
860
case
'd'
:
case
'i'
:
861
addintlen
(
form
);
862
sprintf
(
buff
,
form
,
num2intfrm
(
L
,
arg
));
863
break
;
864
case
'o'
:
case
'u'
:
case
'x'
:
case
'X'
:
865
addintlen
(
form
);
866
sprintf
(
buff
,
form
,
num2uintfrm
(
L
,
arg
));
867
break
;
868
case
'e'
:
case
'E'
:
case
'f'
:
case
'g'
:
case
'G'
:
case
'a'
:
case
'A'
: {
869
TValue tv
;
870
tv
.
n
=
lj_lib_checknum
(
L
,
arg
);
871
if
(
LJ_UNLIKELY
((
tv
.
u32
.
hi
<<
1
) >=
0xffe00000
)) {
872
/* Canonicalize output of non-finite values. */
873
char
*
p
,
nbuf
[
LJ_STR_NUMBUF
];
874
size_t
len
=
lj_str_bufnum
(
nbuf
, &
tv
);
875
if
(
strfrmt
[-
1
] <
'a'
) {
876
nbuf
[
len
-
3
] =
nbuf
[
len
-
3
] -
0x20
;
877
nbuf
[
len
-
2
] =
nbuf
[
len
-
2
] -
0x20
;
878
nbuf
[
len
-
1
] =
nbuf
[
len
-
1
] -
0x20
;
879
}
880
nbuf
[
len
] =
'0円'
;
881
for
(
p
=
form
; *
p
<
'A'
&& *
p
!=
'.'
;
p
++) ;
882
*
p
++ =
's'
; *
p
=
'0円'
;
883
sprintf
(
buff
,
form
,
nbuf
);
884
break
;
885
}
886
sprintf
(
buff
,
form
, (
double
)
tv
.
n
);
887
break
;
888
}
889
case
'q'
:
890
addquoted
(
L
, &
b
,
arg
);
891
continue
;
892
case
'p'
:
893
lj_str_pushf
(
L
,
"%p"
,
lua_topointer
(
L
,
arg
));
894
luaL_addvalue
(&
b
);
895
continue
;
896
case
's'
: {
897
GCstr
*
str
=
meta_tostring
(
L
,
arg
);
898
if
(!
strchr
(
form
,
'.'
) &&
str
->
len
>=
100
) {
899
/* no precision and string is too long to be formatted;
900
keep original string */
901
setstrV
(
L
,
L
->
top
++,
str
);
902
luaL_addvalue
(&
b
);
903
continue
;
904
}
905
sprintf
(
buff
,
form
,
strdata
(
str
));
906
break
;
907
}
908
default
:
909
lj_err_callerv
(
L
,
LJ_ERR_STRFMTO
, *(
strfrmt
-
1
));
910
break
;
911
}
912
luaL_addlstring
(&
b
,
buff
,
strlen
(
buff
));
913
}
914
}
915
luaL_pushresult
(&
b
);
916
return
1
;
917
}
918
919
/* ------------------------------------------------------------------------ */
920
921
#include
"lj_libdef.h"
922
923
LUALIB_API
int
luaopen_string
(
lua_State
*
L
)
924
{
925
GCtab
*
mt
;
926
global_State
*
g
;
927
LJ_LIB_REG
(
L
,
LUA_STRLIBNAME
,
string
);
928
#if defined(LUA_COMPAT_GFIND) && !LJ_52
929
lua_getfield
(
L
, -
1
,
"gmatch"
);
930
lua_setfield
(
L
, -
2
,
"gfind"
);
931
#endif
932
mt
=
lj_tab_new
(
L
,
0
,
1
);
933
/* NOBARRIER: basemt is a GC root. */
934
g
=
G
(
L
);
935
setgcref
(
basemt_it
(
g
,
LJ_TSTR
),
obj2gco
(
mt
));
936
settabV
(
L
,
lj_tab_setstr
(
L
,
mt
,
mmname_str
(
g
,
MM_index
)),
tabV
(
L
->
top
-
1
));
937
mt
->
nomm
= (
uint8_t
)(~(
1u
<<
MM_index
));
938
return
1
;
939
}
940
LuaJIT is a Just-In-Time Compiler for the Lua programming language.
RSS
Atom
AltStyle
によって変換されたページ
(->オリジナル)
/
アドレス:
モード:
デフォルト
音声ブラウザ
ルビ付き
配色反転
文字拡大
モバイル