mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-22 11:03:12 +00:00
Compare commits
1547 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7506b6208f | ||
|
|
5027096d53 | ||
|
|
f19d1605b4 | ||
|
|
4b7addb28a | ||
|
|
83cff80c91 | ||
|
|
efc1d8d408 | ||
|
|
abc11d7b6a | ||
|
|
fe9f378a1a | ||
|
|
58774183a7 | ||
|
|
195a60d1f0 | ||
|
|
6f84247f1f | ||
|
|
2b6b106e57 | ||
|
|
c2150ba849 | ||
|
|
83fa834e1f | ||
|
|
bbb12f3c85 | ||
|
|
351d21d62c | ||
|
|
2a5d6c38ae | ||
|
|
e4a1250ebb | ||
|
|
bed435660e | ||
|
|
1bbdeb3132 | ||
|
|
a4c6e04ab0 | ||
|
|
9f7634d477 | ||
|
|
ae034cf692 | ||
|
|
022c619c63 | ||
|
|
0cf8de8649 | ||
|
|
406f3a7437 | ||
|
|
28e8087029 | ||
|
|
7c1f979959 | ||
|
|
2fca5221ec | ||
|
|
234e134967 | ||
|
|
5608d39789 | ||
|
|
2ecf32ec73 | ||
|
|
bdac405324 | ||
|
|
7386688320 | ||
|
|
d4b78b7ff1 | ||
|
|
528b6bd32f | ||
|
|
754932cef4 | ||
|
|
b02d619dd8 | ||
|
|
e21604783a | ||
|
|
4ff4db3161 | ||
|
|
5885514138 | ||
|
|
e0bc6fe2d6 | ||
|
|
077d1fbd64 | ||
|
|
5eab3d7e22 | ||
|
|
b2612d92eb | ||
|
|
94450ff00f | ||
|
|
438c4ee9ed | ||
|
|
1ba381a1c2 | ||
|
|
93e72a92ac | ||
|
|
ad96b6c736 | ||
|
|
ba64be6f9f | ||
|
|
e1c28ed13e | ||
|
|
474f04e864 | ||
|
|
7c3942cdbd | ||
|
|
88df42a60f | ||
|
|
cada3f5cb0 | ||
|
|
2fc8e86925 | ||
|
|
4c8d42153e | ||
|
|
b5403a6866 | ||
|
|
270ed6e198 | ||
|
|
8900360fab | ||
|
|
b1bb84ddbd | ||
|
|
839570ce3f | ||
|
|
bcf97ecd1b | ||
|
|
4dfdeb146e | ||
|
|
76d73c295f | ||
|
|
c2b391ed42 | ||
|
|
89372a257d | ||
|
|
b519c53fe4 | ||
|
|
027e599037 | ||
|
|
2cfe36a809 | ||
|
|
059fd5cc00 | ||
|
|
64a0ed4bfa | ||
|
|
41928512f0 | ||
|
|
afb50a0587 | ||
|
|
aa20f7642b | ||
|
|
f214c68ff3 | ||
|
|
dc1980dfc8 | ||
|
|
ccd923c44f | ||
|
|
c226ea3f1f | ||
|
|
45b407481d | ||
|
|
8f7e9cc823 | ||
|
|
89a821ced0 | ||
|
|
267e4ad44d | ||
|
|
1a0041982b | ||
|
|
caf513e6c0 | ||
|
|
18a6dc5786 | ||
|
|
22df64244a | ||
|
|
1d47bfa0b6 | ||
|
|
43225367fb | ||
|
|
cde8f75d68 | ||
|
|
9fd43778e2 | ||
|
|
72688f5771 | ||
|
|
3bbb62e673 | ||
|
|
c18f99eb7e | ||
|
|
bd5f12b959 | ||
|
|
267cf5384c | ||
|
|
6f24b08f02 | ||
|
|
d0b11c7955 | ||
|
|
6bdc8b8608 | ||
|
|
b309d82538 | ||
|
|
fb97668f9e | ||
|
|
9e000da81f | ||
|
|
d9c30f9119 | ||
|
|
4030687400 | ||
|
|
1f93f4864f | ||
|
|
e66e892ee5 | ||
|
|
30d967ea05 | ||
|
|
4b0937cc19 | ||
|
|
89b47f9372 | ||
|
|
6249062c2d | ||
|
|
8b5bbaabd9 | ||
|
|
f97c72d341 | ||
|
|
f7453973f8 | ||
|
|
0e6423484f | ||
|
|
adf0cc5a6f | ||
|
|
5ec02a4a2c | ||
|
|
f3f7e725e8 | ||
|
|
172278bc8f | ||
|
|
c178c398b9 | ||
|
|
93ea565bcb | ||
|
|
bb90b64c3f | ||
|
|
c6a8976bc3 | ||
|
|
074426e273 | ||
|
|
b402837628 | ||
|
|
272af34736 | ||
|
|
69420bdfde | ||
|
|
2f9d0c805a | ||
|
|
4893fa39ee | ||
|
|
a5af5f6ba7 | ||
|
|
8b55660274 | ||
|
|
d56cf80f95 | ||
|
|
aedfb9288d | ||
|
|
223bd599ba | ||
|
|
b9a5cec191 | ||
|
|
1e45d4a9be | ||
|
|
6fe520a7cb | ||
|
|
f344a49755 | ||
|
|
39f3ddbc10 | ||
|
|
cc562547a5 | ||
|
|
58b1bda0d9 | ||
|
|
98311b9b91 | ||
|
|
499610965a | ||
|
|
94a76269aa | ||
|
|
ae35b3c4e8 | ||
|
|
1a1d8abd2e | ||
|
|
feeda06e9d | ||
|
|
bc4800f326 | ||
|
|
ccfdc9440a | ||
|
|
182a1a8d56 | ||
|
|
44e2583dc2 | ||
|
|
7b76bcd039 | ||
|
|
2d5e4ae528 | ||
|
|
b61daaccf1 | ||
|
|
01314de8e1 | ||
|
|
c8197328a4 | ||
|
|
800a3376d6 | ||
|
|
6dda5f7f98 | ||
|
|
2a8c095e38 | ||
|
|
01b5d67b11 | ||
|
|
c1eeba215d | ||
|
|
6bd6f53ab8 | ||
|
|
dfc706615e | ||
|
|
8efad53631 | ||
|
|
0c1491ba99 | ||
|
|
1b54306509 | ||
|
|
3911e0738b | ||
|
|
fad27d7775 | ||
|
|
e98378e874 | ||
|
|
389146167f | ||
|
|
73c0e306cf | ||
|
|
6d86016247 | ||
|
|
acefd8de27 | ||
|
|
448fe14b9e | ||
|
|
341b7924a0 | ||
|
|
013cb42122 | ||
|
|
bcd012f9cf | ||
|
|
c4da547259 | ||
|
|
6ad379b7a7 | ||
|
|
ee103e97cd | ||
|
|
e37eb3cba0 | ||
|
|
0ddd938400 | ||
|
|
2d42adb739 | ||
|
|
9fd7a51b34 | ||
|
|
2660b10442 | ||
|
|
969d3291b6 | ||
|
|
c84f7354ff | ||
|
|
b555aa19e7 | ||
|
|
f72573a2aa | ||
|
|
bee8a0e731 | ||
|
|
5d48c02725 | ||
|
|
fad62566dc | ||
|
|
d1ce950dc1 | ||
|
|
eaba8f969c | ||
|
|
40ee98b40e | ||
|
|
b13281b77d | ||
|
|
3c4f673740 | ||
|
|
6d6be8dec6 | ||
|
|
923651ada3 | ||
|
|
8304747d8e | ||
|
|
5b5d5906cb | ||
|
|
9d3edae797 | ||
|
|
208be03a6f | ||
|
|
3b54b3bd80 | ||
|
|
839975415d | ||
|
|
27866518ef | ||
|
|
53292d1c93 | ||
|
|
1e2ed7e6ff | ||
|
|
350248a7cc | ||
|
|
d115e626e6 | ||
|
|
38e5b1ca1c | ||
|
|
a0a138c002 | ||
|
|
e35cad3053 | ||
|
|
8f7e19310c | ||
|
|
c008476417 | ||
|
|
599181ceaf | ||
|
|
432b0c07f9 | ||
|
|
58da8a1a22 | ||
|
|
0e11c78575 | ||
|
|
f80e2cd9b1 | ||
|
|
0ae839b2dd | ||
|
|
0ebecb4e6d | ||
|
|
9cbab6f5ec | ||
|
|
edbed9f980 | ||
|
|
987bb3df47 | ||
|
|
54e733a76f | ||
|
|
6ee8d23ac4 | ||
|
|
fdc4b35281 | ||
|
|
740b91533d | ||
|
|
0207b9210a | ||
|
|
0e9c0c34a9 | ||
|
|
d9762b8f38 | ||
|
|
72a6182601 | ||
|
|
39e0aaa27e | ||
|
|
338f53fbe0 | ||
|
|
5c154d34dc | ||
|
|
2bfecfceae | ||
|
|
3900067026 | ||
|
|
c90e288601 | ||
|
|
c2c585f73a | ||
|
|
219b15e9ec | ||
|
|
30b534b558 | ||
|
|
f5eee7dcbb | ||
|
|
ef4af820d5 | ||
|
|
71317d8502 | ||
|
|
6ad8da0993 | ||
|
|
28d47d96b9 | ||
|
|
1e6781bd41 | ||
|
|
f61a27ac6b | ||
|
|
1020c403dc | ||
|
|
f0d24ac718 | ||
|
|
52d65c5dcb | ||
|
|
2b71c2755a | ||
|
|
df2803469e | ||
|
|
bc71164a99 | ||
|
|
e69f876867 | ||
|
|
f9dc6a3756 | ||
|
|
0f5867534c | ||
|
|
ceb278adf6 | ||
|
|
85dde52107 | ||
|
|
8ad6622936 | ||
|
|
ba26c8a432 | ||
|
|
96c702bb3c | ||
|
|
811ef52b3d | ||
|
|
e0d4fda24e | ||
|
|
11165ce727 | ||
|
|
22b5fbf3b8 | ||
|
|
9228b05dfe | ||
|
|
a39c9b8b10 | ||
|
|
037c3a5c48 | ||
|
|
094b20aae7 | ||
|
|
bf5eacfe80 | ||
|
|
fd12f2ea8e | ||
|
|
7c0c13b07b | ||
|
|
b0dda0483d | ||
|
|
6f2866e5c4 | ||
|
|
213c9966e4 | ||
|
|
072d782651 | ||
|
|
600a64327e | ||
|
|
0d9bfcb721 | ||
|
|
8d895ab2f0 | ||
|
|
c12a7d1b99 | ||
|
|
77c965e9e8 | ||
|
|
0d949678b9 | ||
|
|
29a212db8e | ||
|
|
ccac1d4526 | ||
|
|
4bb883b989 | ||
|
|
6a8ca29d99 | ||
|
|
6a4a2482fc | ||
|
|
04dd921c5f | ||
|
|
8e32cc5283 | ||
|
|
8e45679d3d | ||
|
|
b626198592 | ||
|
|
eebd44da9d | ||
|
|
51a942d095 | ||
|
|
6d941a6de1 | ||
|
|
1a0461a9af | ||
|
|
e23ad8fc6b | ||
|
|
4534fb5269 | ||
|
|
41cc6d226c | ||
|
|
4532d4f146 | ||
|
|
30279f2f8d | ||
|
|
4c9c9ce6bd | ||
|
|
cfb638243f | ||
|
|
4cb84ac881 | ||
|
|
53a74ca029 | ||
|
|
2e06706323 | ||
|
|
649aee1a23 | ||
|
|
933dbbd570 | ||
|
|
1e5e8354d7 | ||
|
|
bc2fba560f | ||
|
|
1ed4fdf94d | ||
|
|
c0e3421462 | ||
|
|
b164e3a8a9 | ||
|
|
284df5430b | ||
|
|
4d88f96ed6 | ||
|
|
8022a53e50 | ||
|
|
698d032a9b | ||
|
|
8eac155b1b | ||
|
|
e8a48483ab | ||
|
|
4faa6499e8 | ||
|
|
704194226d | ||
|
|
ad06d232a6 | ||
|
|
8aa1587245 | ||
|
|
3af6b72aed | ||
|
|
56c70dc7ac | ||
|
|
693b962b43 | ||
|
|
5248d443dc | ||
|
|
9eb37198ea | ||
|
|
c7dc8751c7 | ||
|
|
2a076d8192 | ||
|
|
f27930e7f7 | ||
|
|
902fb94274 | ||
|
|
cb445f17d4 | ||
|
|
3f8a2f69df | ||
|
|
84e600bed3 | ||
|
|
80b60f23c9 | ||
|
|
6b74773f52 | ||
|
|
a6adc69090 | ||
|
|
1e945a1dec | ||
|
|
6c3e969e91 | ||
|
|
1dfddc0d84 | ||
|
|
bae00163b2 | ||
|
|
8a7c2b41a1 | ||
|
|
394a065ea2 | ||
|
|
8ea74c2b93 | ||
|
|
6dfdebc1a2 | ||
|
|
2eea8be7ac | ||
|
|
e241920949 | ||
|
|
e669913b2a | ||
|
|
55f207c1d2 | ||
|
|
b6354a0490 | ||
|
|
064e61d40f | ||
|
|
0971ce9912 | ||
|
|
77311c7243 | ||
|
|
e75d033066 | ||
|
|
a4221deac1 | ||
|
|
f3acbe46df | ||
|
|
471c7d1101 | ||
|
|
a87b039c6d | ||
|
|
623d8182eb | ||
|
|
992fd028f0 | ||
|
|
299d12e1cd | ||
|
|
4484c1ed50 | ||
|
|
eaa60ca8dd | ||
|
|
eef2b1fc62 | ||
|
|
a4c31ac64e | ||
|
|
280f0251da | ||
|
|
55efa75fdf | ||
|
|
ce52533c74 | ||
|
|
d3d5e3063a | ||
|
|
3025e4765a | ||
|
|
446dafdc0b | ||
|
|
c7386fe768 | ||
|
|
d80ed7483d | ||
|
|
c8d0b1014d | ||
|
|
51fd63213e | ||
|
|
a4dc6b9094 | ||
|
|
c35c8f173b | ||
|
|
ddedffc753 | ||
|
|
44485b195c | ||
|
|
950389599d | ||
|
|
c749b13010 | ||
|
|
875b7683c6 | ||
|
|
bfc19ee7b9 | ||
|
|
f2b1bd7319 | ||
|
|
693176efc8 | ||
|
|
435aa384c8 | ||
|
|
9f86498872 | ||
|
|
1f22216d7c | ||
|
|
b68b27f26b | ||
|
|
87cde31c28 | ||
|
|
949d943c32 | ||
|
|
2389772c73 | ||
|
|
22f25bad55 | ||
|
|
9222ff8d7a | ||
|
|
d94fbb6493 | ||
|
|
98434708c4 | ||
|
|
fd27676869 | ||
|
|
7efa79906d | ||
|
|
892189ff90 | ||
|
|
f6b8eba01e | ||
|
|
3c425b76bc | ||
|
|
6de4a012a7 | ||
|
|
99d43388ab | ||
|
|
ac38fd620b | ||
|
|
409646a240 | ||
|
|
da4360787f | ||
|
|
d3a6b8d80b | ||
|
|
672bdcf39f | ||
|
|
d232af70f2 | ||
|
|
c075de7425 | ||
|
|
f2d3bc3e5c | ||
|
|
386c709f42 | ||
|
|
64d6baa176 | ||
|
|
ed6dd39670 | ||
|
|
5527e9e32e | ||
|
|
3c7279a6b7 | ||
|
|
b2e50c3bfa | ||
|
|
99a7d745fb | ||
|
|
b295b875c8 | ||
|
|
a15c64a73b | ||
|
|
b7b595e53a | ||
|
|
0e3f37f38b | ||
|
|
a6293f27cd | ||
|
|
8450e7f366 | ||
|
|
4585da9cbd | ||
|
|
38c47b8a5d | ||
|
|
21d680d5b7 | ||
|
|
ec8e518abc | ||
|
|
082fb732e5 | ||
|
|
b5ea18f44b | ||
|
|
8aac2114e3 | ||
|
|
0e96c761f8 | ||
|
|
60f4f26b85 | ||
|
|
7240de08a9 | ||
|
|
4341106364 | ||
|
|
81a7c44a05 | ||
|
|
80d1082b42 | ||
|
|
9d7ea09789 | ||
|
|
58291a2a48 | ||
|
|
49c21916a2 | ||
|
|
6b4050bf2c | ||
|
|
f4d54182e9 | ||
|
|
f6679a778f | ||
|
|
082430147f | ||
|
|
6dd47e6690 | ||
|
|
d3c4bee0c9 | ||
|
|
15ae26b8bc | ||
|
|
29e7256948 | ||
|
|
4f050fa987 | ||
|
|
066c2c3a54 | ||
|
|
41c66d1b20 | ||
|
|
82ed7efb1b | ||
|
|
f17c17b8c7 | ||
|
|
8a1d7006eb | ||
|
|
4ddc1577ef | ||
|
|
9c4e0d5bb7 | ||
|
|
21b1c449de | ||
|
|
e485aae55b | ||
|
|
5025e6887f | ||
|
|
e4224137f1 | ||
|
|
478575436b | ||
|
|
65eb351a3b | ||
|
|
2e8659d5fc | ||
|
|
baf5987b0b | ||
|
|
7e42653f80 | ||
|
|
89f487e0a4 | ||
|
|
9193035767 | ||
|
|
4fa1ba57cb | ||
|
|
10fd5791f7 | ||
|
|
5d26fb3f18 | ||
|
|
7032f21d18 | ||
|
|
c80b462412 | ||
|
|
744fbea7ee | ||
|
|
5750b2d5ee | ||
|
|
e9581adfc4 | ||
|
|
6803f45aa1 | ||
|
|
8e2facbfb8 | ||
|
|
6f0e88dc59 | ||
|
|
5a0f68999e | ||
|
|
24b333a5e9 | ||
|
|
b45384cc9f | ||
|
|
7fed938593 | ||
|
|
ca4f549f0d | ||
|
|
a04e6b5b29 | ||
|
|
82f3e80e06 | ||
|
|
9ffa0c6e30 | ||
|
|
64d99c1bd5 | ||
|
|
da87df6b86 | ||
|
|
fafc4cad34 | ||
|
|
1b60c522b0 | ||
|
|
a8c1828786 | ||
|
|
ff9b0538a4 | ||
|
|
bed5f878dc | ||
|
|
505da68cb6 | ||
|
|
68e94b2792 | ||
|
|
e3c5d63a97 | ||
|
|
3a0981661c | ||
|
|
47d1047004 | ||
|
|
2bcc691c4d | ||
|
|
76b166f04a | ||
|
|
2ceb642b5d | ||
|
|
2d6d2c75a4 | ||
|
|
194940822e | ||
|
|
be590cfa8c | ||
|
|
6addb504e4 | ||
|
|
db61ec376a | ||
|
|
431feb6f16 | ||
|
|
2c8d373236 | ||
|
|
9b69af0a4d | ||
|
|
046fb69f84 | ||
|
|
6231f1c884 | ||
|
|
35aa00fb13 | ||
|
|
4159600fbc | ||
|
|
04e2a36c4a | ||
|
|
95cb848772 | ||
|
|
302fc580a5 | ||
|
|
3048eed2aa | ||
|
|
e0729a483d | ||
|
|
201becd3d1 | ||
|
|
77e2643728 | ||
|
|
9ba0860c70 | ||
|
|
4c17005c03 | ||
|
|
cf18b59d90 | ||
|
|
fbd932e846 | ||
|
|
8e8a92ca2d | ||
|
|
6ab841beec | ||
|
|
6f40120ad8 | ||
|
|
f8d55affba | ||
|
|
56d24f46d6 | ||
|
|
64e0c4daff | ||
|
|
5bf635c75c | ||
|
|
2011596de0 | ||
|
|
3c6c0f7aa4 | ||
|
|
ea0cc1fade | ||
|
|
ee1f5055ea | ||
|
|
305a29d885 | ||
|
|
2651929f5b | ||
|
|
1af78bc585 | ||
|
|
062f767bbf | ||
|
|
0c66252cd1 | ||
|
|
45afa0fdcf | ||
|
|
4c9c2ac41d | ||
|
|
bfbbe91efa | ||
|
|
eda9f771e6 | ||
|
|
7cb4bbb960 | ||
|
|
2c247b511e | ||
|
|
ea1affda4c | ||
|
|
1c3b563ef8 | ||
|
|
9ffdf2dbde | ||
|
|
000fa2be3a | ||
|
|
7746193b5f | ||
|
|
3f38a711ad | ||
|
|
1d4308f33a | ||
|
|
48e5c36b5e | ||
|
|
1422cae7fb | ||
|
|
9e16b04a5b | ||
|
|
0fbbd5f4d5 | ||
|
|
6eb9b64f06 | ||
|
|
d71c8f8b7d | ||
|
|
68c3762abf | ||
|
|
304272249e | ||
|
|
2102d8b9f0 | ||
|
|
2ee85a91f9 | ||
|
|
8a3a0c1b71 | ||
|
|
b4752f2394 | ||
|
|
f110b51290 | ||
|
|
e0f16b8df5 | ||
|
|
08e56f4316 | ||
|
|
7e57e498f6 | ||
|
|
98b5c7c7c6 | ||
|
|
02d5f4fbe9 | ||
|
|
818ff8314d | ||
|
|
d23e6f8d8e | ||
|
|
f217a56f6e | ||
|
|
46b49adf9e | ||
|
|
d9fb4d06ec | ||
|
|
34a9979255 | ||
|
|
89e7a06deb | ||
|
|
43d02ac456 | ||
|
|
c839159470 | ||
|
|
823b773051 | ||
|
|
f8434d34b6 | ||
|
|
61980c8a1f | ||
|
|
35176383b7 | ||
|
|
c96e20e6c3 | ||
|
|
ce0cdc7bd3 | ||
|
|
7e63080c03 | ||
|
|
1c8ed8a46e | ||
|
|
c4334be9c3 | ||
|
|
e6e69ae805 | ||
|
|
8ce816de7f | ||
|
|
2fb52f6fce | ||
|
|
c72d4d2134 | ||
|
|
18a36c171f | ||
|
|
7b3c1631d1 | ||
|
|
4613fde654 | ||
|
|
143baec319 | ||
|
|
168a07d658 | ||
|
|
281acf4c71 | ||
|
|
d2ab6863e3 | ||
|
|
e55ad63d3c | ||
|
|
ec2eaa70a4 | ||
|
|
d402619347 | ||
|
|
c101d9df17 | ||
|
|
b5653a68ea | ||
|
|
c9942deaa9 | ||
|
|
2df1446c37 | ||
|
|
9421815327 | ||
|
|
1a0c9997ec | ||
|
|
16f060f864 | ||
|
|
ea7c6402dd | ||
|
|
07db2580c4 | ||
|
|
1df72c0afe | ||
|
|
0e41231298 | ||
|
|
8224b5a62a | ||
|
|
d8ab9dea1b | ||
|
|
a8e5c31381 | ||
|
|
3a1556e1fd | ||
|
|
4b5fbab129 | ||
|
|
b1ec1f4d18 | ||
|
|
16d8f4c774 | ||
|
|
f8b5ec48e8 | ||
|
|
7a26926965 | ||
|
|
2990fbc7cf | ||
|
|
e8e38f1682 | ||
|
|
35b4a09c3d | ||
|
|
9035fbe96b | ||
|
|
a41a5fadd2 | ||
|
|
d6f265e703 | ||
|
|
596c77afcd | ||
|
|
e53d985c4f | ||
|
|
348e53245b | ||
|
|
2fde0a0ae4 | ||
|
|
85ec428f3f | ||
|
|
a8ab809928 | ||
|
|
6c7cb5313d | ||
|
|
188e38198a | ||
|
|
294f557268 | ||
|
|
4dd622e180 | ||
|
|
5f8e5f9be5 | ||
|
|
e561896966 | ||
|
|
ea25e20c88 | ||
|
|
003b0fdb02 | ||
|
|
8de6500677 | ||
|
|
7df13e922b | ||
|
|
182d7c7dc7 | ||
|
|
f4d5bc7aa4 | ||
|
|
d53d98b625 | ||
|
|
2bfba716ef | ||
|
|
4cbe33d15d | ||
|
|
a9852273cb | ||
|
|
eb8a2b5e65 | ||
|
|
7304a990cb | ||
|
|
311d7c8f6a | ||
|
|
5a3d2fdac7 | ||
|
|
4b88f68ab8 | ||
|
|
70c224c3e7 | ||
|
|
1932d33b41 | ||
|
|
9cf4525a8f | ||
|
|
0846a6533d | ||
|
|
484404295e | ||
|
|
3e54becb95 | ||
|
|
ab13305b64 | ||
|
|
6fdb123df4 | ||
|
|
6cdc1cf95c | ||
|
|
2dd5a06616 | ||
|
|
e7436bfa95 | ||
|
|
084aab4bcd | ||
|
|
cd99557368 | ||
|
|
04f4004934 | ||
|
|
bbf46f935a | ||
|
|
b792c7144d | ||
|
|
5d5112257c | ||
|
|
747e6c7848 | ||
|
|
45d848c910 | ||
|
|
f12fa7e8f9 | ||
|
|
568a435e9e | ||
|
|
c46f2633be | ||
|
|
b51e28a3e0 | ||
|
|
badfab8561 | ||
|
|
d5c0d687b3 | ||
|
|
57f08426ee | ||
|
|
ba59b879ad | ||
|
|
1e9e16f16b | ||
|
|
ece075ef6e | ||
|
|
c4c429b699 | ||
|
|
21f881910b | ||
|
|
37157273ff | ||
|
|
460ed2e9e2 | ||
|
|
03ce7ab385 | ||
|
|
1c605bed2b | ||
|
|
55136b77ad | ||
|
|
d8798a280a | ||
|
|
c8d6ffd393 | ||
|
|
100329f09f | ||
|
|
553c30c6d1 | ||
|
|
415459e656 | ||
|
|
596e8cfab2 | ||
|
|
dab4419335 | ||
|
|
932ebfa0fd | ||
|
|
9d74307836 | ||
|
|
7be5ea0148 | ||
|
|
525279e9dd | ||
|
|
d0fbf0802f | ||
|
|
fad154f474 | ||
|
|
40543d42d5 | ||
|
|
fa763181c0 | ||
|
|
e48e6c40e7 | ||
|
|
64a318a9f1 | ||
|
|
5e50aeab2b | ||
|
|
53fef98acf | ||
|
|
f94ca6f4b3 | ||
|
|
90536e4a0d | ||
|
|
9c37f5292a | ||
|
|
23ee7dd814 | ||
|
|
990bede9b2 | ||
|
|
b8d18d198e | ||
|
|
6d81c2b818 | ||
|
|
f966199f28 | ||
|
|
793fa4fdeb | ||
|
|
814cd31cee | ||
|
|
bf9466d568 | ||
|
|
317b4fb08f | ||
|
|
2b5c5e3dd3 | ||
|
|
d6eb49e4eb | ||
|
|
751517d7c1 | ||
|
|
03acc7f5a9 | ||
|
|
9320d8b28d | ||
|
|
86883c7d9a | ||
|
|
2553afd6c9 | ||
|
|
9fc8754369 | ||
|
|
ba59ed2e6c | ||
|
|
14aab9085a | ||
|
|
eb2bc91e3f | ||
|
|
38171f3bc9 | ||
|
|
72b6039328 | ||
|
|
c10cceb1f7 | ||
|
|
7dd78ec89d | ||
|
|
01032087ec | ||
|
|
933f6730b2 | ||
|
|
2b7b51614c | ||
|
|
a9122a9fe1 | ||
|
|
78ea3d4091 | ||
|
|
b3c60d1de2 | ||
|
|
b438d5a6b0 | ||
|
|
aa42534208 | ||
|
|
171f8eef01 | ||
|
|
e96b4e782d | ||
|
|
626ad544b7 | ||
|
|
c53da829d3 | ||
|
|
eeb06014da | ||
|
|
cc138adda9 | ||
|
|
5632dbeec3 | ||
|
|
8ca47f76bf | ||
|
|
48e031f2fb | ||
|
|
5479848df6 | ||
|
|
52026eb8f2 | ||
|
|
af1769aa25 | ||
|
|
953fa2c819 | ||
|
|
6f670685e2 | ||
|
|
9618dd47ce | ||
|
|
c72a133178 | ||
|
|
7a4189f830 | ||
|
|
a8b5b36737 | ||
|
|
6e36cf9940 | ||
|
|
1328895ff9 | ||
|
|
4e54a27500 | ||
|
|
a0ac8640c7 | ||
|
|
38e4d81fb1 | ||
|
|
2798c778c7 | ||
|
|
94374cf06f | ||
|
|
624fbf6f22 | ||
|
|
5aa3ed8d8f | ||
|
|
c7d2e2cb0e | ||
|
|
895c0dae3b | ||
|
|
1d364b5c22 | ||
|
|
5a4ebe6a73 | ||
|
|
2be915e3c7 | ||
|
|
f9f009a4c1 | ||
|
|
f1ed482001 | ||
|
|
8a6243d2a0 | ||
|
|
24537b3001 | ||
|
|
25763fc70b | ||
|
|
7400e51451 | ||
|
|
a504c5e624 | ||
|
|
648504119e | ||
|
|
acb0c57844 | ||
|
|
ea129cd9f6 | ||
|
|
4b2efd4785 | ||
|
|
72e3973cf9 | ||
|
|
d4eeb1ff28 | ||
|
|
fd427843a9 | ||
|
|
73e61a9cc6 | ||
|
|
cce8f0086a | ||
|
|
a7be332023 | ||
|
|
3fb46241f2 | ||
|
|
1153873321 | ||
|
|
000b46ec37 | ||
|
|
3b6b31266d | ||
|
|
89d771929a | ||
|
|
77ed1bd68b | ||
|
|
b7d79ff343 | ||
|
|
dab5a4e308 | ||
|
|
999a941110 | ||
|
|
ad36be1bd7 | ||
|
|
66f8fbd1b7 | ||
|
|
7b10ee8d56 | ||
|
|
62a4bcdc71 | ||
|
|
312943c6a0 | ||
|
|
61d13846cd | ||
|
|
8e7796a672 | ||
|
|
6fa241453c | ||
|
|
1f4a84edc2 | ||
|
|
6699279d53 | ||
|
|
2a79d7bed9 | ||
|
|
fd0291845f | ||
|
|
570a8356e6 | ||
|
|
6289b2b8e4 | ||
|
|
3a4a673b43 | ||
|
|
67b055009d | ||
|
|
80d9ec379f | ||
|
|
673ffcce00 | ||
|
|
6170346da2 | ||
|
|
b00b006c4a | ||
|
|
48034ae22e | ||
|
|
1cdc0d7558 | ||
|
|
cb19ab54e9 | ||
|
|
feab147563 | ||
|
|
f5911342e8 | ||
|
|
c6cbc2f6b6 | ||
|
|
ca290355fa | ||
|
|
2b55bc57a4 | ||
|
|
5c831e2465 | ||
|
|
521a387271 | ||
|
|
f25e396181 | ||
|
|
6fd1072fde | ||
|
|
d637d720db | ||
|
|
5c508e45a7 | ||
|
|
2e919505f1 | ||
|
|
af6b5609de | ||
|
|
9e90ee2dde | ||
|
|
8bc018fe20 | ||
|
|
2dbb0129d3 | ||
|
|
f10793e99b | ||
|
|
1e51af2d62 | ||
|
|
7ee9cdb29b | ||
|
|
a3eccf5e37 | ||
|
|
ace41d7c22 | ||
|
|
d0a41eb494 | ||
|
|
060e5384f5 | ||
|
|
0e6a106180 | ||
|
|
bac383441e | ||
|
|
3498bf9329 | ||
|
|
708d57a77e | ||
|
|
c5fb8ef3f7 | ||
|
|
ffe5de468e | ||
|
|
249ffb9362 | ||
|
|
07a1499886 | ||
|
|
9c6f8f8b82 | ||
|
|
f48eeca667 | ||
|
|
ccb0e1b24c | ||
|
|
18bc3216ae | ||
|
|
0782b355a4 | ||
|
|
c91efa5134 | ||
|
|
26ad20aa2b | ||
|
|
283c3f10fe | ||
|
|
2f23367671 | ||
|
|
c082d71a56 | ||
|
|
e2fa2a1a4d | ||
|
|
9882dd1cfd | ||
|
|
b278106336 | ||
|
|
97538286fd | ||
|
|
fd1b230a54 | ||
|
|
33321e89a1 | ||
|
|
b50e663a3a | ||
|
|
14a699cb85 | ||
|
|
098d44162b | ||
|
|
16af94795e | ||
|
|
00f41c6bc9 | ||
|
|
0465688403 | ||
|
|
8cd5834d28 | ||
|
|
040089639f | ||
|
|
81c4e47a6d | ||
|
|
2aef994aa4 | ||
|
|
ffa2bbf1e4 | ||
|
|
6a54fe8293 | ||
|
|
2020ce3c9c | ||
|
|
2557559d5c | ||
|
|
bb0143e476 | ||
|
|
fd2c814fe0 | ||
|
|
bd3d9b70ec | ||
|
|
ee1a218870 | ||
|
|
84ee3da79a | ||
|
|
fdee7de36d | ||
|
|
bf5b74b6ca | ||
|
|
d9b0347741 | ||
|
|
9546537256 | ||
|
|
f84fe84b96 | ||
|
|
ea9bc53261 | ||
|
|
0edb839c95 | ||
|
|
b8bb327f98 | ||
|
|
27d69334ee | ||
|
|
838e63ab62 | ||
|
|
ba264700dc | ||
|
|
e00ad7ab79 | ||
|
|
de176b735f | ||
|
|
cc3e985834 | ||
|
|
3b5f45eea2 | ||
|
|
c3056b04c1 | ||
|
|
58755a6772 | ||
|
|
1cf976c4e4 | ||
|
|
5be836527c | ||
|
|
e9f397945d | ||
|
|
78df0b8161 | ||
|
|
db17245005 | ||
|
|
4edb586077 | ||
|
|
ed1a8313f4 | ||
|
|
c450b7b5d7 | ||
|
|
56846b7dda | ||
|
|
fb232cc43e | ||
|
|
a5c79cc4bd | ||
|
|
4b96ade660 | ||
|
|
76d1e6fa1f | ||
|
|
a6299a0748 | ||
|
|
6cc558bb82 | ||
|
|
84b08bf286 | ||
|
|
4ada09b93c | ||
|
|
2862568eca | ||
|
|
ed2e16a346 | ||
|
|
45d46b9072 | ||
|
|
4924c6d30b | ||
|
|
6b2eb80188 | ||
|
|
298e4baf0e | ||
|
|
c5fb93823a | ||
|
|
f238113677 | ||
|
|
f56d777cc2 | ||
|
|
b124d4c1b8 | ||
|
|
4fe098713f | ||
|
|
146f8ea09d | ||
|
|
69b5bd8c13 | ||
|
|
dd7e962c94 | ||
|
|
5332021086 | ||
|
|
8de3149485 | ||
|
|
e3fee604e1 | ||
|
|
dd152fc910 | ||
|
|
c4b45acae3 | ||
|
|
cf50a582f2 | ||
|
|
ca5e855c34 | ||
|
|
13d1d9fc9d | ||
|
|
242ff32bca | ||
|
|
ba451c1cd2 | ||
|
|
e5490522ce | ||
|
|
ae717c3e7d | ||
|
|
1a7df9108a | ||
|
|
7771e180ec | ||
|
|
82bbb1c944 | ||
|
|
cbf22ac9f3 | ||
|
|
bacaf10f1b | ||
|
|
8f7fa6a562 | ||
|
|
7b96eb28eb | ||
|
|
14ccf96eb0 | ||
|
|
6303886b8c | ||
|
|
ea8557296b | ||
|
|
2a821fb62a | ||
|
|
d982009260 | ||
|
|
a3f028ee3d | ||
|
|
d34b092cdd | ||
|
|
77f4071191 | ||
|
|
653b29145d | ||
|
|
96e0a4e3cc | ||
|
|
1da92850a0 | ||
|
|
9747cf9aee | ||
|
|
7f45b3fd10 | ||
|
|
217ab47577 | ||
|
|
532f47444b | ||
|
|
24f9ee1560 | ||
|
|
d7a76c7c72 | ||
|
|
c175d66e23 | ||
|
|
30cbcfd013 | ||
|
|
05003e3e2a | ||
|
|
64c2cb1b51 | ||
|
|
7f0e4eac8a | ||
|
|
141a4d0992 | ||
|
|
645ce72e7e | ||
|
|
fca4d67a43 | ||
|
|
014cbb9676 | ||
|
|
a39e822184 | ||
|
|
a3a7d129ab | ||
|
|
2e69370594 | ||
|
|
bcdfcde72f | ||
|
|
0c4ea81709 | ||
|
|
b9ad559992 | ||
|
|
f0ac66787e | ||
|
|
5a1b2e51f7 | ||
|
|
7acf6d8767 | ||
|
|
20610723a1 | ||
|
|
9d6bde01a3 | ||
|
|
4a80a75fd6 | ||
|
|
872491e968 | ||
|
|
41252e8c21 | ||
|
|
a9fc577560 | ||
|
|
4f8427a23f | ||
|
|
8ff5bcb372 | ||
|
|
bfe8eeb4b3 | ||
|
|
ccb9cdbc9d | ||
|
|
4006faac29 | ||
|
|
03617f23a1 | ||
|
|
d4d188541f | ||
|
|
3a2766dd0e | ||
|
|
1431f55d28 | ||
|
|
22c0d3ab73 | ||
|
|
940a7ac58c | ||
|
|
05605e62a9 | ||
|
|
3a527f0a66 | ||
|
|
e47a4921fa | ||
|
|
c180036bed | ||
|
|
d35388581f | ||
|
|
2c3f3ac3c6 | ||
|
|
09670ee733 | ||
|
|
fbbda08bb2 | ||
|
|
0f454fe248 | ||
|
|
91c720ad6f | ||
|
|
3335ea11d7 | ||
|
|
8d83881808 | ||
|
|
f4437948ca | ||
|
|
2252409eaa | ||
|
|
87bc0815f6 | ||
|
|
30859a1244 | ||
|
|
107be7ee8c | ||
|
|
86d9d52308 | ||
|
|
9982cb6652 | ||
|
|
ce50c47c2b | ||
|
|
34d9b5555d | ||
|
|
85062632bb | ||
|
|
d2396f9d20 | ||
|
|
471aecd708 | ||
|
|
d283d7fcaa | ||
|
|
b72f0921d4 | ||
|
|
6be649c5cb | ||
|
|
5edde990d6 | ||
|
|
77813b446c | ||
|
|
7138144a68 | ||
|
|
fa729d593b | ||
|
|
9f3baf2ee3 | ||
|
|
7521fe0530 | ||
|
|
c28ae25c70 | ||
|
|
9382454bcd | ||
|
|
d83fc0c00f | ||
|
|
31340cf346 | ||
|
|
d1b26a60eb | ||
|
|
ac4d51b779 | ||
|
|
0efab15f45 | ||
|
|
0199ba1382 | ||
|
|
935863f434 | ||
|
|
13d920e185 | ||
|
|
a4af35f442 | ||
|
|
b1060478f7 | ||
|
|
1999a03ff7 | ||
|
|
f5740e00b1 | ||
|
|
1653b3213a | ||
|
|
fe3954fb04 | ||
|
|
716ecccaed | ||
|
|
26cbebfcfd | ||
|
|
2d27df6f46 | ||
|
|
bab91a3067 | ||
|
|
c1c032eab4 | ||
|
|
7486e53232 | ||
|
|
9aaa35ef14 | ||
|
|
d2f2e299d5 | ||
|
|
d7e4e43a1b | ||
|
|
878110f9f7 | ||
|
|
60692e58dc | ||
|
|
515326dadc | ||
|
|
4ee59edc44 | ||
|
|
8dd9923cf6 | ||
|
|
8c1011c503 | ||
|
|
8924b86ad7 | ||
|
|
14bc029864 | ||
|
|
79e73d907e | ||
|
|
3a06dcf534 | ||
|
|
97fd5053c9 | ||
|
|
3a3159d429 | ||
|
|
97ff6afc84 | ||
|
|
cb9feb34bd | ||
|
|
48f79fe6d4 | ||
|
|
63942496fd | ||
|
|
bf9fc0c7e9 | ||
|
|
325452a242 | ||
|
|
752a501f68 | ||
|
|
008351573a | ||
|
|
00dbf6e996 | ||
|
|
8cc5638f14 | ||
|
|
b8f419eb69 | ||
|
|
8f284e2d7f | ||
|
|
846d55eaef | ||
|
|
6c33f7bc44 | ||
|
|
7797de85b4 | ||
|
|
7ec452c782 | ||
|
|
7f9c3c8c9a | ||
|
|
bad3472124 | ||
|
|
4f665d2469 | ||
|
|
633e5fbe32 | ||
|
|
c1c5cd39e5 | ||
|
|
03f5da6bb5 | ||
|
|
1bfddda435 | ||
|
|
9b0e496afe | ||
|
|
010d1c1d4f | ||
|
|
eb587c63d3 | ||
|
|
bb6d5d826e | ||
|
|
9acce94464 | ||
|
|
c0862d8445 | ||
|
|
1b53e6e28d | ||
|
|
77bdfb2ceb | ||
|
|
2583af26d7 | ||
|
|
a38a3140dd | ||
|
|
bf8f9b8654 | ||
|
|
0ce9921c25 | ||
|
|
adc39705f3 | ||
|
|
a4f827a48d | ||
|
|
7547126570 | ||
|
|
926b44ddf6 | ||
|
|
d3771edc9d | ||
|
|
947727e33a | ||
|
|
27148981d5 | ||
|
|
6fa436e8ff | ||
|
|
2935ba3521 | ||
|
|
5c8ea6f09f | ||
|
|
c16ae57639 | ||
|
|
1c7d44fd4d | ||
|
|
ca7e38137d | ||
|
|
5936d3616c | ||
|
|
e9cfdba22a | ||
|
|
3156661e0b | ||
|
|
b4048a8eab | ||
|
|
aff73cbed7 | ||
|
|
b5244b96aa | ||
|
|
704b016f2c | ||
|
|
3b48beb428 | ||
|
|
4cbead28d5 | ||
|
|
b3f966bcaa | ||
|
|
7b54e37d12 | ||
|
|
e87ac18b84 | ||
|
|
05af87ce8e | ||
|
|
0ee61de22c | ||
|
|
1da8a6b38d | ||
|
|
b2d8237363 | ||
|
|
39f9a96b6c | ||
|
|
588c4a3508 | ||
|
|
d6734890e0 | ||
|
|
4ebb139c2b | ||
|
|
20476d2280 | ||
|
|
3131bca6ef | ||
|
|
3f91484791 | ||
|
|
a0ecd51230 | ||
|
|
dba1db9cc4 | ||
|
|
538414408d | ||
|
|
4cf05fb2e7 | ||
|
|
d9ad981c8c | ||
|
|
21c941fe63 | ||
|
|
ea2437e138 | ||
|
|
86bbc9c701 | ||
|
|
95e1d9f45f | ||
|
|
55cf9375fc | ||
|
|
654f732cd5 | ||
|
|
d4023c8b63 | ||
|
|
375f8606b4 | ||
|
|
d17e6f59fe | ||
|
|
a77d36911d | ||
|
|
4352dc4047 | ||
|
|
172356be19 | ||
|
|
08dabd51c8 | ||
|
|
bd55a58515 | ||
|
|
b646a1b8a3 | ||
|
|
6b312fa09a | ||
|
|
dad66010cd | ||
|
|
27ae0a7500 | ||
|
|
6001d9c2eb | ||
|
|
728abeaeb8 | ||
|
|
2fa130997f | ||
|
|
8c57ec192a | ||
|
|
0fb2b21ed5 | ||
|
|
1fd2c3de81 | ||
|
|
f3536bfc53 | ||
|
|
57999456ef | ||
|
|
35b35f686c | ||
|
|
5d9142110e | ||
|
|
2086e13a46 | ||
|
|
f36b173155 | ||
|
|
7fa1d548ed | ||
|
|
039235b3a3 | ||
|
|
57d43a588e | ||
|
|
8214c53891 | ||
|
|
5e642b15a4 | ||
|
|
ac093c7142 | ||
|
|
01dcc45827 | ||
|
|
d3ac522dc6 | ||
|
|
55d0d57d5c | ||
|
|
1fec2e6063 | ||
|
|
cc4756de35 | ||
|
|
7fb109dbb0 | ||
|
|
7f578be649 | ||
|
|
69946d75c5 | ||
|
|
24f6994b50 | ||
|
|
07dbfd8651 | ||
|
|
ca50a5f518 | ||
|
|
b8c54cbac2 | ||
|
|
3a2c43e9e0 | ||
|
|
205824ab12 | ||
|
|
4ac047b274 | ||
|
|
987a90af8b | ||
|
|
250531c9a7 | ||
|
|
7b471ae27d | ||
|
|
4f93054f3a | ||
|
|
65fad89794 | ||
|
|
286c0f2c23 | ||
|
|
de57064b96 | ||
|
|
6c43e90708 | ||
|
|
1f25b79722 | ||
|
|
6a9080157f | ||
|
|
5cc2ef3ac8 | ||
|
|
3baeb62b0b | ||
|
|
9e27f59033 | ||
|
|
82fa2f979c | ||
|
|
07d7324332 | ||
|
|
d92adda2c9 | ||
|
|
0587400e2d | ||
|
|
35c8c63793 | ||
|
|
c7f5145e9e | ||
|
|
9452169f0a | ||
|
|
a15f43e0f8 | ||
|
|
0eb4754b31 | ||
|
|
f987ff8199 | ||
|
|
64a5d1ca24 | ||
|
|
fa17081012 | ||
|
|
856cb0737d | ||
|
|
f61e3f46e8 | ||
|
|
6b6b943b73 | ||
|
|
75d9b07158 | ||
|
|
8682f7f82f | ||
|
|
35a5b99bed | ||
|
|
98af25d109 | ||
|
|
cd3391461c | ||
|
|
e3b7f86075 | ||
|
|
86d5865457 | ||
|
|
7b783076e5 | ||
|
|
57c0ad694c | ||
|
|
f55a31c24f | ||
|
|
843095afc6 | ||
|
|
a6bad52181 | ||
|
|
012d98380d | ||
|
|
0298997d23 | ||
|
|
678a94bf71 | ||
|
|
03399e86a9 | ||
|
|
22364bac89 | ||
|
|
9188b5451c | ||
|
|
c7ed527911 | ||
|
|
5a1132101b | ||
|
|
ca33bf8b3e | ||
|
|
7d8c80c9a0 | ||
|
|
c6f993428e | ||
|
|
f6118b858d | ||
|
|
ec1bca238e | ||
|
|
6b87f159b4 | ||
|
|
41b447d41a | ||
|
|
c512b5f59a | ||
|
|
fc9b32b4bd | ||
|
|
36ed8679b8 | ||
|
|
a9b1993686 | ||
|
|
05b458ddb2 | ||
|
|
8d8add3710 | ||
|
|
65e7da9793 | ||
|
|
7e5d9b7399 | ||
|
|
92b7b7beff | ||
|
|
c287f050c1 | ||
|
|
f71beb4018 | ||
|
|
75bbdeb6d2 | ||
|
|
72c43b6614 | ||
|
|
a0eddbdeca | ||
|
|
03f7661a4a | ||
|
|
f95d8db4da | ||
|
|
a0ffff8ad6 | ||
|
|
7ced874d7c | ||
|
|
a630eb796d | ||
|
|
f15eaee060 | ||
|
|
13cb2b79e2 | ||
|
|
4d6d090ff2 | ||
|
|
cbd7a2cd8b | ||
|
|
e1db74da90 | ||
|
|
612c33b92a | ||
|
|
77485403d7 | ||
|
|
d19d4f2443 | ||
|
|
e6d348e441 | ||
|
|
4718a12668 | ||
|
|
a7d79831e6 | ||
|
|
8dd4701aa7 | ||
|
|
e6f920df9b | ||
|
|
fee96045ee | ||
|
|
5b469c0a9a | ||
|
|
cc136f996f | ||
|
|
9a6e26db96 | ||
|
|
688cc843ce | ||
|
|
318ee300e3 | ||
|
|
7602195540 | ||
|
|
9067b9c50f | ||
|
|
e5e2771e27 | ||
|
|
8645061a66 | ||
|
|
76ab48df3b | ||
|
|
bd790cbdf1 | ||
|
|
95db7fdb5b | ||
|
|
00efa6cc8a | ||
|
|
8792a40845 | ||
|
|
e031a35330 | ||
|
|
498f634ac5 | ||
|
|
62e70ef755 | ||
|
|
d2145162bf | ||
|
|
0abbe025a2 | ||
|
|
0447f661e0 | ||
|
|
72c2fad82a | ||
|
|
7c7d63ea70 | ||
|
|
05ae055097 | ||
|
|
3404818d15 | ||
|
|
05c61ca2ce | ||
|
|
6abb2dab7e | ||
|
|
7399497c3a | ||
|
|
e2683a46c3 | ||
|
|
b745ce31e1 | ||
|
|
5d2dc04f50 | ||
|
|
c5c94036c3 | ||
|
|
2de52cee4d | ||
|
|
e44f589c53 | ||
|
|
40794a90b8 | ||
|
|
459347e24d | ||
|
|
a0adbb1103 | ||
|
|
b891146397 | ||
|
|
a0f60db114 | ||
|
|
9f0274b5fe | ||
|
|
93da2dbfc9 | ||
|
|
9e8d4a453b | ||
|
|
6baa04b6e1 | ||
|
|
72d665ca44 | ||
|
|
4156933e03 | ||
|
|
29822f14bd | ||
|
|
8737531fbe | ||
|
|
309e26ba7a | ||
|
|
ac85ff82a1 | ||
|
|
39cf6c99a2 | ||
|
|
cb41293320 | ||
|
|
92150dd2e9 | ||
|
|
d06aa9b27d | ||
|
|
da9e8fec20 | ||
|
|
5c07652f6b | ||
|
|
c7b5015e10 | ||
|
|
4a2b253b40 | ||
|
|
f65ecdf767 | ||
|
|
ee3f9c6ecd | ||
|
|
52134f9e57 | ||
|
|
21cd5c9882 | ||
|
|
23587d0b0f | ||
|
|
ce6fa906d3 | ||
|
|
0e20fe5b4e | ||
|
|
978d6af359 | ||
|
|
812088b5ab | ||
|
|
bf54a66346 | ||
|
|
5fb4580108 | ||
|
|
f1c9f9b9dc | ||
|
|
f15cd1d458 | ||
|
|
24a2df9383 | ||
|
|
176e4df90c | ||
|
|
babd730d07 | ||
|
|
fe9640e2dd | ||
|
|
906008f667 | ||
|
|
2da2f121c8 | ||
|
|
a0d2c7172c | ||
|
|
463a789898 | ||
|
|
175529b114 | ||
|
|
6f6039c136 | ||
|
|
2b13eb250d | ||
|
|
84cb4bb4c1 | ||
|
|
784fb9fee7 | ||
|
|
ff6c92b975 | ||
|
|
64801972e7 | ||
|
|
ee61e60631 | ||
|
|
c8c95f1690 | ||
|
|
50344af335 | ||
|
|
3be0f50722 | ||
|
|
6ee014dd99 | ||
|
|
2a4bee5bdd | ||
|
|
4f21696387 | ||
|
|
ae041c97b3 | ||
|
|
6df72e5842 | ||
|
|
b9e06dc065 | ||
|
|
b3cf1bc625 | ||
|
|
20b181c56d | ||
|
|
8e4a175155 | ||
|
|
cfe9506a5a | ||
|
|
fa78623b1c | ||
|
|
e06a9e3701 | ||
|
|
c87dea3d9b | ||
|
|
929ce385a3 | ||
|
|
765749f608 | ||
|
|
5fad5d63ae | ||
|
|
af10c59eaf | ||
|
|
a77b71530d | ||
|
|
803a79059a | ||
|
|
6c9ad16077 | ||
|
|
2ab689f7c1 | ||
|
|
f8a50929a8 | ||
|
|
af3ca3bb2f | ||
|
|
aaf8617dd5 | ||
|
|
1d3e393fd4 | ||
|
|
c3df405e33 | ||
|
|
b1ef8a33d9 | ||
|
|
954625a530 | ||
|
|
9850ca1b94 | ||
|
|
01e1a6aafa | ||
|
|
0f4a771792 | ||
|
|
73bd788a6c | ||
|
|
8cb5378df9 | ||
|
|
82bddd9cb8 | ||
|
|
24ff08f997 | ||
|
|
fc8983227d | ||
|
|
9bdc36526e | ||
|
|
24857a3d8d | ||
|
|
b221c9e84c | ||
|
|
8d2fcef273 | ||
|
|
1d8ca31d55 | ||
|
|
3b95ecd9b2 | ||
|
|
7cc25a6238 | ||
|
|
1ef5430e0a | ||
|
|
b39fc6ee23 | ||
|
|
a074cd79bd | ||
|
|
883757b936 | ||
|
|
35e5a938b0 | ||
|
|
31d7b648b4 | ||
|
|
44e6693a40 | ||
|
|
c458eba6b4 | ||
|
|
6d51c21c06 | ||
|
|
d2aa2069f7 | ||
|
|
8de9c22fd7 | ||
|
|
d649d0adf1 | ||
|
|
0aa5274799 | ||
|
|
bfc3fd425a | ||
|
|
05f508fb42 | ||
|
|
c8b8dc1276 | ||
|
|
1c62785d71 | ||
|
|
4a8bf4f39a | ||
|
|
2f6bfe9104 | ||
|
|
535bbc7219 | ||
|
|
9713b055a0 | ||
|
|
7dee9a97c5 | ||
|
|
aab65a2728 | ||
|
|
c8775ee6f5 | ||
|
|
016b4dc58f | ||
|
|
36d77aaa2b | ||
|
|
f32f613ac0 | ||
|
|
885c5b56bb | ||
|
|
b923f93aee | ||
|
|
ce6efc535c | ||
|
|
320a608c36 | ||
|
|
f47e4275b6 | ||
|
|
228ad16d74 | ||
|
|
9b901c6a38 | ||
|
|
37d64a7028 | ||
|
|
f8bf05513c | ||
|
|
bac9348db9 | ||
|
|
3074dbea0b | ||
|
|
fe4122e579 | ||
|
|
b52cce9056 | ||
|
|
bc938c7b08 | ||
|
|
872b3c2743 | ||
|
|
01269c88ff | ||
|
|
db9ab88a6c | ||
|
|
18af238256 | ||
|
|
7f6767b298 | ||
|
|
810585207d | ||
|
|
3b23f3d27b | ||
|
|
169ca2a2b8 | ||
|
|
8b7ba7bdbe | ||
|
|
a77cec2aea | ||
|
|
8fa51dfc33 | ||
|
|
e95b7b9cf1 | ||
|
|
165bed46a8 | ||
|
|
0dd7b2e959 | ||
|
|
0fde2ea571 | ||
|
|
bfb8bcb86e | ||
|
|
9bb8099008 | ||
|
|
98630badd5 | ||
|
|
d0c4a4012a | ||
|
|
16f63df0c3 | ||
|
|
04688e98a7 | ||
|
|
e0feea9995 | ||
|
|
55ea556060 | ||
|
|
4803e50977 | ||
|
|
f393b64124 | ||
|
|
9ea756ce4f | ||
|
|
f9438461eb | ||
|
|
0fb23f9ab8 | ||
|
|
0390818a02 | ||
|
|
e002796d2e | ||
|
|
b8a0e35f21 | ||
|
|
bd52c5fece | ||
|
|
d2cea9b70f | ||
|
|
7e24d46047 | ||
|
|
8078d777ab | ||
|
|
939ef564ce | ||
|
|
6bf8dd9a31 | ||
|
|
809e6c3a89 | ||
|
|
845acd3314 | ||
|
|
2cf69a6ef0 | ||
|
|
978e010e67 | ||
|
|
cde423cb73 | ||
|
|
cfe8b19c8a | ||
|
|
f69f6e8e70 | ||
|
|
d7b228f342 | ||
|
|
0954a906f4 | ||
|
|
77d53cf5f1 | ||
|
|
5621c52a44 | ||
|
|
f6fa6c7ded | ||
|
|
023e4abd87 | ||
|
|
cab10edd1d | ||
|
|
87a02ffe72 | ||
|
|
e739df0a32 | ||
|
|
b18962929b | ||
|
|
dec2e6fe4c | ||
|
|
7beed39b1d | ||
|
|
ae5a9bb855 | ||
|
|
c48e0e4c32 | ||
|
|
0747a7d7e1 | ||
|
|
4b0a648b21 | ||
|
|
40519e9ee1 | ||
|
|
ce5adba5b2 | ||
|
|
c78466b486 | ||
|
|
deed51d309 | ||
|
|
68a952ff17 | ||
|
|
434cd1ca79 | ||
|
|
8e09fad233 | ||
|
|
e9d4075e43 | ||
|
|
fce05f0cfc | ||
|
|
4cce476dfc | ||
|
|
ad5c37200b | ||
|
|
c0e1365dc2 | ||
|
|
984f727385 | ||
|
|
315945b2bd | ||
|
|
bf686da723 | ||
|
|
6733134ad4 |
23
.github/ISSUE_TEMPLATE/readme-first.md
vendored
Normal file
23
.github/ISSUE_TEMPLATE/readme-first.md
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
name: Readme First
|
||||
about: Issues is bug report only
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
The **Issues** is for bug report only.
|
||||
|
||||
Goto **Discussions** for feature request , questions, etc.
|
||||
|
||||
**Update to master branch HEAD first**, and
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
176
.github/workflows/build-release.yml
vendored
Normal file
176
.github/workflows/build-release.yml
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
name: Build and Release Skynet
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
tags: [ 'v*' ]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
actions: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build ${{ matrix.platform }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: windows
|
||||
os: ubuntu-latest
|
||||
container: debian:13
|
||||
target: mingw
|
||||
artifact: skynet-windows.zip
|
||||
- platform: linux
|
||||
os: ubuntu-latest
|
||||
container: debian:13
|
||||
target: linux
|
||||
artifact: skynet-linux.zip
|
||||
- platform: macosx
|
||||
os: macos-latest
|
||||
target: macosx
|
||||
artifact: skynet-macosx.zip
|
||||
- platform: freebsd
|
||||
os: ubuntu-latest
|
||||
container: debian:13
|
||||
target: freebsd
|
||||
artifact: skynet-freebsd.zip
|
||||
- platform: openbsd
|
||||
os: ubuntu-latest
|
||||
container: debian:13
|
||||
target: openbsd
|
||||
artifact: skynet-openbsd.zip
|
||||
|
||||
container: ${{ matrix.container }}
|
||||
|
||||
steps:
|
||||
- name: Install dependencies (Debian - Windows/Linux)
|
||||
if: matrix.container == 'debian:13'
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
make \
|
||||
pkg-config \
|
||||
mingw-w64 \
|
||||
mingw-w64-tools \
|
||||
mingw-w64-i686-dev \
|
||||
mingw-w64-x86-64-dev \
|
||||
autoconf \
|
||||
automake \
|
||||
libtool \
|
||||
git \
|
||||
zip \
|
||||
ca-certificates \
|
||||
curl \
|
||||
libreadline-dev \
|
||||
libedit-dev \
|
||||
rsync
|
||||
|
||||
- name: Install dependencies (macOS)
|
||||
if: matrix.platform == 'macosx'
|
||||
run: |
|
||||
# macOS usually has most build tools pre-installed
|
||||
# Install any additional dependencies if needed
|
||||
brew install autoconf automake libtool || true
|
||||
|
||||
- name: Install dependencies (FreeBSD/OpenBSD)
|
||||
if: matrix.platform == 'freebsd' || matrix.platform == 'openbsd'
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
make \
|
||||
pkg-config \
|
||||
autoconf \
|
||||
automake \
|
||||
libtool \
|
||||
git \
|
||||
zip \
|
||||
ca-certificates \
|
||||
curl \
|
||||
libreadline-dev \
|
||||
libedit-dev \
|
||||
rsync
|
||||
|
||||
- name: Update CA certificates (Debian containers)
|
||||
if: matrix.container == 'debian:13'
|
||||
run: |
|
||||
update-ca-certificates
|
||||
|
||||
- name: Configure Git SSL (Debian containers)
|
||||
if: matrix.container == 'debian:13'
|
||||
run: |
|
||||
git config --global http.sslverify true
|
||||
git config --global http.sslcainfo /etc/ssl/certs/ca-certificates.crt
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Build ${{ matrix.platform }}
|
||||
run: |
|
||||
make cleanall
|
||||
make ${{ matrix.target }}
|
||||
|
||||
- name: Prepare build files
|
||||
run: |
|
||||
mkdir -p build-output
|
||||
# Copy all files except .git and .github with ignore-errors flag
|
||||
- name: Clean and recreate directory
|
||||
run: |
|
||||
rm -rf build-output/
|
||||
mkdir -p build-output/
|
||||
|
||||
- name: Sync files to build-output excluding specific directories
|
||||
run: |
|
||||
rsync -av --ignore-errors --exclude='.git*' --exclude='.github' --exclude='build-output' . build-output/
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact }}
|
||||
path: build-output/
|
||||
retention-days: 30
|
||||
|
||||
release:
|
||||
name: Create Release
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
|
||||
steps:
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: artifacts
|
||||
|
||||
- name: Prepare release assets
|
||||
run: |
|
||||
mkdir -p release-assets
|
||||
# Copy zip files from artifact directories to release assets
|
||||
for artifact in skynet-windows.zip skynet-linux.zip skynet-macosx.zip skynet-freebsd.zip skynet-openbsd.zip; do
|
||||
if [ -d "artifacts/${artifact}" ]; then
|
||||
# The artifacts are already organized, just copy them
|
||||
cp -r "artifacts/${artifact}/"* "release-assets/" 2>/dev/null || true
|
||||
# Or if we want to create new zip files with consistent naming
|
||||
platform=$(echo ${artifact} | sed 's/skynet-\(.*\)\.zip/\1/')
|
||||
cd "artifacts/${artifact}"
|
||||
zip -r "../../release-assets/skynet-${platform}.zip" .
|
||||
cd ../..
|
||||
fi
|
||||
done
|
||||
ls -la release-assets/
|
||||
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
files: release-assets/*.zip
|
||||
generate_release_notes: true
|
||||
draft: false
|
||||
prerelease: false
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -4,7 +4,15 @@
|
||||
/skynet.pid
|
||||
3rd/lua/lua
|
||||
3rd/lua/luac
|
||||
3rd/lua/all
|
||||
/cservice
|
||||
/luaclib
|
||||
*.so
|
||||
*.dSYM
|
||||
.DS_Store
|
||||
.vscode
|
||||
3rd/lua/lua.exe
|
||||
3rd/lua/luac.exe
|
||||
3rd/lua/lua54.dll
|
||||
skynet.exe
|
||||
*.dll
|
||||
|
||||
1
3rd/compat-mingw/arpa/inet.h
Normal file
1
3rd/compat-mingw/arpa/inet.h
Normal file
@@ -0,0 +1 @@
|
||||
#pragma once
|
||||
5
3rd/compat-mingw/compat.c
Normal file
5
3rd/compat-mingw/compat.c
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "compat.h"
|
||||
|
||||
#include "dlfcn.c"
|
||||
#include "unistd.c"
|
||||
#include "wepoll.c"
|
||||
4
3rd/compat-mingw/compat.h
Normal file
4
3rd/compat-mingw/compat.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "unistd.h"
|
||||
#include "dlfcn.h"
|
||||
20
3rd/compat-mingw/dlfcn.c
Normal file
20
3rd/compat-mingw/dlfcn.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "dlfcn.h"
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
void *dlopen(const char *path, int flag) {
|
||||
return LoadLibraryA(path);
|
||||
}
|
||||
|
||||
const char *dlerror() {
|
||||
DWORD err = GetLastError();
|
||||
HLOCAL LocalAddress = NULL;
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL, err, 0, (PTSTR)&LocalAddress, 0, NULL);
|
||||
return (LPSTR)LocalAddress;
|
||||
}
|
||||
|
||||
void *dlsym(void *dl, const char *sym) {
|
||||
return GetProcAddress(dl, sym);
|
||||
}
|
||||
|
||||
7
3rd/compat-mingw/dlfcn.h
Normal file
7
3rd/compat-mingw/dlfcn.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
enum { RTLD_NOW, RTLD_GLOBAL };
|
||||
|
||||
void *dlopen(const char *path, int flag);
|
||||
const char *dlerror();
|
||||
void *dlsym(void *dl, const char *sym);
|
||||
3
3rd/compat-mingw/netdb.h
Normal file
3
3rd/compat-mingw/netdb.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include <ws2tcpip.h>
|
||||
1
3rd/compat-mingw/netinet/in.h
Normal file
1
3rd/compat-mingw/netinet/in.h
Normal file
@@ -0,0 +1 @@
|
||||
#pragma once
|
||||
1
3rd/compat-mingw/netinet/tcp.h
Normal file
1
3rd/compat-mingw/netinet/tcp.h
Normal file
@@ -0,0 +1 @@
|
||||
#pragma once
|
||||
3
3rd/compat-mingw/sys/epoll.h
Normal file
3
3rd/compat-mingw/sys/epoll.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "wepoll.h"
|
||||
1
3rd/compat-mingw/sys/file.h
Normal file
1
3rd/compat-mingw/sys/file.h
Normal file
@@ -0,0 +1 @@
|
||||
#pragma once
|
||||
3
3rd/compat-mingw/sys/select.h
Normal file
3
3rd/compat-mingw/sys/select.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include <sys/socket.h>
|
||||
17
3rd/compat-mingw/sys/socket.h
Normal file
17
3rd/compat-mingw/sys/socket.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#undef FD_SETSIZE
|
||||
#define FD_SETSIZE 1024
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <conio.h>
|
||||
|
||||
#include <ws2ipdef.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#include "socket_poll.h"
|
||||
#include "socket_epoll.h"
|
||||
381
3rd/compat-mingw/unistd.c
Normal file
381
3rd/compat-mingw/unistd.c
Normal file
@@ -0,0 +1,381 @@
|
||||
#include "unistd.h"
|
||||
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <winsock2.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <windows.h>
|
||||
#include <conio.h>
|
||||
#include <errno.h>
|
||||
|
||||
// WSA error to errno mapping function
|
||||
static void set_errno_from_wsa_error(int wsa_error) {
|
||||
switch (wsa_error) {
|
||||
case WSAECONNRESET:
|
||||
errno = ECONNRESET;
|
||||
break;
|
||||
case WSAECONNABORTED:
|
||||
errno = ECONNABORTED;
|
||||
break;
|
||||
case WSAECONNREFUSED:
|
||||
errno = ECONNREFUSED;
|
||||
break;
|
||||
case WSAENETDOWN:
|
||||
errno = ENETDOWN;
|
||||
break;
|
||||
case WSAENETUNREACH:
|
||||
errno = ENETUNREACH;
|
||||
break;
|
||||
case WSAEHOSTDOWN:
|
||||
errno = EHOSTDOWN;
|
||||
break;
|
||||
case WSAEHOSTUNREACH:
|
||||
errno = EHOSTUNREACH;
|
||||
break;
|
||||
case WSAETIMEDOUT:
|
||||
errno = ETIMEDOUT;
|
||||
break;
|
||||
case WSAENOTCONN:
|
||||
errno = ENOTCONN;
|
||||
break;
|
||||
case WSAEWOULDBLOCK:
|
||||
errno = EAGAIN;
|
||||
break;
|
||||
case WSAEINTR:
|
||||
errno = EINTR;
|
||||
break;
|
||||
case WSAEINVAL:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case WSAEACCES:
|
||||
errno = EACCES;
|
||||
break;
|
||||
case WSAEADDRINUSE:
|
||||
errno = EADDRINUSE;
|
||||
break;
|
||||
case WSAEADDRNOTAVAIL:
|
||||
errno = EADDRNOTAVAIL;
|
||||
break;
|
||||
default:
|
||||
errno = EIO; // Generic I/O error for unknown cases
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Windows Socket initialization
|
||||
static int winsock_initialized = 0;
|
||||
|
||||
static int init_winsock(void) {
|
||||
if (!winsock_initialized) {
|
||||
WSADATA wsaData;
|
||||
int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
if (result != 0) {
|
||||
return -1;
|
||||
}
|
||||
winsock_initialized = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cleanup_winsock(void) {
|
||||
if (winsock_initialized) {
|
||||
WSACleanup();
|
||||
winsock_initialized = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-initialize Winsock when the library is loaded
|
||||
__attribute__((constructor))
|
||||
static void auto_init_winsock(void) {
|
||||
init_winsock();
|
||||
}
|
||||
|
||||
// Auto-cleanup Winsock when the library is unloaded
|
||||
__attribute__((destructor))
|
||||
static void auto_cleanup_winsock(void) {
|
||||
cleanup_winsock();
|
||||
}
|
||||
|
||||
static LONGLONG get_cpu_freq() {
|
||||
LARGE_INTEGER freq;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
return freq.QuadPart;
|
||||
}
|
||||
|
||||
int kill(pid_t pid, int exit_code) {
|
||||
return TerminateProcess((HANDLE)(uintptr_t)pid, exit_code);
|
||||
}
|
||||
|
||||
#define NANOSEC 1000000000
|
||||
#define MICROSEC 1000000
|
||||
|
||||
void usleep(size_t us) {
|
||||
if (us > 1000) {
|
||||
Sleep(us / 1000);
|
||||
return;
|
||||
}
|
||||
LONGLONG delta = get_cpu_freq() / MICROSEC * us;
|
||||
LARGE_INTEGER counter;
|
||||
QueryPerformanceCounter(&counter);
|
||||
LONGLONG start = counter.QuadPart;
|
||||
for (;;) {
|
||||
QueryPerformanceCounter(&counter);
|
||||
if (counter.QuadPart - start >= delta)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void sleep(size_t sec) {
|
||||
Sleep(sec * 1000UL);
|
||||
}
|
||||
|
||||
int clock_gettime(int what, struct timespec* ti) {
|
||||
switch (what) {
|
||||
case CLOCK_MONOTONIC:
|
||||
static __int64 Freq = 0;
|
||||
static __int64 Start = 0;
|
||||
static __int64 StartTime = 0;
|
||||
if (Freq == 0) {
|
||||
StartTime = time(NULL);
|
||||
QueryPerformanceFrequency((LARGE_INTEGER*)&Freq);
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&Start);
|
||||
}
|
||||
__int64 Count = 0;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&Count);
|
||||
|
||||
// 乘以1000,把秒化为毫秒
|
||||
__int64 now = (__int64)((double)(Count - Start) / (double)Freq * 1000.0) + StartTime * 1000;
|
||||
ti->tv_sec = now / 1000;
|
||||
ti->tv_nsec = (now - now / 1000 * 1000) * 1000 * 1000;
|
||||
return 0;
|
||||
case CLOCK_REALTIME:
|
||||
SYSTEMTIME st;
|
||||
GetSystemTime(&st); // 获取 UTC 时间
|
||||
|
||||
// 将 SYSTEMTIME 转换为 UNIX 时间戳
|
||||
FILETIME ft;
|
||||
SystemTimeToFileTime(&st, &ft);
|
||||
ULARGE_INTEGER u64;
|
||||
u64.LowPart = ft.dwLowDateTime;
|
||||
u64.HighPart = ft.dwHighDateTime;
|
||||
|
||||
ti->tv_sec = (uint32_t)((u64.QuadPart - 116444736000000000ULL) / 10000000); // 转换为秒
|
||||
ti->tv_nsec = (uint32_t)((u64.QuadPart % 10000000) * 100); // 获取纳秒部分
|
||||
return 0; // 响应成功
|
||||
case CLOCK_THREAD_CPUTIME_ID:
|
||||
// 获取当前线程的 CPU 时间
|
||||
FILETIME creation_time, exit_time, kernel_time, user_time;
|
||||
if (GetThreadTimes(GetCurrentThread(), &creation_time, &exit_time, &kernel_time, &user_time)) {
|
||||
ULARGE_INTEGER u64;
|
||||
u64.LowPart = user_time.dwLowDateTime;
|
||||
u64.HighPart = user_time.dwHighDateTime;
|
||||
|
||||
ti->tv_sec = (uint32_t)((u64.QuadPart - 116444736000000000ULL) / 10000000); // 转换为秒
|
||||
ti->tv_nsec = (uint32_t)((u64.QuadPart % 10000000) * 100); // 获取纳秒部分
|
||||
return 0;
|
||||
} else {
|
||||
return -1; // 获取失败
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int flock(int fd, int flag) {
|
||||
// Not implemented
|
||||
return 3;
|
||||
}
|
||||
|
||||
int fcntl(int fd, int cmd, long arg) {
|
||||
if (cmd == F_GETFL)
|
||||
return 0;
|
||||
|
||||
if (cmd == F_SETFL && arg == O_NONBLOCK) {
|
||||
u_long ulOption = 1;
|
||||
ioctlsocket(fd, FIONBIO, &ulOption);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void sigfillset(int* flag) {
|
||||
// Not implemented
|
||||
}
|
||||
|
||||
int sigemptyset(int* set) {
|
||||
/*Not implemented*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sigaction(int flag, struct sigaction* action, void* param) {
|
||||
// Not implemented
|
||||
}
|
||||
|
||||
static void socket_keepalive(int fd) {
|
||||
int keepalive = 1;
|
||||
int ret = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepalive,
|
||||
sizeof(keepalive));
|
||||
|
||||
assert(ret != SOCKET_ERROR);
|
||||
}
|
||||
|
||||
int pipe(int fd[2]) {
|
||||
int listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (listen_fd == INVALID_SOCKET) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_in sin;
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
|
||||
|
||||
srand(time(NULL));
|
||||
// use random port(range from 60000 to 60999) to simulate pipe()
|
||||
int port;
|
||||
for (;;) {
|
||||
port = 60000 + rand() % 1000;
|
||||
sin.sin_port = htons(port);
|
||||
if (!bind(listen_fd, (struct sockaddr*)&sin, sizeof(sin)))
|
||||
break;
|
||||
}
|
||||
|
||||
if (listen(listen_fd, 5) == SOCKET_ERROR) {
|
||||
closesocket(listen_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
socket_keepalive(listen_fd);
|
||||
|
||||
int client_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (client_fd == INVALID_SOCKET) {
|
||||
closesocket(listen_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (connect(client_fd, (struct sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR) {
|
||||
closesocket(listen_fd);
|
||||
closesocket(client_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_in client_addr;
|
||||
size_t name_len = sizeof(client_addr);
|
||||
int client_sock = accept(listen_fd, (struct sockaddr*)&client_addr, &name_len);
|
||||
if (client_sock == INVALID_SOCKET) {
|
||||
closesocket(listen_fd);
|
||||
closesocket(client_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
closesocket(listen_fd); // Close listen socket as it's no longer needed
|
||||
|
||||
fd[0] = client_sock;
|
||||
fd[1] = client_fd;
|
||||
|
||||
socket_keepalive(client_sock);
|
||||
socket_keepalive(client_fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write(int fd, const void* ptr, unsigned int sz) {
|
||||
WSABUF vecs[1];
|
||||
vecs[0].buf = (char*)ptr;
|
||||
vecs[0].len = sz;
|
||||
|
||||
DWORD bytesSent;
|
||||
if (WSASend(fd, vecs, 1, &bytesSent, 0, NULL, NULL)) {
|
||||
int wsa_error = WSAGetLastError();
|
||||
set_errno_from_wsa_error(wsa_error);
|
||||
return -1;
|
||||
} else {
|
||||
return bytesSent;
|
||||
}
|
||||
}
|
||||
|
||||
int read(int fd, void* buffer, unsigned int sz) {
|
||||
|
||||
WSABUF vecs[1];
|
||||
vecs[0].buf = buffer;
|
||||
vecs[0].len = sz;
|
||||
|
||||
DWORD bytesRecv = 0;
|
||||
DWORD flags = 0;
|
||||
if (WSARecv(fd, vecs, 1, &bytesRecv, &flags, NULL, NULL)) {
|
||||
int wsa_error = WSAGetLastError();
|
||||
|
||||
if (wsa_error == WSAECONNRESET) {
|
||||
return 0; // Connection closed by peer
|
||||
}
|
||||
|
||||
// Map WSA error to errno for better error reporting
|
||||
set_errno_from_wsa_error(wsa_error);
|
||||
return -1;
|
||||
} else {
|
||||
return bytesRecv;
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper for recv function with better error handling
|
||||
int compat_recv(SOCKET s, char *buf, int len, int flags) {
|
||||
WSABUF vecs[1];
|
||||
vecs[0].buf = buf;
|
||||
vecs[0].len = len;
|
||||
|
||||
DWORD bytesRecv = 0;
|
||||
DWORD wsaFlags = 0;
|
||||
if (WSARecv(s, vecs, 1, &bytesRecv, &wsaFlags, NULL, NULL)) {
|
||||
int wsa_error = WSAGetLastError();
|
||||
|
||||
// Handle non-blocking operations - these are not real errors
|
||||
if (wsa_error == WSAEWOULDBLOCK || wsa_error == WSAEINTR) {
|
||||
// For non-blocking sockets, this is normal - no data available right now
|
||||
set_errno_from_wsa_error(wsa_error);
|
||||
return -1; // Caller should check errno == EAGAIN
|
||||
}
|
||||
|
||||
if (wsa_error == WSAECONNRESET) {
|
||||
return 0; // Connection closed by peer
|
||||
}
|
||||
|
||||
// Map WSA error to errno for better error reporting
|
||||
set_errno_from_wsa_error(wsa_error);
|
||||
return -1;
|
||||
} else {
|
||||
return bytesRecv;
|
||||
}
|
||||
}
|
||||
|
||||
int close(int fd) {
|
||||
shutdown(fd, SD_BOTH);
|
||||
return closesocket(fd);
|
||||
}
|
||||
|
||||
int daemon(int a, int b) {
|
||||
// Not implemented
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* strsep(char** stringp, const char* delim) {
|
||||
char* s;
|
||||
const char* spanp;
|
||||
int c, sc;
|
||||
char* tok;
|
||||
if ((s = *stringp) == NULL)
|
||||
return (NULL);
|
||||
for (tok = s;;) {
|
||||
c = *s++;
|
||||
spanp = delim;
|
||||
do {
|
||||
if ((sc = *spanp++) == c) {
|
||||
if (c == 0)
|
||||
s = NULL;
|
||||
else
|
||||
s[-1] = 0;
|
||||
*stringp = s;
|
||||
return (tok);
|
||||
}
|
||||
} while (sc != 0);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
117
3rd/compat-mingw/unistd.h
Normal file
117
3rd/compat-mingw/unistd.h
Normal file
@@ -0,0 +1,117 @@
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <process.h>
|
||||
#include <io.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
// Define missing errno values for network errors
|
||||
#ifndef ECONNRESET
|
||||
#define ECONNRESET 104
|
||||
#endif
|
||||
#ifndef ECONNABORTED
|
||||
#define ECONNABORTED 103
|
||||
#endif
|
||||
#ifndef ECONNREFUSED
|
||||
#define ECONNREFUSED 111
|
||||
#endif
|
||||
#ifndef ENETDOWN
|
||||
#define ENETDOWN 100
|
||||
#endif
|
||||
#ifndef ENETUNREACH
|
||||
#define ENETUNREACH 101
|
||||
#endif
|
||||
#ifndef EHOSTDOWN
|
||||
#define EHOSTDOWN 112
|
||||
#endif
|
||||
#ifndef EHOSTUNREACH
|
||||
#define EHOSTUNREACH 113
|
||||
#endif
|
||||
#ifndef ETIMEDOUT
|
||||
#define ETIMEDOUT 110
|
||||
#endif
|
||||
#ifndef ENOTCONN
|
||||
#define ENOTCONN 107
|
||||
#endif
|
||||
#ifndef EADDRINUSE
|
||||
#define EADDRINUSE 98
|
||||
#endif
|
||||
#ifndef EADDRNOTAVAIL
|
||||
#define EADDRNOTAVAIL 99
|
||||
#endif
|
||||
|
||||
// Include winsock2.h for gethostname and other network functions
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
// Undefine Windows legacy keywords that conflict with variable names
|
||||
#ifdef near
|
||||
#undef near
|
||||
#endif
|
||||
#ifdef far
|
||||
#undef far
|
||||
#endif
|
||||
|
||||
// Socket compatibility macros
|
||||
#define SHUT_RD SD_RECEIVE
|
||||
#define SHUT_WR SD_SEND
|
||||
#define SHUT_RDWR SD_BOTH
|
||||
|
||||
#define ssize_t size_t
|
||||
|
||||
#define random rand
|
||||
#define srandom srand
|
||||
#define snprintf _snprintf
|
||||
#define localtime_r _localtime64_s
|
||||
|
||||
#define pid_t int
|
||||
|
||||
int kill(pid_t pid, int exit_code);
|
||||
|
||||
void usleep(size_t us);
|
||||
void sleep(size_t ms);
|
||||
|
||||
int clock_gettime(int what, struct timespec *ti);
|
||||
|
||||
enum { LOCK_EX, LOCK_NB };
|
||||
int flock(int fd, int flag);
|
||||
|
||||
struct sigaction {
|
||||
void (*sa_handler)(int);
|
||||
int sa_flags;
|
||||
int sa_mask;
|
||||
};
|
||||
enum { SIGPIPE, SIGHUP, SA_RESTART };
|
||||
void sigfillset(int *flag);
|
||||
int sigemptyset(int* set);
|
||||
void sigaction(int flag, struct sigaction *action, void* param);
|
||||
|
||||
int pipe(int fd[2]);
|
||||
int daemon(int a, int b);
|
||||
|
||||
#define O_NONBLOCK 1
|
||||
#define F_SETFL 0
|
||||
#define F_GETFL 1
|
||||
|
||||
int fcntl(int fd, int cmd, long arg);
|
||||
|
||||
char *strsep(char **stringp, const char *delim);
|
||||
|
||||
int write(int fd, const void* ptr, unsigned int sz);
|
||||
int read(int fd, void* buffer, unsigned int sz);
|
||||
// Wrapper function for recv with better error handling
|
||||
int compat_recv(SOCKET s, char *buf, int len, int flags);
|
||||
|
||||
// Macro to redirect recv calls to our wrapper
|
||||
#define recv compat_recv
|
||||
int close(int fd);
|
||||
|
||||
#define getpid _getpid
|
||||
#define open _open
|
||||
#define dup2 _dup2
|
||||
2253
3rd/compat-mingw/wepoll.c
Normal file
2253
3rd/compat-mingw/wepoll.c
Normal file
File diff suppressed because it is too large
Load Diff
113
3rd/compat-mingw/wepoll.h
Normal file
113
3rd/compat-mingw/wepoll.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* wepoll - epoll for Windows
|
||||
* https://github.com/piscisaureus/wepoll
|
||||
*
|
||||
* Copyright 2012-2020, Bert Belder <bertbelder@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef WEPOLL_H_
|
||||
#define WEPOLL_H_
|
||||
|
||||
#ifndef WEPOLL_EXPORT
|
||||
#define WEPOLL_EXPORT
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum EPOLL_EVENTS {
|
||||
EPOLLIN = (int) (1U << 0),
|
||||
EPOLLPRI = (int) (1U << 1),
|
||||
EPOLLOUT = (int) (1U << 2),
|
||||
EPOLLERR = (int) (1U << 3),
|
||||
EPOLLHUP = (int) (1U << 4),
|
||||
EPOLLRDNORM = (int) (1U << 6),
|
||||
EPOLLRDBAND = (int) (1U << 7),
|
||||
EPOLLWRNORM = (int) (1U << 8),
|
||||
EPOLLWRBAND = (int) (1U << 9),
|
||||
EPOLLMSG = (int) (1U << 10), /* Never reported. */
|
||||
EPOLLRDHUP = (int) (1U << 13),
|
||||
EPOLLONESHOT = (int) (1U << 31)
|
||||
};
|
||||
|
||||
#define EPOLLIN (1U << 0)
|
||||
#define EPOLLPRI (1U << 1)
|
||||
#define EPOLLOUT (1U << 2)
|
||||
#define EPOLLERR (1U << 3)
|
||||
#define EPOLLHUP (1U << 4)
|
||||
#define EPOLLRDNORM (1U << 6)
|
||||
#define EPOLLRDBAND (1U << 7)
|
||||
#define EPOLLWRNORM (1U << 8)
|
||||
#define EPOLLWRBAND (1U << 9)
|
||||
#define EPOLLMSG (1U << 10)
|
||||
#define EPOLLRDHUP (1U << 13)
|
||||
#define EPOLLONESHOT (1U << 31)
|
||||
|
||||
#define EPOLL_CTL_ADD 1
|
||||
#define EPOLL_CTL_MOD 2
|
||||
#define EPOLL_CTL_DEL 3
|
||||
|
||||
typedef void* HANDLE;
|
||||
typedef uintptr_t SOCKET;
|
||||
|
||||
typedef union epoll_data {
|
||||
void* ptr;
|
||||
int fd;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
SOCKET sock; /* Windows specific */
|
||||
HANDLE hnd; /* Windows specific */
|
||||
} epoll_data_t;
|
||||
|
||||
struct epoll_event {
|
||||
uint32_t events; /* Epoll events and flags */
|
||||
epoll_data_t data; /* User data variable */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
WEPOLL_EXPORT HANDLE epoll_create(int size);
|
||||
WEPOLL_EXPORT HANDLE epoll_create1(int flags);
|
||||
|
||||
WEPOLL_EXPORT int epoll_close(HANDLE ephnd);
|
||||
|
||||
WEPOLL_EXPORT int epoll_ctl(HANDLE ephnd,
|
||||
int op,
|
||||
SOCKET sock,
|
||||
struct epoll_event* event);
|
||||
|
||||
WEPOLL_EXPORT int epoll_wait(HANDLE ephnd,
|
||||
struct epoll_event* events,
|
||||
int maxevents,
|
||||
int timeout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* WEPOLL_H_ */
|
||||
Submodule 3rd/jemalloc updated: 3541a904d6...81034ce1f1
109
3rd/lpeg/HISTORY
Normal file
109
3rd/lpeg/HISTORY
Normal file
@@ -0,0 +1,109 @@
|
||||
HISTORY for LPeg 1.1.0
|
||||
|
||||
* Changes from version 1.0.2 to 1.1.0
|
||||
---------------------------------
|
||||
+ accumulator capture
|
||||
+ UTF-8 ranges
|
||||
+ Larger limit for number of rules in a grammar
|
||||
+ Larger limit for number of captures in a match
|
||||
+ bug fixes
|
||||
+ other small improvements
|
||||
|
||||
* Changes from version 1.0.1 to 1.0.2
|
||||
---------------------------------
|
||||
+ some bugs fixed
|
||||
|
||||
* Changes from version 0.12 to 1.0.1
|
||||
---------------------------------
|
||||
+ group "names" can be any Lua value
|
||||
+ some bugs fixed
|
||||
+ other small improvements
|
||||
|
||||
* Changes from version 0.11 to 0.12
|
||||
---------------------------------
|
||||
+ no "unsigned short" limit for pattern sizes
|
||||
+ mathtime captures considered nullable
|
||||
+ some bugs fixed
|
||||
|
||||
* Changes from version 0.10 to 0.11
|
||||
-------------------------------
|
||||
+ complete reimplementation of the code generator
|
||||
+ new syntax for table captures
|
||||
+ new functions in module 're'
|
||||
+ other small improvements
|
||||
|
||||
* Changes from version 0.9 to 0.10
|
||||
-------------------------------
|
||||
+ backtrack stack has configurable size
|
||||
+ better error messages
|
||||
+ Notation for non-terminals in 're' back to A instead o <A>
|
||||
+ experimental look-behind pattern
|
||||
+ support for external extensions
|
||||
+ works with Lua 5.2
|
||||
+ consumes less C stack
|
||||
|
||||
- "and" predicates do not keep captures
|
||||
|
||||
* Changes from version 0.8 to 0.9
|
||||
-------------------------------
|
||||
+ The accumulator capture was replaced by a fold capture;
|
||||
programs that used the old 'lpeg.Ca' will need small changes.
|
||||
+ Some support for character classes from old C locales.
|
||||
+ A new named-group capture.
|
||||
|
||||
* Changes from version 0.7 to 0.8
|
||||
-------------------------------
|
||||
+ New "match-time" capture.
|
||||
+ New "argument capture" that allows passing arguments into the pattern.
|
||||
+ Better documentation for 're'.
|
||||
+ Several small improvements for 're'.
|
||||
+ The 're' module has an incompatibility with previous versions:
|
||||
now, any use of a non-terminal must be enclosed in angle brackets
|
||||
(like <B>).
|
||||
|
||||
* Changes from version 0.6 to 0.7
|
||||
-------------------------------
|
||||
+ Several improvements in module 're':
|
||||
- better documentation;
|
||||
- support for most captures (all but accumulator);
|
||||
- limited repetitions p{n,m}.
|
||||
+ Small improvements in efficiency.
|
||||
+ Several small bugs corrected (special thanks to Hans Hagen
|
||||
and Taco Hoekwater).
|
||||
|
||||
* Changes from version 0.5 to 0.6
|
||||
-------------------------------
|
||||
+ Support for non-numeric indices in grammars.
|
||||
+ Some bug fixes (thanks to the luatex team).
|
||||
+ Some new optimizations; (thanks to Mike Pall).
|
||||
+ A new page layout (thanks to Andre Carregal).
|
||||
+ Minimal documentation for module 're'.
|
||||
|
||||
* Changes from version 0.4 to 0.5
|
||||
-------------------------------
|
||||
+ Several optimizations.
|
||||
+ lpeg.P now accepts booleans.
|
||||
+ Some new examples.
|
||||
+ A proper license.
|
||||
+ Several small improvements.
|
||||
|
||||
* Changes from version 0.3 to 0.4
|
||||
-------------------------------
|
||||
+ Static check for loops in repetitions and grammars.
|
||||
+ Removed label option in captures.
|
||||
+ The implementation of captures uses less memory.
|
||||
|
||||
* Changes from version 0.2 to 0.3
|
||||
-------------------------------
|
||||
+ User-defined patterns in Lua.
|
||||
+ Several new captures.
|
||||
|
||||
* Changes from version 0.1 to 0.2
|
||||
-------------------------------
|
||||
+ Several small corrections.
|
||||
+ Handles embedded zeros like any other character.
|
||||
+ Capture "name" can be any Lua value.
|
||||
+ Unlimited number of captures.
|
||||
+ Match gets an optional initial position.
|
||||
|
||||
(end of HISTORY)
|
||||
4
3rd/lpeg/README.md
Normal file
4
3rd/lpeg/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# LPeg - Parsing Expression Grammars For Lua
|
||||
|
||||
For more information,
|
||||
see [Lpeg](//www.inf.puc-rio.br/~roberto/lpeg/).
|
||||
612
3rd/lpeg/lpcap.c
Normal file
612
3rd/lpeg/lpcap.c
Normal file
@@ -0,0 +1,612 @@
|
||||
|
||||
#include "lua.h"
|
||||
#include "lauxlib.h"
|
||||
|
||||
#include "lpcap.h"
|
||||
#include "lpprint.h"
|
||||
#include "lptypes.h"
|
||||
|
||||
|
||||
#define getfromktable(cs,v) lua_rawgeti((cs)->L, ktableidx((cs)->ptop), v)
|
||||
|
||||
#define pushluaval(cs) getfromktable(cs, (cs)->cap->idx)
|
||||
|
||||
|
||||
|
||||
#define skipclose(cs,head) \
|
||||
if (isopencap(head)) { assert(isclosecap(cs->cap)); cs->cap++; }
|
||||
|
||||
|
||||
/*
|
||||
** Return the size of capture 'cap'. If it is an open capture, 'close'
|
||||
** must be its corresponding close.
|
||||
*/
|
||||
static Index_t capsize (Capture *cap, Capture *close) {
|
||||
if (isopencap(cap)) {
|
||||
assert(isclosecap(close));
|
||||
return close->index - cap->index;
|
||||
}
|
||||
else
|
||||
return cap->siz - 1;
|
||||
}
|
||||
|
||||
|
||||
static Index_t closesize (CapState *cs, Capture *head) {
|
||||
return capsize(head, cs->cap);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Put at the cache for Lua values the value indexed by 'v' in ktable
|
||||
** of the running pattern (if it is not there yet); returns its index.
|
||||
*/
|
||||
static int updatecache (CapState *cs, int v) {
|
||||
int idx = cs->ptop + 1; /* stack index of cache for Lua values */
|
||||
if (v != cs->valuecached) { /* not there? */
|
||||
getfromktable(cs, v); /* get value from 'ktable' */
|
||||
lua_replace(cs->L, idx); /* put it at reserved stack position */
|
||||
cs->valuecached = v; /* keep track of what is there */
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
||||
static int pushcapture (CapState *cs);
|
||||
|
||||
|
||||
/*
|
||||
** Goes back in a list of captures looking for an open capture
|
||||
** corresponding to a close one.
|
||||
*/
|
||||
static Capture *findopen (Capture *cap) {
|
||||
int n = 0; /* number of closes waiting an open */
|
||||
for (;;) {
|
||||
cap--;
|
||||
if (isclosecap(cap)) n++; /* one more open to skip */
|
||||
else if (isopencap(cap))
|
||||
if (n-- == 0) return cap;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Go to the next capture at the same level.
|
||||
*/
|
||||
static void nextcap (CapState *cs) {
|
||||
Capture *cap = cs->cap;
|
||||
if (isopencap(cap)) { /* must look for a close? */
|
||||
int n = 0; /* number of opens waiting a close */
|
||||
for (;;) { /* look for corresponding close */
|
||||
cap++;
|
||||
if (isopencap(cap)) n++;
|
||||
else if (isclosecap(cap))
|
||||
if (n-- == 0) break;
|
||||
}
|
||||
cs->cap = cap + 1; /* + 1 to skip last close */
|
||||
}
|
||||
else {
|
||||
Capture *next;
|
||||
for (next = cap + 1; capinside(cap, next); next++)
|
||||
; /* skip captures inside current one */
|
||||
cs->cap = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Push on the Lua stack all values generated by nested captures inside
|
||||
** the current capture. Returns number of values pushed. 'addextra'
|
||||
** makes it push the entire match after all captured values. The
|
||||
** entire match is pushed also if there are no other nested values,
|
||||
** so the function never returns zero.
|
||||
*/
|
||||
static int pushnestedvalues (CapState *cs, int addextra) {
|
||||
Capture *head = cs->cap++; /* original capture */
|
||||
int n = 0; /* number of pushed subvalues */
|
||||
/* repeat for all nested patterns */
|
||||
while (capinside(head, cs->cap))
|
||||
n += pushcapture(cs);
|
||||
if (addextra || n == 0) { /* need extra? */
|
||||
lua_pushlstring(cs->L, cs->s + head->index, closesize(cs, head));
|
||||
n++;
|
||||
}
|
||||
skipclose(cs, head);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Push only the first value generated by nested captures
|
||||
*/
|
||||
static void pushonenestedvalue (CapState *cs) {
|
||||
int n = pushnestedvalues(cs, 0);
|
||||
if (n > 1)
|
||||
lua_pop(cs->L, n - 1); /* pop extra values */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Checks whether group 'grp' is visible to 'ref', that is, 'grp' is
|
||||
** not nested inside a full capture that does not contain 'ref'. (We
|
||||
** only need to care for full captures because the search at 'findback'
|
||||
** skips open-end blocks; so, if 'grp' is nested in a non-full capture,
|
||||
** 'ref' is also inside it.) To check this, we search backward for the
|
||||
** inner full capture enclosing 'grp'. A full capture cannot contain
|
||||
** non-full captures, so a close capture means we cannot be inside a
|
||||
** full capture anymore.
|
||||
*/
|
||||
static int capvisible (CapState *cs, Capture *grp, Capture *ref) {
|
||||
Capture *cap = grp;
|
||||
int i = MAXLOP; /* maximum distance for an 'open' */
|
||||
while (i-- > 0 && cap-- > cs->ocap) {
|
||||
if (isclosecap(cap))
|
||||
return 1; /* can stop the search */
|
||||
else if (grp->index - cap->index >= UCHAR_MAX)
|
||||
return 1; /* can stop the search */
|
||||
else if (capinside(cap, grp)) /* is 'grp' inside cap? */
|
||||
return capinside(cap, ref); /* ok iff cap also contains 'ref' */
|
||||
}
|
||||
return 1; /* 'grp' is not inside any capture */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Try to find a named group capture with the name given at the top of
|
||||
** the stack; goes backward from 'ref'.
|
||||
*/
|
||||
static Capture *findback (CapState *cs, Capture *ref) {
|
||||
lua_State *L = cs->L;
|
||||
Capture *cap = ref;
|
||||
while (cap-- > cs->ocap) { /* repeat until end of list */
|
||||
if (isclosecap(cap))
|
||||
cap = findopen(cap); /* skip nested captures */
|
||||
else if (capinside(cap, ref))
|
||||
continue; /* enclosing captures are not visible to 'ref' */
|
||||
if (captype(cap) == Cgroup && capvisible(cs, cap, ref)) {
|
||||
getfromktable(cs, cap->idx); /* get group name */
|
||||
if (lp_equal(L, -2, -1)) { /* right group? */
|
||||
lua_pop(L, 2); /* remove reference name and group name */
|
||||
return cap;
|
||||
}
|
||||
else lua_pop(L, 1); /* remove group name */
|
||||
}
|
||||
}
|
||||
luaL_error(L, "back reference '%s' not found", lua_tostring(L, -1));
|
||||
return NULL; /* to avoid warnings */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Back-reference capture. Return number of values pushed.
|
||||
*/
|
||||
static int backrefcap (CapState *cs) {
|
||||
int n;
|
||||
Capture *curr = cs->cap;
|
||||
pushluaval(cs); /* reference name */
|
||||
cs->cap = findback(cs, curr); /* find corresponding group */
|
||||
n = pushnestedvalues(cs, 0); /* push group's values */
|
||||
cs->cap = curr + 1;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Table capture: creates a new table and populates it with nested
|
||||
** captures.
|
||||
*/
|
||||
static int tablecap (CapState *cs) {
|
||||
lua_State *L = cs->L;
|
||||
Capture *head = cs->cap++;
|
||||
int n = 0;
|
||||
lua_newtable(L);
|
||||
while (capinside(head, cs->cap)) {
|
||||
if (captype(cs->cap) == Cgroup && cs->cap->idx != 0) { /* named group? */
|
||||
pushluaval(cs); /* push group name */
|
||||
pushonenestedvalue(cs);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
else { /* not a named group */
|
||||
int i;
|
||||
int k = pushcapture(cs);
|
||||
for (i = k; i > 0; i--) /* store all values into table */
|
||||
lua_rawseti(L, -(i + 1), n + i);
|
||||
n += k;
|
||||
}
|
||||
}
|
||||
skipclose(cs, head);
|
||||
return 1; /* number of values pushed (only the table) */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Table-query capture
|
||||
*/
|
||||
static int querycap (CapState *cs) {
|
||||
int idx = cs->cap->idx;
|
||||
pushonenestedvalue(cs); /* get nested capture */
|
||||
lua_gettable(cs->L, updatecache(cs, idx)); /* query cap. value at table */
|
||||
if (!lua_isnil(cs->L, -1))
|
||||
return 1;
|
||||
else { /* no value */
|
||||
lua_pop(cs->L, 1); /* remove nil */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Fold capture
|
||||
*/
|
||||
static int foldcap (CapState *cs) {
|
||||
int n;
|
||||
lua_State *L = cs->L;
|
||||
Capture *head = cs->cap++;
|
||||
int idx = head->idx;
|
||||
if (isclosecap(cs->cap) || /* no nested captures (large subject)? */
|
||||
(n = pushcapture(cs)) == 0) /* nested captures with no values? */
|
||||
return luaL_error(L, "no initial value for fold capture");
|
||||
if (n > 1)
|
||||
lua_pop(L, n - 1); /* leave only one result for accumulator */
|
||||
while (capinside(head, cs->cap)) {
|
||||
lua_pushvalue(L, updatecache(cs, idx)); /* get folding function */
|
||||
lua_insert(L, -2); /* put it before accumulator */
|
||||
n = pushcapture(cs); /* get next capture's values */
|
||||
lua_call(L, n + 1, 1); /* call folding function */
|
||||
}
|
||||
skipclose(cs, head);
|
||||
return 1; /* only accumulator left on the stack */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Function capture
|
||||
*/
|
||||
static int functioncap (CapState *cs) {
|
||||
int n;
|
||||
int top = lua_gettop(cs->L);
|
||||
pushluaval(cs); /* push function */
|
||||
n = pushnestedvalues(cs, 0); /* push nested captures */
|
||||
lua_call(cs->L, n, LUA_MULTRET); /* call function */
|
||||
return lua_gettop(cs->L) - top; /* return function's results */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Accumulator capture
|
||||
*/
|
||||
static int accumulatorcap (CapState *cs) {
|
||||
lua_State *L = cs->L;
|
||||
int n;
|
||||
if (lua_gettop(L) < cs->firstcap)
|
||||
luaL_error(L, "no previous value for accumulator capture");
|
||||
pushluaval(cs); /* push function */
|
||||
lua_insert(L, -2); /* previous value becomes first argument */
|
||||
n = pushnestedvalues(cs, 0); /* push nested captures */
|
||||
lua_call(L, n + 1, 1); /* call function */
|
||||
return 0; /* did not add any extra value */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Select capture
|
||||
*/
|
||||
static int numcap (CapState *cs) {
|
||||
int idx = cs->cap->idx; /* value to select */
|
||||
if (idx == 0) { /* no values? */
|
||||
nextcap(cs); /* skip entire capture */
|
||||
return 0; /* no value produced */
|
||||
}
|
||||
else {
|
||||
int n = pushnestedvalues(cs, 0);
|
||||
if (n < idx) /* invalid index? */
|
||||
return luaL_error(cs->L, "no capture '%d'", idx);
|
||||
else {
|
||||
lua_pushvalue(cs->L, -(n - idx + 1)); /* get selected capture */
|
||||
lua_replace(cs->L, -(n + 1)); /* put it in place of 1st capture */
|
||||
lua_pop(cs->L, n - 1); /* remove other captures */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Return the stack index of the first runtime capture in the given
|
||||
** list of captures (or zero if no runtime captures)
|
||||
*/
|
||||
int finddyncap (Capture *cap, Capture *last) {
|
||||
for (; cap < last; cap++) {
|
||||
if (cap->kind == Cruntime)
|
||||
return cap->idx; /* stack position of first capture */
|
||||
}
|
||||
return 0; /* no dynamic captures in this segment */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Calls a runtime capture. Returns number of captures "removed" by the
|
||||
** call, that is, those inside the group capture. Captures to be added
|
||||
** are on the Lua stack.
|
||||
*/
|
||||
int runtimecap (CapState *cs, Capture *close, const char *s, int *rem) {
|
||||
int n, id;
|
||||
lua_State *L = cs->L;
|
||||
int otop = lua_gettop(L);
|
||||
Capture *open = findopen(close); /* get open group capture */
|
||||
assert(captype(open) == Cgroup);
|
||||
id = finddyncap(open, close); /* get first dynamic capture argument */
|
||||
close->kind = Cclose; /* closes the group */
|
||||
close->index = s - cs->s;
|
||||
cs->cap = open; cs->valuecached = 0; /* prepare capture state */
|
||||
luaL_checkstack(L, 4, "too many runtime captures");
|
||||
pushluaval(cs); /* push function to be called */
|
||||
lua_pushvalue(L, SUBJIDX); /* push original subject */
|
||||
lua_pushinteger(L, s - cs->s + 1); /* push current position */
|
||||
n = pushnestedvalues(cs, 0); /* push nested captures */
|
||||
lua_call(L, n + 2, LUA_MULTRET); /* call dynamic function */
|
||||
if (id > 0) { /* are there old dynamic captures to be removed? */
|
||||
int i;
|
||||
for (i = id; i <= otop; i++)
|
||||
lua_remove(L, id); /* remove old dynamic captures */
|
||||
*rem = otop - id + 1; /* total number of dynamic captures removed */
|
||||
}
|
||||
else
|
||||
*rem = 0; /* no dynamic captures removed */
|
||||
return close - open - 1; /* number of captures to be removed */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Auxiliary structure for substitution and string captures: keep
|
||||
** information about nested captures for future use, avoiding to push
|
||||
** string results into Lua
|
||||
*/
|
||||
typedef struct StrAux {
|
||||
int isstring; /* whether capture is a string */
|
||||
union {
|
||||
Capture *cp; /* if not a string, respective capture */
|
||||
struct { /* if it is a string... */
|
||||
Index_t idx; /* starts here */
|
||||
Index_t siz; /* with this size */
|
||||
} s;
|
||||
} u;
|
||||
} StrAux;
|
||||
|
||||
#define MAXSTRCAPS 10
|
||||
|
||||
/*
|
||||
** Collect values from current capture into array 'cps'. Current
|
||||
** capture must be Cstring (first call) or Csimple (recursive calls).
|
||||
** (In first call, fills %0 with whole match for Cstring.)
|
||||
** Returns number of elements in the array that were filled.
|
||||
*/
|
||||
static int getstrcaps (CapState *cs, StrAux *cps, int n) {
|
||||
int k = n++;
|
||||
Capture *head = cs->cap++;
|
||||
cps[k].isstring = 1; /* get string value */
|
||||
cps[k].u.s.idx = head->index; /* starts here */
|
||||
while (capinside(head, cs->cap)) {
|
||||
if (n >= MAXSTRCAPS) /* too many captures? */
|
||||
nextcap(cs); /* skip extra captures (will not need them) */
|
||||
else if (captype(cs->cap) == Csimple) /* string? */
|
||||
n = getstrcaps(cs, cps, n); /* put info. into array */
|
||||
else {
|
||||
cps[n].isstring = 0; /* not a string */
|
||||
cps[n].u.cp = cs->cap; /* keep original capture */
|
||||
nextcap(cs);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
cps[k].u.s.siz = closesize(cs, head);
|
||||
skipclose(cs, head);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** add next capture value (which should be a string) to buffer 'b'
|
||||
*/
|
||||
static int addonestring (luaL_Buffer *b, CapState *cs, const char *what);
|
||||
|
||||
|
||||
/*
|
||||
** String capture: add result to buffer 'b' (instead of pushing
|
||||
** it into the stack)
|
||||
*/
|
||||
static void stringcap (luaL_Buffer *b, CapState *cs) {
|
||||
StrAux cps[MAXSTRCAPS];
|
||||
int n;
|
||||
size_t len, i;
|
||||
const char *fmt; /* format string */
|
||||
fmt = lua_tolstring(cs->L, updatecache(cs, cs->cap->idx), &len);
|
||||
n = getstrcaps(cs, cps, 0) - 1; /* collect nested captures */
|
||||
for (i = 0; i < len; i++) { /* traverse format string */
|
||||
if (fmt[i] != '%') /* not an escape? */
|
||||
luaL_addchar(b, fmt[i]); /* add it to buffer */
|
||||
else if (fmt[++i] < '0' || fmt[i] > '9') /* not followed by a digit? */
|
||||
luaL_addchar(b, fmt[i]); /* add to buffer */
|
||||
else {
|
||||
int l = fmt[i] - '0'; /* capture index */
|
||||
if (l > n)
|
||||
luaL_error(cs->L, "invalid capture index (%d)", l);
|
||||
else if (cps[l].isstring)
|
||||
luaL_addlstring(b, cs->s + cps[l].u.s.idx, cps[l].u.s.siz);
|
||||
else {
|
||||
Capture *curr = cs->cap;
|
||||
cs->cap = cps[l].u.cp; /* go back to evaluate that nested capture */
|
||||
if (!addonestring(b, cs, "capture"))
|
||||
luaL_error(cs->L, "no values in capture index %d", l);
|
||||
cs->cap = curr; /* continue from where it stopped */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Substitution capture: add result to buffer 'b'
|
||||
*/
|
||||
static void substcap (luaL_Buffer *b, CapState *cs) {
|
||||
const char *curr = cs->s + cs->cap->index;
|
||||
Capture *head = cs->cap++;
|
||||
while (capinside(head, cs->cap)) {
|
||||
Capture *cap = cs->cap;
|
||||
const char *caps = cs->s + cap->index;
|
||||
luaL_addlstring(b, curr, caps - curr); /* add text up to capture */
|
||||
if (addonestring(b, cs, "replacement"))
|
||||
curr = caps + capsize(cap, cs->cap - 1); /* continue after match */
|
||||
else /* no capture value */
|
||||
curr = caps; /* keep original text in final result */
|
||||
}
|
||||
/* add last piece of text */
|
||||
luaL_addlstring(b, curr, cs->s + head->index + closesize(cs, head) - curr);
|
||||
skipclose(cs, head);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Evaluates a capture and adds its first value to buffer 'b'; returns
|
||||
** whether there was a value
|
||||
*/
|
||||
static int addonestring (luaL_Buffer *b, CapState *cs, const char *what) {
|
||||
switch (captype(cs->cap)) {
|
||||
case Cstring:
|
||||
stringcap(b, cs); /* add capture directly to buffer */
|
||||
return 1;
|
||||
case Csubst:
|
||||
substcap(b, cs); /* add capture directly to buffer */
|
||||
return 1;
|
||||
case Cacc: /* accumulator capture? */
|
||||
return luaL_error(cs->L, "invalid context for an accumulator capture");
|
||||
default: {
|
||||
lua_State *L = cs->L;
|
||||
int n = pushcapture(cs);
|
||||
if (n > 0) {
|
||||
if (n > 1) lua_pop(L, n - 1); /* only one result */
|
||||
if (!lua_isstring(L, -1))
|
||||
return luaL_error(L, "invalid %s value (a %s)",
|
||||
what, luaL_typename(L, -1));
|
||||
luaL_addvalue(b);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if !defined(MAXRECLEVEL)
|
||||
#define MAXRECLEVEL 200
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Push all values of the current capture into the stack; returns
|
||||
** number of values pushed
|
||||
*/
|
||||
static int pushcapture (CapState *cs) {
|
||||
lua_State *L = cs->L;
|
||||
int res;
|
||||
luaL_checkstack(L, 4, "too many captures");
|
||||
if (cs->reclevel++ > MAXRECLEVEL)
|
||||
return luaL_error(L, "subcapture nesting too deep");
|
||||
switch (captype(cs->cap)) {
|
||||
case Cposition: {
|
||||
lua_pushinteger(L, cs->cap->index + 1);
|
||||
cs->cap++;
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
case Cconst: {
|
||||
pushluaval(cs);
|
||||
cs->cap++;
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
case Carg: {
|
||||
int arg = (cs->cap++)->idx;
|
||||
if (arg + FIXEDARGS > cs->ptop)
|
||||
return luaL_error(L, "reference to absent extra argument #%d", arg);
|
||||
lua_pushvalue(L, arg + FIXEDARGS);
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
case Csimple: {
|
||||
int k = pushnestedvalues(cs, 1);
|
||||
lua_insert(L, -k); /* make whole match be first result */
|
||||
res = k;
|
||||
break;
|
||||
}
|
||||
case Cruntime: {
|
||||
lua_pushvalue(L, (cs->cap++)->idx); /* value is in the stack */
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
case Cstring: {
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L, &b);
|
||||
stringcap(&b, cs);
|
||||
luaL_pushresult(&b);
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
case Csubst: {
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L, &b);
|
||||
substcap(&b, cs);
|
||||
luaL_pushresult(&b);
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
case Cgroup: {
|
||||
if (cs->cap->idx == 0) /* anonymous group? */
|
||||
res = pushnestedvalues(cs, 0); /* add all nested values */
|
||||
else { /* named group: add no values */
|
||||
nextcap(cs); /* skip capture */
|
||||
res = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Cbackref: res = backrefcap(cs); break;
|
||||
case Ctable: res = tablecap(cs); break;
|
||||
case Cfunction: res = functioncap(cs); break;
|
||||
case Cacc: res = accumulatorcap(cs); break;
|
||||
case Cnum: res = numcap(cs); break;
|
||||
case Cquery: res = querycap(cs); break;
|
||||
case Cfold: res = foldcap(cs); break;
|
||||
default: assert(0); res = 0;
|
||||
}
|
||||
cs->reclevel--;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Prepare a CapState structure and traverse the entire list of
|
||||
** captures in the stack pushing its results. 's' is the subject
|
||||
** string, 'r' is the final position of the match, and 'ptop'
|
||||
** the index in the stack where some useful values were pushed.
|
||||
** Returns the number of results pushed. (If the list produces no
|
||||
** results, push the final position of the match.)
|
||||
*/
|
||||
int getcaptures (lua_State *L, const char *s, const char *r, int ptop) {
|
||||
Capture *capture = (Capture *)lua_touserdata(L, caplistidx(ptop));
|
||||
int n = 0;
|
||||
/* printcaplist(capture); */
|
||||
if (!isclosecap(capture)) { /* is there any capture? */
|
||||
CapState cs;
|
||||
cs.ocap = cs.cap = capture; cs.L = L; cs.reclevel = 0;
|
||||
cs.s = s; cs.valuecached = 0; cs.ptop = ptop;
|
||||
cs.firstcap = lua_gettop(L) + 1; /* where first value (if any) will go */
|
||||
do { /* collect their values */
|
||||
n += pushcapture(&cs);
|
||||
} while (!isclosecap(cs.cap));
|
||||
assert(lua_gettop(L) - cs.firstcap == n - 1);
|
||||
}
|
||||
if (n == 0) { /* no capture values? */
|
||||
lua_pushinteger(L, r - s + 1); /* return only end position */
|
||||
n = 1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
86
3rd/lpeg/lpcap.h
Normal file
86
3rd/lpeg/lpcap.h
Normal file
@@ -0,0 +1,86 @@
|
||||
|
||||
#if !defined(lpcap_h)
|
||||
#define lpcap_h
|
||||
|
||||
|
||||
#include "lptypes.h"
|
||||
|
||||
|
||||
/* kinds of captures */
|
||||
typedef enum CapKind {
|
||||
Cclose, /* not used in trees */
|
||||
Cposition,
|
||||
Cconst, /* ktable[key] is Lua constant */
|
||||
Cbackref, /* ktable[key] is "name" of group to get capture */
|
||||
Carg, /* 'key' is arg's number */
|
||||
Csimple, /* next node is pattern */
|
||||
Ctable, /* next node is pattern */
|
||||
Cfunction, /* ktable[key] is function; next node is pattern */
|
||||
Cacc, /* ktable[key] is function; next node is pattern */
|
||||
Cquery, /* ktable[key] is table; next node is pattern */
|
||||
Cstring, /* ktable[key] is string; next node is pattern */
|
||||
Cnum, /* numbered capture; 'key' is number of value to return */
|
||||
Csubst, /* substitution capture; next node is pattern */
|
||||
Cfold, /* ktable[key] is function; next node is pattern */
|
||||
Cruntime, /* not used in trees (is uses another type for tree) */
|
||||
Cgroup /* ktable[key] is group's "name" */
|
||||
} CapKind;
|
||||
|
||||
|
||||
/*
|
||||
** An unsigned integer large enough to index any subject entirely.
|
||||
** It can be size_t, but that will double the size of the array
|
||||
** of captures in a 64-bit machine.
|
||||
*/
|
||||
#if !defined(Index_t)
|
||||
typedef uint Index_t;
|
||||
#endif
|
||||
|
||||
#define MAXINDT (~(Index_t)0)
|
||||
|
||||
|
||||
typedef struct Capture {
|
||||
Index_t index; /* subject position */
|
||||
unsigned short idx; /* extra info (group name, arg index, etc.) */
|
||||
byte kind; /* kind of capture */
|
||||
byte siz; /* size of full capture + 1 (0 = not a full capture) */
|
||||
} Capture;
|
||||
|
||||
|
||||
typedef struct CapState {
|
||||
Capture *cap; /* current capture */
|
||||
Capture *ocap; /* (original) capture list */
|
||||
lua_State *L;
|
||||
int ptop; /* stack index of last argument to 'match' */
|
||||
int firstcap; /* stack index of first capture pushed in the stack */
|
||||
const char *s; /* original string */
|
||||
int valuecached; /* value stored in cache slot */
|
||||
int reclevel; /* recursion level */
|
||||
} CapState;
|
||||
|
||||
|
||||
#define captype(cap) ((cap)->kind)
|
||||
|
||||
#define isclosecap(cap) (captype(cap) == Cclose)
|
||||
#define isopencap(cap) ((cap)->siz == 0)
|
||||
|
||||
/* true if c2 is (any number of levels) inside c1 */
|
||||
#define capinside(c1,c2) \
|
||||
(isopencap(c1) ? !isclosecap(c2) \
|
||||
: (c2)->index < (c1)->index + (c1)->siz - 1)
|
||||
|
||||
|
||||
/**
|
||||
** Maximum number of captures to visit when looking for an 'open'.
|
||||
*/
|
||||
#define MAXLOP 20
|
||||
|
||||
|
||||
|
||||
int runtimecap (CapState *cs, Capture *close, const char *s, int *rem);
|
||||
int getcaptures (lua_State *L, const char *s, const char *r, int ptop);
|
||||
int finddyncap (Capture *cap, Capture *last);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
1051
3rd/lpeg/lpcode.c
Normal file
1051
3rd/lpeg/lpcode.c
Normal file
File diff suppressed because it is too large
Load Diff
36
3rd/lpeg/lpcode.h
Normal file
36
3rd/lpeg/lpcode.h
Normal file
@@ -0,0 +1,36 @@
|
||||
|
||||
#if !defined(lpcode_h)
|
||||
#define lpcode_h
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lptypes.h"
|
||||
#include "lptree.h"
|
||||
#include "lpvm.h"
|
||||
|
||||
int checkaux (TTree *tree, int pred);
|
||||
int fixedlen (TTree *tree);
|
||||
int hascaptures (TTree *tree);
|
||||
int lp_gc (lua_State *L);
|
||||
Instruction *compile (lua_State *L, Pattern *p, uint size);
|
||||
void freecode (lua_State *L, Pattern *p);
|
||||
int sizei (const Instruction *i);
|
||||
|
||||
|
||||
#define PEnullable 0
|
||||
#define PEnofail 1
|
||||
|
||||
/*
|
||||
** nofail(t) implies that 't' cannot fail with any input
|
||||
*/
|
||||
#define nofail(t) checkaux(t, PEnofail)
|
||||
|
||||
/*
|
||||
** (not nullable(t)) implies 't' cannot match without consuming
|
||||
** something
|
||||
*/
|
||||
#define nullable(t) checkaux(t, PEnullable)
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
110
3rd/lpeg/lpcset.c
Normal file
110
3rd/lpeg/lpcset.c
Normal file
@@ -0,0 +1,110 @@
|
||||
|
||||
#include "lptypes.h"
|
||||
#include "lpcset.h"
|
||||
|
||||
|
||||
/*
|
||||
** Add to 'c' the index of the (only) bit set in byte 'b'
|
||||
*/
|
||||
static int onlybit (int c, int b) {
|
||||
if ((b & 0xF0) != 0) { c += 4; b >>= 4; }
|
||||
if ((b & 0x0C) != 0) { c += 2; b >>= 2; }
|
||||
if ((b & 0x02) != 0) { c += 1; }
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Check whether a charset is empty (returns IFail), singleton (IChar),
|
||||
** full (IAny), or none of those (ISet). When singleton, 'info.offset'
|
||||
** returns which character it is. When generic set, 'info' returns
|
||||
** information about its range.
|
||||
*/
|
||||
Opcode charsettype (const byte *cs, charsetinfo *info) {
|
||||
int low0, low1, high0, high1;
|
||||
for (low1 = 0; low1 < CHARSETSIZE && cs[low1] == 0; low1++)
|
||||
/* find lowest byte with a 1-bit */;
|
||||
if (low1 == CHARSETSIZE)
|
||||
return IFail; /* no characters in set */
|
||||
for (high1 = CHARSETSIZE - 1; cs[high1] == 0; high1--)
|
||||
/* find highest byte with a 1-bit; low1 is a sentinel */;
|
||||
if (low1 == high1) { /* only one byte with 1-bits? */
|
||||
int b = cs[low1];
|
||||
if ((b & (b - 1)) == 0) { /* does byte has only one 1-bit? */
|
||||
info->offset = onlybit(low1 * BITSPERCHAR, b); /* get that bit */
|
||||
return IChar; /* single character */
|
||||
}
|
||||
}
|
||||
for (low0 = 0; low0 < CHARSETSIZE && cs[low0] == 0xFF; low0++)
|
||||
/* find lowest byte with a 0-bit */;
|
||||
if (low0 == CHARSETSIZE)
|
||||
return IAny; /* set has all bits set */
|
||||
for (high0 = CHARSETSIZE - 1; cs[high0] == 0xFF; high0--)
|
||||
/* find highest byte with a 0-bit; low0 is a sentinel */;
|
||||
if (high1 - low1 <= high0 - low0) { /* range of 1s smaller than of 0s? */
|
||||
info->offset = low1;
|
||||
info->size = high1 - low1 + 1;
|
||||
info->deflt = 0; /* all discharged bits were 0 */
|
||||
}
|
||||
else {
|
||||
info->offset = low0;
|
||||
info->size = high0 - low0 + 1;
|
||||
info->deflt = 0xFF; /* all discharged bits were 1 */
|
||||
}
|
||||
info->cs = cs + info->offset;
|
||||
return ISet;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Get a byte from a compact charset. If index is inside the charset
|
||||
** range, get the byte from the supporting charset (correcting it
|
||||
** by the offset). Otherwise, return the default for the set.
|
||||
*/
|
||||
byte getbytefromcharset (const charsetinfo *info, int index) {
|
||||
if (index < info->size)
|
||||
return info->cs[index];
|
||||
else return info->deflt;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** If 'tree' is a 'char' pattern (TSet, TChar, TAny, TFalse), convert it
|
||||
** into a charset and return 1; else return 0.
|
||||
*/
|
||||
int tocharset (TTree *tree, Charset *cs) {
|
||||
switch (tree->tag) {
|
||||
case TChar: { /* only one char */
|
||||
assert(0 <= tree->u.n && tree->u.n <= UCHAR_MAX);
|
||||
clearset(cs->cs); /* erase all chars */
|
||||
setchar(cs->cs, tree->u.n); /* add that one */
|
||||
return 1;
|
||||
}
|
||||
case TAny: {
|
||||
fillset(cs->cs, 0xFF); /* add all characters to the set */
|
||||
return 1;
|
||||
}
|
||||
case TFalse: {
|
||||
clearset(cs->cs); /* empty set */
|
||||
return 1;
|
||||
}
|
||||
case TSet: { /* fill set */
|
||||
int i;
|
||||
fillset(cs->cs, tree->u.set.deflt);
|
||||
for (i = 0; i < tree->u.set.size; i++)
|
||||
cs->cs[tree->u.set.offset + i] = treebuffer(tree)[i];
|
||||
return 1;
|
||||
}
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void tree2cset (TTree *tree, charsetinfo *info) {
|
||||
assert(tree->tag == TSet);
|
||||
info->offset = tree->u.set.offset;
|
||||
info->size = tree->u.set.size;
|
||||
info->deflt = tree->u.set.deflt;
|
||||
info->cs = treebuffer(tree);
|
||||
}
|
||||
|
||||
30
3rd/lpeg/lpcset.h
Normal file
30
3rd/lpeg/lpcset.h
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
#if !defined(lpset_h)
|
||||
#define lpset_h
|
||||
|
||||
#include "lpcset.h"
|
||||
#include "lpcode.h"
|
||||
#include "lptree.h"
|
||||
|
||||
|
||||
/*
|
||||
** Extra information for the result of 'charsettype'. When result is
|
||||
** IChar, 'offset' is the character. When result is ISet, 'cs' is the
|
||||
** supporting bit array (with offset included), 'offset' is the offset
|
||||
** (in bytes), 'size' is the size (in bytes), and 'delt' is the default
|
||||
** value for bytes outside the set.
|
||||
*/
|
||||
typedef struct {
|
||||
const byte *cs;
|
||||
int offset;
|
||||
int size;
|
||||
int deflt;
|
||||
} charsetinfo;
|
||||
|
||||
|
||||
int tocharset (TTree *tree, Charset *cs);
|
||||
Opcode charsettype (const byte *cs, charsetinfo *info);
|
||||
byte getbytefromcharset (const charsetinfo *info, int index);
|
||||
void tree2cset (TTree *tree, charsetinfo *info);
|
||||
|
||||
#endif
|
||||
BIN
3rd/lpeg/lpeg-128.gif
Normal file
BIN
3rd/lpeg/lpeg-128.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.8 KiB |
1430
3rd/lpeg/lpeg.html
Normal file
1430
3rd/lpeg/lpeg.html
Normal file
File diff suppressed because it is too large
Load Diff
298
3rd/lpeg/lpprint.c
Normal file
298
3rd/lpeg/lpprint.c
Normal file
@@ -0,0 +1,298 @@
|
||||
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#include "lptypes.h"
|
||||
#include "lpprint.h"
|
||||
#include "lpcode.h"
|
||||
|
||||
|
||||
#if defined(LPEG_DEBUG)
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Printing patterns (for debugging)
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
|
||||
void printcharset (const byte *st) {
|
||||
int i;
|
||||
printf("[");
|
||||
for (i = 0; i <= UCHAR_MAX; i++) {
|
||||
int first = i;
|
||||
while (i <= UCHAR_MAX && testchar(st, i)) i++;
|
||||
if (i - 1 == first) /* unary range? */
|
||||
printf("(%02x)", first);
|
||||
else if (i - 1 > first) /* non-empty range? */
|
||||
printf("(%02x-%02x)", first, i - 1);
|
||||
}
|
||||
printf("]");
|
||||
}
|
||||
|
||||
|
||||
static void printIcharset (const Instruction *inst, const byte *buff) {
|
||||
byte cs[CHARSETSIZE];
|
||||
int i;
|
||||
printf("(%02x-%d) ", inst->i.aux2.set.offset, inst->i.aux2.set.size);
|
||||
clearset(cs);
|
||||
for (i = 0; i < CHARSETSIZE * 8; i++) {
|
||||
if (charinset(inst, buff, i))
|
||||
setchar(cs, i);
|
||||
}
|
||||
printcharset(cs);
|
||||
}
|
||||
|
||||
|
||||
static void printTcharset (TTree *tree) {
|
||||
byte cs[CHARSETSIZE];
|
||||
int i;
|
||||
printf("(%02x-%d) ", tree->u.set.offset, tree->u.set.size);
|
||||
fillset(cs, tree->u.set.deflt);
|
||||
for (i = 0; i < tree->u.set.size; i++)
|
||||
cs[tree->u.set.offset + i] = treebuffer(tree)[i];
|
||||
printcharset(cs);
|
||||
}
|
||||
|
||||
|
||||
static const char *capkind (int kind) {
|
||||
const char *const modes[] = {
|
||||
"close", "position", "constant", "backref",
|
||||
"argument", "simple", "table", "function", "accumulator",
|
||||
"query", "string", "num", "substitution", "fold",
|
||||
"runtime", "group"};
|
||||
return modes[kind];
|
||||
}
|
||||
|
||||
|
||||
static void printjmp (const Instruction *op, const Instruction *p) {
|
||||
printf("-> %d", (int)(p + (p + 1)->offset - op));
|
||||
}
|
||||
|
||||
|
||||
void printinst (const Instruction *op, const Instruction *p) {
|
||||
const char *const names[] = {
|
||||
"any", "char", "set",
|
||||
"testany", "testchar", "testset",
|
||||
"span", "utf-range", "behind",
|
||||
"ret", "end",
|
||||
"choice", "jmp", "call", "open_call",
|
||||
"commit", "partial_commit", "back_commit", "failtwice", "fail", "giveup",
|
||||
"fullcapture", "opencapture", "closecapture", "closeruntime",
|
||||
"--"
|
||||
};
|
||||
printf("%02ld: %s ", (long)(p - op), names[p->i.code]);
|
||||
switch ((Opcode)p->i.code) {
|
||||
case IChar: {
|
||||
printf("'%c' (%02x)", p->i.aux1, p->i.aux1);
|
||||
break;
|
||||
}
|
||||
case ITestChar: {
|
||||
printf("'%c' (%02x)", p->i.aux1, p->i.aux1); printjmp(op, p);
|
||||
break;
|
||||
}
|
||||
case IUTFR: {
|
||||
printf("%d - %d", p[1].offset, utf_to(p));
|
||||
break;
|
||||
}
|
||||
case IFullCapture: {
|
||||
printf("%s (size = %d) (idx = %d)",
|
||||
capkind(getkind(p)), getoff(p), p->i.aux2.key);
|
||||
break;
|
||||
}
|
||||
case IOpenCapture: {
|
||||
printf("%s (idx = %d)", capkind(getkind(p)), p->i.aux2.key);
|
||||
break;
|
||||
}
|
||||
case ISet: {
|
||||
printIcharset(p, (p+1)->buff);
|
||||
break;
|
||||
}
|
||||
case ITestSet: {
|
||||
printIcharset(p, (p+2)->buff); printjmp(op, p);
|
||||
break;
|
||||
}
|
||||
case ISpan: {
|
||||
printIcharset(p, (p+1)->buff);
|
||||
break;
|
||||
}
|
||||
case IOpenCall: {
|
||||
printf("-> %d", (p + 1)->offset);
|
||||
break;
|
||||
}
|
||||
case IBehind: {
|
||||
printf("%d", p->i.aux1);
|
||||
break;
|
||||
}
|
||||
case IJmp: case ICall: case ICommit: case IChoice:
|
||||
case IPartialCommit: case IBackCommit: case ITestAny: {
|
||||
printjmp(op, p);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
void printpatt (Instruction *p) {
|
||||
Instruction *op = p;
|
||||
uint n = op[-1].codesize - 1;
|
||||
while (p < op + n) {
|
||||
printinst(op, p);
|
||||
p += sizei(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void printcap (Capture *cap, int ident) {
|
||||
while (ident--) printf(" ");
|
||||
printf("%s (idx: %d - size: %d) -> %lu (%p)\n",
|
||||
capkind(cap->kind), cap->idx, cap->siz, (long)cap->index, (void*)cap);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Print a capture and its nested captures
|
||||
*/
|
||||
static Capture *printcap2close (Capture *cap, int ident) {
|
||||
Capture *head = cap++;
|
||||
printcap(head, ident); /* print head capture */
|
||||
while (capinside(head, cap))
|
||||
cap = printcap2close(cap, ident + 2); /* print nested captures */
|
||||
if (isopencap(head)) {
|
||||
assert(isclosecap(cap));
|
||||
printcap(cap++, ident); /* print and skip close capture */
|
||||
}
|
||||
return cap;
|
||||
}
|
||||
|
||||
|
||||
void printcaplist (Capture *cap) {
|
||||
{ /* for debugging, print first a raw list of captures */
|
||||
Capture *c = cap;
|
||||
while (c->index != MAXINDT) { printcap(c, 0); c++; }
|
||||
}
|
||||
printf(">======\n");
|
||||
while (!isclosecap(cap))
|
||||
cap = printcap2close(cap, 0);
|
||||
printf("=======\n");
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Printing trees (for debugging)
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
static const char *tagnames[] = {
|
||||
"char", "set", "any",
|
||||
"true", "false", "utf8.range",
|
||||
"rep",
|
||||
"seq", "choice",
|
||||
"not", "and",
|
||||
"call", "opencall", "rule", "xinfo", "grammar",
|
||||
"behind",
|
||||
"capture", "run-time"
|
||||
};
|
||||
|
||||
|
||||
void printtree (TTree *tree, int ident) {
|
||||
int i;
|
||||
int sibs = numsiblings[tree->tag];
|
||||
for (i = 0; i < ident; i++) printf(" ");
|
||||
printf("%s", tagnames[tree->tag]);
|
||||
switch (tree->tag) {
|
||||
case TChar: {
|
||||
int c = tree->u.n;
|
||||
if (isprint(c))
|
||||
printf(" '%c'\n", c);
|
||||
else
|
||||
printf(" (%02X)\n", c);
|
||||
break;
|
||||
}
|
||||
case TSet: {
|
||||
printTcharset(tree);
|
||||
printf("\n");
|
||||
break;
|
||||
}
|
||||
case TUTFR: {
|
||||
assert(sib1(tree)->tag == TXInfo);
|
||||
printf(" %d (%02x %d) - %d (%02x %d) \n",
|
||||
tree->u.n, tree->key, tree->cap,
|
||||
sib1(tree)->u.n, sib1(tree)->key, sib1(tree)->cap);
|
||||
break;
|
||||
}
|
||||
case TOpenCall: case TCall: {
|
||||
assert(sib1(sib2(tree))->tag == TXInfo);
|
||||
printf(" key: %d (rule: %d)\n", tree->key, sib1(sib2(tree))->u.n);
|
||||
break;
|
||||
}
|
||||
case TBehind: {
|
||||
printf(" %d\n", tree->u.n);
|
||||
break;
|
||||
}
|
||||
case TCapture: {
|
||||
printf(" kind: '%s' key: %d\n", capkind(tree->cap), tree->key);
|
||||
break;
|
||||
}
|
||||
case TRule: {
|
||||
printf(" key: %d\n", tree->key);
|
||||
sibs = 1; /* do not print 'sib2' (next rule) as a sibling */
|
||||
break;
|
||||
}
|
||||
case TXInfo: {
|
||||
printf(" n: %d\n", tree->u.n);
|
||||
break;
|
||||
}
|
||||
case TGrammar: {
|
||||
TTree *rule = sib1(tree);
|
||||
printf(" %d\n", tree->u.n); /* number of rules */
|
||||
for (i = 0; i < tree->u.n; i++) {
|
||||
printtree(rule, ident + 2);
|
||||
rule = sib2(rule);
|
||||
}
|
||||
assert(rule->tag == TTrue); /* sentinel */
|
||||
sibs = 0; /* siblings already handled */
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf("\n");
|
||||
break;
|
||||
}
|
||||
if (sibs >= 1) {
|
||||
printtree(sib1(tree), ident + 2);
|
||||
if (sibs >= 2)
|
||||
printtree(sib2(tree), ident + 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void printktable (lua_State *L, int idx) {
|
||||
int n, i;
|
||||
lua_getuservalue(L, idx);
|
||||
if (lua_isnil(L, -1)) /* no ktable? */
|
||||
return;
|
||||
n = lua_rawlen(L, -1);
|
||||
printf("[");
|
||||
for (i = 1; i <= n; i++) {
|
||||
printf("%d = ", i);
|
||||
lua_rawgeti(L, -1, i);
|
||||
if (lua_isstring(L, -1))
|
||||
printf("%s ", lua_tostring(L, -1));
|
||||
else
|
||||
printf("%s ", lua_typename(L, lua_type(L, -1)));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
printf("]\n");
|
||||
/* leave ktable at the stack */
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
#endif
|
||||
32
3rd/lpeg/lpprint.h
Normal file
32
3rd/lpeg/lpprint.h
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
#if !defined(lpprint_h)
|
||||
#define lpprint_h
|
||||
|
||||
|
||||
#include "lptree.h"
|
||||
#include "lpvm.h"
|
||||
|
||||
|
||||
#if defined(LPEG_DEBUG)
|
||||
|
||||
void printpatt (Instruction *p);
|
||||
void printtree (TTree *tree, int ident);
|
||||
void printktable (lua_State *L, int idx);
|
||||
void printcharset (const byte *st);
|
||||
void printcaplist (Capture *cap);
|
||||
void printinst (const Instruction *op, const Instruction *p);
|
||||
|
||||
#else
|
||||
|
||||
#define printktable(L,idx) \
|
||||
luaL_error(L, "function only implemented in debug mode")
|
||||
#define printtree(tree,i) \
|
||||
luaL_error(L, "function only implemented in debug mode")
|
||||
#define printpatt(p) \
|
||||
luaL_error(L, "function only implemented in debug mode")
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
1399
3rd/lpeg/lptree.c
Normal file
1399
3rd/lpeg/lptree.c
Normal file
File diff suppressed because it is too large
Load Diff
92
3rd/lpeg/lptree.h
Normal file
92
3rd/lpeg/lptree.h
Normal file
@@ -0,0 +1,92 @@
|
||||
|
||||
#if !defined(lptree_h)
|
||||
#define lptree_h
|
||||
|
||||
|
||||
#include "lptypes.h"
|
||||
|
||||
|
||||
/*
|
||||
** types of trees
|
||||
*/
|
||||
typedef enum TTag {
|
||||
TChar = 0, /* 'n' = char */
|
||||
TSet, /* the set is encoded in 'u.set' and the next 'u.set.size' bytes */
|
||||
TAny,
|
||||
TTrue,
|
||||
TFalse,
|
||||
TUTFR, /* range of UTF-8 codepoints; 'n' has initial codepoint;
|
||||
'cap' has length; 'key' has first byte;
|
||||
extra info is similar for end codepoint */
|
||||
TRep, /* 'sib1'* */
|
||||
TSeq, /* 'sib1' 'sib2' */
|
||||
TChoice, /* 'sib1' / 'sib2' */
|
||||
TNot, /* !'sib1' */
|
||||
TAnd, /* &'sib1' */
|
||||
TCall, /* ktable[key] is rule's key; 'sib2' is rule being called */
|
||||
TOpenCall, /* ktable[key] is rule's key */
|
||||
TRule, /* ktable[key] is rule's key (but key == 0 for unused rules);
|
||||
'sib1' is rule's pattern pre-rule; 'sib2' is next rule;
|
||||
extra info 'n' is rule's sequential number */
|
||||
TXInfo, /* extra info */
|
||||
TGrammar, /* 'sib1' is initial (and first) rule */
|
||||
TBehind, /* 'sib1' is pattern, 'n' is how much to go back */
|
||||
TCapture, /* captures: 'cap' is kind of capture (enum 'CapKind');
|
||||
ktable[key] is Lua value associated with capture;
|
||||
'sib1' is capture body */
|
||||
TRunTime /* run-time capture: 'key' is Lua function;
|
||||
'sib1' is capture body */
|
||||
} TTag;
|
||||
|
||||
|
||||
/*
|
||||
** Tree trees
|
||||
** The first child of a tree (if there is one) is immediately after
|
||||
** the tree. A reference to a second child (ps) is its position
|
||||
** relative to the position of the tree itself.
|
||||
*/
|
||||
typedef struct TTree {
|
||||
byte tag;
|
||||
byte cap; /* kind of capture (if it is a capture) */
|
||||
unsigned short key; /* key in ktable for Lua data (0 if no key) */
|
||||
union {
|
||||
int ps; /* occasional second child */
|
||||
int n; /* occasional counter */
|
||||
struct {
|
||||
byte offset; /* compact set offset (in bytes) */
|
||||
byte size; /* compact set size (in bytes) */
|
||||
byte deflt; /* default value */
|
||||
byte bitmap[1]; /* bitmap (open array) */
|
||||
} set; /* for compact sets */
|
||||
} u;
|
||||
} TTree;
|
||||
|
||||
|
||||
/* access to charset */
|
||||
#define treebuffer(t) ((t)->u.set.bitmap)
|
||||
|
||||
|
||||
/*
|
||||
** A complete pattern has its tree plus, if already compiled,
|
||||
** its corresponding code
|
||||
*/
|
||||
typedef struct Pattern {
|
||||
union Instruction *code;
|
||||
TTree tree[1];
|
||||
} Pattern;
|
||||
|
||||
|
||||
/* number of children for each tree */
|
||||
extern const byte numsiblings[];
|
||||
|
||||
/* access to children */
|
||||
#define sib1(t) ((t) + 1)
|
||||
#define sib2(t) ((t) + (t)->u.ps)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
150
3rd/lpeg/lptypes.h
Normal file
150
3rd/lpeg/lptypes.h
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
** LPeg - PEG pattern matching for Lua
|
||||
** Copyright 2007-2023, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
** written by Roberto Ierusalimschy
|
||||
*/
|
||||
|
||||
#if !defined(lptypes_h)
|
||||
#define lptypes_h
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
|
||||
#define VERSION "1.1.0"
|
||||
|
||||
|
||||
#define PATTERN_T "lpeg-pattern"
|
||||
#define MAXSTACKIDX "lpeg-maxstack"
|
||||
|
||||
|
||||
/*
|
||||
** compatibility with Lua 5.1
|
||||
*/
|
||||
#if (LUA_VERSION_NUM == 501)
|
||||
|
||||
#define lp_equal lua_equal
|
||||
|
||||
#define lua_getuservalue lua_getfenv
|
||||
#define lua_setuservalue lua_setfenv
|
||||
|
||||
#define lua_rawlen lua_objlen
|
||||
|
||||
#define luaL_setfuncs(L,f,n) luaL_register(L,NULL,f)
|
||||
#define luaL_newlib(L,f) luaL_register(L,"lpeg",f)
|
||||
|
||||
typedef size_t lua_Unsigned;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(lp_equal)
|
||||
#define lp_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ)
|
||||
#endif
|
||||
|
||||
|
||||
/* default maximum size for call/backtrack stack */
|
||||
#if !defined(MAXBACK)
|
||||
#define MAXBACK 400
|
||||
#endif
|
||||
|
||||
|
||||
/* maximum number of rules in a grammar (limited by 'unsigned short') */
|
||||
#if !defined(MAXRULES)
|
||||
#define MAXRULES 1000
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* initial size for capture's list */
|
||||
#define INITCAPSIZE 32
|
||||
|
||||
|
||||
/* index, on Lua stack, for subject */
|
||||
#define SUBJIDX 2
|
||||
|
||||
/* number of fixed arguments to 'match' (before capture arguments) */
|
||||
#define FIXEDARGS 3
|
||||
|
||||
/* index, on Lua stack, for capture list */
|
||||
#define caplistidx(ptop) ((ptop) + 2)
|
||||
|
||||
/* index, on Lua stack, for pattern's ktable */
|
||||
#define ktableidx(ptop) ((ptop) + 3)
|
||||
|
||||
/* index, on Lua stack, for backtracking stack */
|
||||
#define stackidx(ptop) ((ptop) + 4)
|
||||
|
||||
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
||||
|
||||
#define BITSPERCHAR 8
|
||||
|
||||
#define CHARSETSIZE ((UCHAR_MAX/BITSPERCHAR) + 1)
|
||||
|
||||
|
||||
|
||||
typedef struct Charset {
|
||||
byte cs[CHARSETSIZE];
|
||||
} Charset;
|
||||
|
||||
|
||||
|
||||
#define loopset(v,b) { int v; for (v = 0; v < CHARSETSIZE; v++) {b;} }
|
||||
|
||||
#define fillset(s,c) memset(s,c,CHARSETSIZE)
|
||||
#define clearset(s) fillset(s,0)
|
||||
|
||||
/* number of slots needed for 'n' bytes */
|
||||
#define bytes2slots(n) (((n) - 1u) / (uint)sizeof(TTree) + 1u)
|
||||
|
||||
/* set 'b' bit in charset 'cs' */
|
||||
#define setchar(cs,b) ((cs)[(b) >> 3] |= (1 << ((b) & 7)))
|
||||
|
||||
|
||||
/*
|
||||
** in capture instructions, 'kind' of capture and its offset are
|
||||
** packed in field 'aux', 4 bits for each
|
||||
*/
|
||||
#define getkind(op) ((op)->i.aux1 & 0xF)
|
||||
#define getoff(op) (((op)->i.aux1 >> 4) & 0xF)
|
||||
#define joinkindoff(k,o) ((k) | ((o) << 4))
|
||||
|
||||
#define MAXOFF 0xF
|
||||
#define MAXAUX 0xFF
|
||||
|
||||
|
||||
/* maximum number of bytes to look behind */
|
||||
#define MAXBEHIND MAXAUX
|
||||
|
||||
|
||||
/* maximum size (in elements) for a pattern */
|
||||
#define MAXPATTSIZE (SHRT_MAX - 10)
|
||||
|
||||
|
||||
/* size (in instructions) for l bytes (l > 0) */
|
||||
#define instsize(l) ((int)(((l) + (uint)sizeof(Instruction) - 1u) \
|
||||
/ (uint)sizeof(Instruction)))
|
||||
|
||||
|
||||
/* size (in elements) for a ISet instruction */
|
||||
#define CHARSETINSTSIZE (1 + instsize(CHARSETSIZE))
|
||||
|
||||
/* size (in elements) for a IFunc instruction */
|
||||
#define funcinstsize(p) ((p)->i.aux + 2)
|
||||
|
||||
|
||||
|
||||
#define testchar(st,c) ((((uint)(st)[((c) >> 3)]) >> ((c) & 7)) & 1)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
455
3rd/lpeg/lpvm.c
Normal file
455
3rd/lpeg/lpvm.c
Normal file
@@ -0,0 +1,455 @@
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "lua.h"
|
||||
#include "lauxlib.h"
|
||||
|
||||
#include "lpcap.h"
|
||||
#include "lptypes.h"
|
||||
#include "lpvm.h"
|
||||
#include "lpprint.h"
|
||||
|
||||
|
||||
/* initial size for call/backtrack stack */
|
||||
#if !defined(INITBACK)
|
||||
#define INITBACK MAXBACK
|
||||
#endif
|
||||
|
||||
|
||||
#define getoffset(p) (((p) + 1)->offset)
|
||||
|
||||
static const Instruction giveup = {{IGiveup, 0, {0}}};
|
||||
|
||||
|
||||
int charinset (const Instruction *i, const byte *buff, uint c) {
|
||||
c -= i->i.aux2.set.offset;
|
||||
if (c >= ((uint)i->i.aux2.set.size /* size in instructions... */
|
||||
* (uint)sizeof(Instruction) /* in bytes... */
|
||||
* 8u)) /* in bits */
|
||||
return i->i.aux1; /* out of range; return default value */
|
||||
return testchar(buff, c);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid.
|
||||
*/
|
||||
static const char *utf8_decode (const char *o, int *val) {
|
||||
static const uint limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFFu};
|
||||
const unsigned char *s = (const unsigned char *)o;
|
||||
uint c = s[0]; /* first byte */
|
||||
uint res = 0; /* final result */
|
||||
if (c < 0x80) /* ascii? */
|
||||
res = c;
|
||||
else {
|
||||
int count = 0; /* to count number of continuation bytes */
|
||||
while (c & 0x40) { /* still have continuation bytes? */
|
||||
int cc = s[++count]; /* read next byte */
|
||||
if ((cc & 0xC0) != 0x80) /* not a continuation byte? */
|
||||
return NULL; /* invalid byte sequence */
|
||||
res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */
|
||||
c <<= 1; /* to test next bit */
|
||||
}
|
||||
res |= (c & 0x7F) << (count * 5); /* add first byte */
|
||||
if (count > 3 || res > 0x10FFFFu || res <= limits[count])
|
||||
return NULL; /* invalid byte sequence */
|
||||
s += count; /* skip continuation bytes read */
|
||||
}
|
||||
*val = res;
|
||||
return (const char *)s + 1; /* +1 to include first byte */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Virtual Machine
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
|
||||
typedef struct Stack {
|
||||
const char *s; /* saved position (or NULL for calls) */
|
||||
const Instruction *p; /* next instruction */
|
||||
int caplevel;
|
||||
} Stack;
|
||||
|
||||
|
||||
#define getstackbase(L, ptop) ((Stack *)lua_touserdata(L, stackidx(ptop)))
|
||||
|
||||
|
||||
/*
|
||||
** Ensures the size of array 'capture' (with size '*capsize' and
|
||||
** 'captop' elements being used) is enough to accomodate 'n' extra
|
||||
** elements plus one. (Because several opcodes add stuff to the capture
|
||||
** array, it is simpler to ensure the array always has at least one free
|
||||
** slot upfront and check its size later.)
|
||||
*/
|
||||
|
||||
/* new size in number of elements cannot overflow integers, and new
|
||||
size in bytes cannot overflow size_t. */
|
||||
#define MAXNEWSIZE \
|
||||
(((size_t)INT_MAX) <= (~(size_t)0 / sizeof(Capture)) ? \
|
||||
((size_t)INT_MAX) : (~(size_t)0 / sizeof(Capture)))
|
||||
|
||||
static Capture *growcap (lua_State *L, Capture *capture, int *capsize,
|
||||
int captop, int n, int ptop) {
|
||||
if (*capsize - captop > n)
|
||||
return capture; /* no need to grow array */
|
||||
else { /* must grow */
|
||||
Capture *newc;
|
||||
uint newsize = captop + n + 1; /* minimum size needed */
|
||||
if (newsize < (MAXNEWSIZE / 3) * 2)
|
||||
newsize += newsize / 2; /* 1.5 that size, if not too big */
|
||||
else if (newsize < (MAXNEWSIZE / 9) * 8)
|
||||
newsize += newsize / 8; /* else, try 9/8 that size */
|
||||
else
|
||||
luaL_error(L, "too many captures");
|
||||
newc = (Capture *)lua_newuserdata(L, newsize * sizeof(Capture));
|
||||
memcpy(newc, capture, captop * sizeof(Capture));
|
||||
*capsize = newsize;
|
||||
lua_replace(L, caplistidx(ptop));
|
||||
return newc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Double the size of the stack
|
||||
*/
|
||||
static Stack *doublestack (lua_State *L, Stack **stacklimit, int ptop) {
|
||||
Stack *stack = getstackbase(L, ptop);
|
||||
Stack *newstack;
|
||||
int n = *stacklimit - stack; /* current stack size */
|
||||
int max, newn;
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX);
|
||||
max = lua_tointeger(L, -1); /* maximum allowed size */
|
||||
lua_pop(L, 1);
|
||||
if (n >= max) /* already at maximum size? */
|
||||
luaL_error(L, "backtrack stack overflow (current limit is %d)", max);
|
||||
newn = 2 * n; /* new size */
|
||||
if (newn > max) newn = max;
|
||||
newstack = (Stack *)lua_newuserdata(L, newn * sizeof(Stack));
|
||||
memcpy(newstack, stack, n * sizeof(Stack));
|
||||
lua_replace(L, stackidx(ptop));
|
||||
*stacklimit = newstack + newn;
|
||||
return newstack + n; /* return next position */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Interpret the result of a dynamic capture: false -> fail;
|
||||
** true -> keep current position; number -> next position.
|
||||
** Return new subject position. 'fr' is stack index where
|
||||
** is the result; 'curr' is current subject position; 'limit'
|
||||
** is subject's size.
|
||||
*/
|
||||
static int resdyncaptures (lua_State *L, int fr, int curr, int limit) {
|
||||
lua_Integer res;
|
||||
if (!lua_toboolean(L, fr)) { /* false value? */
|
||||
lua_settop(L, fr - 1); /* remove results */
|
||||
return -1; /* and fail */
|
||||
}
|
||||
else if (lua_isboolean(L, fr)) /* true? */
|
||||
res = curr; /* keep current position */
|
||||
else {
|
||||
res = lua_tointeger(L, fr) - 1; /* new position */
|
||||
if (res < curr || res > limit)
|
||||
luaL_error(L, "invalid position returned by match-time capture");
|
||||
}
|
||||
lua_remove(L, fr); /* remove first result (offset) */
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Add capture values returned by a dynamic capture to the list
|
||||
** 'capture', nested inside a group. 'fd' indexes the first capture
|
||||
** value, 'n' is the number of values (at least 1). The open group
|
||||
** capture is already in 'capture', before the place for the new entries.
|
||||
*/
|
||||
static void adddyncaptures (Index_t index, Capture *capture, int n, int fd) {
|
||||
int i;
|
||||
assert(capture[-1].kind == Cgroup && capture[-1].siz == 0);
|
||||
capture[-1].idx = 0; /* make group capture an anonymous group */
|
||||
for (i = 0; i < n; i++) { /* add runtime captures */
|
||||
capture[i].kind = Cruntime;
|
||||
capture[i].siz = 1; /* mark it as closed */
|
||||
capture[i].idx = fd + i; /* stack index of capture value */
|
||||
capture[i].index = index;
|
||||
}
|
||||
capture[n].kind = Cclose; /* close group */
|
||||
capture[n].siz = 1;
|
||||
capture[n].index = index;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Remove dynamic captures from the Lua stack (called in case of failure)
|
||||
*/
|
||||
static int removedyncap (lua_State *L, Capture *capture,
|
||||
int level, int last) {
|
||||
int id = finddyncap(capture + level, capture + last); /* index of 1st cap. */
|
||||
int top = lua_gettop(L);
|
||||
if (id == 0) return 0; /* no dynamic captures? */
|
||||
lua_settop(L, id - 1); /* remove captures */
|
||||
return top - id + 1; /* number of values removed */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Find the corresponding 'open' capture before 'cap', when that capture
|
||||
** can become a full capture. If a full capture c1 is followed by an
|
||||
** empty capture c2, there is no way to know whether c2 is inside
|
||||
** c1. So, full captures can enclose only captures that start *before*
|
||||
** its end.
|
||||
*/
|
||||
static Capture *findopen (Capture *cap, Index_t currindex) {
|
||||
int i;
|
||||
cap--; /* check last capture */
|
||||
/* Must it be inside current one, but starts where current one ends? */
|
||||
if (!isopencap(cap) && cap->index == currindex)
|
||||
return NULL; /* current one cannot be a full capture */
|
||||
/* else, look for an 'open' capture */
|
||||
for (i = 0; i < MAXLOP; i++, cap--) {
|
||||
if (currindex - cap->index >= UCHAR_MAX)
|
||||
return NULL; /* capture too long for a full capture */
|
||||
else if (isopencap(cap)) /* open capture? */
|
||||
return cap; /* that's the one to be closed */
|
||||
else if (cap->kind == Cclose)
|
||||
return NULL; /* a full capture should not nest a non-full one */
|
||||
}
|
||||
return NULL; /* not found within allowed search limit */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Opcode interpreter
|
||||
*/
|
||||
const char *match (lua_State *L, const char *o, const char *s, const char *e,
|
||||
Instruction *op, Capture *capture, int ptop) {
|
||||
Stack stackbase[INITBACK];
|
||||
Stack *stacklimit = stackbase + INITBACK;
|
||||
Stack *stack = stackbase; /* point to first empty slot in stack */
|
||||
int capsize = INITCAPSIZE;
|
||||
int captop = 0; /* point to first empty slot in captures */
|
||||
int ndyncap = 0; /* number of dynamic captures (in Lua stack) */
|
||||
const Instruction *p = op; /* current instruction */
|
||||
stack->p = &giveup; stack->s = s; stack->caplevel = 0; stack++;
|
||||
lua_pushlightuserdata(L, stackbase);
|
||||
for (;;) {
|
||||
#if defined(DEBUG)
|
||||
printf("-------------------------------------\n");
|
||||
printcaplist(capture, capture + captop);
|
||||
printf("s: |%s| stck:%d, dyncaps:%d, caps:%d ",
|
||||
s, (int)(stack - getstackbase(L, ptop)), ndyncap, captop);
|
||||
printinst(op, p);
|
||||
#endif
|
||||
assert(stackidx(ptop) + ndyncap == lua_gettop(L) && ndyncap <= captop);
|
||||
switch ((Opcode)p->i.code) {
|
||||
case IEnd: {
|
||||
assert(stack == getstackbase(L, ptop) + 1);
|
||||
capture[captop].kind = Cclose;
|
||||
capture[captop].index = MAXINDT;
|
||||
return s;
|
||||
}
|
||||
case IGiveup: {
|
||||
assert(stack == getstackbase(L, ptop));
|
||||
return NULL;
|
||||
}
|
||||
case IRet: {
|
||||
assert(stack > getstackbase(L, ptop) && (stack - 1)->s == NULL);
|
||||
p = (--stack)->p;
|
||||
continue;
|
||||
}
|
||||
case IAny: {
|
||||
if (s < e) { p++; s++; }
|
||||
else goto fail;
|
||||
continue;
|
||||
}
|
||||
case IUTFR: {
|
||||
int codepoint;
|
||||
if (s >= e)
|
||||
goto fail;
|
||||
s = utf8_decode (s, &codepoint);
|
||||
if (s && p[1].offset <= codepoint && codepoint <= utf_to(p))
|
||||
p += 2;
|
||||
else
|
||||
goto fail;
|
||||
continue;
|
||||
}
|
||||
case ITestAny: {
|
||||
if (s < e) p += 2;
|
||||
else p += getoffset(p);
|
||||
continue;
|
||||
}
|
||||
case IChar: {
|
||||
if ((byte)*s == p->i.aux1 && s < e) { p++; s++; }
|
||||
else goto fail;
|
||||
continue;
|
||||
}
|
||||
case ITestChar: {
|
||||
if ((byte)*s == p->i.aux1 && s < e) p += 2;
|
||||
else p += getoffset(p);
|
||||
continue;
|
||||
}
|
||||
case ISet: {
|
||||
uint c = (byte)*s;
|
||||
if (charinset(p, (p+1)->buff, c) && s < e)
|
||||
{ p += 1 + p->i.aux2.set.size; s++; }
|
||||
else goto fail;
|
||||
continue;
|
||||
}
|
||||
case ITestSet: {
|
||||
uint c = (byte)*s;
|
||||
if (charinset(p, (p + 2)->buff, c) && s < e)
|
||||
p += 2 + p->i.aux2.set.size;
|
||||
else p += getoffset(p);
|
||||
continue;
|
||||
}
|
||||
case IBehind: {
|
||||
int n = p->i.aux1;
|
||||
if (n > s - o) goto fail;
|
||||
s -= n; p++;
|
||||
continue;
|
||||
}
|
||||
case ISpan: {
|
||||
for (; s < e; s++) {
|
||||
uint c = (byte)*s;
|
||||
if (!charinset(p, (p+1)->buff, c)) break;
|
||||
}
|
||||
p += 1 + p->i.aux2.set.size;
|
||||
continue;
|
||||
}
|
||||
case IJmp: {
|
||||
p += getoffset(p);
|
||||
continue;
|
||||
}
|
||||
case IChoice: {
|
||||
if (stack == stacklimit)
|
||||
stack = doublestack(L, &stacklimit, ptop);
|
||||
stack->p = p + getoffset(p);
|
||||
stack->s = s;
|
||||
stack->caplevel = captop;
|
||||
stack++;
|
||||
p += 2;
|
||||
continue;
|
||||
}
|
||||
case ICall: {
|
||||
if (stack == stacklimit)
|
||||
stack = doublestack(L, &stacklimit, ptop);
|
||||
stack->s = NULL;
|
||||
stack->p = p + 2; /* save return address */
|
||||
stack++;
|
||||
p += getoffset(p);
|
||||
continue;
|
||||
}
|
||||
case ICommit: {
|
||||
assert(stack > getstackbase(L, ptop) && (stack - 1)->s != NULL);
|
||||
stack--;
|
||||
p += getoffset(p);
|
||||
continue;
|
||||
}
|
||||
case IPartialCommit: {
|
||||
assert(stack > getstackbase(L, ptop) && (stack - 1)->s != NULL);
|
||||
(stack - 1)->s = s;
|
||||
(stack - 1)->caplevel = captop;
|
||||
p += getoffset(p);
|
||||
continue;
|
||||
}
|
||||
case IBackCommit: {
|
||||
assert(stack > getstackbase(L, ptop) && (stack - 1)->s != NULL);
|
||||
s = (--stack)->s;
|
||||
if (ndyncap > 0) /* are there matchtime captures? */
|
||||
ndyncap -= removedyncap(L, capture, stack->caplevel, captop);
|
||||
captop = stack->caplevel;
|
||||
p += getoffset(p);
|
||||
continue;
|
||||
}
|
||||
case IFailTwice:
|
||||
assert(stack > getstackbase(L, ptop));
|
||||
stack--;
|
||||
/* FALLTHROUGH */
|
||||
case IFail:
|
||||
fail: { /* pattern failed: try to backtrack */
|
||||
do { /* remove pending calls */
|
||||
assert(stack > getstackbase(L, ptop));
|
||||
s = (--stack)->s;
|
||||
} while (s == NULL);
|
||||
if (ndyncap > 0) /* is there matchtime captures? */
|
||||
ndyncap -= removedyncap(L, capture, stack->caplevel, captop);
|
||||
captop = stack->caplevel;
|
||||
p = stack->p;
|
||||
#if defined(DEBUG)
|
||||
printf("**FAIL**\n");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
case ICloseRunTime: {
|
||||
CapState cs;
|
||||
int rem, res, n;
|
||||
int fr = lua_gettop(L) + 1; /* stack index of first result */
|
||||
cs.reclevel = 0; cs.L = L;
|
||||
cs.s = o; cs.ocap = capture; cs.ptop = ptop;
|
||||
n = runtimecap(&cs, capture + captop, s, &rem); /* call function */
|
||||
captop -= n; /* remove nested captures */
|
||||
ndyncap -= rem; /* update number of dynamic captures */
|
||||
fr -= rem; /* 'rem' items were popped from Lua stack */
|
||||
res = resdyncaptures(L, fr, s - o, e - o); /* get result */
|
||||
if (res == -1) /* fail? */
|
||||
goto fail;
|
||||
s = o + res; /* else update current position */
|
||||
n = lua_gettop(L) - fr + 1; /* number of new captures */
|
||||
ndyncap += n; /* update number of dynamic captures */
|
||||
if (n == 0) /* no new captures? */
|
||||
captop--; /* remove open group */
|
||||
else { /* new captures; keep original open group */
|
||||
if (fr + n >= SHRT_MAX)
|
||||
luaL_error(L, "too many results in match-time capture");
|
||||
/* add new captures + close group to 'capture' list */
|
||||
capture = growcap(L, capture, &capsize, captop, n + 1, ptop);
|
||||
adddyncaptures(s - o, capture + captop, n, fr);
|
||||
captop += n + 1; /* new captures + close group */
|
||||
}
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
case ICloseCapture: {
|
||||
Capture *open = findopen(capture + captop, s - o);
|
||||
assert(captop > 0);
|
||||
if (open) { /* if possible, turn capture into a full capture */
|
||||
open->siz = (s - o) - open->index + 1;
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
else { /* must create a close capture */
|
||||
capture[captop].siz = 1; /* mark entry as closed */
|
||||
capture[captop].index = s - o;
|
||||
goto pushcapture;
|
||||
}
|
||||
}
|
||||
case IOpenCapture:
|
||||
capture[captop].siz = 0; /* mark entry as open */
|
||||
capture[captop].index = s - o;
|
||||
goto pushcapture;
|
||||
case IFullCapture:
|
||||
capture[captop].siz = getoff(p) + 1; /* save capture size */
|
||||
capture[captop].index = s - o - getoff(p);
|
||||
/* goto pushcapture; */
|
||||
pushcapture: {
|
||||
capture[captop].idx = p->i.aux2.key;
|
||||
capture[captop].kind = getkind(p);
|
||||
captop++;
|
||||
capture = growcap(L, capture, &capsize, captop, 0, ptop);
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
default: assert(0); return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
79
3rd/lpeg/lpvm.h
Normal file
79
3rd/lpeg/lpvm.h
Normal file
@@ -0,0 +1,79 @@
|
||||
|
||||
#if !defined(lpvm_h)
|
||||
#define lpvm_h
|
||||
|
||||
#include "lpcap.h"
|
||||
|
||||
|
||||
/*
|
||||
** About Character sets in instructions: a set is a bit map with an
|
||||
** initial offset, in bits, and a size, in number of instructions.
|
||||
** aux1 has the default value for the bits outsize that range.
|
||||
*/
|
||||
|
||||
|
||||
/* Virtual Machine's instructions */
|
||||
typedef enum Opcode {
|
||||
IAny, /* if no char, fail */
|
||||
IChar, /* if char != aux1, fail */
|
||||
ISet, /* if char not in set, fail */
|
||||
ITestAny, /* in no char, jump to 'offset' */
|
||||
ITestChar, /* if char != aux1, jump to 'offset' */
|
||||
ITestSet, /* if char not in set, jump to 'offset' */
|
||||
ISpan, /* read a span of chars in set */
|
||||
IUTFR, /* if codepoint not in range [offset, utf_to], fail */
|
||||
IBehind, /* walk back 'aux1' characters (fail if not possible) */
|
||||
IRet, /* return from a rule */
|
||||
IEnd, /* end of pattern */
|
||||
IChoice, /* stack a choice; next fail will jump to 'offset' */
|
||||
IJmp, /* jump to 'offset' */
|
||||
ICall, /* call rule at 'offset' */
|
||||
IOpenCall, /* call rule number 'key' (must be closed to a ICall) */
|
||||
ICommit, /* pop choice and jump to 'offset' */
|
||||
IPartialCommit, /* update top choice to current position and jump */
|
||||
IBackCommit, /* backtrack like "fail" but jump to its own 'offset' */
|
||||
IFailTwice, /* pop one choice and then fail */
|
||||
IFail, /* go back to saved state on choice and jump to saved offset */
|
||||
IGiveup, /* internal use */
|
||||
IFullCapture, /* complete capture of last 'off' chars */
|
||||
IOpenCapture, /* start a capture */
|
||||
ICloseCapture,
|
||||
ICloseRunTime,
|
||||
IEmpty /* to fill empty slots left by optimizations */
|
||||
} Opcode;
|
||||
|
||||
|
||||
/*
|
||||
** All array of instructions has a 'codesize' as its first element
|
||||
** and is referred by a pointer to its second element, which is the
|
||||
** first actual opcode.
|
||||
*/
|
||||
typedef union Instruction {
|
||||
struct Inst {
|
||||
byte code;
|
||||
byte aux1;
|
||||
union {
|
||||
short key;
|
||||
struct {
|
||||
byte offset;
|
||||
byte size;
|
||||
} set;
|
||||
} aux2;
|
||||
} i;
|
||||
int offset;
|
||||
uint codesize;
|
||||
byte buff[1];
|
||||
} Instruction;
|
||||
|
||||
|
||||
/* extract 24-bit value from an instruction */
|
||||
#define utf_to(inst) (((inst)->i.aux2.key << 8) | (inst)->i.aux1)
|
||||
|
||||
|
||||
int charinset (const Instruction *i, const byte *buff, uint c);
|
||||
const char *match (lua_State *L, const char *o, const char *s, const char *e,
|
||||
Instruction *op, Capture *capture, int ptop);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
59
3rd/lpeg/makefile
Normal file
59
3rd/lpeg/makefile
Normal file
@@ -0,0 +1,59 @@
|
||||
LIBNAME = lpeg
|
||||
LUADIR = ../lua/
|
||||
|
||||
COPT = -O2 -DNDEBUG
|
||||
# COPT = -O0 -DLPEG_DEBUG -g
|
||||
|
||||
CWARNS = -Wall -Wextra -pedantic \
|
||||
-Waggregate-return \
|
||||
-Wcast-align \
|
||||
-Wcast-qual \
|
||||
-Wdisabled-optimization \
|
||||
-Wpointer-arith \
|
||||
-Wshadow \
|
||||
-Wredundant-decls \
|
||||
-Wsign-compare \
|
||||
-Wundef \
|
||||
-Wwrite-strings \
|
||||
-Wbad-function-cast \
|
||||
-Wdeclaration-after-statement \
|
||||
-Wmissing-prototypes \
|
||||
-Wmissing-declarations \
|
||||
-Wnested-externs \
|
||||
-Wstrict-prototypes \
|
||||
-Wc++-compat \
|
||||
# -Wunreachable-code \
|
||||
|
||||
|
||||
CFLAGS = $(CWARNS) $(COPT) -std=c99 -I$(LUADIR) -fPIC
|
||||
CC = gcc
|
||||
|
||||
FILES = lpvm.o lpcap.o lptree.o lpcode.o lpprint.o lpcset.o
|
||||
|
||||
# For Linux
|
||||
linux:
|
||||
$(MAKE) lpeg.so "DLLFLAGS = -shared -fPIC"
|
||||
|
||||
# For Mac OS
|
||||
macosx:
|
||||
$(MAKE) lpeg.so "DLLFLAGS = -bundle -undefined dynamic_lookup"
|
||||
|
||||
lpeg.so: $(FILES)
|
||||
env $(CC) $(DLLFLAGS) $(FILES) -o lpeg.so
|
||||
|
||||
$(FILES): makefile
|
||||
|
||||
test: test.lua re.lua lpeg.so
|
||||
./test.lua
|
||||
|
||||
clean:
|
||||
rm -f $(FILES) lpeg.so
|
||||
|
||||
|
||||
lpcap.o: lpcap.c lpcap.h lptypes.h
|
||||
lpcode.o: lpcode.c lptypes.h lpcode.h lptree.h lpvm.h lpcap.h lpcset.h
|
||||
lpcset.o: lpcset.c lptypes.h lpcset.h lpcode.h lptree.h lpvm.h lpcap.h
|
||||
lpprint.o: lpprint.c lptypes.h lpprint.h lptree.h lpvm.h lpcap.h lpcode.h
|
||||
lptree.o: lptree.c lptypes.h lpcap.h lpcode.h lptree.h lpvm.h lpprint.h \
|
||||
lpcset.h
|
||||
lpvm.o: lpvm.c lpcap.h lptypes.h lpvm.h lpprint.h lptree.h
|
||||
472
3rd/lpeg/re.html
Normal file
472
3rd/lpeg/re.html
Normal file
@@ -0,0 +1,472 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"//www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>LPeg.re - Regex syntax for LPEG</title>
|
||||
<link rel="stylesheet"
|
||||
href="//www.inf.puc-rio.br/~roberto/lpeg/doc.css"
|
||||
type="text/css"/>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<div id="container">
|
||||
|
||||
<div id="product">
|
||||
<div id="product_logo">
|
||||
<a href="//www.inf.puc-rio.br/~roberto/lpeg/">
|
||||
<img alt="LPeg logo" src="lpeg-128.gif"/>
|
||||
</a>
|
||||
</div>
|
||||
<div id="product_name"><big><strong>LPeg.re</strong></big></div>
|
||||
<div id="product_description">
|
||||
Regex syntax for LPEG
|
||||
</div>
|
||||
</div> <!-- id="product" -->
|
||||
|
||||
<div id="main">
|
||||
|
||||
<div id="navigation">
|
||||
<h1>re</h1>
|
||||
|
||||
<ul>
|
||||
<li><a href="#basic">Basic Constructions</a></li>
|
||||
<li><a href="#func">Functions</a></li>
|
||||
<li><a href="#ex">Some Examples</a></li>
|
||||
<li><a href="#license">License</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div> <!-- id="navigation" -->
|
||||
|
||||
<div id="content">
|
||||
|
||||
<h2><a name="basic"></a>The <code>re</code> Module</h2>
|
||||
|
||||
<p>
|
||||
The <code>re</code> module
|
||||
(provided by file <code>re.lua</code> in the distribution)
|
||||
supports a somewhat conventional regex syntax
|
||||
for pattern usage within <a href="lpeg.html">LPeg</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The next table summarizes <code>re</code>'s syntax.
|
||||
A <code>p</code> represents an arbitrary pattern;
|
||||
<code>num</code> represents a number (<code>[0-9]+</code>);
|
||||
<code>name</code> represents an identifier
|
||||
(<code>[a-zA-Z][a-zA-Z0-9_]*</code>).
|
||||
Constructions are listed in order of decreasing precedence.
|
||||
<table border="1">
|
||||
<tbody><tr><td><b>Syntax</b></td><td><b>Description</b></td></tr>
|
||||
<tr><td><code>( p )</code></td> <td>grouping</td></tr>
|
||||
<tr><td><code>& p</code></td> <td>and predicate</td></tr>
|
||||
<tr><td><code>! p</code></td> <td>not predicate</td></tr>
|
||||
<tr><td><code>p1 p2</code></td> <td>concatenation</td></tr>
|
||||
<tr><td><code>p1 / p2</code></td> <td>ordered choice</td></tr>
|
||||
<tr><td><code>p ?</code></td> <td>optional match</td></tr>
|
||||
<tr><td><code>p *</code></td> <td>zero or more repetitions</td></tr>
|
||||
<tr><td><code>p +</code></td> <td>one or more repetitions</td></tr>
|
||||
<tr><td><code>p^num</code></td>
|
||||
<td>exactly <code>num</code> repetitions</td></tr>
|
||||
<tr><td><code>p^+num</code></td>
|
||||
<td>at least <code>num</code> repetitions</td></tr>
|
||||
<tr><td><code>p^-num</code></td>
|
||||
<td>at most <code>num</code> repetitions</td></tr>
|
||||
<tr><td>(<code>name <- p</code>)<sup>+</sup></td> <td>grammar</td></tr>
|
||||
<tr><td><code>'string'</code></td> <td>literal string</td></tr>
|
||||
<tr><td><code>"string"</code></td> <td>literal string</td></tr>
|
||||
<tr><td><code>[class]</code></td> <td>character class</td></tr>
|
||||
<tr><td><code>.</code></td> <td>any character</td></tr>
|
||||
<tr><td><code>%name</code></td>
|
||||
<td>pattern <code>defs[name]</code> or a pre-defined pattern</td></tr>
|
||||
<tr><td><code>name</code></td><td>non terminal</td></tr>
|
||||
<tr><td><code><name></code></td><td>non terminal</td></tr>
|
||||
|
||||
<tr><td><code>{}</code></td> <td>position capture</td></tr>
|
||||
<tr><td><code>{ p }</code></td> <td>simple capture</td></tr>
|
||||
<tr><td><code>{: p :}</code></td> <td>anonymous group capture</td></tr>
|
||||
<tr><td><code>{:name: p :}</code></td> <td>named group capture</td></tr>
|
||||
<tr><td><code>{~ p ~}</code></td> <td>substitution capture</td></tr>
|
||||
<tr><td><code>{| p |}</code></td> <td>table capture</td></tr>
|
||||
<tr><td><code>=name</code></td> <td>back reference</td></tr>
|
||||
|
||||
<tr><td><code>p -> 'string'</code></td> <td>string capture</td></tr>
|
||||
<tr><td><code>p -> "string"</code></td> <td>string capture</td></tr>
|
||||
<tr><td><code>p -> num</code></td> <td>numbered capture</td></tr>
|
||||
<tr><td><code>p -> name</code></td> <td>function/query/string capture
|
||||
equivalent to <code>p / defs[name]</code></td></tr>
|
||||
<tr><td><code>p => name</code></td> <td>match-time capture
|
||||
equivalent to <code>lpeg.Cmt(p, defs[name])</code></td></tr>
|
||||
<tr><td><code>p ~> name</code></td> <td>fold capture
|
||||
(deprecated)</td></tr>
|
||||
<tr><td><code>p >> name</code></td> <td>accumulator capture
|
||||
equivalent to <code>(p % defs[name])</code></td></tr>
|
||||
</tbody></table>
|
||||
<p>
|
||||
Any space appearing in a syntax description can be
|
||||
replaced by zero or more space characters and Lua-style short comments
|
||||
(<code>--</code> until end of line).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Character classes define sets of characters.
|
||||
An initial <code>^</code> complements the resulting set.
|
||||
A range <em>x</em><code>-</code><em>y</em> includes in the set
|
||||
all characters with codes between the codes of <em>x</em> and <em>y</em>.
|
||||
A pre-defined class <code>%</code><em>name</em> includes all
|
||||
characters of that class.
|
||||
A simple character includes itself in the set.
|
||||
The only special characters inside a class are <code>^</code>
|
||||
(special only if it is the first character);
|
||||
<code>]</code>
|
||||
(can be included in the set as the first character,
|
||||
after the optional <code>^</code>);
|
||||
<code>%</code> (special only if followed by a letter);
|
||||
and <code>-</code>
|
||||
(can be included in the set as the first or the last character).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Currently the pre-defined classes are similar to those from the
|
||||
Lua's string library
|
||||
(<code>%a</code> for letters,
|
||||
<code>%A</code> for non letters, etc.).
|
||||
There is also a class <code>%nl</code>
|
||||
containing only the newline character,
|
||||
which is particularly handy for grammars written inside long strings,
|
||||
as long strings do not interpret escape sequences like <code>\n</code>.
|
||||
</p>
|
||||
|
||||
|
||||
<h2><a name="func">Functions</a></h2>
|
||||
|
||||
<h3><code>re.compile (string, [, defs])</code></h3>
|
||||
<p>
|
||||
Compiles the given string and
|
||||
returns an equivalent LPeg pattern.
|
||||
The given string may define either an expression or a grammar.
|
||||
The optional <code>defs</code> table provides extra Lua values
|
||||
to be used by the pattern.
|
||||
</p>
|
||||
|
||||
<h3><code>re.find (subject, pattern [, init])</code></h3>
|
||||
<p>
|
||||
Searches the given pattern in the given subject.
|
||||
If it finds a match,
|
||||
returns the index where this occurrence starts and
|
||||
the index where it ends.
|
||||
Otherwise, returns nil.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
An optional numeric argument <code>init</code> makes the search
|
||||
starts at that position in the subject string.
|
||||
As usual in Lua libraries,
|
||||
a negative value counts from the end.
|
||||
</p>
|
||||
|
||||
<h3><code>re.gsub (subject, pattern, replacement)</code></h3>
|
||||
<p>
|
||||
Does a <em>global substitution</em>,
|
||||
replacing all occurrences of <code>pattern</code>
|
||||
in the given <code>subject</code> by <code>replacement</code>.
|
||||
|
||||
<h3><code>re.match (subject, pattern)</code></h3>
|
||||
<p>
|
||||
Matches the given pattern against the given subject,
|
||||
returning all captures.
|
||||
</p>
|
||||
|
||||
<h3><code>re.updatelocale ()</code></h3>
|
||||
<p>
|
||||
Updates the pre-defined character classes to the current locale.
|
||||
</p>
|
||||
|
||||
|
||||
<h2><a name="ex">Some Examples</a></h2>
|
||||
|
||||
<h3>A complete simple program</h3>
|
||||
<p>
|
||||
The next code shows a simple complete Lua program using
|
||||
the <code>re</code> module:
|
||||
</p>
|
||||
<pre class="example">
|
||||
local re = require"re"
|
||||
|
||||
-- find the position of the first numeral in a string
|
||||
print(re.find("the number 423 is odd", "[0-9]+")) --> 12 14
|
||||
|
||||
-- returns all words in a string
|
||||
print(re.match("the number 423 is odd", "({%a+} / .)*"))
|
||||
--> the number is odd
|
||||
|
||||
-- returns the first numeral in a string
|
||||
print(re.match("the number 423 is odd", "s <- {%d+} / . s"))
|
||||
--> 423
|
||||
|
||||
-- substitutes a dot for each vowel in a string
|
||||
print(re.gsub("hello World", "[aeiou]", "."))
|
||||
--> h.ll. W.rld
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>Balanced parentheses</h3>
|
||||
<p>
|
||||
The following call will produce the same pattern produced by the
|
||||
Lua expression in the
|
||||
<a href="lpeg.html#balanced">balanced parentheses</a> example:
|
||||
</p>
|
||||
<pre class="example">
|
||||
b = re.compile[[ balanced <- "(" ([^()] / balanced)* ")" ]]
|
||||
</pre>
|
||||
|
||||
<h3>String reversal</h3>
|
||||
<p>
|
||||
The next example reverses a string:
|
||||
</p>
|
||||
<pre class="example">
|
||||
rev = re.compile[[ R <- (!.) -> '' / ({.} R) -> '%2%1']]
|
||||
print(rev:match"0123456789") --> 9876543210
|
||||
</pre>
|
||||
|
||||
<h3>CSV decoder</h3>
|
||||
<p>
|
||||
The next example replicates the <a href="lpeg.html#CSV">CSV decoder</a>:
|
||||
</p>
|
||||
<pre class="example">
|
||||
record = re.compile[[
|
||||
record <- {| field (',' field)* |} (%nl / !.)
|
||||
field <- escaped / nonescaped
|
||||
nonescaped <- { [^,"%nl]* }
|
||||
escaped <- '"' {~ ([^"] / '""' -> '"')* ~} '"'
|
||||
]]
|
||||
</pre>
|
||||
|
||||
<h3>Lua's long strings</h3>
|
||||
<p>
|
||||
The next example matches Lua long strings:
|
||||
</p>
|
||||
<pre class="example">
|
||||
c = re.compile([[
|
||||
longstring <- ('[' {:eq: '='* :} '[' close)
|
||||
close <- ']' =eq ']' / . close
|
||||
]])
|
||||
|
||||
print(c:match'[==[]]===]]]]==]===[]') --> 17
|
||||
</pre>
|
||||
|
||||
<h3>Abstract Syntax Trees</h3>
|
||||
<p>
|
||||
This example shows a simple way to build an
|
||||
abstract syntax tree (AST) for a given grammar.
|
||||
To keep our example simple,
|
||||
let us consider the following grammar
|
||||
for lists of names:
|
||||
</p>
|
||||
<pre class="example">
|
||||
p = re.compile[[
|
||||
listname <- (name s)*
|
||||
name <- [a-z][a-z]*
|
||||
s <- %s*
|
||||
]]
|
||||
</pre>
|
||||
<p>
|
||||
Now, we will add captures to build a corresponding AST.
|
||||
As a first step, the pattern will build a table to
|
||||
represent each non terminal;
|
||||
terminals will be represented by their corresponding strings:
|
||||
</p>
|
||||
<pre class="example">
|
||||
c = re.compile[[
|
||||
listname <- {| (name s)* |}
|
||||
name <- {| {[a-z][a-z]*} |}
|
||||
s <- %s*
|
||||
]]
|
||||
</pre>
|
||||
<p>
|
||||
Now, a match against <code>"hi hello bye"</code>
|
||||
results in the table
|
||||
<code>{{"hi"}, {"hello"}, {"bye"}}</code>.
|
||||
</p>
|
||||
<p>
|
||||
For such a simple grammar,
|
||||
this AST is more than enough;
|
||||
actually, the tables around each single name
|
||||
are already overkilling.
|
||||
More complex grammars,
|
||||
however, may need some more structure.
|
||||
Specifically,
|
||||
it would be useful if each table had
|
||||
a <code>tag</code> field telling what non terminal
|
||||
that table represents.
|
||||
We can add such a tag using
|
||||
<a href="lpeg.html#cap-g">named group captures</a>:
|
||||
</p>
|
||||
<pre class="example">
|
||||
x = re.compile[[
|
||||
listname <- {| {:tag: '' -> 'list':} (name s)* |}
|
||||
name <- {| {:tag: '' -> 'id':} {[a-z][a-z]*} |}
|
||||
s <- ' '*
|
||||
]]
|
||||
</pre>
|
||||
<p>
|
||||
With these group captures,
|
||||
a match against <code>"hi hello bye"</code>
|
||||
results in the following table:
|
||||
</p>
|
||||
<pre class="example">
|
||||
{tag="list",
|
||||
{tag="id", "hi"},
|
||||
{tag="id", "hello"},
|
||||
{tag="id", "bye"}
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>Indented blocks</h3>
|
||||
<p>
|
||||
This example breaks indented blocks into tables,
|
||||
respecting the indentation:
|
||||
</p>
|
||||
<pre class="example">
|
||||
p = re.compile[[
|
||||
block <- {| {:ident:' '*:} line
|
||||
((=ident !' ' line) / &(=ident ' ') block)* |}
|
||||
line <- {[^%nl]*} %nl
|
||||
]]
|
||||
</pre>
|
||||
<p>
|
||||
As an example,
|
||||
consider the following text:
|
||||
</p>
|
||||
<pre class="example">
|
||||
t = p:match[[
|
||||
first line
|
||||
subline 1
|
||||
subline 2
|
||||
second line
|
||||
third line
|
||||
subline 3.1
|
||||
subline 3.1.1
|
||||
subline 3.2
|
||||
]]
|
||||
</pre>
|
||||
<p>
|
||||
The resulting table <code>t</code> will be like this:
|
||||
</p>
|
||||
<pre class="example">
|
||||
{'first line'; {'subline 1'; 'subline 2'; ident = ' '};
|
||||
'second line';
|
||||
'third line'; { 'subline 3.1'; {'subline 3.1.1'; ident = ' '};
|
||||
'subline 3.2'; ident = ' '};
|
||||
ident = ''}
|
||||
</pre>
|
||||
|
||||
<h3>Macro expander</h3>
|
||||
<p>
|
||||
This example implements a simple macro expander.
|
||||
Macros must be defined as part of the pattern,
|
||||
following some simple rules:
|
||||
</p>
|
||||
<pre class="example">
|
||||
p = re.compile[[
|
||||
text <- {~ item* ~}
|
||||
item <- macro / [^()] / '(' item* ')'
|
||||
arg <- ' '* {~ (!',' item)* ~}
|
||||
args <- '(' arg (',' arg)* ')'
|
||||
-- now we define some macros
|
||||
macro <- ('apply' args) -> '%1(%2)'
|
||||
/ ('add' args) -> '%1 + %2'
|
||||
/ ('mul' args) -> '%1 * %2'
|
||||
]]
|
||||
|
||||
print(p:match"add(mul(a,b), apply(f,x))") --> a * b + f(x)
|
||||
</pre>
|
||||
<p>
|
||||
A <code>text</code> is a sequence of items,
|
||||
wherein we apply a substitution capture to expand any macros.
|
||||
An <code>item</code> is either a macro,
|
||||
any character different from parentheses,
|
||||
or a parenthesized expression.
|
||||
A macro argument (<code>arg</code>) is a sequence
|
||||
of items different from a comma.
|
||||
(Note that a comma may appear inside an item,
|
||||
e.g., inside a parenthesized expression.)
|
||||
Again we do a substitution capture to expand any macro
|
||||
in the argument before expanding the outer macro.
|
||||
<code>args</code> is a list of arguments separated by commas.
|
||||
Finally we define the macros.
|
||||
Each macro is a string substitution;
|
||||
it replaces the macro name and its arguments by its corresponding string,
|
||||
with each <code>%</code><em>n</em> replaced by the <em>n</em>-th argument.
|
||||
</p>
|
||||
|
||||
<h3>Patterns</h3>
|
||||
<p>
|
||||
This example shows the complete syntax
|
||||
of patterns accepted by <code>re</code>.
|
||||
</p>
|
||||
<pre class="example">
|
||||
p = [=[
|
||||
|
||||
pattern <- exp !.
|
||||
exp <- S (grammar / alternative)
|
||||
|
||||
alternative <- seq ('/' S seq)*
|
||||
seq <- prefix*
|
||||
prefix <- '&' S prefix / '!' S prefix / suffix
|
||||
suffix <- primary S (([+*?]
|
||||
/ '^' [+-]? num
|
||||
/ '->' S (string / '{}' / name)
|
||||
/ '>>' S name
|
||||
/ '=>' S name) S)*
|
||||
|
||||
primary <- '(' exp ')' / string / class / defined
|
||||
/ '{:' (name ':')? exp ':}'
|
||||
/ '=' name
|
||||
/ '{}'
|
||||
/ '{~' exp '~}'
|
||||
/ '{|' exp '|}'
|
||||
/ '{' exp '}'
|
||||
/ '.'
|
||||
/ name S !arrow
|
||||
/ '<' name '>' -- old-style non terminals
|
||||
|
||||
grammar <- definition+
|
||||
definition <- name S arrow exp
|
||||
|
||||
class <- '[' '^'? item (!']' item)* ']'
|
||||
item <- defined / range / .
|
||||
range <- . '-' [^]]
|
||||
|
||||
S <- (%s / '--' [^%nl]*)* -- spaces and comments
|
||||
name <- [A-Za-z_][A-Za-z0-9_]*
|
||||
arrow <- '<-'
|
||||
num <- [0-9]+
|
||||
string <- '"' [^"]* '"' / "'" [^']* "'"
|
||||
defined <- '%' name
|
||||
|
||||
]=]
|
||||
|
||||
print(re.match(p, p)) -- a self description must match itself
|
||||
</pre>
|
||||
|
||||
|
||||
|
||||
<h2><a name="license">License</a></h2>
|
||||
|
||||
<p>
|
||||
This module is part of the <a href="lpeg.html">LPeg</a> package and shares
|
||||
its <a href="lpeg.html#license">license</a>.
|
||||
|
||||
|
||||
</div> <!-- id="content" -->
|
||||
|
||||
</div> <!-- id="main" -->
|
||||
|
||||
</div> <!-- id="container" -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
270
3rd/lpeg/re.lua
Normal file
270
3rd/lpeg/re.lua
Normal file
@@ -0,0 +1,270 @@
|
||||
--
|
||||
-- Copyright 2007-2023, Lua.org & PUC-Rio (see 'lpeg.html' for license)
|
||||
-- written by Roberto Ierusalimschy
|
||||
--
|
||||
|
||||
-- imported functions and modules
|
||||
local tonumber, type, print, error = tonumber, type, print, error
|
||||
local setmetatable = setmetatable
|
||||
local m = require"lpeg"
|
||||
|
||||
-- 'm' will be used to parse expressions, and 'mm' will be used to
|
||||
-- create expressions; that is, 're' runs on 'm', creating patterns
|
||||
-- on 'mm'
|
||||
local mm = m
|
||||
|
||||
-- patterns' metatable
|
||||
local mt = getmetatable(mm.P(0))
|
||||
|
||||
|
||||
local version = _VERSION
|
||||
|
||||
-- No more global accesses after this point
|
||||
_ENV = nil -- does no harm in Lua 5.1
|
||||
|
||||
|
||||
local any = m.P(1)
|
||||
|
||||
|
||||
-- Pre-defined names
|
||||
local Predef = { nl = m.P"\n" }
|
||||
|
||||
|
||||
local mem
|
||||
local fmem
|
||||
local gmem
|
||||
|
||||
|
||||
local function updatelocale ()
|
||||
mm.locale(Predef)
|
||||
Predef.a = Predef.alpha
|
||||
Predef.c = Predef.cntrl
|
||||
Predef.d = Predef.digit
|
||||
Predef.g = Predef.graph
|
||||
Predef.l = Predef.lower
|
||||
Predef.p = Predef.punct
|
||||
Predef.s = Predef.space
|
||||
Predef.u = Predef.upper
|
||||
Predef.w = Predef.alnum
|
||||
Predef.x = Predef.xdigit
|
||||
Predef.A = any - Predef.a
|
||||
Predef.C = any - Predef.c
|
||||
Predef.D = any - Predef.d
|
||||
Predef.G = any - Predef.g
|
||||
Predef.L = any - Predef.l
|
||||
Predef.P = any - Predef.p
|
||||
Predef.S = any - Predef.s
|
||||
Predef.U = any - Predef.u
|
||||
Predef.W = any - Predef.w
|
||||
Predef.X = any - Predef.x
|
||||
mem = {} -- restart memoization
|
||||
fmem = {}
|
||||
gmem = {}
|
||||
local mt = {__mode = "v"}
|
||||
setmetatable(mem, mt)
|
||||
setmetatable(fmem, mt)
|
||||
setmetatable(gmem, mt)
|
||||
end
|
||||
|
||||
|
||||
updatelocale()
|
||||
|
||||
|
||||
|
||||
local I = m.P(function (s,i) print(i, s:sub(1, i-1)); return i end)
|
||||
|
||||
|
||||
local function patt_error (s, i)
|
||||
local msg = (#s < i + 20) and s:sub(i)
|
||||
or s:sub(i,i+20) .. "..."
|
||||
msg = ("pattern error near '%s'"):format(msg)
|
||||
error(msg, 2)
|
||||
end
|
||||
|
||||
local function mult (p, n)
|
||||
local np = mm.P(true)
|
||||
while n >= 1 do
|
||||
if n%2 >= 1 then np = np * p end
|
||||
p = p * p
|
||||
n = n/2
|
||||
end
|
||||
return np
|
||||
end
|
||||
|
||||
local function equalcap (s, i, c)
|
||||
if type(c) ~= "string" then return nil end
|
||||
local e = #c + i
|
||||
if s:sub(i, e - 1) == c then return e else return nil end
|
||||
end
|
||||
|
||||
|
||||
local S = (Predef.space + "--" * (any - Predef.nl)^0)^0
|
||||
|
||||
local name = m.R("AZ", "az", "__") * m.R("AZ", "az", "__", "09")^0
|
||||
|
||||
local arrow = S * "<-"
|
||||
|
||||
local seq_follow = m.P"/" + ")" + "}" + ":}" + "~}" + "|}" + (name * arrow) + -1
|
||||
|
||||
name = m.C(name)
|
||||
|
||||
|
||||
-- a defined name only have meaning in a given environment
|
||||
local Def = name * m.Carg(1)
|
||||
|
||||
|
||||
local function getdef (id, defs)
|
||||
local c = defs and defs[id]
|
||||
if not c then error("undefined name: " .. id) end
|
||||
return c
|
||||
end
|
||||
|
||||
-- match a name and return a group of its corresponding definition
|
||||
-- and 'f' (to be folded in 'Suffix')
|
||||
local function defwithfunc (f)
|
||||
return m.Cg(Def / getdef * m.Cc(f))
|
||||
end
|
||||
|
||||
|
||||
local num = m.C(m.R"09"^1) * S / tonumber
|
||||
|
||||
local String = "'" * m.C((any - "'")^0) * "'" +
|
||||
'"' * m.C((any - '"')^0) * '"'
|
||||
|
||||
|
||||
local defined = "%" * Def / function (c,Defs)
|
||||
local cat = Defs and Defs[c] or Predef[c]
|
||||
if not cat then error ("name '" .. c .. "' undefined") end
|
||||
return cat
|
||||
end
|
||||
|
||||
local Range = m.Cs(any * (m.P"-"/"") * (any - "]")) / mm.R
|
||||
|
||||
local item = (defined + Range + m.C(any)) / m.P
|
||||
|
||||
local Class =
|
||||
"["
|
||||
* (m.C(m.P"^"^-1)) -- optional complement symbol
|
||||
* (item * ((item % mt.__add) - "]")^0) /
|
||||
function (c, p) return c == "^" and any - p or p end
|
||||
* "]"
|
||||
|
||||
local function adddef (t, k, exp)
|
||||
if t[k] then
|
||||
error("'"..k.."' already defined as a rule")
|
||||
else
|
||||
t[k] = exp
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
local function firstdef (n, r) return adddef({n}, n, r) end
|
||||
|
||||
|
||||
local function NT (n, b)
|
||||
if not b then
|
||||
error("rule '"..n.."' used outside a grammar")
|
||||
else return mm.V(n)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local exp = m.P{ "Exp",
|
||||
Exp = S * ( m.V"Grammar"
|
||||
+ m.V"Seq" * ("/" * S * m.V"Seq" % mt.__add)^0 );
|
||||
Seq = (m.Cc(m.P"") * (m.V"Prefix" % mt.__mul)^0)
|
||||
* (#seq_follow + patt_error);
|
||||
Prefix = "&" * S * m.V"Prefix" / mt.__len
|
||||
+ "!" * S * m.V"Prefix" / mt.__unm
|
||||
+ m.V"Suffix";
|
||||
Suffix = m.V"Primary" * S *
|
||||
( ( m.P"+" * m.Cc(1, mt.__pow)
|
||||
+ m.P"*" * m.Cc(0, mt.__pow)
|
||||
+ m.P"?" * m.Cc(-1, mt.__pow)
|
||||
+ "^" * ( m.Cg(num * m.Cc(mult))
|
||||
+ m.Cg(m.C(m.S"+-" * m.R"09"^1) * m.Cc(mt.__pow))
|
||||
)
|
||||
+ "->" * S * ( m.Cg((String + num) * m.Cc(mt.__div))
|
||||
+ m.P"{}" * m.Cc(nil, m.Ct)
|
||||
+ defwithfunc(mt.__div)
|
||||
)
|
||||
+ "=>" * S * defwithfunc(mm.Cmt)
|
||||
+ ">>" * S * defwithfunc(mt.__mod)
|
||||
+ "~>" * S * defwithfunc(mm.Cf)
|
||||
) % function (a,b,f) return f(a,b) end * S
|
||||
)^0;
|
||||
Primary = "(" * m.V"Exp" * ")"
|
||||
+ String / mm.P
|
||||
+ Class
|
||||
+ defined
|
||||
+ "{:" * (name * ":" + m.Cc(nil)) * m.V"Exp" * ":}" /
|
||||
function (n, p) return mm.Cg(p, n) end
|
||||
+ "=" * name / function (n) return mm.Cmt(mm.Cb(n), equalcap) end
|
||||
+ m.P"{}" / mm.Cp
|
||||
+ "{~" * m.V"Exp" * "~}" / mm.Cs
|
||||
+ "{|" * m.V"Exp" * "|}" / mm.Ct
|
||||
+ "{" * m.V"Exp" * "}" / mm.C
|
||||
+ m.P"." * m.Cc(any)
|
||||
+ (name * -arrow + "<" * name * ">") * m.Cb("G") / NT;
|
||||
Definition = name * arrow * m.V"Exp";
|
||||
Grammar = m.Cg(m.Cc(true), "G") *
|
||||
((m.V"Definition" / firstdef) * (m.V"Definition" % adddef)^0) / mm.P
|
||||
}
|
||||
|
||||
local pattern = S * m.Cg(m.Cc(false), "G") * exp / mm.P * (-any + patt_error)
|
||||
|
||||
|
||||
local function compile (p, defs)
|
||||
if mm.type(p) == "pattern" then return p end -- already compiled
|
||||
local cp = pattern:match(p, 1, defs)
|
||||
if not cp then error("incorrect pattern", 3) end
|
||||
return cp
|
||||
end
|
||||
|
||||
local function match (s, p, i)
|
||||
local cp = mem[p]
|
||||
if not cp then
|
||||
cp = compile(p)
|
||||
mem[p] = cp
|
||||
end
|
||||
return cp:match(s, i or 1)
|
||||
end
|
||||
|
||||
local function find (s, p, i)
|
||||
local cp = fmem[p]
|
||||
if not cp then
|
||||
cp = compile(p) / 0
|
||||
cp = mm.P{ mm.Cp() * cp * mm.Cp() + 1 * mm.V(1) }
|
||||
fmem[p] = cp
|
||||
end
|
||||
local i, e = cp:match(s, i or 1)
|
||||
if i then return i, e - 1
|
||||
else return i
|
||||
end
|
||||
end
|
||||
|
||||
local function gsub (s, p, rep)
|
||||
local g = gmem[p] or {} -- ensure gmem[p] is not collected while here
|
||||
gmem[p] = g
|
||||
local cp = g[rep]
|
||||
if not cp then
|
||||
cp = compile(p)
|
||||
cp = mm.Cs((cp / rep + 1)^0)
|
||||
g[rep] = cp
|
||||
end
|
||||
return cp:match(s)
|
||||
end
|
||||
|
||||
|
||||
-- exported names
|
||||
local re = {
|
||||
compile = compile,
|
||||
match = match,
|
||||
find = find,
|
||||
gsub = gsub,
|
||||
updatelocale = updatelocale,
|
||||
}
|
||||
|
||||
if version == "Lua 5.1" then _G.re = re end
|
||||
|
||||
return re
|
||||
1667
3rd/lpeg/test.lua
Executable file
1667
3rd/lpeg/test.lua
Executable file
File diff suppressed because it is too large
Load Diff
@@ -1,76 +0,0 @@
|
||||
# If Lua is installed in a non-standard location, please set the LUA_DIR
|
||||
# environment variable to point to prefix for the install. Eg:
|
||||
# Unix: export LUA_DIR=/home/user/pkg
|
||||
# Windows: set LUA_DIR=c:\lua51
|
||||
|
||||
project(lua-cjson C)
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
option(USE_INTERNAL_FPCONV "Use internal strtod() / g_fmt() code for performance")
|
||||
option(MULTIPLE_THREADS "Support multi-threaded apps with internal fpconv - recommended" ON)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release CACHE STRING
|
||||
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
|
||||
FORCE)
|
||||
endif()
|
||||
|
||||
find_package(Lua51 REQUIRED)
|
||||
include_directories(${LUA_INCLUDE_DIR})
|
||||
|
||||
if(NOT USE_INTERNAL_FPCONV)
|
||||
# Use libc number conversion routines (strtod(), sprintf())
|
||||
set(FPCONV_SOURCES fpconv.c)
|
||||
else()
|
||||
# Use internal number conversion routines
|
||||
add_definitions(-DUSE_INTERNAL_FPCONV)
|
||||
set(FPCONV_SOURCES g_fmt.c dtoa.c)
|
||||
|
||||
include(TestBigEndian)
|
||||
TEST_BIG_ENDIAN(IEEE_BIG_ENDIAN)
|
||||
if(IEEE_BIG_ENDIAN)
|
||||
add_definitions(-DIEEE_BIG_ENDIAN)
|
||||
endif()
|
||||
|
||||
if(MULTIPLE_THREADS)
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||
find_package(Threads REQUIRED)
|
||||
if(NOT CMAKE_USE_PTHREADS_INIT)
|
||||
message(FATAL_ERROR
|
||||
"Pthreads not found - required by MULTIPLE_THREADS option")
|
||||
endif()
|
||||
add_definitions(-DMULTIPLE_THREADS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Handle platforms missing isinf() macro (Eg, some Solaris systems).
|
||||
include(CheckSymbolExists)
|
||||
CHECK_SYMBOL_EXISTS(isinf math.h HAVE_ISINF)
|
||||
if(NOT HAVE_ISINF)
|
||||
add_definitions(-DUSE_INTERNAL_ISINF)
|
||||
endif()
|
||||
|
||||
set(_MODULE_LINK "${CMAKE_THREAD_LIBS_INIT}")
|
||||
get_filename_component(_lua_lib_dir ${LUA_LIBRARY} PATH)
|
||||
|
||||
if(APPLE)
|
||||
set(CMAKE_SHARED_MODULE_CREATE_C_FLAGS
|
||||
"${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -undefined dynamic_lookup")
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
# Win32 modules need to be linked to the Lua library.
|
||||
set(_MODULE_LINK ${LUA_LIBRARY} ${_MODULE_LINK})
|
||||
set(_lua_module_dir "${_lua_lib_dir}")
|
||||
# Windows sprintf()/strtod() handle NaN/inf differently. Not supported.
|
||||
add_definitions(-DDISABLE_INVALID_NUMBERS)
|
||||
else()
|
||||
set(_lua_module_dir "${_lua_lib_dir}/lua/5.1")
|
||||
endif()
|
||||
|
||||
add_library(cjson MODULE lua_cjson.c strbuf.c ${FPCONV_SOURCES})
|
||||
set_target_properties(cjson PROPERTIES PREFIX "")
|
||||
target_link_libraries(cjson ${_MODULE_LINK})
|
||||
install(TARGETS cjson DESTINATION "${_lua_module_dir}")
|
||||
|
||||
# vi:ai et sw=4 ts=4:
|
||||
@@ -1,20 +0,0 @@
|
||||
Copyright (c) 2010-2012 Mark Pulford <mark@kyne.com.au>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -1,119 +0,0 @@
|
||||
##### Available defines for CJSON_CFLAGS #####
|
||||
##
|
||||
## USE_INTERNAL_ISINF: Workaround for Solaris platforms missing isinf().
|
||||
## DISABLE_INVALID_NUMBERS: Permanently disable invalid JSON numbers:
|
||||
## NaN, Infinity, hex.
|
||||
##
|
||||
## Optional built-in number conversion uses the following defines:
|
||||
## USE_INTERNAL_FPCONV: Use builtin strtod/dtoa for numeric conversions.
|
||||
## IEEE_BIG_ENDIAN: Required on big endian architectures.
|
||||
## MULTIPLE_THREADS: Must be set when Lua CJSON may be used in a
|
||||
## multi-threaded application. Requries _pthreads_.
|
||||
|
||||
##### Build defaults #####
|
||||
LUA_VERSION = 5.1
|
||||
TARGET = cjson.so
|
||||
PREFIX = /usr/local
|
||||
#CFLAGS = -g -Wall -pedantic -fno-inline
|
||||
CFLAGS = -O3 -Wall -pedantic -DNDEBUG
|
||||
CJSON_CFLAGS = -fpic
|
||||
CJSON_LDFLAGS = -shared
|
||||
LUA_INCLUDE_DIR = $(PREFIX)/include
|
||||
LUA_CMODULE_DIR = $(PREFIX)/lib/lua/$(LUA_VERSION)
|
||||
LUA_MODULE_DIR = $(PREFIX)/share/lua/$(LUA_VERSION)
|
||||
LUA_BIN_DIR = $(PREFIX)/bin
|
||||
|
||||
##### Platform overrides #####
|
||||
##
|
||||
## Tweak one of the platform sections below to suit your situation.
|
||||
##
|
||||
## See http://lua-users.org/wiki/BuildingModules for further platform
|
||||
## specific details.
|
||||
|
||||
## Linux
|
||||
|
||||
## FreeBSD
|
||||
#LUA_INCLUDE_DIR = $(PREFIX)/include/lua51
|
||||
|
||||
## MacOSX (Macports)
|
||||
#PREFIX = /opt/local
|
||||
#CJSON_LDFLAGS = -bundle -undefined dynamic_lookup
|
||||
|
||||
## Solaris
|
||||
#CC = gcc
|
||||
#CJSON_CFLAGS = -fpic -DUSE_INTERNAL_ISINF
|
||||
|
||||
## Windows (MinGW)
|
||||
#TARGET = cjson.dll
|
||||
#PREFIX = /home/user/opt
|
||||
#CJSON_CFLAGS = -DDISABLE_INVALID_NUMBERS
|
||||
#CJSON_LDFLAGS = -shared -L$(PREFIX)/lib -llua51
|
||||
#LUA_BIN_SUFFIX = .lua
|
||||
|
||||
##### Number conversion configuration #####
|
||||
|
||||
## Use Libc support for number conversion (default)
|
||||
FPCONV_OBJS = fpconv.o
|
||||
|
||||
## Use built in number conversion
|
||||
#FPCONV_OBJS = g_fmt.o dtoa.o
|
||||
#CJSON_CFLAGS += -DUSE_INTERNAL_FPCONV
|
||||
|
||||
## Compile built in number conversion for big endian architectures
|
||||
#CJSON_CFLAGS += -DIEEE_BIG_ENDIAN
|
||||
|
||||
## Compile built in number conversion to support multi-threaded
|
||||
## applications (recommended)
|
||||
#CJSON_CFLAGS += -pthread -DMULTIPLE_THREADS
|
||||
#CJSON_LDFLAGS += -pthread
|
||||
|
||||
##### End customisable sections #####
|
||||
|
||||
TEST_FILES = README bench.lua genutf8.pl test.lua octets-escaped.dat \
|
||||
example1.json example2.json example3.json example4.json \
|
||||
example5.json numbers.json rfc-example1.json \
|
||||
rfc-example2.json types.json
|
||||
DATAPERM = 644
|
||||
EXECPERM = 755
|
||||
|
||||
ASCIIDOC = asciidoc
|
||||
|
||||
BUILD_CFLAGS = -I$(LUA_INCLUDE_DIR) $(CJSON_CFLAGS)
|
||||
OBJS = lua_cjson.o strbuf.o $(FPCONV_OBJS)
|
||||
|
||||
.PHONY: all clean install install-extra doc
|
||||
|
||||
.SUFFIXES: .html .txt
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $(CPPFLAGS) $(BUILD_CFLAGS) -o $@ $<
|
||||
|
||||
.txt.html:
|
||||
$(ASCIIDOC) -n -a toc $<
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
doc: manual.html performance.html
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
$(CC) $(LDFLAGS) $(CJSON_LDFLAGS) -o $@ $(OBJS)
|
||||
|
||||
install: $(TARGET)
|
||||
mkdir -p $(DESTDIR)/$(LUA_CMODULE_DIR)
|
||||
cp $(TARGET) $(DESTDIR)/$(LUA_CMODULE_DIR)
|
||||
chmod $(EXECPERM) $(DESTDIR)/$(LUA_CMODULE_DIR)/$(TARGET)
|
||||
|
||||
install-extra:
|
||||
mkdir -p $(DESTDIR)/$(LUA_MODULE_DIR)/cjson/tests \
|
||||
$(DESTDIR)/$(LUA_BIN_DIR)
|
||||
cp lua/cjson/util.lua $(DESTDIR)/$(LUA_MODULE_DIR)/cjson
|
||||
chmod $(DATAPERM) $(DESTDIR)/$(LUA_MODULE_DIR)/cjson/util.lua
|
||||
cp lua/lua2json.lua $(DESTDIR)/$(LUA_BIN_DIR)/lua2json$(LUA_BIN_SUFFIX)
|
||||
chmod $(EXECPERM) $(DESTDIR)/$(LUA_BIN_DIR)/lua2json$(LUA_BIN_SUFFIX)
|
||||
cp lua/json2lua.lua $(DESTDIR)/$(LUA_BIN_DIR)/json2lua$(LUA_BIN_SUFFIX)
|
||||
chmod $(EXECPERM) $(DESTDIR)/$(LUA_BIN_DIR)/json2lua$(LUA_BIN_SUFFIX)
|
||||
cd tests; cp $(TEST_FILES) $(DESTDIR)/$(LUA_MODULE_DIR)/cjson/tests
|
||||
cd tests; chmod $(DATAPERM) $(TEST_FILES); chmod $(EXECPERM) *.lua *.pl
|
||||
|
||||
clean:
|
||||
rm -f *.o $(TARGET)
|
||||
@@ -1,44 +0,0 @@
|
||||
Version 2.1.0 (Mar 1 2012)
|
||||
* Added cjson.safe module interface which returns nil after an error
|
||||
* Improved Makefile compatibility with Solaris make
|
||||
|
||||
Version 2.0.0 (Jan 22 2012)
|
||||
* Improved platform compatibility for strtod/sprintf locale workaround
|
||||
* Added option to build with David Gay's dtoa.c for improved performance
|
||||
* Added support for Lua 5.2
|
||||
* Added option to encode infinity/NaN as JSON null
|
||||
* Fixed encode bug with a raised default limit and deeply nested tables
|
||||
* Updated Makefile for compatibility with non-GNU make implementations
|
||||
* Added CMake build support
|
||||
* Added HTML manual
|
||||
* Increased default nesting limit to 1000
|
||||
* Added support for re-entrant use of encode and decode
|
||||
* Added support for installing lua2json and json2lua utilities
|
||||
* Added encode_invalid_numbers() and decode_invalid_numbers()
|
||||
* Added decode_max_depth()
|
||||
* Removed registration of global cjson module table
|
||||
* Removed refuse_invalid_numbers()
|
||||
|
||||
Version 1.0.4 (Nov 30 2011)
|
||||
* Fixed numeric conversion under locales with a comma decimal separator
|
||||
|
||||
Version 1.0.3 (Sep 15 2011)
|
||||
* Fixed detection of objects with numeric string keys
|
||||
* Provided work around for missing isinf() on Solaris
|
||||
|
||||
Version 1.0.2 (May 30 2011)
|
||||
* Portability improvements for Windows
|
||||
- No longer links with -lm
|
||||
- Use "socket" instead of "posix" for sub-second timing
|
||||
* Removed UTF-8 test dependency on Perl Text::Iconv
|
||||
* Added simple CLI commands for testing Lua <-> JSON conversions
|
||||
* Added cjson.encode_number_precision()
|
||||
|
||||
Version 1.0.1 (May 10 2011)
|
||||
* Added build support for OSX
|
||||
* Removed unnecessary whitespace from JSON output
|
||||
* Added cjson.encode_keep_buffer()
|
||||
* Fixed memory leak on Lua stack overflow exception
|
||||
|
||||
Version 1.0 (May 9 2011)
|
||||
* Initial release
|
||||
@@ -1,9 +0,0 @@
|
||||
The following people have helped with bug reports, testing and/or
|
||||
suggestions:
|
||||
|
||||
- Louis-Philippe Perron (@loopole)
|
||||
- Ondřej Jirman
|
||||
- Steve Donovan <steve.j.donovan@gmail.com>
|
||||
- Zhang "agentzh" Yichun <agentzh@gmail.com>
|
||||
|
||||
Thanks!
|
||||
4358
3rd/lua-cjson/dtoa.c
4358
3rd/lua-cjson/dtoa.c
File diff suppressed because it is too large
Load Diff
@@ -1,74 +0,0 @@
|
||||
#ifndef _DTOA_CONFIG_H
|
||||
#define _DTOA_CONFIG_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Ensure dtoa.c does not USE_LOCALE. Lua CJSON must not use locale
|
||||
* aware conversion routines. */
|
||||
#undef USE_LOCALE
|
||||
|
||||
/* dtoa.c should not touch errno, Lua CJSON does not use it, and it
|
||||
* may not be threadsafe */
|
||||
#define NO_ERRNO
|
||||
|
||||
#define Long int32_t
|
||||
#define ULong uint32_t
|
||||
#define Llong int64_t
|
||||
#define ULLong uint64_t
|
||||
|
||||
#ifdef IEEE_BIG_ENDIAN
|
||||
#define IEEE_MC68k
|
||||
#else
|
||||
#define IEEE_8087
|
||||
#endif
|
||||
|
||||
#define MALLOC(n) xmalloc(n)
|
||||
|
||||
static void *xmalloc(size_t size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p = malloc(size);
|
||||
if (!p) {
|
||||
fprintf(stderr, "Out of memory");
|
||||
abort();
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
#ifdef MULTIPLE_THREADS
|
||||
|
||||
/* Enable locking to support multi-threaded applications */
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static pthread_mutex_t private_dtoa_lock[2] = {
|
||||
PTHREAD_MUTEX_INITIALIZER,
|
||||
PTHREAD_MUTEX_INITIALIZER
|
||||
};
|
||||
|
||||
#define ACQUIRE_DTOA_LOCK(n) do { \
|
||||
int r = pthread_mutex_lock(&private_dtoa_lock[n]); \
|
||||
if (r) { \
|
||||
fprintf(stderr, "pthread_mutex_lock failed with %d\n", r); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FREE_DTOA_LOCK(n) do { \
|
||||
int r = pthread_mutex_unlock(&private_dtoa_lock[n]); \
|
||||
if (r) { \
|
||||
fprintf(stderr, "pthread_mutex_unlock failed with %d\n", r);\
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif /* MULTIPLE_THREADS */
|
||||
|
||||
#endif /* _DTOA_CONFIG_H */
|
||||
|
||||
/* vi:ai et sw=4 ts=4:
|
||||
*/
|
||||
@@ -1,205 +0,0 @@
|
||||
/* fpconv - Floating point conversion routines
|
||||
*
|
||||
* Copyright (c) 2011-2012 Mark Pulford <mark@kyne.com.au>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* JSON uses a '.' decimal separator. strtod() / sprintf() under C libraries
|
||||
* with locale support will break when the decimal separator is a comma.
|
||||
*
|
||||
* fpconv_* will around these issues with a translation buffer if required.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fpconv.h"
|
||||
|
||||
/* Lua CJSON assumes the locale is the same for all threads within a
|
||||
* process and doesn't change after initialisation.
|
||||
*
|
||||
* This avoids the need for per thread storage or expensive checks
|
||||
* for call. */
|
||||
static char locale_decimal_point = '.';
|
||||
|
||||
/* In theory multibyte decimal_points are possible, but
|
||||
* Lua CJSON only supports UTF-8 and known locales only have
|
||||
* single byte decimal points ([.,]).
|
||||
*
|
||||
* localconv() may not be thread safe (=>crash), and nl_langinfo() is
|
||||
* not supported on some platforms. Use sprintf() instead - if the
|
||||
* locale does change, at least Lua CJSON won't crash. */
|
||||
static void fpconv_update_locale()
|
||||
{
|
||||
char buf[8];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%g", 0.5);
|
||||
|
||||
/* Failing this test might imply the platform has a buggy dtoa
|
||||
* implementation or wide characters */
|
||||
if (buf[0] != '0' || buf[2] != '5' || buf[3] != 0) {
|
||||
fprintf(stderr, "Error: wide characters found or printf() bug.");
|
||||
abort();
|
||||
}
|
||||
|
||||
locale_decimal_point = buf[1];
|
||||
}
|
||||
|
||||
/* Check for a valid number character: [-+0-9a-yA-Y.]
|
||||
* Eg: -0.6e+5, infinity, 0xF0.F0pF0
|
||||
*
|
||||
* Used to find the probable end of a number. It doesn't matter if
|
||||
* invalid characters are counted - strtod() will find the valid
|
||||
* number if it exists. The risk is that slightly more memory might
|
||||
* be allocated before a parse error occurs. */
|
||||
static inline int valid_number_character(char ch)
|
||||
{
|
||||
char lower_ch;
|
||||
|
||||
if ('0' <= ch && ch <= '9')
|
||||
return 1;
|
||||
if (ch == '-' || ch == '+' || ch == '.')
|
||||
return 1;
|
||||
|
||||
/* Hex digits, exponent (e), base (p), "infinity",.. */
|
||||
lower_ch = ch | 0x20;
|
||||
if ('a' <= lower_ch && lower_ch <= 'y')
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate the size of the buffer required for a strtod locale
|
||||
* conversion. */
|
||||
static int strtod_buffer_size(const char *s)
|
||||
{
|
||||
const char *p = s;
|
||||
|
||||
while (valid_number_character(*p))
|
||||
p++;
|
||||
|
||||
return p - s;
|
||||
}
|
||||
|
||||
/* Similar to strtod(), but must be passed the current locale's decimal point
|
||||
* character. Guaranteed to be called at the start of any valid number in a string */
|
||||
double fpconv_strtod(const char *nptr, char **endptr)
|
||||
{
|
||||
char localbuf[FPCONV_G_FMT_BUFSIZE];
|
||||
char *buf, *endbuf, *dp;
|
||||
int buflen;
|
||||
double value;
|
||||
|
||||
/* System strtod() is fine when decimal point is '.' */
|
||||
if (locale_decimal_point == '.')
|
||||
return strtod(nptr, endptr);
|
||||
|
||||
buflen = strtod_buffer_size(nptr);
|
||||
if (!buflen) {
|
||||
/* No valid characters found, standard strtod() return */
|
||||
*endptr = (char *)nptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Duplicate number into buffer */
|
||||
if (buflen >= FPCONV_G_FMT_BUFSIZE) {
|
||||
/* Handle unusually large numbers */
|
||||
buf = malloc(buflen + 1);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "Out of memory");
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
/* This is the common case.. */
|
||||
buf = localbuf;
|
||||
}
|
||||
memcpy(buf, nptr, buflen);
|
||||
buf[buflen] = 0;
|
||||
|
||||
/* Update decimal point character if found */
|
||||
dp = strchr(buf, '.');
|
||||
if (dp)
|
||||
*dp = locale_decimal_point;
|
||||
|
||||
value = strtod(buf, &endbuf);
|
||||
*endptr = (char *)&nptr[endbuf - buf];
|
||||
if (buflen >= FPCONV_G_FMT_BUFSIZE)
|
||||
free(buf);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* "fmt" must point to a buffer of at least 6 characters */
|
||||
static void set_number_format(char *fmt, int precision)
|
||||
{
|
||||
int d1, d2, i;
|
||||
|
||||
assert(1 <= precision && precision <= 14);
|
||||
|
||||
/* Create printf format (%.14g) from precision */
|
||||
d1 = precision / 10;
|
||||
d2 = precision % 10;
|
||||
fmt[0] = '%';
|
||||
fmt[1] = '.';
|
||||
i = 2;
|
||||
if (d1) {
|
||||
fmt[i++] = '0' + d1;
|
||||
}
|
||||
fmt[i++] = '0' + d2;
|
||||
fmt[i++] = 'g';
|
||||
fmt[i] = 0;
|
||||
}
|
||||
|
||||
/* Assumes there is always at least 32 characters available in the target buffer */
|
||||
int fpconv_g_fmt(char *str, double num, int precision)
|
||||
{
|
||||
char buf[FPCONV_G_FMT_BUFSIZE];
|
||||
char fmt[6];
|
||||
int len;
|
||||
char *b;
|
||||
|
||||
set_number_format(fmt, precision);
|
||||
|
||||
/* Pass through when decimal point character is dot. */
|
||||
if (locale_decimal_point == '.')
|
||||
return snprintf(str, FPCONV_G_FMT_BUFSIZE, fmt, num);
|
||||
|
||||
/* snprintf() to a buffer then translate for other decimal point characters */
|
||||
len = snprintf(buf, FPCONV_G_FMT_BUFSIZE, fmt, num);
|
||||
|
||||
/* Copy into target location. Translate decimal point if required */
|
||||
b = buf;
|
||||
do {
|
||||
*str++ = (*b == locale_decimal_point ? '.' : *b);
|
||||
} while(*b++);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void fpconv_init()
|
||||
{
|
||||
fpconv_update_locale();
|
||||
}
|
||||
|
||||
/* vi:ai et sw=4 ts=4:
|
||||
*/
|
||||
@@ -1,22 +0,0 @@
|
||||
/* Lua CJSON floating point conversion routines */
|
||||
|
||||
/* Buffer required to store the largest string representation of a double.
|
||||
*
|
||||
* Longest double printed with %.14g is 21 characters long:
|
||||
* -1.7976931348623e+308 */
|
||||
# define FPCONV_G_FMT_BUFSIZE 32
|
||||
|
||||
#ifdef USE_INTERNAL_FPCONV
|
||||
static inline void fpconv_init()
|
||||
{
|
||||
/* Do nothing - not required */
|
||||
}
|
||||
#else
|
||||
extern inline void fpconv_init();
|
||||
#endif
|
||||
|
||||
extern int fpconv_g_fmt(char*, double, int);
|
||||
extern double fpconv_strtod(const char*, char**);
|
||||
|
||||
/* vi:ai et sw=4 ts=4:
|
||||
*/
|
||||
@@ -1,111 +0,0 @@
|
||||
/****************************************************************
|
||||
*
|
||||
* The author of this software is David M. Gay.
|
||||
*
|
||||
* Copyright (c) 1991, 1996 by Lucent Technologies.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose without fee is hereby granted, provided that this entire notice
|
||||
* is included in all copies of any software which is or includes a copy
|
||||
* or modification of this software and in all copies of the supporting
|
||||
* documentation for such software.
|
||||
*
|
||||
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
|
||||
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
|
||||
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
/* g_fmt(buf,x) stores the closest decimal approximation to x in buf;
|
||||
* it suffices to declare buf
|
||||
* char buf[32];
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern char *dtoa(double, int, int, int *, int *, char **);
|
||||
extern int g_fmt(char *, double, int);
|
||||
extern void freedtoa(char*);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
fpconv_g_fmt(char *b, double x, int precision)
|
||||
{
|
||||
register int i, k;
|
||||
register char *s;
|
||||
int decpt, j, sign;
|
||||
char *b0, *s0, *se;
|
||||
|
||||
b0 = b;
|
||||
#ifdef IGNORE_ZERO_SIGN
|
||||
if (!x) {
|
||||
*b++ = '0';
|
||||
*b = 0;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
s = s0 = dtoa(x, 2, precision, &decpt, &sign, &se);
|
||||
if (sign)
|
||||
*b++ = '-';
|
||||
if (decpt == 9999) /* Infinity or Nan */ {
|
||||
while((*b++ = *s++));
|
||||
/* "b" is used to calculate the return length. Decrement to exclude the
|
||||
* Null terminator from the length */
|
||||
b--;
|
||||
goto done0;
|
||||
}
|
||||
if (decpt <= -4 || decpt > precision) {
|
||||
*b++ = *s++;
|
||||
if (*s) {
|
||||
*b++ = '.';
|
||||
while((*b = *s++))
|
||||
b++;
|
||||
}
|
||||
*b++ = 'e';
|
||||
/* sprintf(b, "%+.2d", decpt - 1); */
|
||||
if (--decpt < 0) {
|
||||
*b++ = '-';
|
||||
decpt = -decpt;
|
||||
}
|
||||
else
|
||||
*b++ = '+';
|
||||
for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10);
|
||||
for(;;) {
|
||||
i = decpt / k;
|
||||
*b++ = i + '0';
|
||||
if (--j <= 0)
|
||||
break;
|
||||
decpt -= i*k;
|
||||
decpt *= 10;
|
||||
}
|
||||
*b = 0;
|
||||
}
|
||||
else if (decpt <= 0) {
|
||||
*b++ = '0';
|
||||
*b++ = '.';
|
||||
for(; decpt < 0; decpt++)
|
||||
*b++ = '0';
|
||||
while((*b++ = *s++));
|
||||
b--;
|
||||
}
|
||||
else {
|
||||
while((*b = *s++)) {
|
||||
b++;
|
||||
if (--decpt == 0 && *s)
|
||||
*b++ = '.';
|
||||
}
|
||||
for(; decpt > 0; decpt--)
|
||||
*b++ = '0';
|
||||
*b = 0;
|
||||
}
|
||||
done0:
|
||||
freedtoa(s0);
|
||||
#ifdef IGNORE_ZERO_SIGN
|
||||
done:
|
||||
#endif
|
||||
return b - b0;
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package = "lua-cjson"
|
||||
version = "2.1.0-1"
|
||||
|
||||
source = {
|
||||
url = "http://www.kyne.com.au/~mark/software/download/lua-cjson-2.1.0.zip",
|
||||
}
|
||||
|
||||
description = {
|
||||
summary = "A fast JSON encoding/parsing module",
|
||||
detailed = [[
|
||||
The Lua CJSON module provides JSON support for Lua. It features:
|
||||
- Fast, standards compliant encoding/parsing routines
|
||||
- Full support for JSON with UTF-8, including decoding surrogate pairs
|
||||
- Optional run-time support for common exceptions to the JSON specification
|
||||
(infinity, NaN,..)
|
||||
- No dependencies on other libraries
|
||||
]],
|
||||
homepage = "http://www.kyne.com.au/~mark/software/lua-cjson.php",
|
||||
license = "MIT"
|
||||
}
|
||||
|
||||
dependencies = {
|
||||
"lua >= 5.1"
|
||||
}
|
||||
|
||||
build = {
|
||||
type = "builtin",
|
||||
modules = {
|
||||
cjson = {
|
||||
sources = { "lua_cjson.c", "strbuf.c", "fpconv.c" },
|
||||
defines = {
|
||||
-- LuaRocks does not support platform specific configuration for Solaris.
|
||||
-- Uncomment the line below on Solaris platforms if required.
|
||||
-- "USE_INTERNAL_ISINF"
|
||||
}
|
||||
}
|
||||
},
|
||||
install = {
|
||||
lua = {
|
||||
["cjson.util"] = "lua/cjson/util.lua"
|
||||
},
|
||||
bin = {
|
||||
json2lua = "lua/json2lua.lua",
|
||||
lua2json = "lua/lua2json.lua"
|
||||
}
|
||||
},
|
||||
-- Override default build options (per platform)
|
||||
platforms = {
|
||||
win32 = { modules = { cjson = { defines = {
|
||||
"DISABLE_INVALID_NUMBERS"
|
||||
} } } }
|
||||
},
|
||||
copy_directories = { "tests" }
|
||||
}
|
||||
|
||||
-- vi:ai et sw=4 ts=4:
|
||||
@@ -1,80 +0,0 @@
|
||||
%define luaver 5.1
|
||||
%define lualibdir %{_libdir}/lua/%{luaver}
|
||||
%define luadatadir %{_datadir}/lua/%{luaver}
|
||||
|
||||
Name: lua-cjson
|
||||
Version: 2.1.0
|
||||
Release: 1%{?dist}
|
||||
Summary: A fast JSON encoding/parsing module for Lua
|
||||
|
||||
Group: Development/Libraries
|
||||
License: MIT
|
||||
URL: http://www.kyne.com.au/~mark/software/lua-cjson/
|
||||
Source0: http://www.kyne.com.au/~mark/software/lua-cjson/download/lua-cjson-%{version}.tar.gz
|
||||
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
|
||||
|
||||
BuildRequires: lua >= %{luaver}, lua-devel >= %{luaver}
|
||||
Requires: lua >= %{luaver}
|
||||
|
||||
%description
|
||||
The Lua CJSON module provides JSON support for Lua. It features:
|
||||
- Fast, standards compliant encoding/parsing routines
|
||||
- Full support for JSON with UTF-8, including decoding surrogate pairs
|
||||
- Optional run-time support for common exceptions to the JSON specification
|
||||
(infinity, NaN,..)
|
||||
- No dependencies on other libraries
|
||||
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
|
||||
%build
|
||||
make %{?_smp_mflags} CFLAGS="%{optflags}" LUA_INCLUDE_DIR="%{_includedir}"
|
||||
|
||||
|
||||
%install
|
||||
rm -rf "$RPM_BUILD_ROOT"
|
||||
make install DESTDIR="$RPM_BUILD_ROOT" LUA_CMODULE_DIR="%{lualibdir}"
|
||||
make install-extra DESTDIR="$RPM_BUILD_ROOT" LUA_MODULE_DIR="%{luadatadir}" \
|
||||
LUA_BIN_DIR="%{_bindir}"
|
||||
|
||||
|
||||
%clean
|
||||
rm -rf "$RPM_BUILD_ROOT"
|
||||
|
||||
|
||||
%preun
|
||||
/bin/rm -f "%{luadatadir}/cjson/tests/utf8.dat"
|
||||
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%doc LICENSE NEWS performance.html performance.txt manual.html manual.txt rfc4627.txt THANKS
|
||||
%{lualibdir}/*
|
||||
%{luadatadir}/*
|
||||
%{_bindir}/*
|
||||
|
||||
|
||||
%changelog
|
||||
* Thu Mar 1 2012 Mark Pulford <mark@kyne.com.au> - 2.1.0-1
|
||||
- Update for 2.1.0
|
||||
|
||||
* Sun Jan 22 2012 Mark Pulford <mark@kyne.com.au> - 2.0.0-1
|
||||
- Update for 2.0.0
|
||||
- Install lua2json / json2lua utilities
|
||||
|
||||
* Wed Nov 27 2011 Mark Pulford <mark@kyne.com.au> - 1.0.4-1
|
||||
- Update for 1.0.4
|
||||
|
||||
* Wed Sep 15 2011 Mark Pulford <mark@kyne.com.au> - 1.0.3-1
|
||||
- Update for 1.0.3
|
||||
|
||||
* Sun May 29 2011 Mark Pulford <mark@kyne.com.au> - 1.0.2-1
|
||||
- Update for 1.0.2
|
||||
|
||||
* Sun May 10 2011 Mark Pulford <mark@kyne.com.au> - 1.0.1-1
|
||||
- Update for 1.0.1
|
||||
|
||||
* Sun May 1 2011 Mark Pulford <mark@kyne.com.au> - 1.0-1
|
||||
- Initial package
|
||||
@@ -1,271 +0,0 @@
|
||||
local json = require "cjson"
|
||||
|
||||
-- Various common routines used by the Lua CJSON package
|
||||
--
|
||||
-- Mark Pulford <mark@kyne.com.au>
|
||||
|
||||
-- Determine with a Lua table can be treated as an array.
|
||||
-- Explicitly returns "not an array" for very sparse arrays.
|
||||
-- Returns:
|
||||
-- -1 Not an array
|
||||
-- 0 Empty table
|
||||
-- >0 Highest index in the array
|
||||
local function is_array(table)
|
||||
local max = 0
|
||||
local count = 0
|
||||
for k, v in pairs(table) do
|
||||
if type(k) == "number" then
|
||||
if k > max then max = k end
|
||||
count = count + 1
|
||||
else
|
||||
return -1
|
||||
end
|
||||
end
|
||||
if max > count * 2 then
|
||||
return -1
|
||||
end
|
||||
|
||||
return max
|
||||
end
|
||||
|
||||
local serialise_value
|
||||
|
||||
local function serialise_table(value, indent, depth)
|
||||
local spacing, spacing2, indent2
|
||||
if indent then
|
||||
spacing = "\n" .. indent
|
||||
spacing2 = spacing .. " "
|
||||
indent2 = indent .. " "
|
||||
else
|
||||
spacing, spacing2, indent2 = " ", " ", false
|
||||
end
|
||||
depth = depth + 1
|
||||
if depth > 50 then
|
||||
return "Cannot serialise any further: too many nested tables"
|
||||
end
|
||||
|
||||
local max = is_array(value)
|
||||
|
||||
local comma = false
|
||||
local fragment = { "{" .. spacing2 }
|
||||
if max > 0 then
|
||||
-- Serialise array
|
||||
for i = 1, max do
|
||||
if comma then
|
||||
table.insert(fragment, "," .. spacing2)
|
||||
end
|
||||
table.insert(fragment, serialise_value(value[i], indent2, depth))
|
||||
comma = true
|
||||
end
|
||||
elseif max < 0 then
|
||||
-- Serialise table
|
||||
for k, v in pairs(value) do
|
||||
if comma then
|
||||
table.insert(fragment, "," .. spacing2)
|
||||
end
|
||||
table.insert(fragment,
|
||||
("[%s] = %s"):format(serialise_value(k, indent2, depth),
|
||||
serialise_value(v, indent2, depth)))
|
||||
comma = true
|
||||
end
|
||||
end
|
||||
table.insert(fragment, spacing .. "}")
|
||||
|
||||
return table.concat(fragment)
|
||||
end
|
||||
|
||||
function serialise_value(value, indent, depth)
|
||||
if indent == nil then indent = "" end
|
||||
if depth == nil then depth = 0 end
|
||||
|
||||
if value == json.null then
|
||||
return "json.null"
|
||||
elseif type(value) == "string" then
|
||||
return ("%q"):format(value)
|
||||
elseif type(value) == "nil" or type(value) == "number" or
|
||||
type(value) == "boolean" then
|
||||
return tostring(value)
|
||||
elseif type(value) == "table" then
|
||||
return serialise_table(value, indent, depth)
|
||||
else
|
||||
return "\"<" .. type(value) .. ">\""
|
||||
end
|
||||
end
|
||||
|
||||
local function file_load(filename)
|
||||
local file
|
||||
if filename == nil then
|
||||
file = io.stdin
|
||||
else
|
||||
local err
|
||||
file, err = io.open(filename, "rb")
|
||||
if file == nil then
|
||||
error(("Unable to read '%s': %s"):format(filename, err))
|
||||
end
|
||||
end
|
||||
local data = file:read("*a")
|
||||
|
||||
if filename ~= nil then
|
||||
file:close()
|
||||
end
|
||||
|
||||
if data == nil then
|
||||
error("Failed to read " .. filename)
|
||||
end
|
||||
|
||||
return data
|
||||
end
|
||||
|
||||
local function file_save(filename, data)
|
||||
local file
|
||||
if filename == nil then
|
||||
file = io.stdout
|
||||
else
|
||||
local err
|
||||
file, err = io.open(filename, "wb")
|
||||
if file == nil then
|
||||
error(("Unable to write '%s': %s"):format(filename, err))
|
||||
end
|
||||
end
|
||||
file:write(data)
|
||||
if filename ~= nil then
|
||||
file:close()
|
||||
end
|
||||
end
|
||||
|
||||
local function compare_values(val1, val2)
|
||||
local type1 = type(val1)
|
||||
local type2 = type(val2)
|
||||
if type1 ~= type2 then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Check for NaN
|
||||
if type1 == "number" and val1 ~= val1 and val2 ~= val2 then
|
||||
return true
|
||||
end
|
||||
|
||||
if type1 ~= "table" then
|
||||
return val1 == val2
|
||||
end
|
||||
|
||||
-- check_keys stores all the keys that must be checked in val2
|
||||
local check_keys = {}
|
||||
for k, _ in pairs(val1) do
|
||||
check_keys[k] = true
|
||||
end
|
||||
|
||||
for k, v in pairs(val2) do
|
||||
if not check_keys[k] then
|
||||
return false
|
||||
end
|
||||
|
||||
if not compare_values(val1[k], val2[k]) then
|
||||
return false
|
||||
end
|
||||
|
||||
check_keys[k] = nil
|
||||
end
|
||||
for k, _ in pairs(check_keys) do
|
||||
-- Not the same if any keys from val1 were not found in val2
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local test_count_pass = 0
|
||||
local test_count_total = 0
|
||||
|
||||
local function run_test_summary()
|
||||
return test_count_pass, test_count_total
|
||||
end
|
||||
|
||||
local function run_test(testname, func, input, should_work, output)
|
||||
local function status_line(name, status, value)
|
||||
local statusmap = { [true] = ":success", [false] = ":error" }
|
||||
if status ~= nil then
|
||||
name = name .. statusmap[status]
|
||||
end
|
||||
print(("[%s] %s"):format(name, serialise_value(value, false)))
|
||||
end
|
||||
|
||||
local result = { pcall(func, unpack(input)) }
|
||||
local success = table.remove(result, 1)
|
||||
|
||||
local correct = false
|
||||
if success == should_work and compare_values(result, output) then
|
||||
correct = true
|
||||
test_count_pass = test_count_pass + 1
|
||||
end
|
||||
test_count_total = test_count_total + 1
|
||||
|
||||
local teststatus = { [true] = "PASS", [false] = "FAIL" }
|
||||
print(("==> Test [%d] %s: %s"):format(test_count_total, testname,
|
||||
teststatus[correct]))
|
||||
|
||||
status_line("Input", nil, input)
|
||||
if not correct then
|
||||
status_line("Expected", should_work, output)
|
||||
end
|
||||
status_line("Received", success, result)
|
||||
print()
|
||||
|
||||
return correct, result
|
||||
end
|
||||
|
||||
local function run_test_group(tests)
|
||||
local function run_helper(name, func, input)
|
||||
if type(name) == "string" and #name > 0 then
|
||||
print("==> " .. name)
|
||||
end
|
||||
-- Not a protected call, these functions should never generate errors.
|
||||
func(unpack(input or {}))
|
||||
print()
|
||||
end
|
||||
|
||||
for _, v in ipairs(tests) do
|
||||
-- Run the helper if "should_work" is missing
|
||||
if v[4] == nil then
|
||||
run_helper(unpack(v))
|
||||
else
|
||||
run_test(unpack(v))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Run a Lua script in a separate environment
|
||||
local function run_script(script, env)
|
||||
local env = env or {}
|
||||
local func
|
||||
|
||||
-- Use setfenv() if it exists, otherwise assume Lua 5.2 load() exists
|
||||
if _G.setfenv then
|
||||
func = loadstring(script)
|
||||
if func then
|
||||
setfenv(func, env)
|
||||
end
|
||||
else
|
||||
func = load(script, nil, nil, env)
|
||||
end
|
||||
|
||||
if func == nil then
|
||||
error("Invalid syntax.")
|
||||
end
|
||||
func()
|
||||
|
||||
return env
|
||||
end
|
||||
|
||||
-- Export functions
|
||||
return {
|
||||
serialise_value = serialise_value,
|
||||
file_load = file_load,
|
||||
file_save = file_save,
|
||||
compare_values = compare_values,
|
||||
run_test_summary = run_test_summary,
|
||||
run_test = run_test,
|
||||
run_test_group = run_test_group,
|
||||
run_script = run_script
|
||||
}
|
||||
|
||||
-- vi:ai et sw=4 ts=4:
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
-- usage: json2lua.lua [json_file]
|
||||
--
|
||||
-- Eg:
|
||||
-- echo '[ "testing" ]' | ./json2lua.lua
|
||||
-- ./json2lua.lua test.json
|
||||
|
||||
local json = require "cjson"
|
||||
local util = require "cjson.util"
|
||||
|
||||
local json_text = util.file_load(arg[1])
|
||||
local t = json.decode(json_text)
|
||||
print(util.serialise_value(t))
|
||||
@@ -1,20 +0,0 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
-- usage: lua2json.lua [lua_file]
|
||||
--
|
||||
-- Eg:
|
||||
-- echo '{ "testing" }' | ./lua2json.lua
|
||||
-- ./lua2json.lua test.lua
|
||||
|
||||
local json = require "cjson"
|
||||
local util = require "cjson.util"
|
||||
|
||||
local env = {
|
||||
json = { null = json.null },
|
||||
null = json.null
|
||||
}
|
||||
|
||||
local t = util.run_script("data = " .. util.file_load(arg[1]), env)
|
||||
print(json.encode(t.data))
|
||||
|
||||
-- vi:ai et sw=4 ts=4:
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,611 +0,0 @@
|
||||
= Lua CJSON 2.1.0 Manual =
|
||||
Mark Pulford <mark@kyne.com.au>
|
||||
:revdate: 1st March 2012
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
The Lua CJSON module provides JSON support for Lua.
|
||||
|
||||
*Features*::
|
||||
- Fast, standards compliant encoding/parsing routines
|
||||
- Full support for JSON with UTF-8, including decoding surrogate pairs
|
||||
- Optional run-time support for common exceptions to the JSON
|
||||
specification (infinity, NaN,..)
|
||||
- No dependencies on other libraries
|
||||
|
||||
*Caveats*::
|
||||
- UTF-16 and UTF-32 are not supported
|
||||
|
||||
Lua CJSON is covered by the MIT license. Review the file +LICENSE+ for
|
||||
details.
|
||||
|
||||
The latest version of this software is available from the
|
||||
http://www.kyne.com.au/%7Emark/software/lua-cjson.php[Lua CJSON website].
|
||||
|
||||
Feel free to email me if you have any patches, suggestions, or comments.
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Lua CJSON requires either http://www.lua.org[Lua] 5.1, Lua 5.2, or
|
||||
http://www.luajit.org[LuaJIT] to build.
|
||||
|
||||
The build method can be selected from 4 options:
|
||||
|
||||
Make:: Unix (including Linux, BSD, Mac OSX & Solaris), Windows
|
||||
CMake:: Unix, Windows
|
||||
RPM:: Linux
|
||||
LuaRocks:: Unix, Windows
|
||||
|
||||
|
||||
Make
|
||||
~~~~
|
||||
|
||||
The included +Makefile+ has generic settings.
|
||||
|
||||
First, review and update the included makefile to suit your platform (if
|
||||
required).
|
||||
|
||||
Next, build and install the module:
|
||||
|
||||
[source,sh]
|
||||
make install
|
||||
|
||||
Or install manually into your Lua module directory:
|
||||
|
||||
[source,sh]
|
||||
make
|
||||
cp cjson.so $LUA_MODULE_DIRECTORY
|
||||
|
||||
|
||||
CMake
|
||||
~~~~~
|
||||
|
||||
http://www.cmake.org[CMake] can generate build configuration for many
|
||||
different platforms (including Unix and Windows).
|
||||
|
||||
First, generate the makefile for your platform using CMake. If CMake is
|
||||
unable to find Lua, manually set the +LUA_DIR+ environment variable to
|
||||
the base prefix of your Lua 5.1 installation.
|
||||
|
||||
While +cmake+ is used in the example below, +ccmake+ or +cmake-gui+ may
|
||||
be used to present an interface for changing the default build options.
|
||||
|
||||
[source,sh]
|
||||
mkdir build
|
||||
cd build
|
||||
# Optional: export LUA_DIR=$LUA51_PREFIX
|
||||
cmake ..
|
||||
|
||||
Next, build and install the module:
|
||||
|
||||
[source,sh]
|
||||
make install
|
||||
# Or:
|
||||
make
|
||||
cp cjson.so $LUA_MODULE_DIRECTORY
|
||||
|
||||
Review the
|
||||
http://www.cmake.org/cmake/help/documentation.html[CMake documentation]
|
||||
for further details.
|
||||
|
||||
|
||||
RPM
|
||||
~~~
|
||||
|
||||
Linux distributions using http://rpm.org[RPM] can create a package via
|
||||
the included RPM spec file. Ensure the +rpm-build+ package (or similar)
|
||||
has been installed.
|
||||
|
||||
Build and install the module via RPM:
|
||||
|
||||
[source,sh]
|
||||
rpmbuild -tb lua-cjson-2.1.0.tar.gz
|
||||
rpm -Uvh $LUA_CJSON_RPM
|
||||
|
||||
|
||||
LuaRocks
|
||||
~~~~~~~~
|
||||
|
||||
http://luarocks.org[LuaRocks] can be used to install and manage Lua
|
||||
modules on a wide range of platforms (including Windows).
|
||||
|
||||
First, extract the Lua CJSON source package.
|
||||
|
||||
Next, install the module:
|
||||
|
||||
[source,sh]
|
||||
cd lua-cjson-2.1.0
|
||||
luarocks make
|
||||
|
||||
[NOTE]
|
||||
LuaRocks does not support platform specific configuration for Solaris.
|
||||
On Solaris, you may need to manually uncomment +USE_INTERNAL_ISINF+ in
|
||||
the rockspec before building this module.
|
||||
|
||||
Review the http://luarocks.org/en/Documentation[LuaRocks documentation]
|
||||
for further details.
|
||||
|
||||
|
||||
[[build_options]]
|
||||
Build Options (#define)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Lua CJSON offers several +#define+ build options to address portability
|
||||
issues, and enable non-default features. Some build methods may
|
||||
automatically set platform specific options if required. Other features
|
||||
should be enabled manually.
|
||||
|
||||
USE_INTERNAL_ISINF:: Workaround for Solaris platforms missing +isinf+.
|
||||
DISABLE_INVALID_NUMBERS:: Recommended on platforms where +strtod+ /
|
||||
+sprintf+ are not POSIX compliant (eg, Windows MinGW). Prevents
|
||||
+cjson.encode_invalid_numbers+ and +cjson.decode_invalid_numbers+ from
|
||||
being enabled. However, +cjson.encode_invalid_numbers+ may still be
|
||||
set to +"null"+. When using the Lua CJSON built-in floating point
|
||||
conversion this option is unnecessary and is ignored.
|
||||
|
||||
|
||||
Built-in floating point conversion
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Lua CJSON may be built with David Gay's
|
||||
http://www.netlib.org/fp/[floating point conversion routines]. This can
|
||||
increase overall performance by up to 50% on some platforms when
|
||||
converting a large amount of numeric data. However, this option reduces
|
||||
portability and is disabled by default.
|
||||
|
||||
USE_INTERNAL_FPCONV:: Enable internal number conversion routines.
|
||||
IEEE_BIG_ENDIAN:: Must be set on big endian architectures.
|
||||
MULTIPLE_THREADS:: Must be set if Lua CJSON may be used in a
|
||||
multi-threaded application. Requires the _pthreads_ library.
|
||||
|
||||
|
||||
API (Functions)
|
||||
---------------
|
||||
|
||||
Synopsis
|
||||
~~~~~~~~
|
||||
|
||||
[source,lua]
|
||||
------------
|
||||
-- Module instantiation
|
||||
local cjson = require "cjson"
|
||||
local cjson2 = cjson.new()
|
||||
local cjson_safe = require "cjson.safe"
|
||||
|
||||
-- Translate Lua value to/from JSON
|
||||
text = cjson.encode(value)
|
||||
value = cjson.decode(text)
|
||||
|
||||
-- Get and/or set Lua CJSON configuration
|
||||
setting = cjson.decode_invalid_numbers([setting])
|
||||
setting = cjson.encode_invalid_numbers([setting])
|
||||
keep = cjson.encode_keep_buffer([keep])
|
||||
depth = cjson.encode_max_depth([depth])
|
||||
depth = cjson.decode_max_depth([depth])
|
||||
convert, ratio, safe = cjson.encode_sparse_array([convert[, ratio[, safe]]])
|
||||
------------
|
||||
|
||||
|
||||
Module Instantiation
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[source,lua]
|
||||
------------
|
||||
local cjson = require "cjson"
|
||||
local cjson2 = cjson.new()
|
||||
local cjson_safe = require "cjson.safe"
|
||||
------------
|
||||
|
||||
Import Lua CJSON via the Lua +require+ function. Lua CJSON does not
|
||||
register a global module table.
|
||||
|
||||
The +cjson+ module will throw an error during JSON conversion if any
|
||||
invalid data is encountered. Refer to <<cjson_encode,+cjson.encode+>>
|
||||
and <<cjson_decode,+cjson.decode+>> for details.
|
||||
|
||||
The +cjson.safe+ module behaves identically to the +cjson+ module,
|
||||
except when errors are encountered during JSON conversion. On error, the
|
||||
+cjson_safe.encode+ and +cjson_safe.decode+ functions will return
|
||||
+nil+ followed by the error message.
|
||||
|
||||
+cjson.new+ can be used to instantiate an independent copy of the Lua
|
||||
CJSON module. The new module has a separate persistent encoding buffer,
|
||||
and default settings.
|
||||
|
||||
Lua CJSON can support Lua implementations using multiple preemptive
|
||||
threads within a single Lua state provided the persistent encoding
|
||||
buffer is not shared. This can be achieved by one of the following
|
||||
methods:
|
||||
|
||||
- Disabling the persistent encoding buffer with
|
||||
<<encode_keep_buffer,+cjson.encode_keep_buffer+>>
|
||||
- Ensuring each thread calls <<encode,+cjson.encode+>> separately (ie,
|
||||
treat +cjson.encode+ as non-reentrant).
|
||||
- Using a separate +cjson+ module table per preemptive thread
|
||||
(+cjson.new+)
|
||||
|
||||
[NOTE]
|
||||
Lua CJSON uses +strtod+ and +snprintf+ to perform numeric conversion as
|
||||
they are usually well supported, fast and bug free. However, these
|
||||
functions require a workaround for JSON encoding/parsing under locales
|
||||
using a comma decimal separator. Lua CJSON detects the current locale
|
||||
during instantiation to determine and automatically implement the
|
||||
workaround if required. Lua CJSON should be reinitialised via
|
||||
+cjson.new+ if the locale of the current process changes. Using a
|
||||
different locale per thread is not supported.
|
||||
|
||||
|
||||
decode
|
||||
~~~~~~
|
||||
|
||||
[source,lua]
|
||||
------------
|
||||
value = cjson.decode(json_text)
|
||||
------------
|
||||
|
||||
+cjson.decode+ will deserialise any UTF-8 JSON string into a Lua value
|
||||
or table.
|
||||
|
||||
UTF-16 and UTF-32 JSON strings are not supported.
|
||||
|
||||
+cjson.decode+ requires that any NULL (ASCII 0) and double quote (ASCII
|
||||
34) characters are escaped within strings. All escape codes will be
|
||||
decoded and other bytes will be passed transparently. UTF-8 characters
|
||||
are not validated during decoding and should be checked elsewhere if
|
||||
required.
|
||||
|
||||
JSON +null+ will be converted to a NULL +lightuserdata+ value. This can
|
||||
be compared with +cjson.null+ for convenience.
|
||||
|
||||
By default, numbers incompatible with the JSON specification (infinity,
|
||||
NaN, hexadecimal) can be decoded. This default can be changed with
|
||||
<<decode_invalid_numbers,+cjson.decode_invalid_numbers+>>.
|
||||
|
||||
.Example: Decoding
|
||||
[source,lua]
|
||||
json_text = '[ true, { "foo": "bar" } ]'
|
||||
value = cjson.decode(json_text)
|
||||
-- Returns: { true, { foo = "bar" } }
|
||||
|
||||
[CAUTION]
|
||||
Care must be taken after decoding JSON objects with numeric keys. Each
|
||||
numeric key will be stored as a Lua +string+. Any subsequent code
|
||||
assuming type +number+ may break.
|
||||
|
||||
|
||||
[[decode_invalid_numbers]]
|
||||
decode_invalid_numbers
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[source,lua]
|
||||
------------
|
||||
setting = cjson.decode_invalid_numbers([setting])
|
||||
-- "setting" must be a boolean. Default: true.
|
||||
------------
|
||||
|
||||
Lua CJSON may generate an error when trying to decode numbers not
|
||||
supported by the JSON specification. _Invalid numbers_ are defined as:
|
||||
|
||||
- infinity
|
||||
- not-a-number (NaN)
|
||||
- hexadecimal
|
||||
|
||||
Available settings:
|
||||
|
||||
+true+:: Accept and decode _invalid numbers_. This is the default
|
||||
setting.
|
||||
+false+:: Throw an error when _invalid numbers_ are encountered.
|
||||
|
||||
The current setting is always returned, and is only updated when an
|
||||
argument is provided.
|
||||
|
||||
|
||||
[[decode_max_depth]]
|
||||
decode_max_depth
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
[source,lua]
|
||||
------------
|
||||
depth = cjson.decode_max_depth([depth])
|
||||
-- "depth" must be a positive integer. Default: 1000.
|
||||
------------
|
||||
|
||||
Lua CJSON will generate an error when parsing deeply nested JSON once
|
||||
the maximum array/object depth has been exceeded. This check prevents
|
||||
unnecessarily complicated JSON from slowing down the application, or
|
||||
crashing the application due to lack of process stack space.
|
||||
|
||||
An error may be generated before the depth limit is hit if Lua is unable
|
||||
to allocate more objects on the Lua stack.
|
||||
|
||||
By default, Lua CJSON will reject JSON with arrays and/or objects nested
|
||||
more than 1000 levels deep.
|
||||
|
||||
The current setting is always returned, and is only updated when an
|
||||
argument is provided.
|
||||
|
||||
|
||||
[[encode]]
|
||||
encode
|
||||
~~~~~~
|
||||
|
||||
[source,lua]
|
||||
------------
|
||||
json_text = cjson.encode(value)
|
||||
------------
|
||||
|
||||
+cjson.encode+ will serialise a Lua value into a string containing the
|
||||
JSON representation.
|
||||
|
||||
+cjson.encode+ supports the following types:
|
||||
|
||||
- +boolean+
|
||||
- +lightuserdata+ (NULL value only)
|
||||
- +nil+
|
||||
- +number+
|
||||
- +string+
|
||||
- +table+
|
||||
|
||||
The remaining Lua types will generate an error:
|
||||
|
||||
- +function+
|
||||
- +lightuserdata+ (non-NULL values)
|
||||
- +thread+
|
||||
- +userdata+
|
||||
|
||||
By default, numbers are encoded with 14 significant digits. Refer to
|
||||
<<encode_number_precision,+cjson.encode_number_precision+>> for details.
|
||||
|
||||
Lua CJSON will escape the following characters within each UTF-8 string:
|
||||
|
||||
- Control characters (ASCII 0 - 31)
|
||||
- Double quote (ASCII 34)
|
||||
- Forward slash (ASCII 47)
|
||||
- Blackslash (ASCII 92)
|
||||
- Delete (ASCII 127)
|
||||
|
||||
All other bytes are passed transparently.
|
||||
|
||||
[CAUTION]
|
||||
=========
|
||||
Lua CJSON will successfully encode/decode binary strings, but this is
|
||||
technically not supported by JSON and may not be compatible with other
|
||||
JSON libraries. To ensure the output is valid JSON, applications should
|
||||
ensure all Lua strings passed to +cjson.encode+ are UTF-8.
|
||||
|
||||
Base64 is commonly used to encode binary data as the most efficient
|
||||
encoding under UTF-8 can only reduce the encoded size by a further
|
||||
~8%. Lua Base64 routines can be found in the
|
||||
http://w3.impa.br/%7Ediego/software/luasocket/[LuaSocket] and
|
||||
http://www.tecgraf.puc-rio.br/%7Elhf/ftp/lua/#lbase64[lbase64] packages.
|
||||
=========
|
||||
|
||||
Lua CJSON uses a heuristic to determine whether to encode a Lua table as
|
||||
a JSON array or an object. A Lua table with only positive integer keys
|
||||
of type +number+ will be encoded as a JSON array. All other tables will
|
||||
be encoded as a JSON object.
|
||||
|
||||
Lua CJSON does not use metamethods when serialising tables.
|
||||
|
||||
- +rawget+ is used to iterate over Lua arrays
|
||||
- +next+ is used to iterate over Lua objects
|
||||
|
||||
Lua arrays with missing entries (_sparse arrays_) may optionally be
|
||||
encoded in several different ways. Refer to
|
||||
<<encode_sparse_array,+cjson.encode_sparse_array+>> for details.
|
||||
|
||||
JSON object keys are always strings. Hence +cjson.encode+ only supports
|
||||
table keys which are type +number+ or +string+. All other types will
|
||||
generate an error.
|
||||
|
||||
[NOTE]
|
||||
Standards compliant JSON must be encapsulated in either an object (+{}+)
|
||||
or an array (+[]+). If strictly standards compliant JSON is desired, a
|
||||
table must be passed to +cjson.encode+.
|
||||
|
||||
By default, encoding the following Lua values will generate errors:
|
||||
|
||||
- Numbers incompatible with the JSON specification (infinity, NaN)
|
||||
- Tables nested more than 1000 levels deep
|
||||
- Excessively sparse Lua arrays
|
||||
|
||||
These defaults can be changed with:
|
||||
|
||||
- <<encode_invalid_numbers,+cjson.encode_invalid_numbers+>>
|
||||
- <<encode_max_depth,+cjson.encode_max_depth+>>
|
||||
- <<encode_sparse_array,+cjson.encode_sparse_array+>>
|
||||
|
||||
.Example: Encoding
|
||||
[source,lua]
|
||||
value = { true, { foo = "bar" } }
|
||||
json_text = cjson.encode(value)
|
||||
-- Returns: '[true,{"foo":"bar"}]'
|
||||
|
||||
|
||||
[[encode_invalid_numbers]]
|
||||
encode_invalid_numbers
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
[source,lua]
|
||||
------------
|
||||
setting = cjson.encode_invalid_numbers([setting])
|
||||
-- "setting" must a boolean or "null". Default: false.
|
||||
------------
|
||||
|
||||
Lua CJSON may generate an error when encoding floating point numbers not
|
||||
supported by the JSON specification (_invalid numbers_):
|
||||
|
||||
- infinity
|
||||
- not-a-number (NaN)
|
||||
|
||||
Available settings:
|
||||
|
||||
+true+:: Allow _invalid numbers_ to be encoded. This will generate
|
||||
non-standard JSON, but this output is supported by some libraries.
|
||||
+"null"+:: Encode _invalid numbers_ as a JSON +null+ value. This allows
|
||||
infinity and NaN to be encoded into valid JSON.
|
||||
+false+:: Throw an error when attempting to encode _invalid numbers_.
|
||||
This is the default setting.
|
||||
|
||||
The current setting is always returned, and is only updated when an
|
||||
argument is provided.
|
||||
|
||||
|
||||
[[encode_keep_buffer]]
|
||||
encode_keep_buffer
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[source,lua]
|
||||
------------
|
||||
keep = cjson.encode_keep_buffer([keep])
|
||||
-- "keep" must be a boolean. Default: true.
|
||||
------------
|
||||
|
||||
Lua CJSON can reuse the JSON encoding buffer to improve performance.
|
||||
|
||||
Available settings:
|
||||
|
||||
+true+:: The buffer will grow to the largest size required and is not
|
||||
freed until the Lua CJSON module is garbage collected. This is the
|
||||
default setting.
|
||||
+false+:: Free the encode buffer after each call to +cjson.encode+.
|
||||
|
||||
The current setting is always returned, and is only updated when an
|
||||
argument is provided.
|
||||
|
||||
|
||||
[[encode_max_depth]]
|
||||
encode_max_depth
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
[source,lua]
|
||||
------------
|
||||
depth = cjson.encode_max_depth([depth])
|
||||
-- "depth" must be a positive integer. Default: 1000.
|
||||
------------
|
||||
|
||||
Once the maximum table depth has been exceeded Lua CJSON will generate
|
||||
an error. This prevents a deeply nested or recursive data structure from
|
||||
crashing the application.
|
||||
|
||||
By default, Lua CJSON will generate an error when trying to encode data
|
||||
structures with more than 1000 nested tables.
|
||||
|
||||
The current setting is always returned, and is only updated when an
|
||||
argument is provided.
|
||||
|
||||
.Example: Recursive Lua table
|
||||
[source,lua]
|
||||
a = {}; a[1] = a
|
||||
|
||||
|
||||
[[encode_number_precision]]
|
||||
encode_number_precision
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[source,lua]
|
||||
------------
|
||||
precision = cjson.encode_number_precision([precision])
|
||||
-- "precision" must be an integer between 1 and 14. Default: 14.
|
||||
------------
|
||||
|
||||
The amount of significant digits returned by Lua CJSON when encoding
|
||||
numbers can be changed to balance accuracy versus performance. For data
|
||||
structures containing many numbers, setting
|
||||
+cjson.encode_number_precision+ to a smaller integer, for example +3+,
|
||||
can improve encoding performance by up to 50%.
|
||||
|
||||
By default, Lua CJSON will output 14 significant digits when converting
|
||||
a number to text.
|
||||
|
||||
The current setting is always returned, and is only updated when an
|
||||
argument is provided.
|
||||
|
||||
|
||||
[[encode_sparse_array]]
|
||||
encode_sparse_array
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[source,lua]
|
||||
------------
|
||||
convert, ratio, safe = cjson.encode_sparse_array([convert[, ratio[, safe]]])
|
||||
-- "convert" must be a boolean. Default: false.
|
||||
-- "ratio" must be a positive integer. Default: 2.
|
||||
-- "safe" must be a positive integer. Default: 10.
|
||||
------------
|
||||
|
||||
Lua CJSON classifies a Lua table into one of three kinds when encoding a
|
||||
JSON array. This is determined by the number of values missing from the
|
||||
Lua array as follows:
|
||||
|
||||
Normal:: All values are available.
|
||||
Sparse:: At least 1 value is missing.
|
||||
Excessively sparse:: The number of values missing exceeds the configured
|
||||
ratio.
|
||||
|
||||
Lua CJSON encodes sparse Lua arrays as JSON arrays using JSON +null+ for
|
||||
the missing entries.
|
||||
|
||||
An array is excessively sparse when all the following conditions are
|
||||
met:
|
||||
|
||||
- +ratio+ > +0+
|
||||
- _maximum_index_ > +safe+
|
||||
- _maximum_index_ > _item_count_ * +ratio+
|
||||
|
||||
Lua CJSON will never consider an array to be _excessively sparse_ when
|
||||
+ratio+ = +0+. The +safe+ limit ensures that small Lua arrays are always
|
||||
encoded as sparse arrays.
|
||||
|
||||
By default, attempting to encode an _excessively sparse_ array will
|
||||
generate an error. If +convert+ is set to +true+, _excessively sparse_
|
||||
arrays will be converted to a JSON object.
|
||||
|
||||
The current settings are always returned. A particular setting is only
|
||||
changed when the argument is provided (non-++nil++).
|
||||
|
||||
.Example: Encoding a sparse array
|
||||
[source,lua]
|
||||
cjson.encode({ [3] = "data" })
|
||||
-- Returns: '[null,null,"data"]'
|
||||
|
||||
.Example: Enabling conversion to a JSON object
|
||||
[source,lua]
|
||||
cjson.encode_sparse_array(true)
|
||||
cjson.encode({ [1000] = "excessively sparse" })
|
||||
-- Returns: '{"1000":"excessively sparse"}'
|
||||
|
||||
|
||||
API (Variables)
|
||||
---------------
|
||||
|
||||
_NAME
|
||||
~~~~~
|
||||
|
||||
The name of the Lua CJSON module (+"cjson"+).
|
||||
|
||||
|
||||
_VERSION
|
||||
~~~~~~~~
|
||||
|
||||
The version number of the Lua CJSON module (+"2.1.0"+).
|
||||
|
||||
|
||||
null
|
||||
~~~~
|
||||
|
||||
Lua CJSON decodes JSON +null+ as a Lua +lightuserdata+ NULL pointer.
|
||||
+cjson.null+ is provided for comparison.
|
||||
|
||||
|
||||
[sect1]
|
||||
References
|
||||
----------
|
||||
|
||||
- http://tools.ietf.org/html/rfc4627[RFC 4627]
|
||||
- http://www.json.org/[JSON website]
|
||||
|
||||
|
||||
// vi:ft=asciidoc tw=72:
|
||||
@@ -1,617 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
|
||||
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta name="generator" content="AsciiDoc 8.4.5" />
|
||||
<title>JSON module performance comparison under Lua</title>
|
||||
<style type="text/css">
|
||||
/* Debug borders */
|
||||
p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 {
|
||||
/*
|
||||
border: 1px solid red;
|
||||
*/
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 1em 5% 1em 5%;
|
||||
}
|
||||
|
||||
a {
|
||||
color: blue;
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:visited {
|
||||
color: fuchsia;
|
||||
}
|
||||
|
||||
em {
|
||||
font-style: italic;
|
||||
color: navy;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: bold;
|
||||
color: #083194;
|
||||
}
|
||||
|
||||
tt {
|
||||
color: navy;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
color: #527bbd;
|
||||
font-family: sans-serif;
|
||||
margin-top: 1.2em;
|
||||
margin-bottom: 0.5em;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
border-bottom: 2px solid silver;
|
||||
}
|
||||
h2 {
|
||||
padding-top: 0.5em;
|
||||
}
|
||||
h3 {
|
||||
float: left;
|
||||
}
|
||||
h3 + * {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
div.sectionbody {
|
||||
font-family: serif;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 1px solid silver;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
ul, ol, li > p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
span#author {
|
||||
color: #527bbd;
|
||||
font-family: sans-serif;
|
||||
font-weight: bold;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
span#email {
|
||||
}
|
||||
span#revnumber, span#revdate, span#revremark {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
div#footer {
|
||||
font-family: sans-serif;
|
||||
font-size: small;
|
||||
border-top: 2px solid silver;
|
||||
padding-top: 0.5em;
|
||||
margin-top: 4.0em;
|
||||
}
|
||||
div#footer-text {
|
||||
float: left;
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
div#footer-badges {
|
||||
float: right;
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
|
||||
div#preamble {
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
div.tableblock, div.imageblock, div.exampleblock, div.verseblock,
|
||||
div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
|
||||
div.admonitionblock {
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
div.admonitionblock {
|
||||
margin-top: 2.5em;
|
||||
margin-bottom: 2.5em;
|
||||
}
|
||||
|
||||
div.content { /* Block element content. */
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Block element titles. */
|
||||
div.title, caption.title {
|
||||
color: #527bbd;
|
||||
font-family: sans-serif;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
margin-top: 1.0em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
div.title + * {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
td div.title:first-child {
|
||||
margin-top: 0.0em;
|
||||
}
|
||||
div.content div.title:first-child {
|
||||
margin-top: 0.0em;
|
||||
}
|
||||
div.content + div.title {
|
||||
margin-top: 0.0em;
|
||||
}
|
||||
|
||||
div.sidebarblock > div.content {
|
||||
background: #ffffee;
|
||||
border: 1px solid silver;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
div.listingblock > div.content {
|
||||
border: 1px solid silver;
|
||||
background: #f4f4f4;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
div.quoteblock {
|
||||
padding-left: 2.0em;
|
||||
margin-right: 10%;
|
||||
}
|
||||
div.quoteblock > div.attribution {
|
||||
padding-top: 0.5em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
div.verseblock {
|
||||
padding-left: 2.0em;
|
||||
margin-right: 10%;
|
||||
}
|
||||
div.verseblock > div.content {
|
||||
white-space: pre;
|
||||
}
|
||||
div.verseblock > div.attribution {
|
||||
padding-top: 0.75em;
|
||||
text-align: left;
|
||||
}
|
||||
/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
|
||||
div.verseblock + div.attribution {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.admonitionblock .icon {
|
||||
vertical-align: top;
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
text-decoration: underline;
|
||||
color: #527bbd;
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
div.admonitionblock td.content {
|
||||
padding-left: 0.5em;
|
||||
border-left: 2px solid silver;
|
||||
}
|
||||
|
||||
div.exampleblock > div.content {
|
||||
border-left: 2px solid silver;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
div.imageblock div.content { padding-left: 0; }
|
||||
span.image img { border-style: none; }
|
||||
a.image:visited { color: white; }
|
||||
|
||||
dl {
|
||||
margin-top: 0.8em;
|
||||
margin-bottom: 0.8em;
|
||||
}
|
||||
dt {
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0;
|
||||
font-style: normal;
|
||||
color: navy;
|
||||
}
|
||||
dd > *:first-child {
|
||||
margin-top: 0.1em;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
list-style-position: outside;
|
||||
}
|
||||
ol.arabic {
|
||||
list-style-type: decimal;
|
||||
}
|
||||
ol.loweralpha {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
ol.upperalpha {
|
||||
list-style-type: upper-alpha;
|
||||
}
|
||||
ol.lowerroman {
|
||||
list-style-type: lower-roman;
|
||||
}
|
||||
ol.upperroman {
|
||||
list-style-type: upper-roman;
|
||||
}
|
||||
|
||||
div.compact ul, div.compact ol,
|
||||
div.compact p, div.compact p,
|
||||
div.compact div, div.compact div {
|
||||
margin-top: 0.1em;
|
||||
margin-bottom: 0.1em;
|
||||
}
|
||||
|
||||
div.tableblock > table {
|
||||
border: 3px solid #527bbd;
|
||||
}
|
||||
thead {
|
||||
font-family: sans-serif;
|
||||
font-weight: bold;
|
||||
}
|
||||
tfoot {
|
||||
font-weight: bold;
|
||||
}
|
||||
td > div.verse {
|
||||
white-space: pre;
|
||||
}
|
||||
p.table {
|
||||
margin-top: 0;
|
||||
}
|
||||
/* Because the table frame attribute is overriden by CSS in most browsers. */
|
||||
div.tableblock > table[frame="void"] {
|
||||
border-style: none;
|
||||
}
|
||||
div.tableblock > table[frame="hsides"] {
|
||||
border-left-style: none;
|
||||
border-right-style: none;
|
||||
}
|
||||
div.tableblock > table[frame="vsides"] {
|
||||
border-top-style: none;
|
||||
border-bottom-style: none;
|
||||
}
|
||||
|
||||
|
||||
div.hdlist {
|
||||
margin-top: 0.8em;
|
||||
margin-bottom: 0.8em;
|
||||
}
|
||||
div.hdlist tr {
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
dt.hdlist1.strong, td.hdlist1.strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
td.hdlist1 {
|
||||
vertical-align: top;
|
||||
font-style: normal;
|
||||
padding-right: 0.8em;
|
||||
color: navy;
|
||||
}
|
||||
td.hdlist2 {
|
||||
vertical-align: top;
|
||||
}
|
||||
div.hdlist.compact tr {
|
||||
margin: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.comment {
|
||||
background: yellow;
|
||||
}
|
||||
|
||||
@media print {
|
||||
div#footer-badges { display: none; }
|
||||
}
|
||||
|
||||
div#toctitle {
|
||||
color: #527bbd;
|
||||
font-family: sans-serif;
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
margin-top: 1.0em;
|
||||
margin-bottom: 0.1em;
|
||||
}
|
||||
|
||||
div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
div.toclevel2 {
|
||||
margin-left: 2em;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
div.toclevel3 {
|
||||
margin-left: 4em;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
div.toclevel4 {
|
||||
margin-left: 6em;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
/* Workarounds for IE6's broken and incomplete CSS2. */
|
||||
|
||||
div.sidebar-content {
|
||||
background: #ffffee;
|
||||
border: 1px solid silver;
|
||||
padding: 0.5em;
|
||||
}
|
||||
div.sidebar-title, div.image-title {
|
||||
color: #527bbd;
|
||||
font-family: sans-serif;
|
||||
font-weight: bold;
|
||||
margin-top: 0.0em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
div.listingblock div.content {
|
||||
border: 1px solid silver;
|
||||
background: #f4f4f4;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
div.quoteblock-attribution {
|
||||
padding-top: 0.5em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
div.verseblock-content {
|
||||
white-space: pre;
|
||||
}
|
||||
div.verseblock-attribution {
|
||||
padding-top: 0.75em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.exampleblock-content {
|
||||
border-left: 2px solid silver;
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
|
||||
/* IE6 sets dynamically generated links as visited. */
|
||||
div#toc a:visited { color: blue; }
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
/*<+'])');
|
||||
// Function that scans the DOM tree for header elements (the DOM2
|
||||
// nodeIterator API would be a better technique but not supported by all
|
||||
// browsers).
|
||||
var iterate = function (el) {
|
||||
for (var i = el.firstChild; i != null; i = i.nextSibling) {
|
||||
if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
|
||||
var mo = re.exec(i.tagName)
|
||||
if (mo)
|
||||
result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
|
||||
iterate(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
iterate(el);
|
||||
return result;
|
||||
}
|
||||
|
||||
// This function does the work. toclevels = 1..4.
|
||||
function generateToc(toclevels) {
|
||||
var toc = document.getElementById("toc");
|
||||
var entries = tocEntries(document.getElementsByTagName("body")[0], toclevels);
|
||||
for (var i = 0; i < entries.length; ++i) {
|
||||
var entry = entries[i];
|
||||
if (entry.element.id == "")
|
||||
entry.element.id = "toc" + i;
|
||||
var a = document.createElement("a");
|
||||
a.href = "#" + entry.element.id;
|
||||
a.appendChild(document.createTextNode(entry.text));
|
||||
var div = document.createElement("div");
|
||||
div.appendChild(a);
|
||||
div.className = "toclevel" + entry.toclevel;
|
||||
toc.appendChild(div);
|
||||
}
|
||||
if (entries.length == 0)
|
||||
document.getElementById("header").removeChild(toc);
|
||||
}
|
||||
/*]]>*/
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="header">
|
||||
<h1>JSON module performance comparison under Lua</h1>
|
||||
<span id="author">Mark Pulford</span><br />
|
||||
<span id="email"><tt><<a href="mailto:mark@kyne.com.au">mark@kyne.com.au</a>></tt></span><br />
|
||||
<span id="revdate">January 22, 2012</span>
|
||||
<div id="toc">
|
||||
<div id="toctitle">Table of Contents</div>
|
||||
<noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
|
||||
</div>
|
||||
</div>
|
||||
<div id="preamble">
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph"><p>This performance comparison aims to provide a guide of relative
|
||||
performance between several fast and popular JSON modules.</p></div>
|
||||
<div class="paragraph"><p>The examples used in this comparison were mostly sourced from the
|
||||
<a href="http://json.org">JSON website</a> and
|
||||
<a href="http://tools.ietf.org/html/rfc4627">RFC 4627</a>.</p></div>
|
||||
<div class="paragraph"><p>Performance will vary widely between platforms and data sets. These
|
||||
results should only be used as an approximation.</p></div>
|
||||
</div>
|
||||
</div>
|
||||
<h2 id="_modules">1. Modules</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph"><p>The following JSON modules for Lua were tested:</p></div>
|
||||
<div class="dlist"><dl>
|
||||
<dt class="hdlist1">
|
||||
<a href="http://chiselapp.com/user/dhkolf/repository/dkjson/">DKJSON 2.1</a>
|
||||
</dt>
|
||||
<dd>
|
||||
<div class="ulist"><ul>
|
||||
<li>
|
||||
<p>
|
||||
Lua implementation with no dependencies on other libraries
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
Supports LPeg to improve decode performance
|
||||
</p>
|
||||
</li>
|
||||
</ul></div>
|
||||
</dd>
|
||||
<dt class="hdlist1">
|
||||
<a href="https://github.com/brimworks/lua-yajl">Lua YAJL 2.0</a>
|
||||
</dt>
|
||||
<dd>
|
||||
<div class="ulist"><ul>
|
||||
<li>
|
||||
<p>
|
||||
C wrapper for the YAJL library
|
||||
</p>
|
||||
</li>
|
||||
</ul></div>
|
||||
</dd>
|
||||
<dt class="hdlist1">
|
||||
<a href="http://www.kyne.com.au/%7Emark/software/lua-cjson.php">Lua CSJON 2.0.0</a>
|
||||
</dt>
|
||||
<dd>
|
||||
<div class="ulist"><ul>
|
||||
<li>
|
||||
<p>
|
||||
C implementation with no dependencies on other libraries
|
||||
</p>
|
||||
</li>
|
||||
</ul></div>
|
||||
</dd>
|
||||
</dl></div>
|
||||
</div>
|
||||
<h2 id="_summary">2. Summary</h2>
|
||||
<div class="sectionbody">
|
||||
<div class="paragraph"><p>All modules were built and tested as follows:</p></div>
|
||||
<div class="dlist"><dl>
|
||||
<dt class="hdlist1">
|
||||
DKJSON
|
||||
</dt>
|
||||
<dd>
|
||||
<p>
|
||||
Tested with/without LPeg 10.2.
|
||||
</p>
|
||||
</dd>
|
||||
<dt class="hdlist1">
|
||||
Lua YAJL
|
||||
</dt>
|
||||
<dd>
|
||||
<p>
|
||||
Tested with YAJL 2.0.4.
|
||||
</p>
|
||||
</dd>
|
||||
<dt class="hdlist1">
|
||||
Lua CJSON
|
||||
</dt>
|
||||
<dd>
|
||||
<p>
|
||||
Tested with Libc and internal floating point conversion
|
||||
routines.
|
||||
</p>
|
||||
</dd>
|
||||
</dl></div>
|
||||
<div class="paragraph"><p>The following Lua implementations were used for this comparison:</p></div>
|
||||
<div class="ulist"><ul>
|
||||
<li>
|
||||
<p>
|
||||
<a href="http://www.lua.org">Lua 5.1.4</a> (<em>Lua</em>)
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<a href="http://www.luajit.org">LuaJIT 2.0.0-beta9</a> (<em>JIT</em>)
|
||||
</p>
|
||||
</li>
|
||||
</ul></div>
|
||||
<div class="paragraph"><p>These results show the number of JSON operations per second sustained by
|
||||
each module. All results have been normalised against the pure Lua
|
||||
DKJSON implementation.</p></div>
|
||||
<div class="literalblock">
|
||||
<div class="title">Decoding performance</div>
|
||||
<div class="content">
|
||||
<pre><tt> | DKJSON | Lua YAJL | Lua CJSON
|
||||
| No LPeg With LPeg | | Libc Internal
|
||||
| Lua JIT Lua JIT | Lua JIT | Lua JIT Lua JIT
|
||||
example1 | 1x 2x 2.6x 3.4x | 7.1x 10x | 14x 20x 14x 20x
|
||||
example2 | 1x 2.2x 2.9x 4.4x | 6.7x 9.9x | 14x 22x 14x 22x
|
||||
example3 | 1x 2.1x 3x 4.3x | 6.9x 9.3x | 14x 21x 15x 22x
|
||||
example4 | 1x 2x 2.5x 3.7x | 7.3x 10x | 12x 19x 12x 20x
|
||||
example5 | 1x 2.2x 3x 4.5x | 7.8x 11x | 16x 24x 16x 24x
|
||||
numbers | 1x 2.2x 2.3x 4x | 4.6x 5.5x | 8.9x 10x 13x 17x
|
||||
rfc-example1 | 1x 2.1x 2.8x 4.3x | 6.1x 8.1x | 13x 19x 14x 21x
|
||||
rfc-example2 | 1x 2.1x 3.1x 4.2x | 7.1x 9.2x | 15x 21x 17x 24x
|
||||
types | 1x 2.2x 2.6x 4.3x | 5.3x 7.4x | 12x 20x 13x 21x
|
||||
-------------|-------------------------|------------|-----------------------
|
||||
= Average => | 1x 2.1x 2.7x 4.1x | 6.5x 9x | 13x 20x 14x 21x</tt></pre>
|
||||
</div></div>
|
||||
<div class="literalblock">
|
||||
<div class="title">Encoding performance</div>
|
||||
<div class="content">
|
||||
<pre><tt> | DKJSON | Lua YAJL | Lua CJSON
|
||||
| No LPeg With LPeg | | Libc Internal
|
||||
| Lua JIT Lua JIT | Lua JIT | Lua JIT Lua JIT
|
||||
example1 | 1x 1.8x 0.97x 1.6x | 3.1x 5.2x | 23x 29x 23x 29x
|
||||
example2 | 1x 2x 0.97x 1.7x | 2.6x 4.3x | 22x 28x 22x 28x
|
||||
example3 | 1x 1.9x 0.98x 1.6x | 2.8x 4.3x | 13x 15x 16x 18x
|
||||
example4 | 1x 1.7x 0.96x 1.3x | 3.9x 6.1x | 15x 19x 17x 21x
|
||||
example5 | 1x 2x 0.98x 1.7x | 2.7x 4.5x | 20x 23x 20x 23x
|
||||
numbers | 1x 2.3x 1x 2.2x | 1.3x 1.9x | 3.8x 4.1x 4.2x 4.6x
|
||||
rfc-example1 | 1x 1.9x 0.97x 1.6x | 2.2x 3.2x | 8.5x 9.3x 11x 12x
|
||||
rfc-example2 | 1x 1.9x 0.98x 1.6x | 2.6x 3.9x | 10x 11x 17x 19x
|
||||
types | 1x 2.2x 0.97x 2x | 1.2x 1.9x | 11x 13x 12x 14x
|
||||
-------------|-------------------------|------------|-----------------------
|
||||
= Average => | 1x 1.9x 0.98x 1.7x | 2.5x 3.9x | 14x 17x 16x 19x</tt></pre>
|
||||
</div></div>
|
||||
</div>
|
||||
<div id="footer">
|
||||
<div id="footer-text">
|
||||
Last updated 2012-03-01 22:52:50 CST
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,89 +0,0 @@
|
||||
JSON module performance comparison under Lua
|
||||
============================================
|
||||
Mark Pulford <mark@kyne.com.au>
|
||||
:revdate: January 22, 2012
|
||||
|
||||
This performance comparison aims to provide a guide of relative
|
||||
performance between several fast and popular JSON modules.
|
||||
|
||||
The examples used in this comparison were mostly sourced from the
|
||||
http://json.org[JSON website] and
|
||||
http://tools.ietf.org/html/rfc4627[RFC 4627].
|
||||
|
||||
Performance will vary widely between platforms and data sets. These
|
||||
results should only be used as an approximation.
|
||||
|
||||
|
||||
Modules
|
||||
-------
|
||||
|
||||
The following JSON modules for Lua were tested:
|
||||
|
||||
http://chiselapp.com/user/dhkolf/repository/dkjson/[DKJSON 2.1]::
|
||||
- Lua implementation with no dependencies on other libraries
|
||||
- Supports LPeg to improve decode performance
|
||||
|
||||
https://github.com/brimworks/lua-yajl[Lua YAJL 2.0]::
|
||||
- C wrapper for the YAJL library
|
||||
|
||||
http://www.kyne.com.au/%7Emark/software/lua-cjson.php[Lua CSJON 2.0.0]::
|
||||
- C implementation with no dependencies on other libraries
|
||||
|
||||
|
||||
Summary
|
||||
-------
|
||||
|
||||
All modules were built and tested as follows:
|
||||
|
||||
DKJSON:: Tested with/without LPeg 10.2.
|
||||
Lua YAJL:: Tested with YAJL 2.0.4.
|
||||
Lua CJSON:: Tested with Libc and internal floating point conversion
|
||||
routines.
|
||||
|
||||
The following Lua implementations were used for this comparison:
|
||||
|
||||
- http://www.lua.org[Lua 5.1.4] (_Lua_)
|
||||
- http://www.luajit.org[LuaJIT 2.0.0-beta9] (_JIT_)
|
||||
|
||||
These results show the number of JSON operations per second sustained by
|
||||
each module. All results have been normalised against the pure Lua
|
||||
DKJSON implementation.
|
||||
|
||||
.Decoding performance
|
||||
............................................................................
|
||||
| DKJSON | Lua YAJL | Lua CJSON
|
||||
| No LPeg With LPeg | | Libc Internal
|
||||
| Lua JIT Lua JIT | Lua JIT | Lua JIT Lua JIT
|
||||
example1 | 1x 2x 2.6x 3.4x | 7.1x 10x | 14x 20x 14x 20x
|
||||
example2 | 1x 2.2x 2.9x 4.4x | 6.7x 9.9x | 14x 22x 14x 22x
|
||||
example3 | 1x 2.1x 3x 4.3x | 6.9x 9.3x | 14x 21x 15x 22x
|
||||
example4 | 1x 2x 2.5x 3.7x | 7.3x 10x | 12x 19x 12x 20x
|
||||
example5 | 1x 2.2x 3x 4.5x | 7.8x 11x | 16x 24x 16x 24x
|
||||
numbers | 1x 2.2x 2.3x 4x | 4.6x 5.5x | 8.9x 10x 13x 17x
|
||||
rfc-example1 | 1x 2.1x 2.8x 4.3x | 6.1x 8.1x | 13x 19x 14x 21x
|
||||
rfc-example2 | 1x 2.1x 3.1x 4.2x | 7.1x 9.2x | 15x 21x 17x 24x
|
||||
types | 1x 2.2x 2.6x 4.3x | 5.3x 7.4x | 12x 20x 13x 21x
|
||||
-------------|-------------------------|------------|-----------------------
|
||||
= Average => | 1x 2.1x 2.7x 4.1x | 6.5x 9x | 13x 20x 14x 21x
|
||||
............................................................................
|
||||
|
||||
.Encoding performance
|
||||
.............................................................................
|
||||
| DKJSON | Lua YAJL | Lua CJSON
|
||||
| No LPeg With LPeg | | Libc Internal
|
||||
| Lua JIT Lua JIT | Lua JIT | Lua JIT Lua JIT
|
||||
example1 | 1x 1.8x 0.97x 1.6x | 3.1x 5.2x | 23x 29x 23x 29x
|
||||
example2 | 1x 2x 0.97x 1.7x | 2.6x 4.3x | 22x 28x 22x 28x
|
||||
example3 | 1x 1.9x 0.98x 1.6x | 2.8x 4.3x | 13x 15x 16x 18x
|
||||
example4 | 1x 1.7x 0.96x 1.3x | 3.9x 6.1x | 15x 19x 17x 21x
|
||||
example5 | 1x 2x 0.98x 1.7x | 2.7x 4.5x | 20x 23x 20x 23x
|
||||
numbers | 1x 2.3x 1x 2.2x | 1.3x 1.9x | 3.8x 4.1x 4.2x 4.6x
|
||||
rfc-example1 | 1x 1.9x 0.97x 1.6x | 2.2x 3.2x | 8.5x 9.3x 11x 12x
|
||||
rfc-example2 | 1x 1.9x 0.98x 1.6x | 2.6x 3.9x | 10x 11x 17x 19x
|
||||
types | 1x 2.2x 0.97x 2x | 1.2x 1.9x | 11x 13x 12x 14x
|
||||
-------------|-------------------------|------------|-----------------------
|
||||
= Average => | 1x 1.9x 0.98x 1.7x | 2.5x 3.9x | 14x 17x 16x 19x
|
||||
.............................................................................
|
||||
|
||||
|
||||
// vi:ft=asciidoc tw=72:
|
||||
@@ -1,563 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Network Working Group D. Crockford
|
||||
Request for Comments: 4627 JSON.org
|
||||
Category: Informational July 2006
|
||||
|
||||
|
||||
The application/json Media Type for JavaScript Object Notation (JSON)
|
||||
|
||||
Status of This Memo
|
||||
|
||||
This memo provides information for the Internet community. It does
|
||||
not specify an Internet standard of any kind. Distribution of this
|
||||
memo is unlimited.
|
||||
|
||||
Copyright Notice
|
||||
|
||||
Copyright (C) The Internet Society (2006).
|
||||
|
||||
Abstract
|
||||
|
||||
JavaScript Object Notation (JSON) is a lightweight, text-based,
|
||||
language-independent data interchange format. It was derived from
|
||||
the ECMAScript Programming Language Standard. JSON defines a small
|
||||
set of formatting rules for the portable representation of structured
|
||||
data.
|
||||
|
||||
1. Introduction
|
||||
|
||||
JavaScript Object Notation (JSON) is a text format for the
|
||||
serialization of structured data. It is derived from the object
|
||||
literals of JavaScript, as defined in the ECMAScript Programming
|
||||
Language Standard, Third Edition [ECMA].
|
||||
|
||||
JSON can represent four primitive types (strings, numbers, booleans,
|
||||
and null) and two structured types (objects and arrays).
|
||||
|
||||
A string is a sequence of zero or more Unicode characters [UNICODE].
|
||||
|
||||
An object is an unordered collection of zero or more name/value
|
||||
pairs, where a name is a string and a value is a string, number,
|
||||
boolean, null, object, or array.
|
||||
|
||||
An array is an ordered sequence of zero or more values.
|
||||
|
||||
The terms "object" and "array" come from the conventions of
|
||||
JavaScript.
|
||||
|
||||
JSON's design goals were for it to be minimal, portable, textual, and
|
||||
a subset of JavaScript.
|
||||
|
||||
|
||||
|
||||
Crockford Informational [Page 1]
|
||||
|
||||
RFC 4627 JSON July 2006
|
||||
|
||||
|
||||
1.1. Conventions Used in This Document
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
||||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
||||
document are to be interpreted as described in [RFC2119].
|
||||
|
||||
The grammatical rules in this document are to be interpreted as
|
||||
described in [RFC4234].
|
||||
|
||||
2. JSON Grammar
|
||||
|
||||
A JSON text is a sequence of tokens. The set of tokens includes six
|
||||
structural characters, strings, numbers, and three literal names.
|
||||
|
||||
A JSON text is a serialized object or array.
|
||||
|
||||
JSON-text = object / array
|
||||
|
||||
These are the six structural characters:
|
||||
|
||||
begin-array = ws %x5B ws ; [ left square bracket
|
||||
|
||||
begin-object = ws %x7B ws ; { left curly bracket
|
||||
|
||||
end-array = ws %x5D ws ; ] right square bracket
|
||||
|
||||
end-object = ws %x7D ws ; } right curly bracket
|
||||
|
||||
name-separator = ws %x3A ws ; : colon
|
||||
|
||||
value-separator = ws %x2C ws ; , comma
|
||||
|
||||
Insignificant whitespace is allowed before or after any of the six
|
||||
structural characters.
|
||||
|
||||
ws = *(
|
||||
%x20 / ; Space
|
||||
%x09 / ; Horizontal tab
|
||||
%x0A / ; Line feed or New line
|
||||
%x0D ; Carriage return
|
||||
)
|
||||
|
||||
2.1. Values
|
||||
|
||||
A JSON value MUST be an object, array, number, or string, or one of
|
||||
the following three literal names:
|
||||
|
||||
false null true
|
||||
|
||||
|
||||
|
||||
Crockford Informational [Page 2]
|
||||
|
||||
RFC 4627 JSON July 2006
|
||||
|
||||
|
||||
The literal names MUST be lowercase. No other literal names are
|
||||
allowed.
|
||||
|
||||
value = false / null / true / object / array / number / string
|
||||
|
||||
false = %x66.61.6c.73.65 ; false
|
||||
|
||||
null = %x6e.75.6c.6c ; null
|
||||
|
||||
true = %x74.72.75.65 ; true
|
||||
|
||||
2.2. Objects
|
||||
|
||||
An object structure is represented as a pair of curly brackets
|
||||
surrounding zero or more name/value pairs (or members). A name is a
|
||||
string. A single colon comes after each name, separating the name
|
||||
from the value. A single comma separates a value from a following
|
||||
name. The names within an object SHOULD be unique.
|
||||
|
||||
object = begin-object [ member *( value-separator member ) ]
|
||||
end-object
|
||||
|
||||
member = string name-separator value
|
||||
|
||||
2.3. Arrays
|
||||
|
||||
An array structure is represented as square brackets surrounding zero
|
||||
or more values (or elements). Elements are separated by commas.
|
||||
|
||||
array = begin-array [ value *( value-separator value ) ] end-array
|
||||
|
||||
2.4. Numbers
|
||||
|
||||
The representation of numbers is similar to that used in most
|
||||
programming languages. A number contains an integer component that
|
||||
may be prefixed with an optional minus sign, which may be followed by
|
||||
a fraction part and/or an exponent part.
|
||||
|
||||
Octal and hex forms are not allowed. Leading zeros are not allowed.
|
||||
|
||||
A fraction part is a decimal point followed by one or more digits.
|
||||
|
||||
An exponent part begins with the letter E in upper or lowercase,
|
||||
which may be followed by a plus or minus sign. The E and optional
|
||||
sign are followed by one or more digits.
|
||||
|
||||
Numeric values that cannot be represented as sequences of digits
|
||||
(such as Infinity and NaN) are not permitted.
|
||||
|
||||
|
||||
|
||||
Crockford Informational [Page 3]
|
||||
|
||||
RFC 4627 JSON July 2006
|
||||
|
||||
|
||||
number = [ minus ] int [ frac ] [ exp ]
|
||||
|
||||
decimal-point = %x2E ; .
|
||||
|
||||
digit1-9 = %x31-39 ; 1-9
|
||||
|
||||
e = %x65 / %x45 ; e E
|
||||
|
||||
exp = e [ minus / plus ] 1*DIGIT
|
||||
|
||||
frac = decimal-point 1*DIGIT
|
||||
|
||||
int = zero / ( digit1-9 *DIGIT )
|
||||
|
||||
minus = %x2D ; -
|
||||
|
||||
plus = %x2B ; +
|
||||
|
||||
zero = %x30 ; 0
|
||||
|
||||
2.5. Strings
|
||||
|
||||
The representation of strings is similar to conventions used in the C
|
||||
family of programming languages. A string begins and ends with
|
||||
quotation marks. All Unicode characters may be placed within the
|
||||
quotation marks except for the characters that must be escaped:
|
||||
quotation mark, reverse solidus, and the control characters (U+0000
|
||||
through U+001F).
|
||||
|
||||
Any character may be escaped. If the character is in the Basic
|
||||
Multilingual Plane (U+0000 through U+FFFF), then it may be
|
||||
represented as a six-character sequence: a reverse solidus, followed
|
||||
by the lowercase letter u, followed by four hexadecimal digits that
|
||||
encode the character's code point. The hexadecimal letters A though
|
||||
F can be upper or lowercase. So, for example, a string containing
|
||||
only a single reverse solidus character may be represented as
|
||||
"\u005C".
|
||||
|
||||
Alternatively, there are two-character sequence escape
|
||||
representations of some popular characters. So, for example, a
|
||||
string containing only a single reverse solidus character may be
|
||||
represented more compactly as "\\".
|
||||
|
||||
To escape an extended character that is not in the Basic Multilingual
|
||||
Plane, the character is represented as a twelve-character sequence,
|
||||
encoding the UTF-16 surrogate pair. So, for example, a string
|
||||
containing only the G clef character (U+1D11E) may be represented as
|
||||
"\uD834\uDD1E".
|
||||
|
||||
|
||||
|
||||
Crockford Informational [Page 4]
|
||||
|
||||
RFC 4627 JSON July 2006
|
||||
|
||||
|
||||
string = quotation-mark *char quotation-mark
|
||||
|
||||
char = unescaped /
|
||||
escape (
|
||||
%x22 / ; " quotation mark U+0022
|
||||
%x5C / ; \ reverse solidus U+005C
|
||||
%x2F / ; / solidus U+002F
|
||||
%x62 / ; b backspace U+0008
|
||||
%x66 / ; f form feed U+000C
|
||||
%x6E / ; n line feed U+000A
|
||||
%x72 / ; r carriage return U+000D
|
||||
%x74 / ; t tab U+0009
|
||||
%x75 4HEXDIG ) ; uXXXX U+XXXX
|
||||
|
||||
escape = %x5C ; \
|
||||
|
||||
quotation-mark = %x22 ; "
|
||||
|
||||
unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
|
||||
|
||||
3. Encoding
|
||||
|
||||
JSON text SHALL be encoded in Unicode. The default encoding is
|
||||
UTF-8.
|
||||
|
||||
Since the first two characters of a JSON text will always be ASCII
|
||||
characters [RFC0020], it is possible to determine whether an octet
|
||||
stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
|
||||
at the pattern of nulls in the first four octets.
|
||||
|
||||
00 00 00 xx UTF-32BE
|
||||
00 xx 00 xx UTF-16BE
|
||||
xx 00 00 00 UTF-32LE
|
||||
xx 00 xx 00 UTF-16LE
|
||||
xx xx xx xx UTF-8
|
||||
|
||||
4. Parsers
|
||||
|
||||
A JSON parser transforms a JSON text into another representation. A
|
||||
JSON parser MUST accept all texts that conform to the JSON grammar.
|
||||
A JSON parser MAY accept non-JSON forms or extensions.
|
||||
|
||||
An implementation may set limits on the size of texts that it
|
||||
accepts. An implementation may set limits on the maximum depth of
|
||||
nesting. An implementation may set limits on the range of numbers.
|
||||
An implementation may set limits on the length and character contents
|
||||
of strings.
|
||||
|
||||
|
||||
|
||||
|
||||
Crockford Informational [Page 5]
|
||||
|
||||
RFC 4627 JSON July 2006
|
||||
|
||||
|
||||
5. Generators
|
||||
|
||||
A JSON generator produces JSON text. The resulting text MUST
|
||||
strictly conform to the JSON grammar.
|
||||
|
||||
6. IANA Considerations
|
||||
|
||||
The MIME media type for JSON text is application/json.
|
||||
|
||||
Type name: application
|
||||
|
||||
Subtype name: json
|
||||
|
||||
Required parameters: n/a
|
||||
|
||||
Optional parameters: n/a
|
||||
|
||||
Encoding considerations: 8bit if UTF-8; binary if UTF-16 or UTF-32
|
||||
|
||||
JSON may be represented using UTF-8, UTF-16, or UTF-32. When JSON
|
||||
is written in UTF-8, JSON is 8bit compatible. When JSON is
|
||||
written in UTF-16 or UTF-32, the binary content-transfer-encoding
|
||||
must be used.
|
||||
|
||||
Security considerations:
|
||||
|
||||
Generally there are security issues with scripting languages. JSON
|
||||
is a subset of JavaScript, but it is a safe subset that excludes
|
||||
assignment and invocation.
|
||||
|
||||
A JSON text can be safely passed into JavaScript's eval() function
|
||||
(which compiles and executes a string) if all the characters not
|
||||
enclosed in strings are in the set of characters that form JSON
|
||||
tokens. This can be quickly determined in JavaScript with two
|
||||
regular expressions and calls to the test and replace methods.
|
||||
|
||||
var my_JSON_object = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
|
||||
text.replace(/"(\\.|[^"\\])*"/g, ''))) &&
|
||||
eval('(' + text + ')');
|
||||
|
||||
Interoperability considerations: n/a
|
||||
|
||||
Published specification: RFC 4627
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Crockford Informational [Page 6]
|
||||
|
||||
RFC 4627 JSON July 2006
|
||||
|
||||
|
||||
Applications that use this media type:
|
||||
|
||||
JSON has been used to exchange data between applications written
|
||||
in all of these programming languages: ActionScript, C, C#,
|
||||
ColdFusion, Common Lisp, E, Erlang, Java, JavaScript, Lua,
|
||||
Objective CAML, Perl, PHP, Python, Rebol, Ruby, and Scheme.
|
||||
|
||||
Additional information:
|
||||
|
||||
Magic number(s): n/a
|
||||
File extension(s): .json
|
||||
Macintosh file type code(s): TEXT
|
||||
|
||||
Person & email address to contact for further information:
|
||||
Douglas Crockford
|
||||
douglas@crockford.com
|
||||
|
||||
Intended usage: COMMON
|
||||
|
||||
Restrictions on usage: none
|
||||
|
||||
Author:
|
||||
Douglas Crockford
|
||||
douglas@crockford.com
|
||||
|
||||
Change controller:
|
||||
Douglas Crockford
|
||||
douglas@crockford.com
|
||||
|
||||
7. Security Considerations
|
||||
|
||||
See Security Considerations in Section 6.
|
||||
|
||||
8. Examples
|
||||
|
||||
This is a JSON object:
|
||||
|
||||
{
|
||||
"Image": {
|
||||
"Width": 800,
|
||||
"Height": 600,
|
||||
"Title": "View from 15th Floor",
|
||||
"Thumbnail": {
|
||||
"Url": "http://www.example.com/image/481989943",
|
||||
"Height": 125,
|
||||
"Width": "100"
|
||||
},
|
||||
"IDs": [116, 943, 234, 38793]
|
||||
|
||||
|
||||
|
||||
Crockford Informational [Page 7]
|
||||
|
||||
RFC 4627 JSON July 2006
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Its Image member is an object whose Thumbnail member is an object
|
||||
and whose IDs member is an array of numbers.
|
||||
|
||||
This is a JSON array containing two objects:
|
||||
|
||||
[
|
||||
{
|
||||
"precision": "zip",
|
||||
"Latitude": 37.7668,
|
||||
"Longitude": -122.3959,
|
||||
"Address": "",
|
||||
"City": "SAN FRANCISCO",
|
||||
"State": "CA",
|
||||
"Zip": "94107",
|
||||
"Country": "US"
|
||||
},
|
||||
{
|
||||
"precision": "zip",
|
||||
"Latitude": 37.371991,
|
||||
"Longitude": -122.026020,
|
||||
"Address": "",
|
||||
"City": "SUNNYVALE",
|
||||
"State": "CA",
|
||||
"Zip": "94085",
|
||||
"Country": "US"
|
||||
}
|
||||
]
|
||||
|
||||
9. References
|
||||
|
||||
9.1. Normative References
|
||||
|
||||
[ECMA] European Computer Manufacturers Association, "ECMAScript
|
||||
Language Specification 3rd Edition", December 1999,
|
||||
<http://www.ecma-international.org/publications/files/
|
||||
ecma-st/ECMA-262.pdf>.
|
||||
|
||||
[RFC0020] Cerf, V., "ASCII format for network interchange", RFC 20,
|
||||
October 1969.
|
||||
|
||||
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
|
||||
Requirement Levels", BCP 14, RFC 2119, March 1997.
|
||||
|
||||
[RFC4234] Crocker, D. and P. Overell, "Augmented BNF for Syntax
|
||||
Specifications: ABNF", RFC 4234, October 2005.
|
||||
|
||||
|
||||
|
||||
Crockford Informational [Page 8]
|
||||
|
||||
RFC 4627 JSON July 2006
|
||||
|
||||
|
||||
[UNICODE] The Unicode Consortium, "The Unicode Standard Version 4.0",
|
||||
2003, <http://www.unicode.org/versions/Unicode4.1.0/>.
|
||||
|
||||
Author's Address
|
||||
|
||||
Douglas Crockford
|
||||
JSON.org
|
||||
EMail: douglas@crockford.com
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Crockford Informational [Page 9]
|
||||
|
||||
RFC 4627 JSON July 2006
|
||||
|
||||
|
||||
Full Copyright Statement
|
||||
|
||||
Copyright (C) The Internet Society (2006).
|
||||
|
||||
This document is subject to the rights, licenses and restrictions
|
||||
contained in BCP 78, and except as set forth therein, the authors
|
||||
retain all their rights.
|
||||
|
||||
This document and the information contained herein are provided on an
|
||||
"AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
|
||||
OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
|
||||
ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
|
||||
INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
Intellectual Property
|
||||
|
||||
The IETF takes no position regarding the validity or scope of any
|
||||
Intellectual Property Rights or other rights that might be claimed to
|
||||
pertain to the implementation or use of the technology described in
|
||||
this document or the extent to which any license under such rights
|
||||
might or might not be available; nor does it represent that it has
|
||||
made any independent effort to identify any such rights. Information
|
||||
on the procedures with respect to rights in RFC documents can be
|
||||
found in BCP 78 and BCP 79.
|
||||
|
||||
Copies of IPR disclosures made to the IETF Secretariat and any
|
||||
assurances of licenses to be made available, or the result of an
|
||||
attempt made to obtain a general license or permission for the use of
|
||||
such proprietary rights by implementers or users of this
|
||||
specification can be obtained from the IETF on-line IPR repository at
|
||||
http://www.ietf.org/ipr.
|
||||
|
||||
The IETF invites any interested party to bring to its attention any
|
||||
copyrights, patents or patent applications, or other proprietary
|
||||
rights that may cover technology that may be required to implement
|
||||
this standard. Please address the information to the IETF at
|
||||
ietf-ipr@ietf.org.
|
||||
|
||||
Acknowledgement
|
||||
|
||||
Funding for the RFC Editor function is provided by the IETF
|
||||
Administrative Support Activity (IASA).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Crockford Informational [Page 10]
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
PLATFORM="`uname -s`"
|
||||
[ "$1" ] && VERSION="$1" || VERSION="2.1.0"
|
||||
|
||||
set -e
|
||||
|
||||
# Portable "ggrep -A" replacement.
|
||||
# Work around Solaris awk record limit of 2559 bytes.
|
||||
# contextgrep PATTERN POST_MATCH_LINES
|
||||
contextgrep() {
|
||||
cut -c -2500 | awk "/$1/ { count = ($2 + 1) } count > 0 { count--; print }"
|
||||
}
|
||||
|
||||
do_tests() {
|
||||
echo
|
||||
cd tests
|
||||
lua -e 'print("Testing Lua CJSON version " .. require("cjson")._VERSION)'
|
||||
./test.lua | contextgrep 'FAIL|Summary' 3 | grep -v PASS | cut -c -150
|
||||
cd ..
|
||||
}
|
||||
|
||||
echo "===== Setting LuaRocks PATH ====="
|
||||
eval "`luarocks path`"
|
||||
|
||||
echo "===== Building UTF-8 test data ====="
|
||||
( cd tests && ./genutf8.pl; )
|
||||
|
||||
echo "===== Cleaning old build data ====="
|
||||
make clean
|
||||
rm -f tests/cjson.so
|
||||
|
||||
echo "===== Verifying cjson.so is not installed ====="
|
||||
|
||||
cd tests
|
||||
if lua -e 'require "cjson"' 2>/dev/null
|
||||
then
|
||||
cat <<EOT
|
||||
Please ensure you do not have the Lua CJSON module installed before
|
||||
running these tests.
|
||||
EOT
|
||||
exit
|
||||
fi
|
||||
cd ..
|
||||
|
||||
echo "===== Testing LuaRocks build ====="
|
||||
luarocks make --local
|
||||
do_tests
|
||||
luarocks remove --local lua-cjson
|
||||
make clean
|
||||
|
||||
echo "===== Testing Makefile build ====="
|
||||
make
|
||||
cp -r lua/cjson cjson.so tests
|
||||
do_tests
|
||||
make clean
|
||||
rm -rf tests/cjson{,.so}
|
||||
|
||||
echo "===== Testing Cmake build ====="
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
cd ..
|
||||
cp -r lua/cjson build/cjson.so tests
|
||||
do_tests
|
||||
rm -rf build tests/cjson{,.so}
|
||||
|
||||
if [ "$PLATFORM" = "Linux" ]
|
||||
then
|
||||
echo "===== Testing RPM build ====="
|
||||
SRCTGZ=""
|
||||
TGZ=lua-cjson-$VERSION.tar.gz
|
||||
for D in .. packages .
|
||||
do
|
||||
[ -r "$D/$TGZ" ] && SRCTGZ="$D/$TGZ"
|
||||
done
|
||||
if [ "$SRCTGZ" ]
|
||||
then
|
||||
LOG=/tmp/build.$$
|
||||
rpmbuild -tb "$SRCTGZ" > "$LOG"
|
||||
RPM="`awk '/^Wrote: / && ! /debuginfo/ { print $2}' < "$LOG"`"
|
||||
sudo -- rpm -Uvh \"$RPM\"
|
||||
do_tests
|
||||
sudo -- rpm -e lua-cjson
|
||||
rm -f "$LOG"
|
||||
else
|
||||
echo "==> skipping, $TGZ not found"
|
||||
fi
|
||||
fi
|
||||
|
||||
# vi:ai et sw=4 ts=4:
|
||||
@@ -1,251 +0,0 @@
|
||||
/* strbuf - String buffer routines
|
||||
*
|
||||
* Copyright (c) 2010-2012 Mark Pulford <mark@kyne.com.au>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "strbuf.h"
|
||||
|
||||
static void die(const char *fmt, ...)
|
||||
{
|
||||
va_list arg;
|
||||
|
||||
va_start(arg, fmt);
|
||||
vfprintf(stderr, fmt, arg);
|
||||
va_end(arg);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void strbuf_init(strbuf_t *s, int len)
|
||||
{
|
||||
int size;
|
||||
|
||||
if (len <= 0)
|
||||
size = STRBUF_DEFAULT_SIZE;
|
||||
else
|
||||
size = len + 1; /* \0 terminator */
|
||||
|
||||
s->buf = NULL;
|
||||
s->size = size;
|
||||
s->length = 0;
|
||||
s->increment = STRBUF_DEFAULT_INCREMENT;
|
||||
s->dynamic = 0;
|
||||
s->reallocs = 0;
|
||||
s->debug = 0;
|
||||
|
||||
s->buf = malloc(size);
|
||||
if (!s->buf)
|
||||
die("Out of memory");
|
||||
|
||||
strbuf_ensure_null(s);
|
||||
}
|
||||
|
||||
strbuf_t *strbuf_new(int len)
|
||||
{
|
||||
strbuf_t *s;
|
||||
|
||||
s = malloc(sizeof(strbuf_t));
|
||||
if (!s)
|
||||
die("Out of memory");
|
||||
|
||||
strbuf_init(s, len);
|
||||
|
||||
/* Dynamic strbuf allocation / deallocation */
|
||||
s->dynamic = 1;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void strbuf_set_increment(strbuf_t *s, int increment)
|
||||
{
|
||||
/* Increment > 0: Linear buffer growth rate
|
||||
* Increment < -1: Exponential buffer growth rate */
|
||||
if (increment == 0 || increment == -1)
|
||||
die("BUG: Invalid string increment");
|
||||
|
||||
s->increment = increment;
|
||||
}
|
||||
|
||||
static inline void debug_stats(strbuf_t *s)
|
||||
{
|
||||
if (s->debug) {
|
||||
fprintf(stderr, "strbuf(%lx) reallocs: %d, length: %d, size: %d\n",
|
||||
(long)s, s->reallocs, s->length, s->size);
|
||||
}
|
||||
}
|
||||
|
||||
/* If strbuf_t has not been dynamically allocated, strbuf_free() can
|
||||
* be called any number of times strbuf_init() */
|
||||
void strbuf_free(strbuf_t *s)
|
||||
{
|
||||
debug_stats(s);
|
||||
|
||||
if (s->buf) {
|
||||
free(s->buf);
|
||||
s->buf = NULL;
|
||||
}
|
||||
if (s->dynamic)
|
||||
free(s);
|
||||
}
|
||||
|
||||
char *strbuf_free_to_string(strbuf_t *s, int *len)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
debug_stats(s);
|
||||
|
||||
strbuf_ensure_null(s);
|
||||
|
||||
buf = s->buf;
|
||||
if (len)
|
||||
*len = s->length;
|
||||
|
||||
if (s->dynamic)
|
||||
free(s);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int calculate_new_size(strbuf_t *s, int len)
|
||||
{
|
||||
int reqsize, newsize;
|
||||
|
||||
if (len <= 0)
|
||||
die("BUG: Invalid strbuf length requested");
|
||||
|
||||
/* Ensure there is room for optional NULL termination */
|
||||
reqsize = len + 1;
|
||||
|
||||
/* If the user has requested to shrink the buffer, do it exactly */
|
||||
if (s->size > reqsize)
|
||||
return reqsize;
|
||||
|
||||
newsize = s->size;
|
||||
if (s->increment < 0) {
|
||||
/* Exponential sizing */
|
||||
while (newsize < reqsize)
|
||||
newsize *= -s->increment;
|
||||
} else {
|
||||
/* Linear sizing */
|
||||
newsize = ((newsize + s->increment - 1) / s->increment) * s->increment;
|
||||
}
|
||||
|
||||
return newsize;
|
||||
}
|
||||
|
||||
|
||||
/* Ensure strbuf can handle a string length bytes long (ignoring NULL
|
||||
* optional termination). */
|
||||
void strbuf_resize(strbuf_t *s, int len)
|
||||
{
|
||||
int newsize;
|
||||
|
||||
newsize = calculate_new_size(s, len);
|
||||
|
||||
if (s->debug > 1) {
|
||||
fprintf(stderr, "strbuf(%lx) resize: %d => %d\n",
|
||||
(long)s, s->size, newsize);
|
||||
}
|
||||
|
||||
s->size = newsize;
|
||||
s->buf = realloc(s->buf, s->size);
|
||||
if (!s->buf)
|
||||
die("Out of memory");
|
||||
s->reallocs++;
|
||||
}
|
||||
|
||||
void strbuf_append_string(strbuf_t *s, const char *str)
|
||||
{
|
||||
int space, i;
|
||||
|
||||
space = strbuf_empty_length(s);
|
||||
|
||||
for (i = 0; str[i]; i++) {
|
||||
if (space < 1) {
|
||||
strbuf_resize(s, s->length + 1);
|
||||
space = strbuf_empty_length(s);
|
||||
}
|
||||
|
||||
s->buf[s->length] = str[i];
|
||||
s->length++;
|
||||
space--;
|
||||
}
|
||||
}
|
||||
|
||||
/* strbuf_append_fmt() should only be used when an upper bound
|
||||
* is known for the output string. */
|
||||
void strbuf_append_fmt(strbuf_t *s, int len, const char *fmt, ...)
|
||||
{
|
||||
va_list arg;
|
||||
int fmt_len;
|
||||
|
||||
strbuf_ensure_empty_length(s, len);
|
||||
|
||||
va_start(arg, fmt);
|
||||
fmt_len = vsnprintf(s->buf + s->length, len, fmt, arg);
|
||||
va_end(arg);
|
||||
|
||||
if (fmt_len < 0)
|
||||
die("BUG: Unable to convert number"); /* This should never happen.. */
|
||||
|
||||
s->length += fmt_len;
|
||||
}
|
||||
|
||||
/* strbuf_append_fmt_retry() can be used when the there is no known
|
||||
* upper bound for the output string. */
|
||||
void strbuf_append_fmt_retry(strbuf_t *s, const char *fmt, ...)
|
||||
{
|
||||
va_list arg;
|
||||
int fmt_len, try;
|
||||
int empty_len;
|
||||
|
||||
/* If the first attempt to append fails, resize the buffer appropriately
|
||||
* and try again */
|
||||
for (try = 0; ; try++) {
|
||||
va_start(arg, fmt);
|
||||
/* Append the new formatted string */
|
||||
/* fmt_len is the length of the string required, excluding the
|
||||
* trailing NULL */
|
||||
empty_len = strbuf_empty_length(s);
|
||||
/* Add 1 since there is also space to store the terminating NULL. */
|
||||
fmt_len = vsnprintf(s->buf + s->length, empty_len + 1, fmt, arg);
|
||||
va_end(arg);
|
||||
|
||||
if (fmt_len <= empty_len)
|
||||
break; /* SUCCESS */
|
||||
if (try > 0)
|
||||
die("BUG: length of formatted string changed");
|
||||
|
||||
strbuf_resize(s, s->length + fmt_len);
|
||||
}
|
||||
|
||||
s->length += fmt_len;
|
||||
}
|
||||
|
||||
/* vi:ai et sw=4 ts=4:
|
||||
*/
|
||||
@@ -1,154 +0,0 @@
|
||||
/* strbuf - String buffer routines
|
||||
*
|
||||
* Copyright (c) 2010-2012 Mark Pulford <mark@kyne.com.au>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* Size: Total bytes allocated to *buf
|
||||
* Length: String length, excluding optional NULL terminator.
|
||||
* Increment: Allocation increments when resizing the string buffer.
|
||||
* Dynamic: True if created via strbuf_new()
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
char *buf;
|
||||
int size;
|
||||
int length;
|
||||
int increment;
|
||||
int dynamic;
|
||||
int reallocs;
|
||||
int debug;
|
||||
} strbuf_t;
|
||||
|
||||
#ifndef STRBUF_DEFAULT_SIZE
|
||||
#define STRBUF_DEFAULT_SIZE 1023
|
||||
#endif
|
||||
#ifndef STRBUF_DEFAULT_INCREMENT
|
||||
#define STRBUF_DEFAULT_INCREMENT -2
|
||||
#endif
|
||||
|
||||
/* Initialise */
|
||||
extern strbuf_t *strbuf_new(int len);
|
||||
extern void strbuf_init(strbuf_t *s, int len);
|
||||
extern void strbuf_set_increment(strbuf_t *s, int increment);
|
||||
|
||||
/* Release */
|
||||
extern void strbuf_free(strbuf_t *s);
|
||||
extern char *strbuf_free_to_string(strbuf_t *s, int *len);
|
||||
|
||||
/* Management */
|
||||
extern void strbuf_resize(strbuf_t *s, int len);
|
||||
static int strbuf_empty_length(strbuf_t *s);
|
||||
static int strbuf_length(strbuf_t *s);
|
||||
static char *strbuf_string(strbuf_t *s, int *len);
|
||||
static void strbuf_ensure_empty_length(strbuf_t *s, int len);
|
||||
static char *strbuf_empty_ptr(strbuf_t *s);
|
||||
static void strbuf_extend_length(strbuf_t *s, int len);
|
||||
|
||||
/* Update */
|
||||
extern void strbuf_append_fmt(strbuf_t *s, int len, const char *fmt, ...);
|
||||
extern void strbuf_append_fmt_retry(strbuf_t *s, const char *format, ...);
|
||||
static void strbuf_append_mem(strbuf_t *s, const char *c, int len);
|
||||
extern void strbuf_append_string(strbuf_t *s, const char *str);
|
||||
static void strbuf_append_char(strbuf_t *s, const char c);
|
||||
static void strbuf_ensure_null(strbuf_t *s);
|
||||
|
||||
/* Reset string for before use */
|
||||
static inline void strbuf_reset(strbuf_t *s)
|
||||
{
|
||||
s->length = 0;
|
||||
}
|
||||
|
||||
static inline int strbuf_allocated(strbuf_t *s)
|
||||
{
|
||||
return s->buf != NULL;
|
||||
}
|
||||
|
||||
/* Return bytes remaining in the string buffer
|
||||
* Ensure there is space for a NULL terminator. */
|
||||
static inline int strbuf_empty_length(strbuf_t *s)
|
||||
{
|
||||
return s->size - s->length - 1;
|
||||
}
|
||||
|
||||
static inline void strbuf_ensure_empty_length(strbuf_t *s, int len)
|
||||
{
|
||||
if (len > strbuf_empty_length(s))
|
||||
strbuf_resize(s, s->length + len);
|
||||
}
|
||||
|
||||
static inline char *strbuf_empty_ptr(strbuf_t *s)
|
||||
{
|
||||
return s->buf + s->length;
|
||||
}
|
||||
|
||||
static inline void strbuf_extend_length(strbuf_t *s, int len)
|
||||
{
|
||||
s->length += len;
|
||||
}
|
||||
|
||||
static inline int strbuf_length(strbuf_t *s)
|
||||
{
|
||||
return s->length;
|
||||
}
|
||||
|
||||
static inline void strbuf_append_char(strbuf_t *s, const char c)
|
||||
{
|
||||
strbuf_ensure_empty_length(s, 1);
|
||||
s->buf[s->length++] = c;
|
||||
}
|
||||
|
||||
static inline void strbuf_append_char_unsafe(strbuf_t *s, const char c)
|
||||
{
|
||||
s->buf[s->length++] = c;
|
||||
}
|
||||
|
||||
static inline void strbuf_append_mem(strbuf_t *s, const char *c, int len)
|
||||
{
|
||||
strbuf_ensure_empty_length(s, len);
|
||||
memcpy(s->buf + s->length, c, len);
|
||||
s->length += len;
|
||||
}
|
||||
|
||||
static inline void strbuf_append_mem_unsafe(strbuf_t *s, const char *c, int len)
|
||||
{
|
||||
memcpy(s->buf + s->length, c, len);
|
||||
s->length += len;
|
||||
}
|
||||
|
||||
static inline void strbuf_ensure_null(strbuf_t *s)
|
||||
{
|
||||
s->buf[s->length] = 0;
|
||||
}
|
||||
|
||||
static inline char *strbuf_string(strbuf_t *s, int *len)
|
||||
{
|
||||
if (len)
|
||||
*len = s->length;
|
||||
|
||||
return s->buf;
|
||||
}
|
||||
|
||||
/* vi:ai et sw=4 ts=4:
|
||||
*/
|
||||
@@ -1,4 +0,0 @@
|
||||
These JSON examples were taken from the JSON website
|
||||
(http://json.org/example.html) and RFC 4627.
|
||||
|
||||
Used with permission.
|
||||
@@ -1,131 +0,0 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
-- This benchmark script measures wall clock time and should be
|
||||
-- run on an unloaded system.
|
||||
--
|
||||
-- Your Mileage May Vary.
|
||||
--
|
||||
-- Mark Pulford <mark@kyne.com.au>
|
||||
|
||||
local json_module = os.getenv("JSON_MODULE") or "cjson"
|
||||
|
||||
require "socket"
|
||||
local json = require(json_module)
|
||||
local util = require "cjson.util"
|
||||
|
||||
local function find_func(mod, funcnames)
|
||||
for _, v in ipairs(funcnames) do
|
||||
if mod[v] then
|
||||
return mod[v]
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
local json_encode = find_func(json, { "encode", "Encode", "to_string", "stringify", "json" })
|
||||
local json_decode = find_func(json, { "decode", "Decode", "to_value", "parse" })
|
||||
|
||||
local function average(t)
|
||||
local total = 0
|
||||
for _, v in ipairs(t) do
|
||||
total = total + v
|
||||
end
|
||||
return total / #t
|
||||
end
|
||||
|
||||
function benchmark(tests, seconds, rep)
|
||||
local function bench(func, iter)
|
||||
-- Use socket.gettime() to measure microsecond resolution
|
||||
-- wall clock time.
|
||||
local t = socket.gettime()
|
||||
for i = 1, iter do
|
||||
func(i)
|
||||
end
|
||||
t = socket.gettime() - t
|
||||
|
||||
-- Don't trust any results when the run lasted for less than a
|
||||
-- millisecond - return nil.
|
||||
if t < 0.001 then
|
||||
return nil
|
||||
end
|
||||
|
||||
return (iter / t)
|
||||
end
|
||||
|
||||
-- Roughly calculate the number of interations required
|
||||
-- to obtain a particular time period.
|
||||
local function calc_iter(func, seconds)
|
||||
local iter = 1
|
||||
local rate
|
||||
-- Warm up the bench function first.
|
||||
func()
|
||||
while not rate do
|
||||
rate = bench(func, iter)
|
||||
iter = iter * 10
|
||||
end
|
||||
return math.ceil(seconds * rate)
|
||||
end
|
||||
|
||||
local test_results = {}
|
||||
for name, func in pairs(tests) do
|
||||
-- k(number), v(string)
|
||||
-- k(string), v(function)
|
||||
-- k(number), v(function)
|
||||
if type(func) == "string" then
|
||||
name = func
|
||||
func = _G[name]
|
||||
end
|
||||
|
||||
local iter = calc_iter(func, seconds)
|
||||
|
||||
local result = {}
|
||||
for i = 1, rep do
|
||||
result[i] = bench(func, iter)
|
||||
end
|
||||
|
||||
-- Remove the slowest half (round down) of the result set
|
||||
table.sort(result)
|
||||
for i = 1, math.floor(#result / 2) do
|
||||
table.remove(result, 1)
|
||||
end
|
||||
|
||||
test_results[name] = average(result)
|
||||
end
|
||||
|
||||
return test_results
|
||||
end
|
||||
|
||||
function bench_file(filename)
|
||||
local data_json = util.file_load(filename)
|
||||
local data_obj = json_decode(data_json)
|
||||
|
||||
local function test_encode()
|
||||
json_encode(data_obj)
|
||||
end
|
||||
local function test_decode()
|
||||
json_decode(data_json)
|
||||
end
|
||||
|
||||
local tests = {}
|
||||
if json_encode then tests.encode = test_encode end
|
||||
if json_decode then tests.decode = test_decode end
|
||||
|
||||
return benchmark(tests, 0.1, 5)
|
||||
end
|
||||
|
||||
-- Optionally load any custom configuration required for this module
|
||||
local success, data = pcall(util.file_load, ("bench-%s.lua"):format(json_module))
|
||||
if success then
|
||||
util.run_script(data, _G)
|
||||
configure(json)
|
||||
end
|
||||
|
||||
for i = 1, #arg do
|
||||
local results = bench_file(arg[i])
|
||||
for k, v in pairs(results) do
|
||||
print(("%s\t%s\t%d"):format(arg[i], k, v))
|
||||
end
|
||||
end
|
||||
|
||||
-- vi:ai et sw=4 ts=4:
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"glossary": {
|
||||
"title": "example glossary",
|
||||
"GlossDiv": {
|
||||
"title": "S",
|
||||
"GlossList": {
|
||||
"GlossEntry": {
|
||||
"ID": "SGML",
|
||||
"SortAs": "SGML",
|
||||
"GlossTerm": "Standard Generalized Mark up Language",
|
||||
"Acronym": "SGML",
|
||||
"Abbrev": "ISO 8879:1986",
|
||||
"GlossDef": {
|
||||
"para": "A meta-markup language, used to create markup languages such as DocBook.",
|
||||
"GlossSeeAlso": ["GML", "XML"]
|
||||
},
|
||||
"GlossSee": "markup"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{"menu": {
|
||||
"id": "file",
|
||||
"value": "File",
|
||||
"popup": {
|
||||
"menuitem": [
|
||||
{"value": "New", "onclick": "CreateNewDoc()"},
|
||||
{"value": "Open", "onclick": "OpenDoc()"},
|
||||
{"value": "Close", "onclick": "CloseDoc()"}
|
||||
]
|
||||
}
|
||||
}}
|
||||
@@ -1,26 +0,0 @@
|
||||
{"widget": {
|
||||
"debug": "on",
|
||||
"window": {
|
||||
"title": "Sample Konfabulator Widget",
|
||||
"name": "main_window",
|
||||
"width": 500,
|
||||
"height": 500
|
||||
},
|
||||
"image": {
|
||||
"src": "Images/Sun.png",
|
||||
"name": "sun1",
|
||||
"hOffset": 250,
|
||||
"vOffset": 250,
|
||||
"alignment": "center"
|
||||
},
|
||||
"text": {
|
||||
"data": "Click Here",
|
||||
"size": 36,
|
||||
"style": "bold",
|
||||
"name": "text1",
|
||||
"hOffset": 250,
|
||||
"vOffset": 100,
|
||||
"alignment": "center",
|
||||
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
|
||||
}
|
||||
}}
|
||||
@@ -1,88 +0,0 @@
|
||||
{"web-app": {
|
||||
"servlet": [
|
||||
{
|
||||
"servlet-name": "cofaxCDS",
|
||||
"servlet-class": "org.cofax.cds.CDSServlet",
|
||||
"init-param": {
|
||||
"configGlossary:installationAt": "Philadelphia, PA",
|
||||
"configGlossary:adminEmail": "ksm@pobox.com",
|
||||
"configGlossary:poweredBy": "Cofax",
|
||||
"configGlossary:poweredByIcon": "/images/cofax.gif",
|
||||
"configGlossary:staticPath": "/content/static",
|
||||
"templateProcessorClass": "org.cofax.WysiwygTemplate",
|
||||
"templateLoaderClass": "org.cofax.FilesTemplateLoader",
|
||||
"templatePath": "templates",
|
||||
"templateOverridePath": "",
|
||||
"defaultListTemplate": "listTemplate.htm",
|
||||
"defaultFileTemplate": "articleTemplate.htm",
|
||||
"useJSP": false,
|
||||
"jspListTemplate": "listTemplate.jsp",
|
||||
"jspFileTemplate": "articleTemplate.jsp",
|
||||
"cachePackageTagsTrack": 200,
|
||||
"cachePackageTagsStore": 200,
|
||||
"cachePackageTagsRefresh": 60,
|
||||
"cacheTemplatesTrack": 100,
|
||||
"cacheTemplatesStore": 50,
|
||||
"cacheTemplatesRefresh": 15,
|
||||
"cachePagesTrack": 200,
|
||||
"cachePagesStore": 100,
|
||||
"cachePagesRefresh": 10,
|
||||
"cachePagesDirtyRead": 10,
|
||||
"searchEngineListTemplate": "forSearchEnginesList.htm",
|
||||
"searchEngineFileTemplate": "forSearchEngines.htm",
|
||||
"searchEngineRobotsDb": "WEB-INF/robots.db",
|
||||
"useDataStore": true,
|
||||
"dataStoreClass": "org.cofax.SqlDataStore",
|
||||
"redirectionClass": "org.cofax.SqlRedirection",
|
||||
"dataStoreName": "cofax",
|
||||
"dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver",
|
||||
"dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon",
|
||||
"dataStoreUser": "sa",
|
||||
"dataStorePassword": "dataStoreTestQuery",
|
||||
"dataStoreTestQuery": "SET NOCOUNT ON;select test='test';",
|
||||
"dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log",
|
||||
"dataStoreInitConns": 10,
|
||||
"dataStoreMaxConns": 100,
|
||||
"dataStoreConnUsageLimit": 100,
|
||||
"dataStoreLogLevel": "debug",
|
||||
"maxUrlLength": 500}},
|
||||
{
|
||||
"servlet-name": "cofaxEmail",
|
||||
"servlet-class": "org.cofax.cds.EmailServlet",
|
||||
"init-param": {
|
||||
"mailHost": "mail1",
|
||||
"mailHostOverride": "mail2"}},
|
||||
{
|
||||
"servlet-name": "cofaxAdmin",
|
||||
"servlet-class": "org.cofax.cds.AdminServlet"},
|
||||
|
||||
{
|
||||
"servlet-name": "fileServlet",
|
||||
"servlet-class": "org.cofax.cds.FileServlet"},
|
||||
{
|
||||
"servlet-name": "cofaxTools",
|
||||
"servlet-class": "org.cofax.cms.CofaxToolsServlet",
|
||||
"init-param": {
|
||||
"templatePath": "toolstemplates/",
|
||||
"log": 1,
|
||||
"logLocation": "/usr/local/tomcat/logs/CofaxTools.log",
|
||||
"logMaxSize": "",
|
||||
"dataLog": 1,
|
||||
"dataLogLocation": "/usr/local/tomcat/logs/dataLog.log",
|
||||
"dataLogMaxSize": "",
|
||||
"removePageCache": "/content/admin/remove?cache=pages&id=",
|
||||
"removeTemplateCache": "/content/admin/remove?cache=templates&id=",
|
||||
"fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder",
|
||||
"lookInContext": 1,
|
||||
"adminGroupID": 4,
|
||||
"betaServer": true}}],
|
||||
"servlet-mapping": {
|
||||
"cofaxCDS": "/",
|
||||
"cofaxEmail": "/cofaxutil/aemail/*",
|
||||
"cofaxAdmin": "/admin/*",
|
||||
"fileServlet": "/static/*",
|
||||
"cofaxTools": "/tools/*"},
|
||||
|
||||
"taglib": {
|
||||
"taglib-uri": "cofax.tld",
|
||||
"taglib-location": "/WEB-INF/tlds/cofax.tld"}}}
|
||||
@@ -1,27 +0,0 @@
|
||||
{"menu": {
|
||||
"header": "SVG Viewer",
|
||||
"items": [
|
||||
{"id": "Open"},
|
||||
{"id": "OpenNew", "label": "Open New"},
|
||||
null,
|
||||
{"id": "ZoomIn", "label": "Zoom In"},
|
||||
{"id": "ZoomOut", "label": "Zoom Out"},
|
||||
{"id": "OriginalView", "label": "Original View"},
|
||||
null,
|
||||
{"id": "Quality"},
|
||||
{"id": "Pause"},
|
||||
{"id": "Mute"},
|
||||
null,
|
||||
{"id": "Find", "label": "Find..."},
|
||||
{"id": "FindAgain", "label": "Find Again"},
|
||||
{"id": "Copy"},
|
||||
{"id": "CopyAgain", "label": "Copy Again"},
|
||||
{"id": "CopySVG", "label": "Copy SVG"},
|
||||
{"id": "ViewSVG", "label": "View SVG"},
|
||||
{"id": "ViewSource", "label": "View Source"},
|
||||
{"id": "SaveAs", "label": "Save As"},
|
||||
null,
|
||||
{"id": "Help"},
|
||||
{"id": "About", "label": "About Adobe CVG Viewer..."}
|
||||
]
|
||||
}}
|
||||
@@ -1,23 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
# Create test comparison data using a different UTF-8 implementation.
|
||||
|
||||
# The generated utf8.dat file must have the following MD5 sum:
|
||||
# cff03b039d850f370a7362f3313e5268
|
||||
|
||||
use strict;
|
||||
|
||||
# 0xD800 - 0xDFFF are used to encode supplementary codepoints
|
||||
# 0x10000 - 0x10FFFF are supplementary codepoints
|
||||
my (@codepoints) = (0 .. 0xD7FF, 0xE000 .. 0x10FFFF);
|
||||
|
||||
my $utf8 = pack("U*", @codepoints);
|
||||
defined($utf8) or die "Unable create UTF-8 string\n";
|
||||
|
||||
open(FH, ">:utf8", "utf8.dat")
|
||||
or die "Unable to open utf8.dat: $!\n";
|
||||
print FH $utf8
|
||||
or die "Unable to write utf8.dat\n";
|
||||
close(FH);
|
||||
|
||||
# vi:ai et sw=4 ts=4:
|
||||
@@ -1,7 +0,0 @@
|
||||
[ 0.110001,
|
||||
0.12345678910111,
|
||||
0.412454033640,
|
||||
2.6651441426902,
|
||||
2.718281828459,
|
||||
3.1415926535898,
|
||||
2.1406926327793 ]
|
||||
@@ -1 +0,0 @@
|
||||
"\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !\"#$%&'()*+,-.\/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u007f€亗儎厗噲墛媽崕彁憭摂晼棙櫄洔潪煚、¥ウЖ┆<D096><E29486><EFBFBD>辈炒刀犯购患骄坷谅媚牌侨墒颂臀闲岩釉罩棕仝圮蒉哙徕沅彐玷殛腱眍镳耱篝貊鼬<E8B28A><E9BCAC><EFBFBD><EFBFBD>"
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"Image": {
|
||||
"Width": 800,
|
||||
"Height": 600,
|
||||
"Title": "View from 15th Floor",
|
||||
"Thumbnail": {
|
||||
"Url": "http://www.example.com/image/481989943",
|
||||
"Height": 125,
|
||||
"Width": "100"
|
||||
},
|
||||
"IDs": [116, 943, 234, 38793]
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
[
|
||||
{
|
||||
"precision": "zip",
|
||||
"Latitude": 37.7668,
|
||||
"Longitude": -122.3959,
|
||||
"Address": "",
|
||||
"City": "SAN FRANCISCO",
|
||||
"State": "CA",
|
||||
"Zip": "94107",
|
||||
"Country": "US"
|
||||
},
|
||||
{
|
||||
"precision": "zip",
|
||||
"Latitude": 37.371991,
|
||||
"Longitude": -122.026020,
|
||||
"Address": "",
|
||||
"City": "SUNNYVALE",
|
||||
"State": "CA",
|
||||
"Zip": "94085",
|
||||
"Country": "US"
|
||||
}
|
||||
]
|
||||
@@ -1,423 +0,0 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
-- Lua CJSON tests
|
||||
--
|
||||
-- Mark Pulford <mark@kyne.com.au>
|
||||
--
|
||||
-- Note: The output of this script is easier to read with "less -S"
|
||||
|
||||
local json = require "cjson"
|
||||
local json_safe = require "cjson.safe"
|
||||
local util = require "cjson.util"
|
||||
|
||||
local function gen_raw_octets()
|
||||
local chars = {}
|
||||
for i = 0, 255 do chars[i + 1] = string.char(i) end
|
||||
return table.concat(chars)
|
||||
end
|
||||
|
||||
-- Generate every UTF-16 codepoint, including supplementary codes
|
||||
local function gen_utf16_escaped()
|
||||
-- Create raw table escapes
|
||||
local utf16_escaped = {}
|
||||
local count = 0
|
||||
|
||||
local function append_escape(code)
|
||||
local esc = ('\\u%04X'):format(code)
|
||||
table.insert(utf16_escaped, esc)
|
||||
end
|
||||
|
||||
table.insert(utf16_escaped, '"')
|
||||
for i = 0, 0xD7FF do
|
||||
append_escape(i)
|
||||
end
|
||||
-- Skip 0xD800 - 0xDFFF since they are used to encode supplementary
|
||||
-- codepoints
|
||||
for i = 0xE000, 0xFFFF do
|
||||
append_escape(i)
|
||||
end
|
||||
-- Append surrogate pair for each supplementary codepoint
|
||||
for high = 0xD800, 0xDBFF do
|
||||
for low = 0xDC00, 0xDFFF do
|
||||
append_escape(high)
|
||||
append_escape(low)
|
||||
end
|
||||
end
|
||||
table.insert(utf16_escaped, '"')
|
||||
|
||||
return table.concat(utf16_escaped)
|
||||
end
|
||||
|
||||
function load_testdata()
|
||||
local data = {}
|
||||
|
||||
-- Data for 8bit raw <-> escaped octets tests
|
||||
data.octets_raw = gen_raw_octets()
|
||||
data.octets_escaped = util.file_load("octets-escaped.dat")
|
||||
|
||||
-- Data for \uXXXX -> UTF-8 test
|
||||
data.utf16_escaped = gen_utf16_escaped()
|
||||
|
||||
-- Load matching data for utf16_escaped
|
||||
local utf8_loaded
|
||||
utf8_loaded, data.utf8_raw = pcall(util.file_load, "utf8.dat")
|
||||
if not utf8_loaded then
|
||||
data.utf8_raw = "Failed to load utf8.dat - please run genutf8.pl"
|
||||
end
|
||||
|
||||
data.table_cycle = {}
|
||||
data.table_cycle[1] = data.table_cycle
|
||||
|
||||
local big = {}
|
||||
for i = 1, 1100 do
|
||||
big = { { 10, false, true, json.null }, "string", a = big }
|
||||
end
|
||||
data.deeply_nested_data = big
|
||||
|
||||
return data
|
||||
end
|
||||
|
||||
function test_decode_cycle(filename)
|
||||
local obj1 = json.decode(util.file_load(filename))
|
||||
local obj2 = json.decode(json.encode(obj1))
|
||||
return util.compare_values(obj1, obj2)
|
||||
end
|
||||
|
||||
-- Set up data used in tests
|
||||
local Inf = math.huge;
|
||||
local NaN = math.huge * 0;
|
||||
|
||||
local testdata = load_testdata()
|
||||
|
||||
local cjson_tests = {
|
||||
-- Test API variables
|
||||
{ "Check module name, version",
|
||||
function () return json._NAME, json._VERSION end, { },
|
||||
true, { "cjson", "2.1.0" } },
|
||||
|
||||
-- Test decoding simple types
|
||||
{ "Decode string",
|
||||
json.decode, { '"test string"' }, true, { "test string" } },
|
||||
{ "Decode numbers",
|
||||
json.decode, { '[ 0.0, -5e3, -1, 0.3e-3, 1023.2, 0e10 ]' },
|
||||
true, { { 0.0, -5000, -1, 0.0003, 1023.2, 0 } } },
|
||||
{ "Decode null",
|
||||
json.decode, { 'null' }, true, { json.null } },
|
||||
{ "Decode true",
|
||||
json.decode, { 'true' }, true, { true } },
|
||||
{ "Decode false",
|
||||
json.decode, { 'false' }, true, { false } },
|
||||
{ "Decode object with numeric keys",
|
||||
json.decode, { '{ "1": "one", "3": "three" }' },
|
||||
true, { { ["1"] = "one", ["3"] = "three" } } },
|
||||
{ "Decode object with string keys",
|
||||
json.decode, { '{ "a": "a", "b": "b" }' },
|
||||
true, { { a = "a", b = "b" } } },
|
||||
{ "Decode array",
|
||||
json.decode, { '[ "one", null, "three" ]' },
|
||||
true, { { "one", json.null, "three" } } },
|
||||
|
||||
-- Test decoding errors
|
||||
{ "Decode UTF-16BE [throw error]",
|
||||
json.decode, { '\0"\0"' },
|
||||
false, { "JSON parser does not support UTF-16 or UTF-32" } },
|
||||
{ "Decode UTF-16LE [throw error]",
|
||||
json.decode, { '"\0"\0' },
|
||||
false, { "JSON parser does not support UTF-16 or UTF-32" } },
|
||||
{ "Decode UTF-32BE [throw error]",
|
||||
json.decode, { '\0\0\0"' },
|
||||
false, { "JSON parser does not support UTF-16 or UTF-32" } },
|
||||
{ "Decode UTF-32LE [throw error]",
|
||||
json.decode, { '"\0\0\0' },
|
||||
false, { "JSON parser does not support UTF-16 or UTF-32" } },
|
||||
{ "Decode partial JSON [throw error]",
|
||||
json.decode, { '{ "unexpected eof": ' },
|
||||
false, { "Expected value but found T_END at character 21" } },
|
||||
{ "Decode with extra comma [throw error]",
|
||||
json.decode, { '{ "extra data": true }, false' },
|
||||
false, { "Expected the end but found T_COMMA at character 23" } },
|
||||
{ "Decode invalid escape code [throw error]",
|
||||
json.decode, { [[ { "bad escape \q code" } ]] },
|
||||
false, { "Expected object key string but found invalid escape code at character 16" } },
|
||||
{ "Decode invalid unicode escape [throw error]",
|
||||
json.decode, { [[ { "bad unicode \u0f6 escape" } ]] },
|
||||
false, { "Expected object key string but found invalid unicode escape code at character 17" } },
|
||||
{ "Decode invalid keyword [throw error]",
|
||||
json.decode, { ' [ "bad barewood", test ] ' },
|
||||
false, { "Expected value but found invalid token at character 20" } },
|
||||
{ "Decode invalid number #1 [throw error]",
|
||||
json.decode, { '[ -+12 ]' },
|
||||
false, { "Expected value but found invalid number at character 3" } },
|
||||
{ "Decode invalid number #2 [throw error]",
|
||||
json.decode, { '-v' },
|
||||
false, { "Expected value but found invalid number at character 1" } },
|
||||
{ "Decode invalid number exponent [throw error]",
|
||||
json.decode, { '[ 0.4eg10 ]' },
|
||||
false, { "Expected comma or array end but found invalid token at character 6" } },
|
||||
|
||||
-- Test decoding nested arrays / objects
|
||||
{ "Set decode_max_depth(5)",
|
||||
json.decode_max_depth, { 5 }, true, { 5 } },
|
||||
{ "Decode array at nested limit",
|
||||
json.decode, { '[[[[[ "nested" ]]]]]' },
|
||||
true, { {{{{{ "nested" }}}}} } },
|
||||
{ "Decode array over nested limit [throw error]",
|
||||
json.decode, { '[[[[[[ "nested" ]]]]]]' },
|
||||
false, { "Found too many nested data structures (6) at character 6" } },
|
||||
{ "Decode object at nested limit",
|
||||
json.decode, { '{"a":{"b":{"c":{"d":{"e":"nested"}}}}}' },
|
||||
true, { {a={b={c={d={e="nested"}}}}} } },
|
||||
{ "Decode object over nested limit [throw error]",
|
||||
json.decode, { '{"a":{"b":{"c":{"d":{"e":{"f":"nested"}}}}}}' },
|
||||
false, { "Found too many nested data structures (6) at character 26" } },
|
||||
{ "Set decode_max_depth(1000)",
|
||||
json.decode_max_depth, { 1000 }, true, { 1000 } },
|
||||
{ "Decode deeply nested array [throw error]",
|
||||
json.decode, { string.rep("[", 1100) .. '1100' .. string.rep("]", 1100)},
|
||||
false, { "Found too many nested data structures (1001) at character 1001" } },
|
||||
|
||||
-- Test encoding nested tables
|
||||
{ "Set encode_max_depth(5)",
|
||||
json.encode_max_depth, { 5 }, true, { 5 } },
|
||||
{ "Encode nested table as array at nested limit",
|
||||
json.encode, { {{{{{"nested"}}}}} }, true, { '[[[[["nested"]]]]]' } },
|
||||
{ "Encode nested table as array after nested limit [throw error]",
|
||||
json.encode, { { {{{{{"nested"}}}}} } },
|
||||
false, { "Cannot serialise, excessive nesting (6)" } },
|
||||
{ "Encode nested table as object at nested limit",
|
||||
json.encode, { {a={b={c={d={e="nested"}}}}} },
|
||||
true, { '{"a":{"b":{"c":{"d":{"e":"nested"}}}}}' } },
|
||||
{ "Encode nested table as object over nested limit [throw error]",
|
||||
json.encode, { {a={b={c={d={e={f="nested"}}}}}} },
|
||||
false, { "Cannot serialise, excessive nesting (6)" } },
|
||||
{ "Encode table with cycle [throw error]",
|
||||
json.encode, { testdata.table_cycle },
|
||||
false, { "Cannot serialise, excessive nesting (6)" } },
|
||||
{ "Set encode_max_depth(1000)",
|
||||
json.encode_max_depth, { 1000 }, true, { 1000 } },
|
||||
{ "Encode deeply nested data [throw error]",
|
||||
json.encode, { testdata.deeply_nested_data },
|
||||
false, { "Cannot serialise, excessive nesting (1001)" } },
|
||||
|
||||
-- Test encoding simple types
|
||||
{ "Encode null",
|
||||
json.encode, { json.null }, true, { 'null' } },
|
||||
{ "Encode true",
|
||||
json.encode, { true }, true, { 'true' } },
|
||||
{ "Encode false",
|
||||
json.encode, { false }, true, { 'false' } },
|
||||
{ "Encode empty object",
|
||||
json.encode, { { } }, true, { '{}' } },
|
||||
{ "Encode integer",
|
||||
json.encode, { 10 }, true, { '10' } },
|
||||
{ "Encode string",
|
||||
json.encode, { "hello" }, true, { '"hello"' } },
|
||||
{ "Encode Lua function [throw error]",
|
||||
json.encode, { function () end },
|
||||
false, { "Cannot serialise function: type not supported" } },
|
||||
|
||||
-- Test decoding invalid numbers
|
||||
{ "Set decode_invalid_numbers(true)",
|
||||
json.decode_invalid_numbers, { true }, true, { true } },
|
||||
{ "Decode hexadecimal",
|
||||
json.decode, { '0x6.ffp1' }, true, { 13.9921875 } },
|
||||
{ "Decode numbers with leading zero",
|
||||
json.decode, { '[ 0123, 00.33 ]' }, true, { { 123, 0.33 } } },
|
||||
{ "Decode +-Inf",
|
||||
json.decode, { '[ +Inf, Inf, -Inf ]' }, true, { { Inf, Inf, -Inf } } },
|
||||
{ "Decode +-Infinity",
|
||||
json.decode, { '[ +Infinity, Infinity, -Infinity ]' },
|
||||
true, { { Inf, Inf, -Inf } } },
|
||||
{ "Decode +-NaN",
|
||||
json.decode, { '[ +NaN, NaN, -NaN ]' }, true, { { NaN, NaN, NaN } } },
|
||||
{ "Decode Infrared (not infinity) [throw error]",
|
||||
json.decode, { 'Infrared' },
|
||||
false, { "Expected the end but found invalid token at character 4" } },
|
||||
{ "Decode Noodle (not NaN) [throw error]",
|
||||
json.decode, { 'Noodle' },
|
||||
false, { "Expected value but found invalid token at character 1" } },
|
||||
{ "Set decode_invalid_numbers(false)",
|
||||
json.decode_invalid_numbers, { false }, true, { false } },
|
||||
{ "Decode hexadecimal [throw error]",
|
||||
json.decode, { '0x6' },
|
||||
false, { "Expected value but found invalid number at character 1" } },
|
||||
{ "Decode numbers with leading zero [throw error]",
|
||||
json.decode, { '[ 0123, 00.33 ]' },
|
||||
false, { "Expected value but found invalid number at character 3" } },
|
||||
{ "Decode +-Inf [throw error]",
|
||||
json.decode, { '[ +Inf, Inf, -Inf ]' },
|
||||
false, { "Expected value but found invalid token at character 3" } },
|
||||
{ "Decode +-Infinity [throw error]",
|
||||
json.decode, { '[ +Infinity, Infinity, -Infinity ]' },
|
||||
false, { "Expected value but found invalid token at character 3" } },
|
||||
{ "Decode +-NaN [throw error]",
|
||||
json.decode, { '[ +NaN, NaN, -NaN ]' },
|
||||
false, { "Expected value but found invalid token at character 3" } },
|
||||
{ 'Set decode_invalid_numbers("on")',
|
||||
json.decode_invalid_numbers, { "on" }, true, { true } },
|
||||
|
||||
-- Test encoding invalid numbers
|
||||
{ "Set encode_invalid_numbers(false)",
|
||||
json.encode_invalid_numbers, { false }, true, { false } },
|
||||
{ "Encode NaN [throw error]",
|
||||
json.encode, { NaN },
|
||||
false, { "Cannot serialise number: must not be NaN or Inf" } },
|
||||
{ "Encode Infinity [throw error]",
|
||||
json.encode, { Inf },
|
||||
false, { "Cannot serialise number: must not be NaN or Inf" } },
|
||||
{ "Set encode_invalid_numbers(\"null\")",
|
||||
json.encode_invalid_numbers, { "null" }, true, { "null" } },
|
||||
{ "Encode NaN as null",
|
||||
json.encode, { NaN }, true, { "null" } },
|
||||
{ "Encode Infinity as null",
|
||||
json.encode, { Inf }, true, { "null" } },
|
||||
{ "Set encode_invalid_numbers(true)",
|
||||
json.encode_invalid_numbers, { true }, true, { true } },
|
||||
{ "Encode NaN",
|
||||
json.encode, { NaN }, true, { "nan" } },
|
||||
{ "Encode Infinity",
|
||||
json.encode, { Inf }, true, { "inf" } },
|
||||
{ 'Set encode_invalid_numbers("off")',
|
||||
json.encode_invalid_numbers, { "off" }, true, { false } },
|
||||
|
||||
-- Test encoding tables
|
||||
{ "Set encode_sparse_array(true, 2, 3)",
|
||||
json.encode_sparse_array, { true, 2, 3 }, true, { true, 2, 3 } },
|
||||
{ "Encode sparse table as array #1",
|
||||
json.encode, { { [3] = "sparse test" } },
|
||||
true, { '[null,null,"sparse test"]' } },
|
||||
{ "Encode sparse table as array #2",
|
||||
json.encode, { { [1] = "one", [4] = "sparse test" } },
|
||||
true, { '["one",null,null,"sparse test"]' } },
|
||||
{ "Encode sparse array as object",
|
||||
json.encode, { { [1] = "one", [5] = "sparse test" } },
|
||||
true, { '{"1":"one","5":"sparse test"}' } },
|
||||
{ "Encode table with numeric string key as object",
|
||||
json.encode, { { ["2"] = "numeric string key test" } },
|
||||
true, { '{"2":"numeric string key test"}' } },
|
||||
{ "Set encode_sparse_array(false)",
|
||||
json.encode_sparse_array, { false }, true, { false, 2, 3 } },
|
||||
{ "Encode table with incompatible key [throw error]",
|
||||
json.encode, { { [false] = "wrong" } },
|
||||
false, { "Cannot serialise boolean: table key must be a number or string" } },
|
||||
|
||||
-- Test escaping
|
||||
{ "Encode all octets (8-bit clean)",
|
||||
json.encode, { testdata.octets_raw }, true, { testdata.octets_escaped } },
|
||||
{ "Decode all escaped octets",
|
||||
json.decode, { testdata.octets_escaped }, true, { testdata.octets_raw } },
|
||||
{ "Decode single UTF-16 escape",
|
||||
json.decode, { [["\uF800"]] }, true, { "\239\160\128" } },
|
||||
{ "Decode all UTF-16 escapes (including surrogate combinations)",
|
||||
json.decode, { testdata.utf16_escaped }, true, { testdata.utf8_raw } },
|
||||
{ "Decode swapped surrogate pair [throw error]",
|
||||
json.decode, { [["\uDC00\uD800"]] },
|
||||
false, { "Expected value but found invalid unicode escape code at character 2" } },
|
||||
{ "Decode duplicate high surrogate [throw error]",
|
||||
json.decode, { [["\uDB00\uDB00"]] },
|
||||
false, { "Expected value but found invalid unicode escape code at character 2" } },
|
||||
{ "Decode duplicate low surrogate [throw error]",
|
||||
json.decode, { [["\uDB00\uDB00"]] },
|
||||
false, { "Expected value but found invalid unicode escape code at character 2" } },
|
||||
{ "Decode missing low surrogate [throw error]",
|
||||
json.decode, { [["\uDB00"]] },
|
||||
false, { "Expected value but found invalid unicode escape code at character 2" } },
|
||||
{ "Decode invalid low surrogate [throw error]",
|
||||
json.decode, { [["\uDB00\uD"]] },
|
||||
false, { "Expected value but found invalid unicode escape code at character 2" } },
|
||||
|
||||
-- Test locale support
|
||||
--
|
||||
-- The standard Lua interpreter is ANSI C online doesn't support locales
|
||||
-- by default. Force a known problematic locale to test strtod()/sprintf().
|
||||
{ "Set locale to cs_CZ (comma separator)", function ()
|
||||
os.setlocale("cs_CZ")
|
||||
json.new()
|
||||
end },
|
||||
{ "Encode number under comma locale",
|
||||
json.encode, { 1.5 }, true, { '1.5' } },
|
||||
{ "Decode number in array under comma locale",
|
||||
json.decode, { '[ 10, "test" ]' }, true, { { 10, "test" } } },
|
||||
{ "Revert locale to POSIX", function ()
|
||||
os.setlocale("C")
|
||||
json.new()
|
||||
end },
|
||||
|
||||
-- Test encode_keep_buffer() and enable_number_precision()
|
||||
{ "Set encode_keep_buffer(false)",
|
||||
json.encode_keep_buffer, { false }, true, { false } },
|
||||
{ "Set encode_number_precision(3)",
|
||||
json.encode_number_precision, { 3 }, true, { 3 } },
|
||||
{ "Encode number with precision 3",
|
||||
json.encode, { 1/3 }, true, { "0.333" } },
|
||||
{ "Set encode_number_precision(14)",
|
||||
json.encode_number_precision, { 14 }, true, { 14 } },
|
||||
{ "Set encode_keep_buffer(true)",
|
||||
json.encode_keep_buffer, { true }, true, { true } },
|
||||
|
||||
-- Test config API errors
|
||||
-- Function is listed as '?' due to pcall
|
||||
{ "Set encode_number_precision(0) [throw error]",
|
||||
json.encode_number_precision, { 0 },
|
||||
false, { "bad argument #1 to '?' (expected integer between 1 and 14)" } },
|
||||
{ "Set encode_number_precision(\"five\") [throw error]",
|
||||
json.encode_number_precision, { "five" },
|
||||
false, { "bad argument #1 to '?' (number expected, got string)" } },
|
||||
{ "Set encode_keep_buffer(nil, true) [throw error]",
|
||||
json.encode_keep_buffer, { nil, true },
|
||||
false, { "bad argument #2 to '?' (found too many arguments)" } },
|
||||
{ "Set encode_max_depth(\"wrong\") [throw error]",
|
||||
json.encode_max_depth, { "wrong" },
|
||||
false, { "bad argument #1 to '?' (number expected, got string)" } },
|
||||
{ "Set decode_max_depth(0) [throw error]",
|
||||
json.decode_max_depth, { "0" },
|
||||
false, { "bad argument #1 to '?' (expected integer between 1 and 2147483647)" } },
|
||||
{ "Set encode_invalid_numbers(-2) [throw error]",
|
||||
json.encode_invalid_numbers, { -2 },
|
||||
false, { "bad argument #1 to '?' (invalid option '-2')" } },
|
||||
{ "Set decode_invalid_numbers(true, false) [throw error]",
|
||||
json.decode_invalid_numbers, { true, false },
|
||||
false, { "bad argument #2 to '?' (found too many arguments)" } },
|
||||
{ "Set encode_sparse_array(\"not quite on\") [throw error]",
|
||||
json.encode_sparse_array, { "not quite on" },
|
||||
false, { "bad argument #1 to '?' (invalid option 'not quite on')" } },
|
||||
|
||||
{ "Reset Lua CJSON configuration", function () json = json.new() end },
|
||||
-- Wrap in a function to ensure the table returned by json.new() is used
|
||||
{ "Check encode_sparse_array()",
|
||||
function (...) return json.encode_sparse_array(...) end, { },
|
||||
true, { false, 2, 10 } },
|
||||
|
||||
{ "Encode (safe) simple value",
|
||||
json_safe.encode, { true },
|
||||
true, { "true" } },
|
||||
{ "Encode (safe) argument validation [throw error]",
|
||||
json_safe.encode, { "arg1", "arg2" },
|
||||
false, { "bad argument #1 to '?' (expected 1 argument)" } },
|
||||
{ "Decode (safe) error generation",
|
||||
json_safe.decode, { "Oops" },
|
||||
true, { nil, "Expected value but found invalid token at character 1" } },
|
||||
{ "Decode (safe) error generation after new()",
|
||||
function(...) return json_safe.new().decode(...) end, { "Oops" },
|
||||
true, { nil, "Expected value but found invalid token at character 1" } },
|
||||
}
|
||||
|
||||
print(("==> Testing Lua CJSON version %s\n"):format(json._VERSION))
|
||||
|
||||
util.run_test_group(cjson_tests)
|
||||
|
||||
for _, filename in ipairs(arg) do
|
||||
util.run_test("Decode cycle " .. filename, test_decode_cycle, { filename },
|
||||
true, { true })
|
||||
end
|
||||
|
||||
local pass, total = util.run_test_summary()
|
||||
|
||||
if pass == total then
|
||||
print("==> Summary: all tests succeeded")
|
||||
else
|
||||
print(("==> Summary: %d/%d tests failed"):format(total - pass, total))
|
||||
os.exit(1)
|
||||
end
|
||||
|
||||
-- vi:ai et sw=4 ts=4:
|
||||
@@ -1 +0,0 @@
|
||||
{ "array": [ 10, true, null ] }
|
||||
@@ -1,6 +0,0 @@
|
||||
install :
|
||||
gcc -g -Wall -fPIC --shared -o int64.so int64.c
|
||||
|
||||
clean :
|
||||
rm int64.so
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
See https://github.com/cloudwu/lua-int64
|
||||
It will remove when Lua upgrade to 5.3 .
|
||||
@@ -1,317 +0,0 @@
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
static int64_t
|
||||
_int64(lua_State *L, int index) {
|
||||
int type = lua_type(L,index);
|
||||
int64_t n = 0;
|
||||
switch(type) {
|
||||
case LUA_TNUMBER: {
|
||||
lua_Number d = lua_tonumber(L,index);
|
||||
n = (int64_t)d;
|
||||
break;
|
||||
}
|
||||
case LUA_TSTRING: {
|
||||
size_t len = 0;
|
||||
const uint8_t * str = (const uint8_t *)lua_tolstring(L, index, &len);
|
||||
if (len>8) {
|
||||
return luaL_error(L, "The string (length = %d) is not an int64 string", len);
|
||||
}
|
||||
int i = 0;
|
||||
uint64_t n64 = 0;
|
||||
for (i=0;i<(int)len;i++) {
|
||||
n64 |= (uint64_t)str[i] << (i*8);
|
||||
}
|
||||
n = (int64_t)n64;
|
||||
break;
|
||||
}
|
||||
case LUA_TLIGHTUSERDATA: {
|
||||
void * p = lua_touserdata(L,index);
|
||||
n = (intptr_t)p;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return luaL_error(L, "argument %d error type %s", index, lua_typename(L,type));
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_pushint64(lua_State *L, int64_t n) {
|
||||
void * p = (void *)(intptr_t)n;
|
||||
lua_pushlightuserdata(L,p);
|
||||
}
|
||||
|
||||
static int
|
||||
int64_add(lua_State *L) {
|
||||
int64_t a = _int64(L,1);
|
||||
int64_t b = _int64(L,2);
|
||||
_pushint64(L, a+b);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
int64_sub(lua_State *L) {
|
||||
int64_t a = _int64(L,1);
|
||||
int64_t b = _int64(L,2);
|
||||
_pushint64(L, a-b);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
int64_mul(lua_State *L) {
|
||||
int64_t a = _int64(L,1);
|
||||
int64_t b = _int64(L,2);
|
||||
_pushint64(L, a * b);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
int64_div(lua_State *L) {
|
||||
int64_t a = _int64(L,1);
|
||||
int64_t b = _int64(L,2);
|
||||
if (b == 0) {
|
||||
return luaL_error(L, "div by zero");
|
||||
}
|
||||
_pushint64(L, a / b);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
int64_mod(lua_State *L) {
|
||||
int64_t a = _int64(L,1);
|
||||
int64_t b = _int64(L,2);
|
||||
if (b == 0) {
|
||||
return luaL_error(L, "mod by zero");
|
||||
}
|
||||
_pushint64(L, a % b);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int64_t
|
||||
_pow64(int64_t a, int64_t b) {
|
||||
if (b == 1) {
|
||||
return a;
|
||||
}
|
||||
int64_t a2 = a * a;
|
||||
if (b % 2 == 1) {
|
||||
return _pow64(a2, b/2) * a;
|
||||
} else {
|
||||
return _pow64(a2, b/2);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
int64_pow(lua_State *L) {
|
||||
int64_t a = _int64(L,1);
|
||||
int64_t b = _int64(L,2);
|
||||
int64_t p;
|
||||
if (b > 0) {
|
||||
p = _pow64(a,b);
|
||||
} else if (b == 0) {
|
||||
p = 1;
|
||||
} else {
|
||||
return luaL_error(L, "pow by nagtive number %d",(int)b);
|
||||
}
|
||||
_pushint64(L, p);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
int64_unm(lua_State *L) {
|
||||
int64_t a = _int64(L,1);
|
||||
_pushint64(L, -a);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
int64_new(lua_State *L) {
|
||||
int top = lua_gettop(L);
|
||||
int64_t n;
|
||||
switch(top) {
|
||||
case 0 :
|
||||
lua_pushlightuserdata(L,NULL);
|
||||
break;
|
||||
case 1 :
|
||||
n = _int64(L,1);
|
||||
_pushint64(L,n);
|
||||
break;
|
||||
default: {
|
||||
int base = luaL_checkinteger(L,2);
|
||||
if (base < 2) {
|
||||
luaL_error(L, "base must be >= 2");
|
||||
}
|
||||
const char * str = luaL_checkstring(L, 1);
|
||||
n = strtoll(str, NULL, base);
|
||||
_pushint64(L,n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
int64_eq(lua_State *L) {
|
||||
// __eq metamethod can't be invoke by lightuserdata
|
||||
int64_t a = _int64(L,1);
|
||||
int64_t b = _int64(L,2);
|
||||
lua_pushboolean(L,a == b);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
int64_lt(lua_State *L) {
|
||||
int64_t a = _int64(L,1);
|
||||
int64_t b = _int64(L,2);
|
||||
lua_pushboolean(L,a < b);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
int64_le(lua_State *L) {
|
||||
int64_t a = _int64(L,1);
|
||||
int64_t b = _int64(L,2);
|
||||
lua_pushboolean(L,a <= b);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
int64_len(lua_State *L) {
|
||||
int64_t a = _int64(L,1);
|
||||
lua_pushnumber(L,(lua_Number)a);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
tostring(lua_State *L) {
|
||||
static char hex[16] = "0123456789ABCDEF";
|
||||
uintptr_t n = (uintptr_t)lua_touserdata(L,1);
|
||||
if (lua_gettop(L) == 1) {
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L , &b);
|
||||
luaL_addstring(&b, "int64: 0x");
|
||||
int i;
|
||||
bool strip = true;
|
||||
for (i=15;i>=0;i--) {
|
||||
int c = (n >> (i*4)) & 0xf;
|
||||
if (strip && c ==0) {
|
||||
continue;
|
||||
}
|
||||
strip = false;
|
||||
luaL_addchar(&b, hex[c]);
|
||||
}
|
||||
if (strip) {
|
||||
luaL_addchar(&b , '0');
|
||||
}
|
||||
luaL_pushresult(&b);
|
||||
} else {
|
||||
int base = luaL_checkinteger(L,2);
|
||||
int shift =0, mask =0;
|
||||
switch(base) {
|
||||
case 0: {
|
||||
unsigned char buffer[8];
|
||||
int i;
|
||||
for (i=0;i<8;i++) {
|
||||
buffer[i] = (n >> (i*8)) & 0xff;
|
||||
}
|
||||
lua_pushlstring(L,(const char *)buffer, 8);
|
||||
return 1;
|
||||
}
|
||||
case 10: {
|
||||
int64_t dec = (int64_t)n;
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L , &b);
|
||||
if (dec<0) {
|
||||
luaL_addchar(&b, '-');
|
||||
dec = -dec;
|
||||
}
|
||||
int buffer[32];
|
||||
int i;
|
||||
for (i=0;i<32;i++) {
|
||||
buffer[i] = dec%10;
|
||||
dec /= 10;
|
||||
if (dec == 0)
|
||||
break;
|
||||
}
|
||||
while (i>=0) {
|
||||
luaL_addchar(&b, hex[buffer[i]]);
|
||||
--i;
|
||||
}
|
||||
luaL_pushresult(&b);
|
||||
return 1;
|
||||
}
|
||||
case 2:
|
||||
shift = 1;
|
||||
mask = 1;
|
||||
break;
|
||||
case 8:
|
||||
shift = 3;
|
||||
mask = 7;
|
||||
break;
|
||||
case 16:
|
||||
shift = 4;
|
||||
mask = 0xf;
|
||||
break;
|
||||
default:
|
||||
luaL_error(L, "Unsupport base %d",base);
|
||||
break;
|
||||
}
|
||||
int i;
|
||||
char buffer[64];
|
||||
for (i=0;i<64;i+=shift) {
|
||||
buffer[i/shift] = hex[(n>>(64-shift-i)) & mask];
|
||||
}
|
||||
lua_pushlstring(L, buffer, 64 / shift);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
make_mt(lua_State *L) {
|
||||
luaL_Reg lib[] = {
|
||||
{ "__add", int64_add },
|
||||
{ "__sub", int64_sub },
|
||||
{ "__mul", int64_mul },
|
||||
{ "__div", int64_div },
|
||||
{ "__mod", int64_mod },
|
||||
{ "__unm", int64_unm },
|
||||
{ "__pow", int64_pow },
|
||||
{ "__eq", int64_eq },
|
||||
{ "__lt", int64_lt },
|
||||
{ "__le", int64_le },
|
||||
{ "__len", int64_len },
|
||||
{ "__tostring", tostring },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
luaL_newlib(L,lib);
|
||||
}
|
||||
|
||||
int
|
||||
luaopen_int64(lua_State *L) {
|
||||
if (sizeof(intptr_t)!=sizeof(int64_t)) {
|
||||
return luaL_error(L, "Only support 64bit architecture");
|
||||
}
|
||||
lua_pushlightuserdata(L,NULL);
|
||||
make_mt(L);
|
||||
lua_setmetatable(L,-2);
|
||||
lua_pop(L,1);
|
||||
|
||||
lua_newtable(L);
|
||||
lua_pushcfunction(L, int64_new);
|
||||
lua_setfield(L, -2, "new");
|
||||
lua_pushcfunction(L, tostring);
|
||||
lua_setfield(L, -2, "tostring");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
lib = require "int64"
|
||||
|
||||
local int64 = lib.new
|
||||
print(lib.tostring(int64 "\1\2\3\4\5\6\7\8"))
|
||||
|
||||
a = 1 + int64(1)
|
||||
b = int64 "\16" + int64("9",10)
|
||||
print(lib.tostring(a,10), lib.tostring(b,2))
|
||||
print("+", a+b)
|
||||
print("-", lib.tostring(a-b,10))
|
||||
print("*", a*b)
|
||||
print("/", a/b)
|
||||
print("%", a%b)
|
||||
print("^", a^b)
|
||||
print("==", a == b)
|
||||
print(">", a > b)
|
||||
print("#", #a)
|
||||
187
3rd/lua/Makefile
187
3rd/lua/Makefile
@@ -1,187 +0,0 @@
|
||||
# Makefile for building Lua
|
||||
# See ../doc/readme.html for installation and customization instructions.
|
||||
|
||||
# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
|
||||
|
||||
# Your platform. See PLATS for possible values.
|
||||
PLAT= none
|
||||
|
||||
CC= gcc
|
||||
CFLAGS= -O2 -Wall -DLUA_COMPAT_ALL $(SYSCFLAGS) $(MYCFLAGS)
|
||||
LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS)
|
||||
LIBS= -lm $(SYSLIBS) $(MYLIBS)
|
||||
|
||||
AR= ar rcu
|
||||
RANLIB= ranlib
|
||||
RM= rm -f
|
||||
|
||||
SYSCFLAGS=
|
||||
SYSLDFLAGS=
|
||||
SYSLIBS=
|
||||
|
||||
MYCFLAGS=
|
||||
MYLDFLAGS=
|
||||
MYLIBS=
|
||||
MYOBJS=
|
||||
|
||||
# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
|
||||
|
||||
PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris
|
||||
|
||||
LUA_A= liblua.a
|
||||
CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o \
|
||||
lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o \
|
||||
ltm.o lundump.o lvm.o lzio.o
|
||||
LIB_O= lauxlib.o lbaselib.o lbitlib.o lcorolib.o ldblib.o liolib.o \
|
||||
lmathlib.o loslib.o lstrlib.o ltablib.o loadlib.o linit.o
|
||||
BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS)
|
||||
|
||||
LUA_T= lua
|
||||
LUA_O= lua.o
|
||||
|
||||
LUAC_T= luac
|
||||
LUAC_O= luac.o
|
||||
|
||||
ALL_O= $(BASE_O) $(LUA_O) $(LUAC_O)
|
||||
ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)
|
||||
ALL_A= $(LUA_A)
|
||||
|
||||
# Targets start here.
|
||||
default: $(PLAT)
|
||||
|
||||
all: $(ALL_T)
|
||||
|
||||
o: $(ALL_O)
|
||||
|
||||
a: $(ALL_A)
|
||||
|
||||
$(LUA_A): $(BASE_O)
|
||||
$(AR) $@ $(BASE_O)
|
||||
$(RANLIB) $@
|
||||
|
||||
$(LUA_T): $(LUA_O) $(LUA_A)
|
||||
$(CC) -o $@ $(LDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)
|
||||
|
||||
$(LUAC_T): $(LUAC_O) $(LUA_A)
|
||||
$(CC) -o $@ $(LDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS)
|
||||
|
||||
clean:
|
||||
$(RM) $(ALL_T) $(ALL_O)
|
||||
|
||||
depend:
|
||||
@$(CC) $(CFLAGS) -MM l*.c
|
||||
|
||||
echo:
|
||||
@echo "PLAT= $(PLAT)"
|
||||
@echo "CC= $(CC)"
|
||||
@echo "CFLAGS= $(CFLAGS)"
|
||||
@echo "LDFLAGS= $(SYSLDFLAGS)"
|
||||
@echo "LIBS= $(LIBS)"
|
||||
@echo "AR= $(AR)"
|
||||
@echo "RANLIB= $(RANLIB)"
|
||||
@echo "RM= $(RM)"
|
||||
|
||||
# Convenience targets for popular platforms
|
||||
ALL= all
|
||||
|
||||
none:
|
||||
@echo "Please do 'make PLATFORM' where PLATFORM is one of these:"
|
||||
@echo " $(PLATS)"
|
||||
|
||||
aix:
|
||||
$(MAKE) $(ALL) CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" SYSLDFLAGS="-brtl -bexpall"
|
||||
|
||||
ansi:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_ANSI"
|
||||
|
||||
bsd:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-Wl,-E"
|
||||
|
||||
freebsd:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -lreadline"
|
||||
|
||||
generic: $(ALL)
|
||||
|
||||
linux:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline"
|
||||
|
||||
macosx:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline" CC=cc
|
||||
|
||||
mingw:
|
||||
$(MAKE) "LUA_A=lua52.dll" "LUA_T=lua.exe" \
|
||||
"AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \
|
||||
"SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe
|
||||
$(MAKE) "LUAC_T=luac.exe" luac.exe
|
||||
|
||||
posix:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX"
|
||||
|
||||
solaris:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl"
|
||||
|
||||
# list targets that do not create files (but not all makes understand .PHONY)
|
||||
.PHONY: all $(PLATS) default o a clean depend echo none
|
||||
|
||||
# DO NOT DELETE
|
||||
|
||||
lapi.o: lapi.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h ltm.h \
|
||||
lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h ltable.h lundump.h \
|
||||
lvm.h
|
||||
lauxlib.o: lauxlib.c lua.h luaconf.h lauxlib.h
|
||||
lbaselib.o: lbaselib.c lua.h luaconf.h lauxlib.h lualib.h
|
||||
lbitlib.o: lbitlib.c lua.h luaconf.h lauxlib.h lualib.h
|
||||
lcode.o: lcode.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \
|
||||
lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h lgc.h \
|
||||
lstring.h ltable.h lvm.h
|
||||
lcorolib.o: lcorolib.c lua.h luaconf.h lauxlib.h lualib.h
|
||||
lctype.o: lctype.c lctype.h lua.h luaconf.h llimits.h
|
||||
ldblib.o: ldblib.c lua.h luaconf.h lauxlib.h lualib.h
|
||||
ldebug.o: ldebug.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h \
|
||||
ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h ldebug.h ldo.h \
|
||||
lfunc.h lstring.h lgc.h ltable.h lvm.h
|
||||
ldo.o: ldo.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h ltm.h \
|
||||
lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h lparser.h \
|
||||
lstring.h ltable.h lundump.h lvm.h
|
||||
ldump.o: ldump.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h \
|
||||
lzio.h lmem.h lundump.h
|
||||
lfunc.o: lfunc.c lua.h luaconf.h lfunc.h lobject.h llimits.h lgc.h \
|
||||
lstate.h ltm.h lzio.h lmem.h
|
||||
lgc.o: lgc.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
|
||||
lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h
|
||||
linit.o: linit.c lua.h luaconf.h lualib.h lauxlib.h
|
||||
liolib.o: liolib.c lua.h luaconf.h lauxlib.h lualib.h
|
||||
llex.o: llex.c lua.h luaconf.h lctype.h llimits.h ldo.h lobject.h \
|
||||
lstate.h ltm.h lzio.h lmem.h llex.h lparser.h lstring.h lgc.h ltable.h
|
||||
lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h
|
||||
lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
|
||||
ltm.h lzio.h lmem.h ldo.h lgc.h
|
||||
loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h
|
||||
lobject.o: lobject.c lua.h luaconf.h lctype.h llimits.h ldebug.h lstate.h \
|
||||
lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h lvm.h
|
||||
lopcodes.o: lopcodes.c lopcodes.h llimits.h lua.h luaconf.h
|
||||
loslib.o: loslib.c lua.h luaconf.h lauxlib.h lualib.h
|
||||
lparser.o: lparser.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \
|
||||
lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h lfunc.h \
|
||||
lstring.h lgc.h ltable.h
|
||||
lstate.o: lstate.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h \
|
||||
ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h lstring.h \
|
||||
ltable.h
|
||||
lstring.o: lstring.c lua.h luaconf.h lmem.h llimits.h lobject.h lstate.h \
|
||||
ltm.h lzio.h lstring.h lgc.h
|
||||
lstrlib.o: lstrlib.c lua.h luaconf.h lauxlib.h lualib.h
|
||||
ltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
|
||||
ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h
|
||||
ltablib.o: ltablib.c lua.h luaconf.h lauxlib.h lualib.h
|
||||
ltm.o: ltm.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h lzio.h \
|
||||
lmem.h lstring.h lgc.h ltable.h
|
||||
lua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h
|
||||
luac.o: luac.c lua.h luaconf.h lauxlib.h lobject.h llimits.h lstate.h \
|
||||
ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h
|
||||
lundump.o: lundump.c lua.h luaconf.h ldebug.h lstate.h lobject.h \
|
||||
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h lundump.h
|
||||
lvm.o: lvm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
|
||||
lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h lvm.h
|
||||
lzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \
|
||||
lzio.h
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
This is a modify version of lua 5.2.3 (http://www.lua.org/ftp/lua-5.2.3.tar.gz) .
|
||||
This is a modify version of lua 5.5.1 .
|
||||
|
||||
For detail : http://lua-users.org/lists/lua-l/2014-03/msg00489.html
|
||||
For detail ,
|
||||
Shared Proto : http://lua-users.org/lists/lua-l/2014-03/msg00489.html
|
||||
Shared short string : https://blog.codingnow.com/2019/06/string_comparison.html
|
||||
|
||||
7
3rd/lua/README.md
Normal file
7
3rd/lua/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Lua
|
||||
|
||||
This is the repository of Lua development code, as seen by the Lua team. It contains the full history of all commits but is mirrored irregularly. For complete information about Lua, visit [Lua.org](https://www.lua.org/).
|
||||
|
||||
Please **do not** send pull requests. To report issues, post a message to the [Lua mailing list](https://www.lua.org/lua-l.html).
|
||||
|
||||
Download official Lua releases from [Lua.org](https://www.lua.org/download.html).
|
||||
1328
3rd/lua/lapi.c
1328
3rd/lua/lapi.c
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lapi.h,v 2.7.1.1 2013/04/12 18:48:47 roberto Exp $
|
||||
** $Id: lapi.h $
|
||||
** Auxiliary functions from Lua API
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -11,14 +11,55 @@
|
||||
#include "llimits.h"
|
||||
#include "lstate.h"
|
||||
|
||||
#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \
|
||||
"stack overflow");}
|
||||
|
||||
#if defined(LUA_USE_APICHECK)
|
||||
#include <assert.h>
|
||||
#define api_check(l,e,msg) assert(e)
|
||||
#else /* for testing */
|
||||
#define api_check(l,e,msg) ((void)(l), lua_assert((e) && msg))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Increments 'L->top.p', checking for stack overflows */
|
||||
#define api_incr_top(L) \
|
||||
(L->top.p++, api_check(L, L->top.p <= L->ci->top.p, "stack overflow"))
|
||||
|
||||
|
||||
/*
|
||||
** macros that are executed whenever program enters the Lua core
|
||||
** ('lua_lock') and leaves the core ('lua_unlock')
|
||||
*/
|
||||
#if !defined(lua_lock)
|
||||
#define lua_lock(L) ((void) 0)
|
||||
#define lua_unlock(L) ((void) 0)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** If a call returns too many multiple returns, the callee may not have
|
||||
** stack space to accommodate all results. In this case, this macro
|
||||
** increases its stack space ('L->ci->top.p').
|
||||
*/
|
||||
#define adjustresults(L,nres) \
|
||||
{ if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; }
|
||||
{ if ((nres) <= LUA_MULTRET && L->ci->top.p < L->top.p) \
|
||||
L->ci->top.p = L->top.p; }
|
||||
|
||||
#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \
|
||||
"not enough elements in the stack")
|
||||
|
||||
/* Ensure the stack has at least 'n' elements */
|
||||
#define api_checknelems(L,n) \
|
||||
api_check(L, (n) < (L->top.p - L->ci->func.p), \
|
||||
"not enough elements in the stack")
|
||||
|
||||
|
||||
/* Ensure the stack has at least 'n' elements to be popped. (Some
|
||||
** functions only update a slot after checking it for popping, but that
|
||||
** is only an optimization for a pop followed by a push.)
|
||||
*/
|
||||
#define api_checkpop(L,n) \
|
||||
api_check(L, (n) < L->top.p - L->ci->func.p && \
|
||||
L->tbclist.p < L->top.p - (n), \
|
||||
"not enough free elements in the stack")
|
||||
|
||||
#endif
|
||||
|
||||
1108
3rd/lua/lauxlib.c
1108
3rd/lua/lauxlib.c
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lauxlib.h,v 1.120.1.1 2013/04/12 18:48:47 roberto Exp $
|
||||
** $Id: lauxlib.h $
|
||||
** Auxiliary functions for building Lua libraries
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -12,44 +12,60 @@
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "luaconf.h"
|
||||
#include "lua.h"
|
||||
|
||||
|
||||
/* global table */
|
||||
#define LUA_GNAME "_G"
|
||||
|
||||
/* extra error code for `luaL_load' */
|
||||
|
||||
typedef struct luaL_Buffer luaL_Buffer;
|
||||
|
||||
|
||||
/* extra error code for 'luaL_loadfilex' */
|
||||
#define LUA_ERRFILE (LUA_ERRERR+1)
|
||||
|
||||
|
||||
/* key, in the registry, for table of loaded modules */
|
||||
#define LUA_LOADED_TABLE "_LOADED"
|
||||
|
||||
|
||||
/* key, in the registry, for table of preloaded loaders */
|
||||
#define LUA_PRELOAD_TABLE "_PRELOAD"
|
||||
|
||||
|
||||
typedef struct luaL_Reg {
|
||||
const char *name;
|
||||
lua_CFunction func;
|
||||
} luaL_Reg;
|
||||
|
||||
|
||||
LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver);
|
||||
#define luaL_checkversion(L) luaL_checkversion_(L, LUA_VERSION_NUM)
|
||||
#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number))
|
||||
|
||||
LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz);
|
||||
#define luaL_checkversion(L) \
|
||||
luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES)
|
||||
|
||||
LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
|
||||
LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
|
||||
LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len);
|
||||
LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
|
||||
LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg,
|
||||
LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg);
|
||||
LUALIB_API int (luaL_typeerror) (lua_State *L, int arg, const char *tname);
|
||||
LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg,
|
||||
size_t *l);
|
||||
LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg,
|
||||
LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg,
|
||||
const char *def, size_t *l);
|
||||
LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg);
|
||||
LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def);
|
||||
LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg);
|
||||
LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def);
|
||||
|
||||
LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
|
||||
LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
|
||||
LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg);
|
||||
LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg,
|
||||
lua_Integer def);
|
||||
LUALIB_API lua_Unsigned (luaL_checkunsigned) (lua_State *L, int numArg);
|
||||
LUALIB_API lua_Unsigned (luaL_optunsigned) (lua_State *L, int numArg,
|
||||
lua_Unsigned def);
|
||||
|
||||
LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
|
||||
LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
|
||||
LUALIB_API void (luaL_checkany) (lua_State *L, int narg);
|
||||
LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t);
|
||||
LUALIB_API void (luaL_checkany) (lua_State *L, int arg);
|
||||
|
||||
LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname);
|
||||
LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname);
|
||||
@@ -59,13 +75,17 @@ LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
|
||||
LUALIB_API void (luaL_where) (lua_State *L, int lvl);
|
||||
LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
|
||||
|
||||
LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
|
||||
LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def,
|
||||
const char *const lst[]);
|
||||
|
||||
LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname);
|
||||
LUALIB_API int (luaL_execresult) (lua_State *L, int stat);
|
||||
|
||||
/* pre-defined references */
|
||||
LUALIB_API void *(luaL_alloc) (void *ud, void *ptr, size_t osize,
|
||||
size_t nsize);
|
||||
|
||||
|
||||
/* predefined references */
|
||||
#define LUA_NOREF (-2)
|
||||
#define LUA_REFNIL (-1)
|
||||
|
||||
@@ -74,6 +94,8 @@ LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
|
||||
|
||||
LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename,
|
||||
const char *mode);
|
||||
LUALIB_API int (luaL_loadfilex_) (lua_State *L, const char *filename,
|
||||
const char *mode);
|
||||
|
||||
#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL)
|
||||
|
||||
@@ -83,10 +105,14 @@ LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
|
||||
|
||||
LUALIB_API lua_State *(luaL_newstate) (void);
|
||||
|
||||
LUALIB_API int (luaL_len) (lua_State *L, int idx);
|
||||
LUALIB_API unsigned (luaL_makeseed) (lua_State *L);
|
||||
|
||||
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
|
||||
const char *r);
|
||||
LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx);
|
||||
|
||||
LUALIB_API void (luaL_addgsub) (luaL_Buffer *b, const char *s,
|
||||
const char *p, const char *r);
|
||||
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s,
|
||||
const char *p, const char *r);
|
||||
|
||||
LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
|
||||
|
||||
@@ -108,16 +134,17 @@ LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname,
|
||||
#define luaL_newlibtable(L,l) \
|
||||
lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
|
||||
|
||||
#define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
|
||||
#define luaL_newlib(L,l) \
|
||||
(luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
|
||||
|
||||
#define luaL_argcheck(L, cond,arg,extramsg) \
|
||||
((void)(luai_likely(cond) || luaL_argerror(L, (arg), (extramsg))))
|
||||
|
||||
#define luaL_argexpected(L,cond,arg,tname) \
|
||||
((void)(luai_likely(cond) || luaL_typeerror(L, (arg), (tname))))
|
||||
|
||||
#define luaL_argcheck(L, cond,numarg,extramsg) \
|
||||
((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))
|
||||
#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
|
||||
#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
|
||||
#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
|
||||
#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
|
||||
#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n)))
|
||||
#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d)))
|
||||
|
||||
#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
|
||||
|
||||
@@ -134,19 +161,43 @@ LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname,
|
||||
#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL)
|
||||
|
||||
|
||||
/*
|
||||
** Perform arithmetic operations on lua_Integer values with wrap-around
|
||||
** semantics, as the Lua core does.
|
||||
*/
|
||||
#define luaL_intop(op,v1,v2) \
|
||||
((lua_Integer)((lua_Unsigned)(v1) op (lua_Unsigned)(v2)))
|
||||
|
||||
|
||||
/* push the value used to represent failure/error */
|
||||
#if defined(LUA_FAILISFALSE)
|
||||
#define luaL_pushfail(L) lua_pushboolean(L, 0)
|
||||
#else
|
||||
#define luaL_pushfail(L) lua_pushnil(L)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Generic Buffer manipulation
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
typedef struct luaL_Buffer {
|
||||
struct luaL_Buffer {
|
||||
char *b; /* buffer address */
|
||||
size_t size; /* buffer size */
|
||||
size_t n; /* number of characters in buffer */
|
||||
lua_State *L;
|
||||
char initb[LUAL_BUFFERSIZE]; /* initial buffer */
|
||||
} luaL_Buffer;
|
||||
union {
|
||||
LUAI_MAXALIGN; /* ensure maximum alignment for buffer */
|
||||
char b[LUAL_BUFFERSIZE]; /* initial buffer */
|
||||
} init;
|
||||
};
|
||||
|
||||
|
||||
#define luaL_bufflen(bf) ((bf)->n)
|
||||
#define luaL_buffaddr(bf) ((bf)->b)
|
||||
|
||||
|
||||
#define luaL_addchar(B,c) \
|
||||
@@ -155,6 +206,8 @@ typedef struct luaL_Buffer {
|
||||
|
||||
#define luaL_addsize(B,s) ((B)->n += (s))
|
||||
|
||||
#define luaL_buffsub(B,s) ((B)->n -= (s))
|
||||
|
||||
LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);
|
||||
LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz);
|
||||
LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
|
||||
@@ -193,18 +246,26 @@ typedef struct luaL_Stream {
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
/*
|
||||
** {============================================================
|
||||
** Compatibility with deprecated conversions
|
||||
** =============================================================
|
||||
*/
|
||||
#if defined(LUA_COMPAT_APIINTCASTS)
|
||||
|
||||
/* compatibility with old module system */
|
||||
#if defined(LUA_COMPAT_MODULE)
|
||||
#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a))
|
||||
#define luaL_optunsigned(L,a,d) \
|
||||
((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d)))
|
||||
|
||||
LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname,
|
||||
int sizehint);
|
||||
LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname,
|
||||
const luaL_Reg *l, int nup);
|
||||
#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
|
||||
#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
|
||||
|
||||
#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0))
|
||||
#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n)))
|
||||
#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d)))
|
||||
|
||||
#endif
|
||||
/* }============================================================ */
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
/*
|
||||
** $Id: lbaselib.c,v 1.276.1.1 2013/04/12 18:48:47 roberto Exp $
|
||||
** $Id: lbaselib.c $
|
||||
** Basic library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define lbaselib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
@@ -11,86 +15,109 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define lbaselib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
#include "llimits.h"
|
||||
|
||||
|
||||
static int luaB_print (lua_State *L) {
|
||||
int n = lua_gettop(L); /* number of arguments */
|
||||
int i;
|
||||
lua_getglobal(L, "tostring");
|
||||
for (i=1; i<=n; i++) {
|
||||
const char *s;
|
||||
for (i = 1; i <= n; i++) { /* for each argument */
|
||||
size_t l;
|
||||
lua_pushvalue(L, -1); /* function to be called */
|
||||
lua_pushvalue(L, i); /* value to print */
|
||||
lua_call(L, 1, 1);
|
||||
s = lua_tolstring(L, -1, &l); /* get result */
|
||||
if (s == NULL)
|
||||
return luaL_error(L,
|
||||
LUA_QL("tostring") " must return a string to " LUA_QL("print"));
|
||||
if (i>1) luai_writestring("\t", 1);
|
||||
luai_writestring(s, l);
|
||||
const char *s = luaL_tolstring(L, i, &l); /* convert it to string */
|
||||
if (i > 1) /* not the first element? */
|
||||
lua_writestring("\t", 1); /* add a tab before it */
|
||||
lua_writestring(s, l); /* print it */
|
||||
lua_pop(L, 1); /* pop result */
|
||||
}
|
||||
luai_writeline();
|
||||
lua_writeline();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Creates a warning with all given arguments.
|
||||
** Check first for errors; otherwise an error may interrupt
|
||||
** the composition of a warning, leaving it unfinished.
|
||||
*/
|
||||
static int luaB_warn (lua_State *L) {
|
||||
int n = lua_gettop(L); /* number of arguments */
|
||||
int i;
|
||||
luaL_checkstring(L, 1); /* at least one argument */
|
||||
for (i = 2; i <= n; i++)
|
||||
luaL_checkstring(L, i); /* make sure all arguments are strings */
|
||||
for (i = 1; i < n; i++) /* compose warning */
|
||||
lua_warning(L, lua_tostring(L, i), 1);
|
||||
lua_warning(L, lua_tostring(L, n), 0); /* close warning */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define SPACECHARS " \f\n\r\t\v"
|
||||
|
||||
static const char *b_str2int (const char *s, unsigned base, lua_Integer *pn) {
|
||||
lua_Unsigned n = 0;
|
||||
int neg = 0;
|
||||
s += strspn(s, SPACECHARS); /* skip initial spaces */
|
||||
if (*s == '-') { s++; neg = 1; } /* handle sign */
|
||||
else if (*s == '+') s++;
|
||||
if (!isalnum(cast_uchar(*s))) /* no digit? */
|
||||
return NULL;
|
||||
do {
|
||||
unsigned digit = cast_uint(isdigit(cast_uchar(*s))
|
||||
? *s - '0'
|
||||
: (toupper(cast_uchar(*s)) - 'A') + 10);
|
||||
if (digit >= base) return NULL; /* invalid numeral */
|
||||
n = n * base + digit;
|
||||
s++;
|
||||
} while (isalnum(cast_uchar(*s)));
|
||||
s += strspn(s, SPACECHARS); /* skip trailing spaces */
|
||||
*pn = (lua_Integer)((neg) ? (0u - n) : n);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_tonumber (lua_State *L) {
|
||||
if (lua_isnoneornil(L, 2)) { /* standard conversion */
|
||||
int isnum;
|
||||
lua_Number n = lua_tonumberx(L, 1, &isnum);
|
||||
if (isnum) {
|
||||
lua_pushnumber(L, n);
|
||||
if (lua_isnoneornil(L, 2)) { /* standard conversion? */
|
||||
if (lua_type(L, 1) == LUA_TNUMBER) { /* already a number? */
|
||||
lua_settop(L, 1); /* yes; return it */
|
||||
return 1;
|
||||
} /* else not a number; must be something */
|
||||
luaL_checkany(L, 1);
|
||||
}
|
||||
else {
|
||||
size_t l;
|
||||
const char *s = lua_tolstring(L, 1, &l);
|
||||
if (s != NULL && lua_stringtonumber(L, s) == l + 1)
|
||||
return 1; /* successful conversion to number */
|
||||
/* else not a number */
|
||||
luaL_checkany(L, 1); /* (but there must be some parameter) */
|
||||
}
|
||||
}
|
||||
else {
|
||||
size_t l;
|
||||
const char *s = luaL_checklstring(L, 1, &l);
|
||||
const char *e = s + l; /* end point for 's' */
|
||||
int base = luaL_checkint(L, 2);
|
||||
int neg = 0;
|
||||
const char *s;
|
||||
lua_Integer n = 0; /* to avoid warnings */
|
||||
lua_Integer base = luaL_checkinteger(L, 2);
|
||||
luaL_checktype(L, 1, LUA_TSTRING); /* no numbers as strings */
|
||||
s = lua_tolstring(L, 1, &l);
|
||||
luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
|
||||
s += strspn(s, SPACECHARS); /* skip initial spaces */
|
||||
if (*s == '-') { s++; neg = 1; } /* handle signal */
|
||||
else if (*s == '+') s++;
|
||||
if (isalnum((unsigned char)*s)) {
|
||||
lua_Number n = 0;
|
||||
do {
|
||||
int digit = (isdigit((unsigned char)*s)) ? *s - '0'
|
||||
: toupper((unsigned char)*s) - 'A' + 10;
|
||||
if (digit >= base) break; /* invalid numeral; force a fail */
|
||||
n = n * (lua_Number)base + (lua_Number)digit;
|
||||
s++;
|
||||
} while (isalnum((unsigned char)*s));
|
||||
s += strspn(s, SPACECHARS); /* skip trailing spaces */
|
||||
if (s == e) { /* no invalid trailing characters? */
|
||||
lua_pushnumber(L, (neg) ? -n : n);
|
||||
return 1;
|
||||
} /* else not a number */
|
||||
if (b_str2int(s, cast_uint(base), &n) == s + l) {
|
||||
lua_pushinteger(L, n);
|
||||
return 1;
|
||||
} /* else not a number */
|
||||
}
|
||||
lua_pushnil(L); /* not a number */
|
||||
} /* else not a number */
|
||||
luaL_pushfail(L); /* not a number */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_error (lua_State *L) {
|
||||
int level = luaL_optint(L, 2, 1);
|
||||
int level = (int)luaL_optinteger(L, 2, 1);
|
||||
lua_settop(L, 1);
|
||||
if (lua_isstring(L, 1) && level > 0) { /* add extra information? */
|
||||
luaL_where(L, level);
|
||||
if (lua_type(L, 1) == LUA_TSTRING && level > 0) {
|
||||
luaL_where(L, level); /* add extra information */
|
||||
lua_pushvalue(L, 1);
|
||||
lua_concat(L, 2);
|
||||
}
|
||||
@@ -112,9 +139,8 @@ static int luaB_getmetatable (lua_State *L) {
|
||||
static int luaB_setmetatable (lua_State *L) {
|
||||
int t = lua_type(L, 2);
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
|
||||
"nil or table expected");
|
||||
if (luaL_getmetafield(L, 1, "__metatable"))
|
||||
luaL_argexpected(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table");
|
||||
if (l_unlikely(luaL_getmetafield(L, 1, "__metatable") != LUA_TNIL))
|
||||
return luaL_error(L, "cannot change a protected metatable");
|
||||
lua_settop(L, 2);
|
||||
lua_setmetatable(L, 1);
|
||||
@@ -132,9 +158,9 @@ static int luaB_rawequal (lua_State *L) {
|
||||
|
||||
static int luaB_rawlen (lua_State *L) {
|
||||
int t = lua_type(L, 1);
|
||||
luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1,
|
||||
"table or string expected");
|
||||
lua_pushinteger(L, lua_rawlen(L, 1));
|
||||
luaL_argexpected(L, t == LUA_TTABLE || t == LUA_TSTRING, 1,
|
||||
"table or string");
|
||||
lua_pushinteger(L, l_castU2S(lua_rawlen(L, 1)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -157,56 +183,85 @@ static int luaB_rawset (lua_State *L) {
|
||||
}
|
||||
|
||||
|
||||
static int luaB_collectgarbage (lua_State *L) {
|
||||
static const char *const opts[] = {"stop", "restart", "collect",
|
||||
"count", "step", "setpause", "setstepmul",
|
||||
"setmajorinc", "isrunning", "generational", "incremental", NULL};
|
||||
static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
|
||||
LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL,
|
||||
LUA_GCSETMAJORINC, LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC};
|
||||
int o = optsnum[luaL_checkoption(L, 1, "collect", opts)];
|
||||
int ex = luaL_optint(L, 2, 0);
|
||||
int res = lua_gc(L, o, ex);
|
||||
switch (o) {
|
||||
case LUA_GCCOUNT: {
|
||||
int b = lua_gc(L, LUA_GCCOUNTB, 0);
|
||||
lua_pushnumber(L, res + ((lua_Number)b/1024));
|
||||
lua_pushinteger(L, b);
|
||||
return 2;
|
||||
}
|
||||
case LUA_GCSTEP: case LUA_GCISRUNNING: {
|
||||
lua_pushboolean(L, res);
|
||||
return 1;
|
||||
}
|
||||
default: {
|
||||
lua_pushinteger(L, res);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_type (lua_State *L) {
|
||||
luaL_checkany(L, 1);
|
||||
lua_pushstring(L, luaL_typename(L, 1));
|
||||
static int pushmode (lua_State *L, int oldmode) {
|
||||
if (oldmode == -1)
|
||||
luaL_pushfail(L); /* invalid call to 'lua_gc' */
|
||||
else
|
||||
lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental"
|
||||
: "generational");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int pairsmeta (lua_State *L, const char *method, int iszero,
|
||||
lua_CFunction iter) {
|
||||
if (!luaL_getmetafield(L, 1, method)) { /* no metamethod? */
|
||||
luaL_checktype(L, 1, LUA_TTABLE); /* argument must be a table */
|
||||
lua_pushcfunction(L, iter); /* will return generator, */
|
||||
lua_pushvalue(L, 1); /* state, */
|
||||
if (iszero) lua_pushinteger(L, 0); /* and initial value */
|
||||
else lua_pushnil(L);
|
||||
/*
|
||||
** check whether call to 'lua_gc' was valid (not inside a finalizer)
|
||||
*/
|
||||
#define checkvalres(res) { if (res == -1) break; }
|
||||
|
||||
static int luaB_collectgarbage (lua_State *L) {
|
||||
static const char *const opts[] = {"stop", "restart", "collect",
|
||||
"count", "step", "isrunning", "generational", "incremental",
|
||||
"param", NULL};
|
||||
static const char optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
|
||||
LUA_GCCOUNT, LUA_GCSTEP, LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC,
|
||||
LUA_GCPARAM};
|
||||
int o = optsnum[luaL_checkoption(L, 1, "collect", opts)];
|
||||
switch (o) {
|
||||
case LUA_GCCOUNT: {
|
||||
int k = lua_gc(L, o);
|
||||
int b = lua_gc(L, LUA_GCCOUNTB);
|
||||
checkvalres(k);
|
||||
lua_pushnumber(L, (lua_Number)k + ((lua_Number)b/1024));
|
||||
return 1;
|
||||
}
|
||||
case LUA_GCSTEP: {
|
||||
lua_Integer n = luaL_optinteger(L, 2, 0);
|
||||
int res = lua_gc(L, o, cast_sizet(n));
|
||||
checkvalres(res);
|
||||
lua_pushboolean(L, res);
|
||||
return 1;
|
||||
}
|
||||
case LUA_GCISRUNNING: {
|
||||
int res = lua_gc(L, o);
|
||||
checkvalres(res);
|
||||
lua_pushboolean(L, res);
|
||||
return 1;
|
||||
}
|
||||
case LUA_GCGEN: {
|
||||
return pushmode(L, lua_gc(L, o));
|
||||
}
|
||||
case LUA_GCINC: {
|
||||
return pushmode(L, lua_gc(L, o));
|
||||
}
|
||||
case LUA_GCPARAM: {
|
||||
static const char *const params[] = {
|
||||
"minormul", "majorminor", "minormajor",
|
||||
"pause", "stepmul", "stepsize", NULL};
|
||||
static const char pnum[] = {
|
||||
LUA_GCPMINORMUL, LUA_GCPMAJORMINOR, LUA_GCPMINORMAJOR,
|
||||
LUA_GCPPAUSE, LUA_GCPSTEPMUL, LUA_GCPSTEPSIZE};
|
||||
int p = pnum[luaL_checkoption(L, 2, NULL, params)];
|
||||
lua_Integer value = luaL_optinteger(L, 3, -1);
|
||||
lua_pushinteger(L, lua_gc(L, o, p, (int)value));
|
||||
return 1;
|
||||
}
|
||||
default: {
|
||||
int res = lua_gc(L, o);
|
||||
checkvalres(res);
|
||||
lua_pushinteger(L, res);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lua_pushvalue(L, 1); /* argument 'self' to metamethod */
|
||||
lua_call(L, 1, 3); /* get 3 values from metamethod */
|
||||
}
|
||||
return 3;
|
||||
luaL_pushfail(L); /* invalid call (inside a finalizer) */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_type (lua_State *L) {
|
||||
int t = lua_type(L, 1);
|
||||
luaL_argcheck(L, t != LUA_TNONE, 1, "value expected");
|
||||
lua_pushstring(L, lua_typename(L, t));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -222,28 +277,53 @@ static int luaB_next (lua_State *L) {
|
||||
}
|
||||
|
||||
|
||||
static int pairscont (lua_State *L, int status, lua_KContext k) {
|
||||
(void)L; (void)status; (void)k; /* unused */
|
||||
return 4; /* __pairs did all the work, just return its results */
|
||||
}
|
||||
|
||||
static int luaB_pairs (lua_State *L) {
|
||||
return pairsmeta(L, "__pairs", 0, luaB_next);
|
||||
luaL_checkany(L, 1);
|
||||
if (luaL_getmetafield(L, 1, "__pairs") == LUA_TNIL) { /* no metamethod? */
|
||||
lua_pushcfunction(L, luaB_next); /* will return generator and */
|
||||
lua_pushvalue(L, 1); /* state */
|
||||
lua_pushnil(L); /* initial value */
|
||||
lua_pushnil(L); /* to-be-closed object */
|
||||
}
|
||||
else {
|
||||
lua_pushvalue(L, 1); /* argument 'self' to metamethod */
|
||||
lua_callk(L, 1, 4, 0, pairscont); /* get 4 values from metamethod */
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Traversal function for 'ipairs'
|
||||
*/
|
||||
static int ipairsaux (lua_State *L) {
|
||||
int i = luaL_checkint(L, 2);
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
i++; /* next value */
|
||||
lua_Integer i = luaL_checkinteger(L, 2);
|
||||
i = luaL_intop(+, i, 1);
|
||||
lua_pushinteger(L, i);
|
||||
lua_rawgeti(L, 1, i);
|
||||
return (lua_isnil(L, -1)) ? 1 : 2;
|
||||
return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** 'ipairs' function. Returns 'ipairsaux', given "table", 0.
|
||||
** (The given "table" may not be a table.)
|
||||
*/
|
||||
static int luaB_ipairs (lua_State *L) {
|
||||
return pairsmeta(L, "__ipairs", 1, ipairsaux);
|
||||
luaL_checkany(L, 1);
|
||||
lua_pushcfunction(L, ipairsaux); /* iteration function */
|
||||
lua_pushvalue(L, 1); /* state */
|
||||
lua_pushinteger(L, 0); /* initial value */
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
static int load_aux (lua_State *L, int status, int envidx) {
|
||||
if (status == LUA_OK) {
|
||||
if (l_likely(status == LUA_OK)) {
|
||||
if (envidx != 0) { /* 'env' parameter? */
|
||||
lua_pushvalue(L, envidx); /* environment for loaded function */
|
||||
if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */
|
||||
@@ -252,16 +332,26 @@ static int load_aux (lua_State *L, int status, int envidx) {
|
||||
return 1;
|
||||
}
|
||||
else { /* error (message is on top of the stack) */
|
||||
lua_pushnil(L);
|
||||
luaL_pushfail(L);
|
||||
lua_insert(L, -2); /* put before error message */
|
||||
return 2; /* return nil plus error message */
|
||||
return 2; /* return fail plus error message */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const char *getMode (lua_State *L, int idx) {
|
||||
const char *mode = luaL_optstring(L, idx, NULL);
|
||||
if (mode != NULL && strchr(mode, 'B') != NULL) {
|
||||
/* Lua code cannot use fixed buffers */
|
||||
luaL_argerror(L, idx, "invalid mode");
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_loadfile (lua_State *L) {
|
||||
const char *fname = luaL_optstring(L, 1, NULL);
|
||||
const char *mode = luaL_optstring(L, 2, NULL);
|
||||
const char *mode = getMode(L, 2);
|
||||
int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */
|
||||
int status = luaL_loadfilex(L, fname, mode);
|
||||
return load_aux(L, status, env);
|
||||
@@ -276,33 +366,24 @@ static int luaB_loadfile (lua_State *L) {
|
||||
|
||||
|
||||
/*
|
||||
** reserved slot, above all arguments, to hold a copy of the returned
|
||||
** string to avoid it being collected while parsed. 'load' has four
|
||||
** optional arguments (chunk, source name, mode, and environment).
|
||||
*/
|
||||
#define RESERVEDSLOT 5
|
||||
|
||||
|
||||
/*
|
||||
** Reader for generic `load' function: `lua_load' uses the
|
||||
** stack for internal stuff, so the reader cannot change the
|
||||
** stack top. Instead, it keeps its resulting string in a
|
||||
** reserved slot inside the stack.
|
||||
** Reader for generic 'load' function.
|
||||
*/
|
||||
static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
|
||||
(void)(ud); /* not used */
|
||||
int *firstcall = cast(int *, ud);
|
||||
luaL_checkstack(L, 2, "too many nested functions");
|
||||
if (*firstcall)
|
||||
*firstcall = 0;
|
||||
else
|
||||
lua_pop(L, 1); /* remove previous result */
|
||||
lua_pushvalue(L, 1); /* get function */
|
||||
lua_call(L, 0, 1); /* call it */
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, 1); /* pop result */
|
||||
*size = 0;
|
||||
return NULL;
|
||||
}
|
||||
else if (!lua_isstring(L, -1))
|
||||
else if (l_unlikely(!lua_isstring(L, -1)))
|
||||
luaL_error(L, "reader function must return a string");
|
||||
lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */
|
||||
return lua_tolstring(L, RESERVEDSLOT, size);
|
||||
return lua_tolstring(L, -1, size);
|
||||
}
|
||||
|
||||
|
||||
@@ -310,17 +391,17 @@ static int luaB_load (lua_State *L) {
|
||||
int status;
|
||||
size_t l;
|
||||
const char *s = lua_tolstring(L, 1, &l);
|
||||
const char *mode = luaL_optstring(L, 3, "bt");
|
||||
const char *mode = getMode(L, 3);
|
||||
int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */
|
||||
if (s != NULL) { /* loading a string? */
|
||||
const char *chunkname = luaL_optstring(L, 2, s);
|
||||
status = luaL_loadbufferx(L, s, l, chunkname, mode);
|
||||
}
|
||||
else { /* loading from a reader function */
|
||||
int firstcall = 1; /* userdata for generic_reader */
|
||||
const char *chunkname = luaL_optstring(L, 2, "=(load)");
|
||||
luaL_checktype(L, 1, LUA_TFUNCTION);
|
||||
lua_settop(L, RESERVEDSLOT); /* create reserved slot */
|
||||
status = lua_load(L, generic_reader, NULL, chunkname, mode);
|
||||
status = lua_load(L, generic_reader, &firstcall, chunkname, mode);
|
||||
}
|
||||
return load_aux(L, status, env);
|
||||
}
|
||||
@@ -328,7 +409,8 @@ static int luaB_load (lua_State *L) {
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
static int dofilecont (lua_State *L) {
|
||||
static int dofilecont (lua_State *L, int d1, lua_KContext d2) {
|
||||
(void)d1; (void)d2; /* only to match 'lua_Kfunction' prototype */
|
||||
return lua_gettop(L) - 1;
|
||||
}
|
||||
|
||||
@@ -336,17 +418,23 @@ static int dofilecont (lua_State *L) {
|
||||
static int luaB_dofile (lua_State *L) {
|
||||
const char *fname = luaL_optstring(L, 1, NULL);
|
||||
lua_settop(L, 1);
|
||||
if (luaL_loadfile(L, fname) != LUA_OK)
|
||||
if (l_unlikely(luaL_loadfilex(L, fname, "bt") != LUA_OK))
|
||||
return lua_error(L);
|
||||
lua_callk(L, 0, LUA_MULTRET, 0, dofilecont);
|
||||
return dofilecont(L);
|
||||
return dofilecont(L, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
static int luaB_assert (lua_State *L) {
|
||||
if (!lua_toboolean(L, 1))
|
||||
return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
|
||||
return lua_gettop(L);
|
||||
if (l_likely(lua_toboolean(L, 1))) /* condition is true? */
|
||||
return lua_gettop(L); /* return all arguments */
|
||||
else { /* error */
|
||||
luaL_checkany(L, 1); /* there must be a condition */
|
||||
lua_remove(L, 1); /* remove it */
|
||||
lua_pushliteral(L, "assertion failed!"); /* default message */
|
||||
lua_settop(L, 1); /* leave only message (default if no other one) */
|
||||
return luaB_error(L); /* call 'error' */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -357,53 +445,57 @@ static int luaB_select (lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
int i = luaL_checkint(L, 1);
|
||||
lua_Integer i = luaL_checkinteger(L, 1);
|
||||
if (i < 0) i = n + i;
|
||||
else if (i > n) i = n;
|
||||
luaL_argcheck(L, 1 <= i, 1, "index out of range");
|
||||
return n - i;
|
||||
return n - (int)i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int finishpcall (lua_State *L, int status) {
|
||||
if (!lua_checkstack(L, 1)) { /* no space for extra boolean? */
|
||||
lua_settop(L, 0); /* create space for return values */
|
||||
lua_pushboolean(L, 0);
|
||||
lua_pushstring(L, "stack overflow");
|
||||
/*
|
||||
** Continuation function for 'pcall' and 'xpcall'. Both functions
|
||||
** already pushed a 'true' before doing the call, so in case of success
|
||||
** 'finishpcall' only has to return everything in the stack minus
|
||||
** 'extra' values (where 'extra' is exactly the number of items to be
|
||||
** ignored).
|
||||
*/
|
||||
static int finishpcall (lua_State *L, int status, lua_KContext extra) {
|
||||
if (l_unlikely(status != LUA_OK && status != LUA_YIELD)) { /* error? */
|
||||
lua_pushboolean(L, 0); /* first result (false) */
|
||||
lua_pushvalue(L, -2); /* error message */
|
||||
return 2; /* return false, msg */
|
||||
}
|
||||
lua_pushboolean(L, status); /* first result (status) */
|
||||
lua_replace(L, 1); /* put first result in first slot */
|
||||
return lua_gettop(L);
|
||||
}
|
||||
|
||||
|
||||
static int pcallcont (lua_State *L) {
|
||||
int status = lua_getctx(L, NULL);
|
||||
return finishpcall(L, (status == LUA_YIELD));
|
||||
else
|
||||
return lua_gettop(L) - (int)extra; /* return all results */
|
||||
}
|
||||
|
||||
|
||||
static int luaB_pcall (lua_State *L) {
|
||||
int status;
|
||||
luaL_checkany(L, 1);
|
||||
lua_pushnil(L);
|
||||
lua_insert(L, 1); /* create space for status result */
|
||||
status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, pcallcont);
|
||||
return finishpcall(L, (status == LUA_OK));
|
||||
lua_pushboolean(L, 1); /* first result if no errors */
|
||||
lua_insert(L, 1); /* put it in place */
|
||||
status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall);
|
||||
return finishpcall(L, status, 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Do a protected call with error handling. After 'lua_rotate', the
|
||||
** stack will have <f, err, true, f, [args...]>; so, the function passes
|
||||
** 2 to 'finishpcall' to skip the 2 first values when returning results.
|
||||
*/
|
||||
static int luaB_xpcall (lua_State *L) {
|
||||
int status;
|
||||
int n = lua_gettop(L);
|
||||
luaL_argcheck(L, n >= 2, 2, "value expected");
|
||||
lua_pushvalue(L, 1); /* exchange function... */
|
||||
lua_copy(L, 2, 1); /* ...and error handler */
|
||||
lua_replace(L, 2);
|
||||
status = lua_pcallk(L, n - 2, LUA_MULTRET, 1, 0, pcallcont);
|
||||
return finishpcall(L, (status == LUA_OK));
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION); /* check error function */
|
||||
lua_pushboolean(L, 1); /* first result */
|
||||
lua_pushvalue(L, 1); /* function */
|
||||
lua_rotate(L, 3, 2); /* move them below function's arguments */
|
||||
status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, finishpcall);
|
||||
return finishpcall(L, status, 2);
|
||||
}
|
||||
|
||||
|
||||
@@ -423,13 +515,11 @@ static const luaL_Reg base_funcs[] = {
|
||||
{"ipairs", luaB_ipairs},
|
||||
{"loadfile", luaB_loadfile},
|
||||
{"load", luaB_load},
|
||||
#if defined(LUA_COMPAT_LOADSTRING)
|
||||
{"loadstring", luaB_load},
|
||||
#endif
|
||||
{"next", luaB_next},
|
||||
{"pairs", luaB_pairs},
|
||||
{"pcall", luaB_pcall},
|
||||
{"print", luaB_print},
|
||||
{"warn", luaB_warn},
|
||||
{"rawequal", luaB_rawequal},
|
||||
{"rawlen", luaB_rawlen},
|
||||
{"rawget", luaB_rawget},
|
||||
@@ -440,19 +530,23 @@ static const luaL_Reg base_funcs[] = {
|
||||
{"tostring", luaB_tostring},
|
||||
{"type", luaB_type},
|
||||
{"xpcall", luaB_xpcall},
|
||||
/* placeholders */
|
||||
{LUA_GNAME, NULL},
|
||||
{"_VERSION", NULL},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
LUAMOD_API int luaopen_base (lua_State *L) {
|
||||
/* set global _G */
|
||||
lua_pushglobaltable(L);
|
||||
lua_pushglobaltable(L);
|
||||
lua_setfield(L, -2, "_G");
|
||||
/* open lib into global table */
|
||||
lua_pushglobaltable(L);
|
||||
luaL_setfuncs(L, base_funcs, 0);
|
||||
/* set global _G */
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -2, LUA_GNAME);
|
||||
/* set global _VERSION */
|
||||
lua_pushliteral(L, LUA_VERSION);
|
||||
lua_setfield(L, -2, "_VERSION"); /* set global _VERSION */
|
||||
lua_setfield(L, -2, "_VERSION");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,212 +0,0 @@
|
||||
/*
|
||||
** $Id: lbitlib.c,v 1.18.1.2 2013/07/09 18:01:41 roberto Exp $
|
||||
** Standard library for bitwise operations
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define lbitlib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
|
||||
|
||||
/* number of bits to consider in a number */
|
||||
#if !defined(LUA_NBITS)
|
||||
#define LUA_NBITS 32
|
||||
#endif
|
||||
|
||||
|
||||
#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1))
|
||||
|
||||
/* macro to trim extra bits */
|
||||
#define trim(x) ((x) & ALLONES)
|
||||
|
||||
|
||||
/* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */
|
||||
#define mask(n) (~((ALLONES << 1) << ((n) - 1)))
|
||||
|
||||
|
||||
typedef lua_Unsigned b_uint;
|
||||
|
||||
|
||||
|
||||
static b_uint andaux (lua_State *L) {
|
||||
int i, n = lua_gettop(L);
|
||||
b_uint r = ~(b_uint)0;
|
||||
for (i = 1; i <= n; i++)
|
||||
r &= luaL_checkunsigned(L, i);
|
||||
return trim(r);
|
||||
}
|
||||
|
||||
|
||||
static int b_and (lua_State *L) {
|
||||
b_uint r = andaux(L);
|
||||
lua_pushunsigned(L, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_test (lua_State *L) {
|
||||
b_uint r = andaux(L);
|
||||
lua_pushboolean(L, r != 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_or (lua_State *L) {
|
||||
int i, n = lua_gettop(L);
|
||||
b_uint r = 0;
|
||||
for (i = 1; i <= n; i++)
|
||||
r |= luaL_checkunsigned(L, i);
|
||||
lua_pushunsigned(L, trim(r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_xor (lua_State *L) {
|
||||
int i, n = lua_gettop(L);
|
||||
b_uint r = 0;
|
||||
for (i = 1; i <= n; i++)
|
||||
r ^= luaL_checkunsigned(L, i);
|
||||
lua_pushunsigned(L, trim(r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_not (lua_State *L) {
|
||||
b_uint r = ~luaL_checkunsigned(L, 1);
|
||||
lua_pushunsigned(L, trim(r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_shift (lua_State *L, b_uint r, int i) {
|
||||
if (i < 0) { /* shift right? */
|
||||
i = -i;
|
||||
r = trim(r);
|
||||
if (i >= LUA_NBITS) r = 0;
|
||||
else r >>= i;
|
||||
}
|
||||
else { /* shift left */
|
||||
if (i >= LUA_NBITS) r = 0;
|
||||
else r <<= i;
|
||||
r = trim(r);
|
||||
}
|
||||
lua_pushunsigned(L, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_lshift (lua_State *L) {
|
||||
return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkint(L, 2));
|
||||
}
|
||||
|
||||
|
||||
static int b_rshift (lua_State *L) {
|
||||
return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkint(L, 2));
|
||||
}
|
||||
|
||||
|
||||
static int b_arshift (lua_State *L) {
|
||||
b_uint r = luaL_checkunsigned(L, 1);
|
||||
int i = luaL_checkint(L, 2);
|
||||
if (i < 0 || !(r & ((b_uint)1 << (LUA_NBITS - 1))))
|
||||
return b_shift(L, r, -i);
|
||||
else { /* arithmetic shift for 'negative' number */
|
||||
if (i >= LUA_NBITS) r = ALLONES;
|
||||
else
|
||||
r = trim((r >> i) | ~(~(b_uint)0 >> i)); /* add signal bit */
|
||||
lua_pushunsigned(L, r);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int b_rot (lua_State *L, int i) {
|
||||
b_uint r = luaL_checkunsigned(L, 1);
|
||||
i &= (LUA_NBITS - 1); /* i = i % NBITS */
|
||||
r = trim(r);
|
||||
if (i != 0) /* avoid undefined shift of LUA_NBITS when i == 0 */
|
||||
r = (r << i) | (r >> (LUA_NBITS - i));
|
||||
lua_pushunsigned(L, trim(r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_lrot (lua_State *L) {
|
||||
return b_rot(L, luaL_checkint(L, 2));
|
||||
}
|
||||
|
||||
|
||||
static int b_rrot (lua_State *L) {
|
||||
return b_rot(L, -luaL_checkint(L, 2));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** get field and width arguments for field-manipulation functions,
|
||||
** checking whether they are valid.
|
||||
** ('luaL_error' called without 'return' to avoid later warnings about
|
||||
** 'width' being used uninitialized.)
|
||||
*/
|
||||
static int fieldargs (lua_State *L, int farg, int *width) {
|
||||
int f = luaL_checkint(L, farg);
|
||||
int w = luaL_optint(L, farg + 1, 1);
|
||||
luaL_argcheck(L, 0 <= f, farg, "field cannot be negative");
|
||||
luaL_argcheck(L, 0 < w, farg + 1, "width must be positive");
|
||||
if (f + w > LUA_NBITS)
|
||||
luaL_error(L, "trying to access non-existent bits");
|
||||
*width = w;
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
static int b_extract (lua_State *L) {
|
||||
int w;
|
||||
b_uint r = luaL_checkunsigned(L, 1);
|
||||
int f = fieldargs(L, 2, &w);
|
||||
r = (r >> f) & mask(w);
|
||||
lua_pushunsigned(L, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_replace (lua_State *L) {
|
||||
int w;
|
||||
b_uint r = luaL_checkunsigned(L, 1);
|
||||
b_uint v = luaL_checkunsigned(L, 2);
|
||||
int f = fieldargs(L, 3, &w);
|
||||
int m = mask(w);
|
||||
v &= m; /* erase bits outside given width */
|
||||
r = (r & ~(m << f)) | (v << f);
|
||||
lua_pushunsigned(L, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const luaL_Reg bitlib[] = {
|
||||
{"arshift", b_arshift},
|
||||
{"band", b_and},
|
||||
{"bnot", b_not},
|
||||
{"bor", b_or},
|
||||
{"bxor", b_xor},
|
||||
{"btest", b_test},
|
||||
{"extract", b_extract},
|
||||
{"lrotate", b_lrot},
|
||||
{"lshift", b_lshift},
|
||||
{"replace", b_replace},
|
||||
{"rrotate", b_rrot},
|
||||
{"rshift", b_rshift},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
|
||||
LUAMOD_API int luaopen_bit32 (lua_State *L) {
|
||||
luaL_newlib(L, bitlib);
|
||||
return 1;
|
||||
}
|
||||
|
||||
1981
3rd/lua/lcode.c
1981
3rd/lua/lcode.c
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lcode.h,v 1.58.1.1 2013/04/12 18:48:47 roberto Exp $
|
||||
** $Id: lcode.h $
|
||||
** Code generator for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -24,45 +24,64 @@
|
||||
** grep "ORDER OPR" if you change these enums (ORDER OP)
|
||||
*/
|
||||
typedef enum BinOpr {
|
||||
OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW,
|
||||
/* arithmetic operators */
|
||||
OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW,
|
||||
OPR_DIV, OPR_IDIV,
|
||||
/* bitwise operators */
|
||||
OPR_BAND, OPR_BOR, OPR_BXOR,
|
||||
OPR_SHL, OPR_SHR,
|
||||
/* string operator */
|
||||
OPR_CONCAT,
|
||||
/* comparison operators */
|
||||
OPR_EQ, OPR_LT, OPR_LE,
|
||||
OPR_NE, OPR_GT, OPR_GE,
|
||||
/* logical operators */
|
||||
OPR_AND, OPR_OR,
|
||||
OPR_NOBINOPR
|
||||
} BinOpr;
|
||||
|
||||
|
||||
typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
|
||||
/* true if operation is foldable (that is, it is arithmetic or bitwise) */
|
||||
#define foldbinop(op) ((op) <= OPR_SHR)
|
||||
|
||||
|
||||
#define getcode(fs,e) ((fs)->f->sp->code[(e)->u.info])
|
||||
#define luaK_codeABC(fs,o,a,b,c) luaK_codeABCk(fs,o,a,b,c,0)
|
||||
|
||||
|
||||
typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
|
||||
|
||||
|
||||
/* get (pointer to) instruction of given 'expdesc' */
|
||||
#define getinstruction(fs,e) ((fs)->f->code[(e)->u.info])
|
||||
|
||||
#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)
|
||||
|
||||
#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET)
|
||||
|
||||
#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t)
|
||||
|
||||
LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
|
||||
LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);
|
||||
LUAI_FUNC int luaK_codek (FuncState *fs, int reg, int k);
|
||||
LUAI_FUNC int luaK_code (FuncState *fs, Instruction i);
|
||||
LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, int Bx);
|
||||
LUAI_FUNC int luaK_codeABCk (FuncState *fs, OpCode o, int A, int B, int C,
|
||||
int k);
|
||||
LUAI_FUNC int luaK_codevABCk (FuncState *fs, OpCode o, int A, int B, int C,
|
||||
int k);
|
||||
LUAI_FUNC int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v);
|
||||
LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
|
||||
LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);
|
||||
LUAI_FUNC void luaK_codecheckglobal (FuncState *fs, expdesc *var, int k,
|
||||
int line);
|
||||
LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n);
|
||||
LUAI_FUNC void luaK_checkstack (FuncState *fs, int n);
|
||||
LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s);
|
||||
LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r);
|
||||
LUAI_FUNC void luaK_int (FuncState *fs, int reg, lua_Integer n);
|
||||
LUAI_FUNC void luaK_vapar2local (FuncState *fs, expdesc *var);
|
||||
LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
|
||||
LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
|
||||
LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e);
|
||||
LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
|
||||
LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);
|
||||
LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e);
|
||||
@@ -70,14 +89,17 @@ LUAI_FUNC int luaK_jump (FuncState *fs);
|
||||
LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret);
|
||||
LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target);
|
||||
LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);
|
||||
LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level);
|
||||
LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2);
|
||||
LUAI_FUNC int luaK_getlabel (FuncState *fs);
|
||||
LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line);
|
||||
LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
|
||||
LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1,
|
||||
expdesc *v2, int line);
|
||||
LUAI_FUNC void luaK_settablesize (FuncState *fs, int pc,
|
||||
int ra, int asize, int hsize);
|
||||
LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
|
||||
LUAI_FUNC void luaK_finish (FuncState *fs);
|
||||
LUAI_FUNC l_noret luaK_semerror (LexState *ls, const char *fmt, ...);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,37 +1,45 @@
|
||||
/*
|
||||
** $Id: lcorolib.c,v 1.5.1.1 2013/04/12 18:48:47 roberto Exp $
|
||||
** $Id: lcorolib.c $
|
||||
** Coroutine Library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#define lcorolib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
#include "llimits.h"
|
||||
|
||||
|
||||
static lua_State *getco (lua_State *L) {
|
||||
lua_State *co = lua_tothread(L, 1);
|
||||
luaL_argexpected(L, co, 1, "thread");
|
||||
return co;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Resumes a coroutine. Returns the number of results for non-error
|
||||
** cases or -1 for errors.
|
||||
*/
|
||||
static int auxresume (lua_State *L, lua_State *co, int narg) {
|
||||
int status;
|
||||
if (!lua_checkstack(co, narg)) {
|
||||
int status, nres;
|
||||
if (l_unlikely(!lua_checkstack(co, narg))) {
|
||||
lua_pushliteral(L, "too many arguments to resume");
|
||||
return -1; /* error flag */
|
||||
}
|
||||
if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) {
|
||||
lua_pushliteral(L, "cannot resume dead coroutine");
|
||||
return -1; /* error flag */
|
||||
}
|
||||
lua_xmove(L, co, narg);
|
||||
status = lua_resume(co, L, narg);
|
||||
if (status == LUA_OK || status == LUA_YIELD) {
|
||||
int nres = lua_gettop(co);
|
||||
if (!lua_checkstack(L, nres + 1)) {
|
||||
status = lua_resume(co, L, narg, &nres);
|
||||
if (l_likely(status == LUA_OK || status == LUA_YIELD)) {
|
||||
if (l_unlikely(!lua_checkstack(L, nres + 1))) {
|
||||
lua_pop(co, nres); /* remove results anyway */
|
||||
lua_pushliteral(L, "too many results to resume");
|
||||
return -1; /* error flag */
|
||||
@@ -47,11 +55,10 @@ static int auxresume (lua_State *L, lua_State *co, int narg) {
|
||||
|
||||
|
||||
static int luaB_coresume (lua_State *L) {
|
||||
lua_State *co = lua_tothread(L, 1);
|
||||
lua_State *co = getco(L);
|
||||
int r;
|
||||
luaL_argcheck(L, co, 1, "coroutine expected");
|
||||
r = auxresume(L, co, lua_gettop(L) - 1);
|
||||
if (r < 0) {
|
||||
if (l_unlikely(r < 0)) {
|
||||
lua_pushboolean(L, 0);
|
||||
lua_insert(L, -2);
|
||||
return 2; /* return false + error message */
|
||||
@@ -59,7 +66,7 @@ static int luaB_coresume (lua_State *L) {
|
||||
else {
|
||||
lua_pushboolean(L, 1);
|
||||
lua_insert(L, -(r + 1));
|
||||
return r + 1; /* return true + `resume' returns */
|
||||
return r + 1; /* return true + 'resume' returns */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,9 +74,16 @@ static int luaB_coresume (lua_State *L) {
|
||||
static int luaB_auxwrap (lua_State *L) {
|
||||
lua_State *co = lua_tothread(L, lua_upvalueindex(1));
|
||||
int r = auxresume(L, co, lua_gettop(L));
|
||||
if (r < 0) {
|
||||
if (lua_isstring(L, -1)) { /* error object is a string? */
|
||||
luaL_where(L, 1); /* add extra info */
|
||||
if (l_unlikely(r < 0)) { /* error? */
|
||||
int stat = lua_status(co);
|
||||
if (stat != LUA_OK && stat != LUA_YIELD) { /* error in the coroutine? */
|
||||
stat = lua_closethread(co, L); /* close its tbc variables */
|
||||
lua_assert(stat != LUA_OK);
|
||||
lua_xmove(co, L, 1); /* move error message to the caller */
|
||||
}
|
||||
if (stat != LUA_ERRMEM && /* not a memory error and ... */
|
||||
lua_type(L, -1) == LUA_TSTRING) { /* ... error object is a string? */
|
||||
luaL_where(L, 1); /* add extra info, if available */
|
||||
lua_insert(L, -2);
|
||||
lua_concat(L, 2);
|
||||
}
|
||||
@@ -101,30 +115,53 @@ static int luaB_yield (lua_State *L) {
|
||||
}
|
||||
|
||||
|
||||
static int luaB_costatus (lua_State *L) {
|
||||
lua_State *co = lua_tothread(L, 1);
|
||||
luaL_argcheck(L, co, 1, "coroutine expected");
|
||||
if (L == co) lua_pushliteral(L, "running");
|
||||
#define COS_RUN 0
|
||||
#define COS_DEAD 1
|
||||
#define COS_YIELD 2
|
||||
#define COS_NORM 3
|
||||
|
||||
|
||||
static const char *const statname[] =
|
||||
{"running", "dead", "suspended", "normal"};
|
||||
|
||||
|
||||
static int auxstatus (lua_State *L, lua_State *co) {
|
||||
if (L == co) return COS_RUN;
|
||||
else {
|
||||
switch (lua_status(co)) {
|
||||
case LUA_YIELD:
|
||||
lua_pushliteral(L, "suspended");
|
||||
break;
|
||||
return COS_YIELD;
|
||||
case LUA_OK: {
|
||||
lua_Debug ar;
|
||||
if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */
|
||||
lua_pushliteral(L, "normal"); /* it is running */
|
||||
if (lua_getstack(co, 0, &ar)) /* does it have frames? */
|
||||
return COS_NORM; /* it is running */
|
||||
else if (lua_gettop(co) == 0)
|
||||
lua_pushliteral(L, "dead");
|
||||
return COS_DEAD;
|
||||
else
|
||||
lua_pushliteral(L, "suspended"); /* initial state */
|
||||
break;
|
||||
return COS_YIELD; /* initial state */
|
||||
}
|
||||
default: /* some error occurred */
|
||||
lua_pushliteral(L, "dead");
|
||||
break;
|
||||
return COS_DEAD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_costatus (lua_State *L) {
|
||||
lua_State *co = getco(L);
|
||||
lua_pushstring(L, statname[auxstatus(L, co)]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static lua_State *getoptco (lua_State *L) {
|
||||
return (lua_isnone(L, 1) ? L : getco(L));
|
||||
}
|
||||
|
||||
|
||||
static int luaB_yieldable (lua_State *L) {
|
||||
lua_State *co = getoptco(L);
|
||||
lua_pushboolean(L, lua_isyieldable(co));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -136,6 +173,37 @@ static int luaB_corunning (lua_State *L) {
|
||||
}
|
||||
|
||||
|
||||
static int luaB_close (lua_State *L) {
|
||||
lua_State *co = getoptco(L);
|
||||
int status = auxstatus(L, co);
|
||||
switch (status) {
|
||||
case COS_DEAD: case COS_YIELD: {
|
||||
status = lua_closethread(co, L);
|
||||
if (status == LUA_OK) {
|
||||
lua_pushboolean(L, 1);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
lua_pushboolean(L, 0);
|
||||
lua_xmove(co, L, 1); /* move error message */
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
case COS_NORM:
|
||||
return luaL_error(L, "cannot close a %s coroutine", statname[status]);
|
||||
case COS_RUN:
|
||||
lua_geti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD); /* get main */
|
||||
if (lua_tothread(L, -1) == co)
|
||||
return luaL_error(L, "cannot close main thread");
|
||||
lua_closethread(co, L); /* close itself */
|
||||
/* previous call does not return *//* FALLTHROUGH */
|
||||
default:
|
||||
lua_assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const luaL_Reg co_funcs[] = {
|
||||
{"create", luaB_cocreate},
|
||||
{"resume", luaB_coresume},
|
||||
@@ -143,6 +211,8 @@ static const luaL_Reg co_funcs[] = {
|
||||
{"status", luaB_costatus},
|
||||
{"wrap", luaB_cowrap},
|
||||
{"yield", luaB_yield},
|
||||
{"isyieldable", luaB_yieldable},
|
||||
{"close", luaB_close},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lctype.c,v 1.11.1.1 2013/04/12 18:48:47 roberto Exp $
|
||||
** $Id: lctype.c $
|
||||
** 'ctype' functions for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -7,12 +7,24 @@
|
||||
#define lctype_c
|
||||
#define LUA_CORE
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include "lctype.h"
|
||||
|
||||
#if !LUA_USE_CTYPE /* { */
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
#if defined (LUA_UCID) /* accept UniCode IDentifiers? */
|
||||
/* consider all non-ASCII codepoints to be alphabetic */
|
||||
#define NONA 0x01
|
||||
#else
|
||||
#define NONA 0x00 /* default */
|
||||
#endif
|
||||
|
||||
|
||||
LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = {
|
||||
0x00, /* EOZ */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */
|
||||
@@ -31,22 +43,22 @@ LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = {
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */
|
||||
0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* f. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* 8. */
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* 9. */
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* a. */
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* b. */
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
|
||||
0x00, 0x00, NONA, NONA, NONA, NONA, NONA, NONA, /* c. */
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* d. */
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* e. */
|
||||
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
|
||||
NONA, NONA, NONA, NONA, NONA, 0x00, 0x00, 0x00, /* f. */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
#endif /* } */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lctype.h,v 1.12.1.1 2013/04/12 18:48:47 roberto Exp $
|
||||
** $Id: lctype.h $
|
||||
** 'ctype' functions for Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -13,7 +13,7 @@
|
||||
/*
|
||||
** WARNING: the functions defined here do not necessarily correspond
|
||||
** to the similar functions in the standard C ctype.h. They are
|
||||
** optimized for the specific needs of Lua
|
||||
** optimized for the specific needs of Lua.
|
||||
*/
|
||||
|
||||
#if !defined(LUA_USE_CTYPE)
|
||||
@@ -61,14 +61,20 @@
|
||||
#define lisprint(c) testprop(c, MASK(PRINTBIT))
|
||||
#define lisxdigit(c) testprop(c, MASK(XDIGITBIT))
|
||||
|
||||
|
||||
/*
|
||||
** this 'ltolower' only works for alphabetic characters
|
||||
** In ASCII, this 'ltolower' is correct for alphabetic characters and
|
||||
** for '.'. That is enough for Lua needs. ('check_exp' ensures that
|
||||
** the character either is an upper-case letter or is unchanged by
|
||||
** the transformation, which holds for lower-case letters and '.'.)
|
||||
*/
|
||||
#define ltolower(c) ((c) | ('A' ^ 'a'))
|
||||
#define ltolower(c) \
|
||||
check_exp(('A' <= (c) && (c) <= 'Z') || (c) == ((c) | ('A' ^ 'a')), \
|
||||
(c) | ('A' ^ 'a'))
|
||||
|
||||
|
||||
/* two more entries for 0 and -1 (EOZ) */
|
||||
LUAI_DDEC const lu_byte luai_ctype_[UCHAR_MAX + 2];
|
||||
/* one entry for each character and for -1 (EOZ) */
|
||||
LUAI_DDEC(const lu_byte luai_ctype_[UCHAR_MAX + 2];)
|
||||
|
||||
|
||||
#else /* }{ */
|
||||
|
||||
297
3rd/lua/ldblib.c
297
3rd/lua/ldblib.c
@@ -1,26 +1,43 @@
|
||||
/*
|
||||
** $Id: ldblib.c,v 1.132.1.1 2013/04/12 18:48:47 roberto Exp $
|
||||
** $Id: ldblib.c $
|
||||
** Interface from Lua to its debug API
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define ldblib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ldblib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
#include "llimits.h"
|
||||
|
||||
|
||||
#define HOOKKEY "_HKEY"
|
||||
/*
|
||||
** The hook table at registry[HOOKKEY] maps threads to their current
|
||||
** hook function.
|
||||
*/
|
||||
static const char *const HOOKKEY = "_HOOKKEY";
|
||||
|
||||
|
||||
/*
|
||||
** If L1 != L, L1 can be in any state, and therefore there are no
|
||||
** guarantees about its stack space; any push in L1 must be
|
||||
** checked.
|
||||
*/
|
||||
static void checkstack (lua_State *L, lua_State *L1, int n) {
|
||||
if (l_unlikely(L != L1 && !lua_checkstack(L1, n)))
|
||||
luaL_error(L, "stack overflow");
|
||||
}
|
||||
|
||||
|
||||
static int db_getregistry (lua_State *L) {
|
||||
lua_pushvalue(L, LUA_REGISTRYINDEX);
|
||||
@@ -39,8 +56,7 @@ static int db_getmetatable (lua_State *L) {
|
||||
|
||||
static int db_setmetatable (lua_State *L) {
|
||||
int t = lua_type(L, 2);
|
||||
luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
|
||||
"nil or table expected");
|
||||
luaL_argexpected(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table");
|
||||
lua_settop(L, 2);
|
||||
lua_setmetatable(L, 1);
|
||||
return 1; /* return 1st argument */
|
||||
@@ -48,44 +64,34 @@ static int db_setmetatable (lua_State *L) {
|
||||
|
||||
|
||||
static int db_getuservalue (lua_State *L) {
|
||||
int n = (int)luaL_optinteger(L, 2, 1);
|
||||
if (lua_type(L, 1) != LUA_TUSERDATA)
|
||||
lua_pushnil(L);
|
||||
else
|
||||
lua_getuservalue(L, 1);
|
||||
luaL_pushfail(L);
|
||||
else if (lua_getiuservalue(L, 1, n) != LUA_TNONE) {
|
||||
lua_pushboolean(L, 1);
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int db_setuservalue (lua_State *L) {
|
||||
if (lua_type(L, 1) == LUA_TLIGHTUSERDATA)
|
||||
luaL_argerror(L, 1, "full userdata expected, got light userdata");
|
||||
int n = (int)luaL_optinteger(L, 3, 1);
|
||||
luaL_checktype(L, 1, LUA_TUSERDATA);
|
||||
if (!lua_isnoneornil(L, 2))
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
luaL_checkany(L, 2);
|
||||
lua_settop(L, 2);
|
||||
lua_setuservalue(L, 1);
|
||||
if (!lua_setiuservalue(L, 1, n))
|
||||
luaL_pushfail(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void settabss (lua_State *L, const char *i, const char *v) {
|
||||
lua_pushstring(L, v);
|
||||
lua_setfield(L, -2, i);
|
||||
}
|
||||
|
||||
|
||||
static void settabsi (lua_State *L, const char *i, int v) {
|
||||
lua_pushinteger(L, v);
|
||||
lua_setfield(L, -2, i);
|
||||
}
|
||||
|
||||
|
||||
static void settabsb (lua_State *L, const char *i, int v) {
|
||||
lua_pushboolean(L, v);
|
||||
lua_setfield(L, -2, i);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Auxiliary function used by several library functions: check for
|
||||
** an optional thread as function's first argument and set 'arg' with
|
||||
** 1 if this argument is present (so that functions can skip it to
|
||||
** access their other arguments)
|
||||
*/
|
||||
static lua_State *getthread (lua_State *L, int *arg) {
|
||||
if (lua_isthread(L, 1)) {
|
||||
*arg = 1;
|
||||
@@ -93,46 +99,78 @@ static lua_State *getthread (lua_State *L, int *arg) {
|
||||
}
|
||||
else {
|
||||
*arg = 0;
|
||||
return L;
|
||||
return L; /* function will operate over current thread */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Variations of 'lua_settable', used by 'db_getinfo' to put results
|
||||
** from 'lua_getinfo' into result table. Key is always a string;
|
||||
** value can be a string, an int, or a boolean.
|
||||
*/
|
||||
static void settabss (lua_State *L, const char *k, const char *v) {
|
||||
lua_pushstring(L, v);
|
||||
lua_setfield(L, -2, k);
|
||||
}
|
||||
|
||||
static void settabsi (lua_State *L, const char *k, int v) {
|
||||
lua_pushinteger(L, v);
|
||||
lua_setfield(L, -2, k);
|
||||
}
|
||||
|
||||
static void settabsb (lua_State *L, const char *k, int v) {
|
||||
lua_pushboolean(L, v);
|
||||
lua_setfield(L, -2, k);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** In function 'db_getinfo', the call to 'lua_getinfo' may push
|
||||
** results on the stack; later it creates the result table to put
|
||||
** these objects. Function 'treatstackoption' puts the result from
|
||||
** 'lua_getinfo' on top of the result table so that it can call
|
||||
** 'lua_setfield'.
|
||||
*/
|
||||
static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
|
||||
if (L == L1) {
|
||||
lua_pushvalue(L, -2);
|
||||
lua_remove(L, -3);
|
||||
}
|
||||
if (L == L1)
|
||||
lua_rotate(L, -2, 1); /* exchange object and table */
|
||||
else
|
||||
lua_xmove(L1, L, 1);
|
||||
lua_setfield(L, -2, fname);
|
||||
lua_xmove(L1, L, 1); /* move object to the "main" stack */
|
||||
lua_setfield(L, -2, fname); /* put object into table */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Calls 'lua_getinfo' and collects all results in a new table.
|
||||
** L1 needs stack space for an optional input (function) plus
|
||||
** two optional outputs (function and line table) from function
|
||||
** 'lua_getinfo'.
|
||||
*/
|
||||
static int db_getinfo (lua_State *L) {
|
||||
lua_Debug ar;
|
||||
int arg;
|
||||
lua_State *L1 = getthread(L, &arg);
|
||||
const char *options = luaL_optstring(L, arg+2, "flnStu");
|
||||
if (lua_isnumber(L, arg+1)) {
|
||||
if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {
|
||||
lua_pushnil(L); /* level out of range */
|
||||
const char *options = luaL_optstring(L, arg+2, "flnSrtu");
|
||||
checkstack(L, L1, 3);
|
||||
luaL_argcheck(L, options[0] != '>', arg + 2, "invalid option '>'");
|
||||
if (lua_isfunction(L, arg + 1)) { /* info about a function? */
|
||||
options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */
|
||||
lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */
|
||||
lua_xmove(L, L1, 1);
|
||||
}
|
||||
else { /* stack level */
|
||||
if (!lua_getstack(L1, (int)luaL_checkinteger(L, arg + 1), &ar)) {
|
||||
luaL_pushfail(L); /* level out of range */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (lua_isfunction(L, arg+1)) {
|
||||
lua_pushfstring(L, ">%s", options);
|
||||
options = lua_tostring(L, -1);
|
||||
lua_pushvalue(L, arg+1);
|
||||
lua_xmove(L, L1, 1);
|
||||
}
|
||||
else
|
||||
return luaL_argerror(L, arg+1, "function or level expected");
|
||||
if (!lua_getinfo(L1, options, &ar))
|
||||
return luaL_argerror(L, arg+2, "invalid option");
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_newtable(L); /* table to collect results */
|
||||
if (strchr(options, 'S')) {
|
||||
settabss(L, "source", ar.source);
|
||||
lua_pushlstring(L, ar.source, ar.srclen);
|
||||
lua_setfield(L, -2, "source");
|
||||
settabss(L, "short_src", ar.short_src);
|
||||
settabsi(L, "linedefined", ar.linedefined);
|
||||
settabsi(L, "lastlinedefined", ar.lastlinedefined);
|
||||
@@ -149,8 +187,14 @@ static int db_getinfo (lua_State *L) {
|
||||
settabss(L, "name", ar.name);
|
||||
settabss(L, "namewhat", ar.namewhat);
|
||||
}
|
||||
if (strchr(options, 't'))
|
||||
if (strchr(options, 'r')) {
|
||||
settabsi(L, "ftransfer", ar.ftransfer);
|
||||
settabsi(L, "ntransfer", ar.ntransfer);
|
||||
}
|
||||
if (strchr(options, 't')) {
|
||||
settabsb(L, "istailcall", ar.istailcall);
|
||||
settabsi(L, "extraargs", ar.extraargs);
|
||||
}
|
||||
if (strchr(options, 'L'))
|
||||
treatstackoption(L, L1, "activelines");
|
||||
if (strchr(options, 'f'))
|
||||
@@ -162,26 +206,28 @@ static int db_getinfo (lua_State *L) {
|
||||
static int db_getlocal (lua_State *L) {
|
||||
int arg;
|
||||
lua_State *L1 = getthread(L, &arg);
|
||||
lua_Debug ar;
|
||||
const char *name;
|
||||
int nvar = luaL_checkint(L, arg+2); /* local-variable index */
|
||||
int nvar = (int)luaL_checkinteger(L, arg + 2); /* local-variable index */
|
||||
if (lua_isfunction(L, arg + 1)) { /* function argument? */
|
||||
lua_pushvalue(L, arg + 1); /* push function */
|
||||
lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */
|
||||
return 1;
|
||||
return 1; /* return only name (there is no value) */
|
||||
}
|
||||
else { /* stack-level argument */
|
||||
if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */
|
||||
lua_Debug ar;
|
||||
const char *name;
|
||||
int level = (int)luaL_checkinteger(L, arg + 1);
|
||||
if (l_unlikely(!lua_getstack(L1, level, &ar))) /* out of range? */
|
||||
return luaL_argerror(L, arg+1, "level out of range");
|
||||
checkstack(L, L1, 1);
|
||||
name = lua_getlocal(L1, &ar, nvar);
|
||||
if (name) {
|
||||
lua_xmove(L1, L, 1); /* push local value */
|
||||
lua_xmove(L1, L, 1); /* move local value */
|
||||
lua_pushstring(L, name); /* push name */
|
||||
lua_pushvalue(L, -2); /* re-order */
|
||||
lua_rotate(L, -2, 1); /* re-order */
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
lua_pushnil(L); /* no name (nor value) */
|
||||
luaL_pushfail(L); /* no name (nor value) */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -190,26 +236,36 @@ static int db_getlocal (lua_State *L) {
|
||||
|
||||
static int db_setlocal (lua_State *L) {
|
||||
int arg;
|
||||
const char *name;
|
||||
lua_State *L1 = getthread(L, &arg);
|
||||
lua_Debug ar;
|
||||
if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */
|
||||
int level = (int)luaL_checkinteger(L, arg + 1);
|
||||
int nvar = (int)luaL_checkinteger(L, arg + 2);
|
||||
if (l_unlikely(!lua_getstack(L1, level, &ar))) /* out of range? */
|
||||
return luaL_argerror(L, arg+1, "level out of range");
|
||||
luaL_checkany(L, arg+3);
|
||||
lua_settop(L, arg+3);
|
||||
checkstack(L, L1, 1);
|
||||
lua_xmove(L, L1, 1);
|
||||
lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2)));
|
||||
name = lua_setlocal(L1, &ar, nvar);
|
||||
if (name == NULL)
|
||||
lua_pop(L1, 1); /* pop value (if not popped by 'lua_setlocal') */
|
||||
lua_pushstring(L, name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** get (if 'get' is true) or set an upvalue from a closure
|
||||
*/
|
||||
static int auxupvalue (lua_State *L, int get) {
|
||||
const char *name;
|
||||
int n = luaL_checkint(L, 2);
|
||||
luaL_checktype(L, 1, LUA_TFUNCTION);
|
||||
int n = (int)luaL_checkinteger(L, 2); /* upvalue index */
|
||||
luaL_checktype(L, 1, LUA_TFUNCTION); /* closure */
|
||||
name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
|
||||
if (name == NULL) return 0;
|
||||
lua_pushstring(L, name);
|
||||
lua_insert(L, -(get+1));
|
||||
lua_insert(L, -(get+1)); /* no-op if get is false */
|
||||
return get + 1;
|
||||
}
|
||||
|
||||
@@ -225,27 +281,37 @@ static int db_setupvalue (lua_State *L) {
|
||||
}
|
||||
|
||||
|
||||
static int checkupval (lua_State *L, int argf, int argnup) {
|
||||
lua_Debug ar;
|
||||
int nup = luaL_checkint(L, argnup);
|
||||
luaL_checktype(L, argf, LUA_TFUNCTION);
|
||||
lua_pushvalue(L, argf);
|
||||
lua_getinfo(L, ">u", &ar);
|
||||
luaL_argcheck(L, 1 <= nup && nup <= ar.nups, argnup, "invalid upvalue index");
|
||||
return nup;
|
||||
/*
|
||||
** Check whether a given upvalue from a given closure exists and
|
||||
** returns its index
|
||||
*/
|
||||
static void *checkupval (lua_State *L, int argf, int argnup, int *pnup) {
|
||||
void *id;
|
||||
int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */
|
||||
luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */
|
||||
id = lua_upvalueid(L, argf, nup);
|
||||
if (pnup) {
|
||||
luaL_argcheck(L, id != NULL, argnup, "invalid upvalue index");
|
||||
*pnup = nup;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
static int db_upvalueid (lua_State *L) {
|
||||
int n = checkupval(L, 1, 2);
|
||||
lua_pushlightuserdata(L, lua_upvalueid(L, 1, n));
|
||||
void *id = checkupval(L, 1, 2, NULL);
|
||||
if (id != NULL)
|
||||
lua_pushlightuserdata(L, id);
|
||||
else
|
||||
luaL_pushfail(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int db_upvaluejoin (lua_State *L) {
|
||||
int n1 = checkupval(L, 1, 2);
|
||||
int n2 = checkupval(L, 3, 4);
|
||||
int n1, n2;
|
||||
checkupval(L, 1, 2, &n1);
|
||||
checkupval(L, 3, 4, &n2);
|
||||
luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected");
|
||||
luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected");
|
||||
lua_upvaluejoin(L, 1, n1, 3, n2);
|
||||
@@ -253,26 +319,29 @@ static int db_upvaluejoin (lua_State *L) {
|
||||
}
|
||||
|
||||
|
||||
#define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY)
|
||||
|
||||
|
||||
/*
|
||||
** Call hook function registered at hook table for the current
|
||||
** thread (if there is one)
|
||||
*/
|
||||
static void hookf (lua_State *L, lua_Debug *ar) {
|
||||
static const char *const hooknames[] =
|
||||
{"call", "return", "line", "count", "tail call"};
|
||||
gethooktable(L);
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, HOOKKEY);
|
||||
lua_pushthread(L);
|
||||
lua_rawget(L, -2);
|
||||
if (lua_isfunction(L, -1)) {
|
||||
lua_pushstring(L, hooknames[(int)ar->event]);
|
||||
if (lua_rawget(L, -2) == LUA_TFUNCTION) { /* is there a hook function? */
|
||||
lua_pushstring(L, hooknames[(int)ar->event]); /* push event name */
|
||||
if (ar->currentline >= 0)
|
||||
lua_pushinteger(L, ar->currentline);
|
||||
lua_pushinteger(L, ar->currentline); /* push current line */
|
||||
else lua_pushnil(L);
|
||||
lua_assert(lua_getinfo(L, "lS", ar));
|
||||
lua_call(L, 2, 0);
|
||||
lua_call(L, 2, 0); /* call hook function */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Convert a string mask (for 'sethook') into a bit mask
|
||||
*/
|
||||
static int makemask (const char *smask, int count) {
|
||||
int mask = 0;
|
||||
if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
|
||||
@@ -283,6 +352,9 @@ static int makemask (const char *smask, int count) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Convert a bit mask (for 'gethook') into a string mask
|
||||
*/
|
||||
static char *unmakemask (int mask, char *smask) {
|
||||
int i = 0;
|
||||
if (mask & LUA_MASKCALL) smask[i++] = 'c';
|
||||
@@ -297,26 +369,28 @@ static int db_sethook (lua_State *L) {
|
||||
int arg, mask, count;
|
||||
lua_Hook func;
|
||||
lua_State *L1 = getthread(L, &arg);
|
||||
if (lua_isnoneornil(L, arg+1)) {
|
||||
if (lua_isnoneornil(L, arg+1)) { /* no hook? */
|
||||
lua_settop(L, arg+1);
|
||||
func = NULL; mask = 0; count = 0; /* turn off hooks */
|
||||
}
|
||||
else {
|
||||
const char *smask = luaL_checkstring(L, arg+2);
|
||||
luaL_checktype(L, arg+1, LUA_TFUNCTION);
|
||||
count = luaL_optint(L, arg+3, 0);
|
||||
count = (int)luaL_optinteger(L, arg + 3, 0);
|
||||
func = hookf; mask = makemask(smask, count);
|
||||
}
|
||||
if (gethooktable(L) == 0) { /* creating hook table? */
|
||||
lua_pushstring(L, "k");
|
||||
if (!luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY)) {
|
||||
/* table just created; initialize it */
|
||||
lua_pushliteral(L, "k");
|
||||
lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */
|
||||
lua_setmetatable(L, -2); /* metatable(hooktable) = hooktable */
|
||||
}
|
||||
lua_pushthread(L1); lua_xmove(L1, L, 1);
|
||||
lua_pushvalue(L, arg+1);
|
||||
lua_rawset(L, -3); /* set new hook */
|
||||
lua_sethook(L1, func, mask, count); /* set hooks */
|
||||
checkstack(L, L1, 1);
|
||||
lua_pushthread(L1); lua_xmove(L1, L, 1); /* key (thread) */
|
||||
lua_pushvalue(L, arg + 1); /* value (hook function) */
|
||||
lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */
|
||||
lua_sethook(L1, func, mask, count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -327,16 +401,21 @@ static int db_gethook (lua_State *L) {
|
||||
char buff[5];
|
||||
int mask = lua_gethookmask(L1);
|
||||
lua_Hook hook = lua_gethook(L1);
|
||||
if (hook != NULL && hook != hookf) /* external hook? */
|
||||
if (hook == NULL) { /* no hook? */
|
||||
luaL_pushfail(L);
|
||||
return 1;
|
||||
}
|
||||
else if (hook != hookf) /* external hook? */
|
||||
lua_pushliteral(L, "external hook");
|
||||
else {
|
||||
gethooktable(L);
|
||||
else { /* hook table must exist */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, HOOKKEY);
|
||||
checkstack(L, L1, 1);
|
||||
lua_pushthread(L1); lua_xmove(L1, L, 1);
|
||||
lua_rawget(L, -2); /* get hook */
|
||||
lua_rawget(L, -2); /* 1st result = hooktable[L1] */
|
||||
lua_remove(L, -2); /* remove hook table */
|
||||
}
|
||||
lua_pushstring(L, unmakemask(mask, buff));
|
||||
lua_pushinteger(L, lua_gethookcount(L1));
|
||||
lua_pushstring(L, unmakemask(mask, buff)); /* 2nd result = mask */
|
||||
lua_pushinteger(L, lua_gethookcount(L1)); /* 3rd result = count */
|
||||
return 3;
|
||||
}
|
||||
|
||||
@@ -344,13 +423,13 @@ static int db_gethook (lua_State *L) {
|
||||
static int db_debug (lua_State *L) {
|
||||
for (;;) {
|
||||
char buffer[250];
|
||||
luai_writestringerror("%s", "lua_debug> ");
|
||||
if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
|
||||
lua_writestringerror("%s", "lua_debug> ");
|
||||
if (fgets(buffer, sizeof(buffer), stdin) == NULL ||
|
||||
strcmp(buffer, "cont\n") == 0)
|
||||
return 0;
|
||||
if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
|
||||
if (luaL_loadbufferx(L, buffer, strlen(buffer), "=(debug command)", "t") ||
|
||||
lua_pcall(L, 0, 0, 0))
|
||||
luai_writestringerror("%s\n", lua_tostring(L, -1));
|
||||
lua_writestringerror("%s\n", luaL_tolstring(L, -1, NULL));
|
||||
lua_settop(L, 0); /* remove eventual returns */
|
||||
}
|
||||
}
|
||||
@@ -363,7 +442,7 @@ static int db_traceback (lua_State *L) {
|
||||
if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */
|
||||
lua_pushvalue(L, arg + 1); /* return it untouched */
|
||||
else {
|
||||
int level = luaL_optint(L, arg + 2, (L == L1) ? 1 : 0);
|
||||
int level = (int)luaL_optinteger(L, arg + 2, (L == L1) ? 1 : 0);
|
||||
luaL_traceback(L, L1, msg, level);
|
||||
}
|
||||
return 1;
|
||||
|
||||
848
3rd/lua/ldebug.c
848
3rd/lua/ldebug.c
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: ldebug.h,v 2.7.1.1 2013/04/12 18:48:47 roberto Exp $
|
||||
** $Id: ldebug.h $
|
||||
** Auxiliary functions from Debug Interface module
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -11,24 +11,55 @@
|
||||
#include "lstate.h"
|
||||
|
||||
|
||||
#define pcRel(pc, p) (cast(int, (pc) - (p)->sp->code) - 1)
|
||||
#define pcRel(pc, p) (cast_int((pc) - (p)->code) - 1)
|
||||
|
||||
|
||||
/* Active Lua function (given call info) */
|
||||
#define ci_func(ci) (clLvalue(s2v((ci)->func.p)))
|
||||
|
||||
#define getfuncline(f,pc) (((f)->sp->lineinfo) ? (f)->sp->lineinfo[pc] : 0)
|
||||
|
||||
#define resethookcount(L) (L->hookcount = L->basehookcount)
|
||||
|
||||
/* Active Lua function (given call info) */
|
||||
#define ci_func(ci) (clLvalue((ci)->func))
|
||||
/*
|
||||
** mark for entries in 'lineinfo' array that has absolute information in
|
||||
** 'abslineinfo' array
|
||||
*/
|
||||
#define ABSLINEINFO (-0x80)
|
||||
|
||||
|
||||
/*
|
||||
** MAXimum number of successive Instructions WiTHout ABSolute line
|
||||
** information. (A power of two allows fast divisions.)
|
||||
*/
|
||||
#if !defined(MAXIWTHABS)
|
||||
#define MAXIWTHABS 128
|
||||
#endif
|
||||
|
||||
|
||||
LUAI_FUNC int luaG_getfuncline (const Proto *f, int pc);
|
||||
LUAI_FUNC const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n,
|
||||
StkId *pos);
|
||||
LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o,
|
||||
const char *opname);
|
||||
LUAI_FUNC l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2);
|
||||
LUAI_FUNC l_noret luaG_aritherror (lua_State *L, const TValue *p1,
|
||||
LUAI_FUNC l_noret luaG_callerror (lua_State *L, const TValue *o);
|
||||
LUAI_FUNC l_noret luaG_forerror (lua_State *L, const TValue *o,
|
||||
const char *what);
|
||||
LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1,
|
||||
const TValue *p2);
|
||||
LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1,
|
||||
const TValue *p2,
|
||||
const char *msg);
|
||||
LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1,
|
||||
const TValue *p2);
|
||||
LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1,
|
||||
const TValue *p2);
|
||||
LUAI_FUNC l_noret luaG_errnnil (lua_State *L, LClosure *cl, int k);
|
||||
LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...);
|
||||
LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg,
|
||||
TString *src, int line);
|
||||
LUAI_FUNC l_noret luaG_errormsg (lua_State *L);
|
||||
LUAI_FUNC int luaG_traceexec (lua_State *L, const Instruction *pc);
|
||||
LUAI_FUNC int luaG_tracecall (lua_State *L);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user