Compare commits
813 Commits
v0.3.1
...
es_rev9865
| Author | SHA1 | Date | |
|---|---|---|---|
| cc3c8af6b4 | |||
| b35ec65577 | |||
| 4482520a86 | |||
| e9afc9ad17 | |||
| 55ab6969ee | |||
| d982bc06ad | |||
| 2ca87d53b8 | |||
| 1a4db1d7c6 | |||
| 3bb9101b07 | |||
| 1b2496b7f0 | |||
| d20c377580 | |||
| 166d0839b7 | |||
| fbe0732210 | |||
| b5d6a75155 | |||
| 4fc4b02449 | |||
| 5276bd1479 | |||
|
|
81ab31b19a | ||
|
|
e21e30ff74 | ||
|
|
3a9ba75717 | ||
| 7d94413297 | |||
| 35855941e6 | |||
| 50ba8ca703 | |||
| dde6a0b7de | |||
| b64a281d75 | |||
| b69b8aaaf9 | |||
| 65b28ed877 | |||
| 6c7637716b | |||
| ff9a238f5c | |||
| eec3cbdba1 | |||
| 29c4931dc0 | |||
|
|
9cd0f0b117 | ||
|
|
aa0eb4fc43 | ||
|
|
dbdc594b59 | ||
|
|
4176a8c68b | ||
|
|
0557d1ee2d | ||
|
|
eed8af9a0a | ||
|
|
1b881c4f60 | ||
|
|
770488dbd3 | ||
| 3f69081d32 | |||
| 7033db7dc4 | |||
| a1a16b4a22 | |||
| 98e92ee0fe | |||
| 29b55f36cf | |||
| 061e88c9fe | |||
| 66f204b1f2 | |||
| c92b1b8c3b | |||
| 98c12b8fb9 | |||
| 5fee483fd9 | |||
| f7a7afccd6 | |||
| e2c70e6d70 | |||
| a5e150d1c0 | |||
| 39887c8bdb | |||
|
|
1f1e2abbda | ||
| 1796d9631f | |||
| 389975e409 | |||
| 6c51590369 | |||
|
|
cc65bae644 | ||
|
|
c824f707cf | ||
| 47c5b798b3 | |||
| f0cba1d536 | |||
| ed891546bc | |||
| 8651ff6e1e | |||
| 629edea991 | |||
|
|
1e10ce8518 | ||
| 4f8f17ad48 | |||
| 148518984e | |||
| 33150e34d6 | |||
| af60a5719e | |||
| 31557cfc33 | |||
| 78c0cd5b0d | |||
| 412534d0be | |||
|
|
0f6aa8d7ae | ||
|
|
2c745c63d3 | ||
|
|
efd80c1287 | ||
|
|
01f649fd88 | ||
|
|
f23aeb6412 | ||
|
|
1a4596c79b | ||
|
|
b16e4aa570 | ||
|
|
5255b15fa9 | ||
|
|
57048373f4 | ||
|
|
9e06fb2ab8 | ||
|
|
f2405e0ccd | ||
|
|
6e3a7deb6e | ||
|
|
f254b599c0 | ||
| 99a05b95ba | |||
| 54dd43c38a | |||
| 903f925a79 | |||
| 80709578d6 | |||
| c0d5b7c968 | |||
| 7bea163f46 | |||
| 8992dbc515 | |||
| c2d3ea6138 | |||
| 9e336deb49 | |||
| 0160ce05dd | |||
| 7d089a88c2 | |||
| ab0bc7b314 | |||
| 0e3e97a7fd | |||
| b790c7fd21 | |||
| d0836d49a4 | |||
| 9424b1e369 | |||
| 64463df552 | |||
|
|
61f90bba38 | ||
|
|
fac3dd3946 | ||
|
|
e1b583a2b3 | ||
|
|
8c8dfdd4a3 | ||
|
|
857397e226 | ||
|
|
94340c1c01 | ||
| 8b60ab08e3 | |||
|
|
28e51cc314 | ||
|
|
a7c8d40b3e | ||
| d4c0ff03b4 | |||
| 7fbfda3a66 | |||
| 9e467689df | |||
| dd5c89e31c | |||
| fffa763d05 | |||
| d015c065f6 | |||
| 8ea443c115 | |||
| 019393fdb1 | |||
| da8028f8b3 | |||
| 20ed000879 | |||
|
|
24620b228c | ||
|
|
9c7e29b836 | ||
|
|
a0e9a41e21 | ||
|
|
dd9aff03d3 | ||
|
|
dc35925eb0 | ||
| a1a620a9c3 | |||
| d8ea9ba63c | |||
| c42af5b2de | |||
| d9cbc72058 | |||
| 7e057b20b1 | |||
| 3165c1e5c6 | |||
| 89e26519e4 | |||
| 9d20e85c03 | |||
| 48cb99498c | |||
| 8246bc1444 | |||
| 9e1083eba8 | |||
| 4907bc3085 | |||
| 7d2ce8a77f | |||
| b4a9c92ffc | |||
| bf0eb9a02d | |||
| ddf73077b3 | |||
| 3da80fce0d | |||
| 0970de5dc6 | |||
| 557b11f4e6 | |||
| 7f27a6c797 | |||
| c778e454cd | |||
| 44757b73eb | |||
| 525978db1d | |||
| 71c90a2f39 | |||
| 8057dca032 | |||
| 91d7b956b9 | |||
| 881625a0f6 | |||
| b7a12eddaf | |||
|
|
44b1ccbc3c | ||
|
|
30261632f6 | ||
|
|
08db0748f4 | ||
|
|
9dc22bee24 | ||
|
|
c4d362ff31 | ||
|
|
4a35ff7b77 | ||
|
|
871e9792a5 | ||
| 5f4ab50bf9 | |||
| f0a49aaf0a | |||
| 1aae58e00b | |||
| f81e5251e8 | |||
| b26504b4a1 | |||
| 4eddad0bcb | |||
| 1b9aa0c598 | |||
| 6e52774507 | |||
| e5403462bc | |||
| 33b555ff27 | |||
| 4c552671c1 | |||
| 25a362d043 | |||
| 023e03bb8f | |||
| 0caad2105f | |||
| f14fdc2a69 | |||
| 440d3f9c91 | |||
| 975ef90bab | |||
| 8c63e74b81 | |||
| 6b9d248542 | |||
| 6d2318ac9b | |||
|
|
0f76518b63 | ||
|
|
bb5faec3c6 | ||
|
|
22301fc15d | ||
|
|
f482ef06d5 | ||
|
|
4f62da8f90 | ||
|
|
eaa3dd435a | ||
|
|
e1d1d52260 | ||
| 0cc0ba047f | |||
| 641e114fed | |||
| 73d45c9817 | |||
| 519b959073 | |||
| 2cc751f326 | |||
| 99588faf40 | |||
|
|
9c6b6b978a | ||
| 0647a74875 | |||
|
|
de9d99e6bc | ||
| ae9f67391c | |||
| 82f832a556 | |||
| 19dbbf89e7 | |||
|
|
5d6e3c69ee | ||
|
|
984d04e972 | ||
|
|
83486ae0cc | ||
|
|
4fe5c5da7e | ||
|
|
ec1d8ca52f | ||
|
|
0404627153 | ||
|
|
de282948e6 | ||
|
|
93f1fed997 | ||
| f6ebd414d6 | |||
| ff19adc6c8 | |||
|
|
41d24c91b4 | ||
| 0427f7a8d3 | |||
| 985a5e5ce7 | |||
| fe4c283336 | |||
|
|
20e704604a | ||
|
|
0db02a8c52 | ||
| 1b4b50ee80 | |||
| 446c692f97 | |||
| 7dfc6ea67a | |||
|
|
a5a257f452 | ||
|
|
bde0e2900b | ||
|
|
361773101e | ||
|
|
052860b62c | ||
|
|
c5e1b1ee69 | ||
| 0b1697f20d | |||
| add71543a4 | |||
| 66a1e0629c | |||
| 425c976032 | |||
|
|
397dcc6128 | ||
| a3c403323d | |||
| 942896aa0c | |||
| 93c92c0e38 | |||
| 394ca46f03 | |||
| 67641da44d | |||
|
|
a826051979 | ||
|
|
ce4c62a989 | ||
| b59966595e | |||
| fcf8b63666 | |||
| cad9322839 | |||
| 31fcd61401 | |||
|
|
0b11663da4 | ||
| 5a179f514c | |||
| f099a70b87 | |||
| 1163b99f39 | |||
| ca6ccc7291 | |||
| bb11c24681 | |||
| d158579bdc | |||
| 02f5a09689 | |||
| cb3de17be9 | |||
| fd66d79ecb | |||
| d6b77e938b | |||
| 3c8dc0a9e1 | |||
| fdfeea508e | |||
| 99d0340e1b | |||
| a74cda2f33 | |||
| 322fd80f40 | |||
| 7168941495 | |||
| 161607cf8a | |||
| d45cd032a7 | |||
|
|
9db9a4957a | ||
|
|
d089921ef5 | ||
|
|
7f3ece2da9 | ||
| 4b497060a0 | |||
| d40131f863 | |||
| 9999b5e400 | |||
| 6e27f66306 | |||
| a4c1263190 | |||
| 46920fb991 | |||
| d50b3cb28c | |||
| 6481d2ec7d | |||
| f94820c824 | |||
| 1d0a2363d8 | |||
|
|
2100b856b0 | ||
|
|
e687affd17 | ||
|
|
195f3b4f68 | ||
| cc7d268610 | |||
|
|
acc8cda04f | ||
|
|
7c5637c063 | ||
|
|
b87392906b | ||
|
|
4e7e1e9c45 | ||
| da92d2d365 | |||
| ae0ba66416 | |||
| 718cebc700 | |||
| a2cbcbbbc6 | |||
|
|
c5363c948c | ||
|
|
4f7086a6de | ||
|
|
3c4e15b386 | ||
|
|
6685b3679b | ||
|
|
d6a27c26aa | ||
|
|
e7c4b949f5 | ||
|
|
f89e0abe69 | ||
|
|
cbcf9550f8 | ||
|
|
d4b877f18e | ||
|
|
605a094910 | ||
|
|
a16a7358d1 | ||
|
|
655c95158f | ||
| 9eca723dc5 | |||
| bbc2bab0eb | |||
|
|
fe913b0072 | ||
|
|
9ec2baf7d3 | ||
| cc6d2f3023 | |||
| 2ac717592d | |||
|
|
7ca62463b7 | ||
| 95971618ca | |||
| cb881877ac | |||
|
|
2cc26f98c6 | ||
|
|
47b4357a72 | ||
|
|
a60bd19e58 | ||
|
|
439e43fad9 | ||
|
|
7abbc96347 | ||
|
|
e9b4a8abd5 | ||
| cb7c20a0b7 | |||
| f5c2f9e017 | |||
|
|
45ddc47b0e | ||
|
|
8f148f2a5e | ||
|
|
5c9edeeae8 | ||
|
|
13349d07a8 | ||
| 991389e9b9 | |||
| d8487e6c12 | |||
|
|
b7750b9d06 | ||
|
|
d82cacc18f | ||
|
|
564248284a | ||
|
|
ee473d8844 | ||
|
|
2fb0d73439 | ||
|
|
5dd8a83081 | ||
|
|
f83a8db25c | ||
|
|
a3e5da052e | ||
|
|
942db6d708 | ||
|
|
48deb869de | ||
|
|
69b67b3b4b | ||
|
|
6acdcb4e6d | ||
|
|
e832478b76 | ||
|
|
c8e9a835f5 | ||
|
|
06c5f068db | ||
|
|
b81207e42e | ||
|
|
b312d69afa | ||
|
|
d1238a441d | ||
|
|
580739d0b4 | ||
|
|
093dec1808 | ||
|
|
2fb521aa42 | ||
|
|
992504a49f | ||
|
|
8696681710 | ||
|
|
73ce700ece | ||
|
|
c766881052 | ||
|
|
8bd14f5f21 | ||
|
|
45cd633e12 | ||
|
|
0744e13132 | ||
|
|
320584a693 | ||
|
|
514a44e022 | ||
|
|
191a00649f | ||
|
|
ecfd5738ce | ||
|
|
25fe7c8725 | ||
|
|
dbcb1def29 | ||
|
|
c4acbf563f | ||
|
|
c9599f449f | ||
|
|
e675e8aad9 | ||
|
|
37aac7053a | ||
|
|
9c9a132329 | ||
|
|
ce305d4e54 | ||
|
|
d3c66cd7fe | ||
|
|
7bf95cd927 | ||
|
|
05d4f24f6f | ||
|
|
d9c837918b | ||
|
|
5adee83350 | ||
|
|
720e26d19d | ||
|
|
29356c0b61 | ||
|
|
b39dd5c40d | ||
|
|
1ae44e74e7 | ||
|
|
7a5d1e378d | ||
| c68f6a30e6 | |||
| 07ec0d001f | |||
| 4f15745647 | |||
| 20367851cc | |||
| 2978ec33b7 | |||
| 3d126b04a9 | |||
| 33fd3c8009 | |||
| ea1c8a23cd | |||
| 1827723ccc | |||
|
|
949d3514b8 | ||
|
|
7818b9dc1c | ||
|
|
d15da0ffd4 | ||
|
|
a0665313ed | ||
|
|
8a7bd30ce0 | ||
| f2da98c387 | |||
|
|
51c4e8ab9e | ||
|
|
f369b26d88 | ||
|
|
40bb88a55f | ||
|
|
72e7493842 | ||
|
|
6213021f45 | ||
|
|
eb3fb7e5f7 | ||
|
|
1ec14ec397 | ||
|
|
38f422896d | ||
|
|
3895cf4399 | ||
|
|
7e69fddac9 | ||
| e6f1a06545 | |||
| e20dd076c3 | |||
|
|
a2cc3d8b29 | ||
|
|
fa4cbd8fa8 | ||
|
|
884b6b1339 | ||
|
|
9576779cce | ||
|
|
0721384b60 | ||
|
|
0d79799a5d | ||
|
|
86339d8163 | ||
|
|
64bde6220c | ||
|
|
3406780f65 | ||
|
|
597e0e82b9 | ||
|
|
137af843af | ||
|
|
8a96ed87b1 | ||
|
|
59b0d0d9fa | ||
|
|
c9102af0aa | ||
|
|
6838089570 | ||
|
|
aba60a473a | ||
|
|
9a392ba292 | ||
|
|
85369d5247 | ||
|
|
7c11de3073 | ||
|
|
4d07a6330d | ||
|
|
dad4191c40 | ||
|
|
b70450cfe9 | ||
|
|
10b950a7e7 | ||
|
|
1b831375ef | ||
|
|
a979bf24d4 | ||
|
|
4b11bbb73d | ||
|
|
f1cefd6173 | ||
|
|
ac31e1c29e | ||
|
|
61f032a819 | ||
| 026f8ae608 | |||
| ab07c2e0ce | |||
| 637303930a | |||
|
|
78ee9872bd | ||
| 4dd1731e60 | |||
|
|
2c2770b4f1 | ||
|
|
8c04a9183f | ||
|
|
373e13208f | ||
|
|
250d41c2d7 | ||
|
|
9329ea946e | ||
| ddd19023b0 | |||
| 9b329c8b8a | |||
| 6f48cf80f2 | |||
| 464cbcae80 | |||
| 8c57856232 | |||
| 4f490aaacc | |||
| 3065637c80 | |||
| cf01756c1c | |||
| 58dc2ec792 | |||
| 88e6837222 | |||
| d376f99832 | |||
| 3072ce7dec | |||
|
|
82fdd53adb | ||
|
|
b97073b14a | ||
|
|
9a10e6f2a3 | ||
|
|
60d77892e5 | ||
|
|
9e11931b44 | ||
|
|
8fe7f4db82 | ||
|
|
26e6a62e6b | ||
|
|
d26c68cd1e | ||
|
|
01327a4b06 | ||
|
|
d3299f8e06 | ||
|
|
1100328fee | ||
|
|
cb1a4825d2 | ||
|
|
aa9f4c4ed8 | ||
|
|
c6d59d3366 | ||
|
|
8353f34c45 | ||
|
|
b6c082e1fe | ||
|
|
48251fb872 | ||
|
|
f14728c1a7 | ||
|
|
295e6e9198 | ||
|
|
e21af4a0e8 | ||
|
|
805ac5dacf | ||
|
|
93f8cd789f | ||
|
|
7b0d264aab | ||
|
|
4d0dc964da | ||
|
|
95fd5f93fc | ||
| 0f7dca0701 | |||
| 843955b7b8 | |||
| 88192335b6 | |||
| b04159fb35 | |||
| 1d0eb14918 | |||
|
|
113df6efe1 | ||
|
|
e7951338c9 | ||
|
|
83329ca4b7 | ||
|
|
f51201eae1 | ||
|
|
c52a513378 | ||
|
|
6908bfe7bf | ||
|
|
a5fa428e98 | ||
|
|
24f760c043 | ||
|
|
3f089d6811 | ||
|
|
7e673b4628 | ||
|
|
ca633d3524 | ||
|
|
7dd726ca42 | ||
|
|
3f6caa76dc | ||
|
|
5a18cb4246 | ||
|
|
b33de9985f | ||
|
|
3a9ede6e8c | ||
|
|
87569ccee9 | ||
|
|
16b79ef193 | ||
|
|
f360e8a867 | ||
|
|
57dd4ce259 | ||
|
|
252b5ff758 | ||
|
|
b19598d902 | ||
|
|
b5ef1fbbb5 | ||
|
|
bc864bde39 | ||
|
|
0a2883e040 | ||
|
|
24474e6b31 | ||
| dd31970b01 | |||
| f31ed103d0 | |||
|
|
6c0eeebf27 | ||
| 48f5cb78d5 | |||
|
|
20a768749f | ||
|
|
2d964b1137 | ||
|
|
a1245b77fd | ||
|
|
f2ee91764d | ||
| fff08a29e7 | |||
|
|
a6260ed5a2 | ||
| 2f3a462c42 | |||
|
|
37e6d74a34 | ||
| f8a0bbf88b | |||
|
|
cbd7dc8176 | ||
|
|
1da678f726 | ||
|
|
fccb6776b0 | ||
|
|
f2e85aca42 | ||
|
|
2fbffb8c9e | ||
|
|
dd8bddd45c | ||
|
|
358fe04699 | ||
|
|
647beea245 | ||
|
|
251974fd2f | ||
|
|
81952e7898 | ||
|
|
1ba9792547 | ||
|
|
45e3a6d7cc | ||
|
|
be05edac7d | ||
|
|
6761d22fa8 | ||
|
|
9db93cf4c9 | ||
|
|
15dd993b95 | ||
|
|
0f8444a585 | ||
|
|
6230d643c8 | ||
|
|
cfe452543a | ||
|
|
26ec7d94c6 | ||
|
|
95f823e7a1 | ||
|
|
09544ba6d2 | ||
|
|
15676a7c9e | ||
| b5bdf88bf4 | |||
| 74e96d7816 | |||
| 527e877b30 | |||
|
|
efc1550ab9 | ||
|
|
f53974b138 | ||
|
|
6860860161 | ||
|
|
9c65194d91 | ||
|
|
b1cf630443 | ||
|
|
b3e383ea82 | ||
|
|
36368aff0b | ||
|
|
162735b328 | ||
|
|
27023283e7 | ||
|
|
8fc405fef1 | ||
|
|
44d8903a10 | ||
|
|
113c52f6b0 | ||
|
|
e29a4c8c8a | ||
| 9499601daf | |||
|
|
0887f7d22f | ||
|
|
327ecff63a | ||
|
|
55e91bff7f | ||
|
|
8b179fd98d | ||
|
|
e5841f2dad | ||
|
|
d45405f261 | ||
|
|
133ed9a0be | ||
|
|
33220b2b8e | ||
|
|
f542975872 | ||
| ed9fac0545 | |||
|
|
4dd4678b65 | ||
|
|
bbd48d24e4 | ||
| 3b66d77ddc | |||
| fc5ef995bc | |||
| 4c5fa0ed61 | |||
| ea9161b2f2 | |||
| 3c139315e5 | |||
| 15a96a402d | |||
| 5959099c55 | |||
|
|
9f40c6355c | ||
|
|
0fcb80aa29 | ||
|
|
59a12dcac1 | ||
|
|
eb47c101ca | ||
|
|
c67a7f4982 | ||
|
|
aba394502c | ||
|
|
0c265f4f78 | ||
|
|
32518cfb41 | ||
|
|
225f821206 | ||
|
|
f506d9e925 | ||
|
|
edce18fb1f | ||
|
|
ad15ab13c5 | ||
|
|
f52f6512a0 | ||
|
|
7bdafbd21e | ||
|
|
6486c8c472 | ||
|
|
fb345c5f0c | ||
|
|
deaeaa434d | ||
|
|
f9cc0afb9e | ||
|
|
ee0400463f | ||
|
|
fa35c22d2d | ||
|
|
422b73058c | ||
|
|
c50a46206d | ||
|
|
f866c067cb | ||
|
|
811d087d74 | ||
|
|
633243311d | ||
|
|
f5d5381fae | ||
|
|
bbc3249212 | ||
|
|
625b8803df | ||
|
|
0d8090b6f4 | ||
|
|
718c0af085 | ||
|
|
5a94264dc0 | ||
|
|
8269f3ea5b | ||
|
|
d6333362a7 | ||
|
|
3e43fd52ae | ||
|
|
1111333223 | ||
|
|
ae9952a941 | ||
|
|
3b2ad80dc3 | ||
|
|
1c08439c1a | ||
|
|
16c89180d2 | ||
|
|
bc6b4f90c3 | ||
|
|
275cc7aa21 | ||
|
|
e186475a81 | ||
|
|
595d0c501a | ||
|
|
4e09a15454 | ||
|
|
b7ab840d71 | ||
|
|
b72e6871e8 | ||
|
|
f14ea29636 | ||
|
|
cb7f1f0ee3 | ||
|
|
ef34217a6d | ||
|
|
ab7ee8e4c3 | ||
|
|
1a1df35ff1 | ||
|
|
0c0fb5c9c8 | ||
|
|
c29a6ad195 | ||
|
|
6fdffb7418 | ||
|
|
8db642cf3b | ||
|
|
850a05d6bb | ||
|
|
74995101d1 | ||
|
|
fa5d13e19d | ||
|
|
9f7e72f0a4 | ||
|
|
c224bf1bb1 | ||
|
|
b5b71a3db0 | ||
|
|
cc1abfd1f9 | ||
|
|
771c91227e | ||
|
|
1276ea0d1b | ||
|
|
611ce6eb9c | ||
|
|
2870df8478 | ||
|
|
59b2163a62 | ||
|
|
065318749b | ||
|
|
600ee095cc | ||
|
|
ecb49619da | ||
|
|
b73939d0a0 | ||
|
|
6c83639149 | ||
|
|
e77ee9bdf3 | ||
|
|
9449f0d16e | ||
|
|
4ff29e1fb3 | ||
|
|
4de85df5b6 | ||
|
|
294ccb04d3 | ||
|
|
4f0567ad88 | ||
|
|
65c613d0a4 | ||
|
|
a16bca2f29 | ||
| 517720c99c | |||
|
|
86e942ae0a | ||
| 9938cc941d | |||
| 2651171294 | |||
| 07f71dfc4e | |||
| 51730e0877 | |||
| 9958bb27a1 | |||
|
|
37b94bbf0d | ||
|
|
3ae898476f | ||
|
|
eefe547553 | ||
|
|
2903a1d3cd | ||
|
|
0755e2d2bc | ||
|
|
b5957d0f59 | ||
|
|
143608fd85 | ||
|
|
b2d9fe1a4b | ||
|
|
aff7948c65 | ||
|
|
bcdfcdd468 | ||
|
|
5e62d82e9c | ||
|
|
275c26b55b | ||
|
|
123fc8252e | ||
|
|
c93e50a7e2 | ||
|
|
9c8bc59224 | ||
|
|
b074570e99 | ||
|
|
bf5bae803d | ||
|
|
35224b1b17 | ||
|
|
2ed362f5d3 | ||
|
|
fe971d07ec | ||
|
|
f82456f352 | ||
|
|
bbbf958d7d | ||
|
|
4c901c3130 | ||
|
|
eade6d584c | ||
|
|
9c8a034a04 | ||
|
|
2dac1ff6c9 | ||
|
|
e9013e548b | ||
|
|
bc976c37b1 | ||
|
|
3249c377f1 | ||
|
|
2415a57ab0 | ||
|
|
7e4f51a7ce | ||
|
|
10caa4c1df | ||
|
|
a552b8fcfa | ||
|
|
9395e31c53 | ||
|
|
ce04737d46 | ||
|
|
259815467c | ||
|
|
3b517d3c53 | ||
|
|
c261f02c84 | ||
|
|
7815557f84 | ||
|
|
090e294f10 | ||
|
|
33d523e5bf | ||
|
|
7bc09bda8f | ||
|
|
45fd51b4b5 | ||
|
|
f3849679e8 | ||
|
|
bf0a8e8efb | ||
|
|
84c3039806 | ||
|
|
0c4a410ac0 | ||
|
|
b55f363651 | ||
|
|
7dd36014cc | ||
|
|
78ff0134c7 | ||
|
|
69da6c6d06 | ||
|
|
277eb0b4b6 | ||
|
|
8dbd24afd1 | ||
|
|
0a9d208529 | ||
|
|
8ab6dba1c8 | ||
|
|
e0bfdab106 | ||
|
|
fd09b39c1d | ||
| 8e743f3253 | |||
| 8d9dca1a94 | |||
| 5753af3e43 | |||
|
|
63f1976663 | ||
|
|
4b87a00637 | ||
|
|
8d12d1c0bc | ||
|
|
2c3d5b6f59 | ||
|
|
e8c66fa769 | ||
|
|
09f32e7025 | ||
|
|
0fca8daeb1 | ||
|
|
285e295b5a | ||
|
|
e6371c7adc | ||
|
|
ab7ff11cb6 | ||
|
|
ba11e84ed6 | ||
| 2676b16425 | |||
| f7012e5b85 | |||
| a149d8de97 | |||
| eea8894724 | |||
| 5b988ab760 | |||
| 88a38509de | |||
|
|
6dee9e85b5 | ||
|
|
2d795eb3c1 | ||
|
|
717b0f7ba8 | ||
|
|
2d373cab5b | ||
|
|
e20f45b2c3 | ||
|
|
917388b99e | ||
|
|
ed1f899534 | ||
|
|
60a80209dc | ||
|
|
e4f495b282 | ||
|
|
0efcd3cd07 | ||
| c216b96707 | |||
| cb3f983b91 | |||
| dc25723a35 | |||
| 8040dd5826 | |||
|
|
42ba1588c6 | ||
|
|
d0fda6de66 | ||
|
|
cef69039f5 | ||
|
|
cdf3a25f88 | ||
|
|
d1a0229944 | ||
|
|
63beaabfa0 | ||
|
|
caac696465 | ||
|
|
c741e41597 | ||
|
|
60fa076796 | ||
|
|
7dbed3ade1 | ||
|
|
a6cad7e811 | ||
|
|
47da8c17ea | ||
|
|
ad5b52f4e4 | ||
|
|
7679898159 | ||
|
|
d344df6e7e | ||
|
|
e0c3c783fa | ||
|
|
30663dc9fb | ||
|
|
8db7d0daa3 | ||
|
|
48bc71c6e3 | ||
|
|
2d3dadc85e | ||
|
|
e5765d356f | ||
|
|
f8f1773d18 | ||
|
|
15782c7795 | ||
|
|
b777e81ab1 | ||
|
|
e29346dec8 | ||
|
|
8535a8378c | ||
|
|
dcdc700bac | ||
|
|
31c2be768f | ||
|
|
9180667ac4 | ||
|
|
4f79bf2add | ||
|
|
9eaada0bdb | ||
|
|
c7e6fe38fb | ||
|
|
9e8548d65a | ||
|
|
3c41ca0864 | ||
|
|
c344ecceec | ||
|
|
ce2ca051f6 | ||
|
|
c63e307179 | ||
|
|
1daab0598a | ||
|
|
98ad77a57d | ||
|
|
b4ab4875fc | ||
|
|
6ead464a6b | ||
|
|
3d36c353fc | ||
|
|
0eff04c847 | ||
|
|
2b92ba9e62 | ||
|
|
c23bf7a05d | ||
|
|
92cbf48b49 | ||
|
|
1dc6ff6df1 | ||
|
|
e72ffab2ca | ||
|
|
e7a06ebc2e | ||
|
|
e12e0b35ee | ||
|
|
c6dac0384b | ||
|
|
e48cee9b4a | ||
|
|
9229b66091 | ||
|
|
eea428831c | ||
|
|
ad12d3e16d | ||
|
|
b1fcedf501 | ||
|
|
2b00192e87 | ||
|
|
2b82e7f07f | ||
|
|
f820d25a9e | ||
|
|
6e76747772 | ||
|
|
15d12b86aa |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,4 +3,5 @@ tests/temp/
|
||||
.svn/
|
||||
*.swp
|
||||
*~
|
||||
*.scm
|
||||
*#
|
||||
|
||||
@@ -1,38 +1,7 @@
|
||||
History for Eiffel-Web-Framework
|
||||
[2015-06-10]
|
||||
* Updated EWF design to better support concurrency, including SCOOP via
|
||||
the new standalone connector.
|
||||
|
||||
[2011-09-23] Jocelyn
|
||||
* library "ewsgi":
|
||||
- NEW simple autotest cases using Nino web server
|
||||
-fixed issue with RAW_POST_DATA being added in form_data_parameters
|
||||
instead of meta_variables ...
|
||||
- Implemented WGI_VALUE for parameter's type (query_parameter,
|
||||
form_data_parameter, item ...)
|
||||
* Nino connector: added feature to shutdown the server from the WGI application
|
||||
* NEW library "http_client": a new library to perform simple http requests
|
||||
such as get, head, post, put, ... (currently implemented with Eiffel cURL)
|
||||
* NEW library "http_authorization": added simple library to support
|
||||
HTTP_AUTHORIZATION. For now only "Basic" auth type is supported ..
|
||||
|
||||
[2011-09-22] Javier
|
||||
* NEW Example: added partial Restbuck example
|
||||
|
||||
[2011-09-21] Jocelyn
|
||||
* Nino connector: fixed an issue with missing value for Content-Type and Content-Length
|
||||
|
||||
[2011-09-13] Jocelyn
|
||||
* library "router": now using a generic design to allow customization of
|
||||
request handler context class.
|
||||
* NEW library "server/request/rest": first attempt to provide a library to
|
||||
help building RESTful application (the interfaces are likely to change
|
||||
soon) EXPERIMENTAL
|
||||
|
||||
[2011-09-09] Jocelyn
|
||||
* library "uri-template": better support for {/vars} and {?vars}
|
||||
|
||||
[2011-09-07] Jocelyn
|
||||
* library "router": now routing depends on uri (or uri template) and request methods
|
||||
* Nino connector: Fixed issue where HTTP_ prefix were missing for header meta variable.
|
||||
|
||||
[2011-09-07] Jocelyn
|
||||
* changelog: starting to write down changelogs file
|
||||
|
||||
[Previous ] Many significant changes in v0
|
||||
|
||||
142
CONTRIBUTING.md
Normal file
142
CONTRIBUTING.md
Normal file
@@ -0,0 +1,142 @@
|
||||
# Contributing to this project
|
||||
|
||||
Please take a moment to review this document in order to make the contribution
|
||||
process easy and effective for everyone involved.
|
||||
|
||||
Following these guidelines helps to communicate that you respect the time of
|
||||
the developers managing and developing this open source project. In return,
|
||||
they should reciprocate that respect in addressing your issue or assessing
|
||||
patches and features.
|
||||
|
||||
|
||||
## Using the issue tracker
|
||||
|
||||
The issue tracker is the preferred channel for [bug reports](#bugs),
|
||||
[features requests](#features) and [submitting pull
|
||||
requests](#pull-requests), but please respect the following restrictions:
|
||||
|
||||
* Please **do not** use the issue tracker for personal support requests (use
|
||||
[Stack Overflow](http://stackoverflow.com) or IRC).
|
||||
|
||||
* Please **do not** derail or troll issues. Keep the discussion on topic and
|
||||
respect the opinions of others.
|
||||
|
||||
|
||||
<a name="bugs"></a>
|
||||
## Bug reports
|
||||
|
||||
A bug is a _demonstrable problem_ that is caused by the code in the repository.
|
||||
Good bug reports are extremely helpful - thank you!
|
||||
|
||||
Guidelines for bug reports:
|
||||
|
||||
1. **Use the GitHub issue search** — check if the issue has already been
|
||||
reported.
|
||||
|
||||
2. **Check if the issue has been fixed** — try to reproduce it using the
|
||||
latest `master` or development branch in the repository.
|
||||
|
||||
3. **Isolate the problem** — ideally create a [reduced test
|
||||
case](http://css-tricks.com/6263-reduced-test-cases/) and a live example.
|
||||
|
||||
A good bug report shouldn't leave others needing to chase you up for more
|
||||
information. Please try to be as detailed as possible in your report. What is
|
||||
your environment? What steps will reproduce the issue? What browser(s) and OS
|
||||
experience the problem? What would you expect to be the outcome? All these
|
||||
details will help people to fix any potential bugs.
|
||||
|
||||
Example:
|
||||
|
||||
> Short and descriptive example bug report title
|
||||
>
|
||||
> A summary of the issue and the browser/OS environment in which it occurs. If
|
||||
> suitable, include the steps required to reproduce the bug.
|
||||
>
|
||||
> 1. This is the first step
|
||||
> 2. This is the second step
|
||||
> 3. Further steps, etc.
|
||||
>
|
||||
> `<url>` - a link to the reduced test case
|
||||
>
|
||||
> Any other information you want to share that is relevant to the issue being
|
||||
> reported. This might include the lines of code that you have identified as
|
||||
> causing the bug, and potential solutions (and your opinions on their
|
||||
> merits).
|
||||
|
||||
|
||||
<a name="features"></a>
|
||||
## Feature requests
|
||||
|
||||
Feature requests are welcome. But take a moment to find out whether your idea
|
||||
fits with the scope and aims of the project. It's up to *you* to make a strong
|
||||
case to convince the project's developers of the merits of this feature. Please
|
||||
provide as much detail and context as possible.
|
||||
|
||||
|
||||
<a name="pull-requests"></a>
|
||||
## Pull requests
|
||||
|
||||
Good pull requests - patches, improvements, new features - are a fantastic
|
||||
help. They should remain focused in scope and avoid containing unrelated
|
||||
commits.
|
||||
|
||||
**Please ask first** before embarking on any significant pull request (e.g.
|
||||
implementing features, refactoring code, porting to a different language),
|
||||
otherwise you risk spending a lot of time working on something that the
|
||||
project's developers might not want to merge into the project.
|
||||
|
||||
Please adhere to the coding conventions used throughout a project (indentation,
|
||||
accurate comments, etc.) and any other requirements (such as test coverage).
|
||||
|
||||
Adhering to the following this process is the best way to get your work
|
||||
included in the project:
|
||||
|
||||
1. [Fork](http://help.github.com/fork-a-repo/) the project, clone your fork,
|
||||
and configure the remotes:
|
||||
|
||||
```bash
|
||||
# Clone your fork of the repo into the current directory
|
||||
git clone https://github.com/<your-username>/<repo-name>
|
||||
# Navigate to the newly cloned directory
|
||||
cd <repo-name>
|
||||
# Assign the original repo to a remote called "upstream"
|
||||
git remote add upstream https://github.com/<upstream-owner>/<repo-name>
|
||||
```
|
||||
|
||||
2. If you cloned a while ago, get the latest changes from upstream:
|
||||
|
||||
```bash
|
||||
git checkout <dev-branch>
|
||||
git pull upstream <dev-branch>
|
||||
```
|
||||
|
||||
3. Create a new topic branch (off the main project development branch) to
|
||||
contain your feature, change, or fix:
|
||||
|
||||
```bash
|
||||
git checkout -b <topic-branch-name>
|
||||
```
|
||||
|
||||
4. Commit your changes in logical chunks. Please adhere to these [git commit
|
||||
message guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
|
||||
or your code is unlikely be merged into the main project. Use Git's
|
||||
[interactive rebase](https://help.github.com/articles/interactive-rebase)
|
||||
feature to tidy up your commits before making them public.
|
||||
|
||||
5. Locally merge (or rebase) the upstream development branch into your topic branch:
|
||||
|
||||
```bash
|
||||
git pull [--rebase] upstream <dev-branch>
|
||||
```
|
||||
|
||||
6. Push your topic branch up to your fork:
|
||||
|
||||
```bash
|
||||
git push origin <topic-branch-name>
|
||||
```
|
||||
|
||||
7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/)
|
||||
with a clear title and description.
|
||||
|
||||
**IMPORTANT**: By submitting a patch, you agree to allow the project owner to
|
||||
license your work under the same license as that used by the project.
|
||||
121
MIGRATION.md
Normal file
121
MIGRATION.md
Normal file
@@ -0,0 +1,121 @@
|
||||
Date: 2015-june
|
||||
|
||||
# Goal:
|
||||
=======
|
||||
- support safe concurrency with EWF
|
||||
- provide a concurrent standalone connector
|
||||
|
||||
# Status:
|
||||
=========
|
||||
- The version v0 of EWF has mainly 3 connectors: CGI, libFCGI, and nino.
|
||||
- CGI and libFCGI connectors does not need any concurrency support.
|
||||
- But the nino connector had a pseudo concurrency support with Thread, however one could do write code that result in hasardeous concurrency execution.
|
||||
|
||||
So, it was decided to provide an improved Eiffel web nino connector, and update EWF design to make it concurrency compliant.
|
||||
|
||||
# Decisions:
|
||||
============
|
||||
- instead of updating current nino library, we now have a new "standalone" connector which is inspired by nino, but have support for the 3 concurrency modes: none, thread and SCOOP.
|
||||
|
||||
|
||||
# Overview
|
||||
==========
|
||||
Adding support for SCOOP concurrency mode add constraints to the design, but also helps ensuring the concurrency design of EWF is correct.
|
||||
|
||||
As a consequence, we had to introduce a new interface WSF_EXECUTION which is instantiated for each incoming request. See its simplified interface :
|
||||
<code lang="eiffel">
|
||||
deferred class WSF_EXECUTION
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make (req: WGI_REQUEST; res: WGI_RESPONSE)
|
||||
do
|
||||
...
|
||||
īnitialize
|
||||
end
|
||||
|
||||
initialize
|
||||
-- Initialize Current object.
|
||||
--| To be redefined if needed.
|
||||
do
|
||||
end
|
||||
|
||||
|
||||
feature -- Access
|
||||
|
||||
request: WSF_REQUEST
|
||||
-- Access to request data.
|
||||
-- Header, Query, Post, Input data..
|
||||
|
||||
response: WSF_RESPONSE
|
||||
-- Access to output stream, back to the client.
|
||||
|
||||
feature -- Execution
|
||||
|
||||
execute
|
||||
-- Execute Current `request',
|
||||
-- getting data from `request'
|
||||
-- and response to client via `response'.
|
||||
deferred
|
||||
ensure
|
||||
is_valid_end_of_execution: is_valid_end_of_execution
|
||||
end
|
||||
|
||||
end
|
||||
</code>
|
||||
|
||||
And the related request execution routines are extracted from WSF_SERVICE which becomes almost useless. The "service" part is not mostly responsible of launching the expected connector and set optional options, and declare the type of "execution" interface.
|
||||
|
||||
As a result, the well known WSF_DEFAULT_SERVICE has now a formal generic that should conform to WSF_EXECUTION with a `make' creation procedure. See update code:
|
||||
|
||||
<code lang="eiffel">
|
||||
class
|
||||
APPLICATION
|
||||
|
||||
inherit
|
||||
WSF_DEFAULT_SERVICE [APPLICATION_EXECUTION]
|
||||
redefine
|
||||
initialize
|
||||
end
|
||||
|
||||
create
|
||||
make_and_launch
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
initialize
|
||||
-- Initialize current service.
|
||||
do
|
||||
set_service_option ("port", 9090)
|
||||
end
|
||||
|
||||
end
|
||||
</code>
|
||||
|
||||
Where APPLICATION_EXECUTION is an implementation of the WSF_EXECUTION interface (with the `make' creation procedure).
|
||||
|
||||
In addition to add better and safer concurrency support, there are other advantages:
|
||||
- we now have a clear separation between the service launcher, and the request execution itself.
|
||||
- the WSF_EXECUTION is created per request, with two main attributes <code>request: WSF_REQUEST</code> and <code>response: WSF_RESPONSE</code>.
|
||||
|
||||
# How to migrate to new design
|
||||
- you can check the various example from the EWF repository, there should all be migrated to new design and comparing previous and new code, this will show you how the migration was done.
|
||||
- a frequent process:
|
||||
- identify the root class of your service, (the class implementing the WSF_SERVICE), let us name it APPLICATION_SERVICE
|
||||
- copy the APPLICATION_SERVICE file to APPLICATION_EXECUTION file.
|
||||
- change the class name to be APPLICATION_EXECUTION, and replace _SERVICE occurences by _EXECUTION (note the new WSF_ROUTED_EXECUTION and so on, which are mainly migration from previous WSF_ROUTED_SERVICE .., and also WSF_FILTERED_ROUTED_EXECUTION which is new.
|
||||
- replace "make_and_launch" by "make", remove the initialize redefinition if any.
|
||||
- in the APPLICATION_SERVICE class, remove most of the ROUTED, FILTERED ... inheritance, and keep WSF_DEFAULT_SERVICE, with a new formal generic i.e WSF_DEFAULT_SERVICE [APPLICATION_EXECUTION].
|
||||
- in the eventual redefined initialize, remove code related to routers, filters, ...
|
||||
- remove all the execution related code.
|
||||
- And you should be done.
|
||||
- To be short, this is mostly creating a new _EXECUTION class, and move the execution related code into this class from the _SERVICE class.
|
||||
- Then, you can replace the usage of nino connector by using the new "Standalone" connector, and switch to SCOOP concurrency mode, to ensure you are not messing up with concurrency. Your own code/libraris may not be SCOOP compliant, we recommend to migrate to SCOOP, but as an intermediate solutioņ, you can use the other concurrency mode (none or thread).
|
||||
|
||||
Note: the new design impacts the _SERVICE classes, connectors, but WSF_REQUEST, WSF_RESPONSE , WSF_ROUTER are compatible, so the migration is really easy.
|
||||
|
||||
We may take the opportunity to update the design deeper according to user feedback, and eventually "wsf" library will be renamed "wsf2".
|
||||
This is work in progress, all comments , feedback, suggestions, bug report are welcome.
|
||||
Hopefully before the final version of the new design is out.
|
||||
|
||||
|
||||
68
README.md
68
README.md
@@ -3,6 +3,27 @@
|
||||
|
||||
## Overview
|
||||
|
||||
The Eiffel Web Framework (EWF) provides Eiffel users with a layer to build anything on top of the http protocol such as websites, web API/services.
|
||||
|
||||
This layer is multi-platform: it can be set on Windows, Linux operating systems, and in addition it can run on top of any httpd servers such as Apache2, IIS, nginx, lighttpd. EWF includes as well a standalone httpd web server component, written in Eiffel, which enables users to run easily a web server on their machine, or even embed this component in any application written with Eiffel.
|
||||
|
||||
Currently EWF offers a collection of Eiffel libraries designed to be integrated with each others, and among other functionalities, it give simple access to the request data, to handle content negotiation, url dispatcher, integrate with openid system, and so on.
|
||||
|
||||
There is a growing ecosystem around EWF, that provides useful components:
|
||||
* OpenID and OAuth consumer library
|
||||
* Various hypermedia format such as HAL, Collection+json, …
|
||||
* Websocket server and client
|
||||
* Template engine
|
||||
* API Auto-documentation with swagger
|
||||
* A simple experimental CMS.
|
||||
* ...
|
||||
|
||||
So if you want to build a website, a web api, RESTful service, …or even if you want to consume other web api, EWF is a solution.
|
||||
|
||||
EWF brings with it all the advantages of the Eiffel technology and tools with its powerful features such as Design by Contract, debugging, testing tools which enable to build efficient systems expected to be repeatedly refined, extended, and improved in a predictable and controllable way so as to become with time bugfree systems. Enjoy the full power of debugging your web server application from the IDE.
|
||||
|
||||
## Project
|
||||
|
||||
Official project site for Eiffel Web Framework:
|
||||
|
||||
* http://eiffelwebframework.github.com/EWF/
|
||||
@@ -14,26 +35,21 @@ For more information please have a look at the related wiki:
|
||||
For download, check
|
||||
* https://github.com/EiffelWebFramework/EWF/downloads
|
||||
|
||||
Tasks and issues are managed with github issue system
|
||||
* See https://github.com/EiffelWebFramework/EWF/issues
|
||||
* And visual dashboard: https://waffle.io/eiffelwebframework/ewf
|
||||
* Forum/group post: https://groups.google.com/forum/#!forum/eiffel-web-framework
|
||||
|
||||
## Requirements
|
||||
* Compiling from EiffelStudio 7.0
|
||||
* Developped using EiffelStudio 7.1 (on Windows, Linux)
|
||||
* Tested using EiffelStudio 7.1 with "jenkins" CI server (not anymore compatible with 6.8 due to use of `TABLE_ITERABLE')
|
||||
* Compiling from EiffelStudio 13.11 to 15.05 and more recent version of the compiler.
|
||||
* Currently being developped using EiffelStudio 15.01 (on Windows, Linux)
|
||||
* Tested using EiffelStudio 15.01 with "jenkins" CI server (not anymore compatible with 6.8 due to use of `TABLE_ITERABLE')
|
||||
* The code have to allow __void-safe__ compilation and non void-safe system (see [more about void-safety](http://docs.eiffel.com/book/method/void-safe-programming-eiffel) )
|
||||
|
||||
## How to get the source code?
|
||||
|
||||
Using git version >= 1.6.5
|
||||
* git clone --recursive https://github.com/EiffelWebFramework/EWF.git
|
||||
|
||||
Otherwise, try
|
||||
Using git
|
||||
* git clone https://github.com/EiffelWebFramework/EWF.git
|
||||
* cd Eiffel-Web-Framework
|
||||
* git submodule update --init
|
||||
* git submodule foreach --recursive git checkout master
|
||||
|
||||
An alternative to the last 2 instructions is to use the script from tools folder:
|
||||
* cd tools
|
||||
* update_git_working_copy
|
||||
|
||||
* And to build the required and related Clibs
|
||||
* cd contrib/ise_library/cURL
|
||||
@@ -51,7 +67,7 @@ An alternative to the last 2 instructions is to use the script from tools folder
|
||||
### protocol
|
||||
* __http__: HTTP related classes, constants for status code, content types, ... [read more](library/protocol/http)
|
||||
* __uri_template__: URI Template library (parsing and expander) [read more](library/protocol/uri_template)
|
||||
* __CONNEG__: CONNEG library (Content-type Negociation) [read more](library/protocol/CONNEG)
|
||||
* __CONNEG__: Content negotiation library (Content-type Negociation) [read more](library/protocol/content_negotiation)
|
||||
|
||||
### client
|
||||
* __http_client__: simple HTTP client based on cURL [read more](library/client/http_client)
|
||||
@@ -59,10 +75,6 @@ An alternative to the last 2 instructions is to use the script from tools folder
|
||||
### text
|
||||
* __encoder__: Various simpler encoders: base64, url-encoder, xml entities, html entities [read more](library/text/encoder)
|
||||
|
||||
### crypto
|
||||
* eel
|
||||
* eapml
|
||||
|
||||
### Others
|
||||
* error: very simple/basic library to handle error
|
||||
|
||||
@@ -75,6 +87,24 @@ An alternative to the last 2 instructions is to use the script from tools folder
|
||||
## Examples
|
||||
..
|
||||
|
||||
## Contributing to this project
|
||||
|
||||
Anyone and everyone is welcome to contribute. Please take a moment to
|
||||
review the [guidelines for contributing](CONTRIBUTING.md).
|
||||
|
||||
* [Bug reports](CONTRIBUTING.md#bugs)
|
||||
* [Feature requests](CONTRIBUTING.md#features)
|
||||
* [Pull requests](CONTRIBUTING.md#pull-requests)
|
||||
|
||||
## Community
|
||||
|
||||
Keep track of development and community news.
|
||||
|
||||
* Follow [@EiffelWeb](https://twitter.com/EiffelWeb) on Twitter
|
||||
* [Forum](https://groups.google.com/forum/#!forum/eiffel-web-framework) on Google groups.
|
||||
* Follow our [page](https://plus.google.com/u/0/110650349519032194479) and [community](https://plus.google.com/communities/110457383244374256721) on Google+
|
||||
* Have a question that's not a feature request or bug report? [Ask on the mailing list](http://groups.google.com/group/eiffel-web-framework)
|
||||
|
||||
|
||||
For more information please have a look at the related wiki:
|
||||
* https://github.com/EiffelWebFramework/EWF/wiki
|
||||
|
||||
@@ -29,7 +29,9 @@
|
||||
|
||||
<target name="_build_tpl_" >
|
||||
<argument name="_target_name" />
|
||||
<geant target="${_target_name}" dir="ise_library" file="build.eant" reuse_variables="true" />
|
||||
<!--
|
||||
<geant target="${_target_name}" dir="library" file="build.eant" reuse_variables="true" />
|
||||
-->
|
||||
</target>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<project name="build_library" default="help">
|
||||
<description>
|
||||
description: "Compile Eiffel Web Framework / Contrib / ISE library"
|
||||
</description>
|
||||
|
||||
<target name="help">
|
||||
<echo message="usage:"/>
|
||||
<echo message=" geant compile"/>
|
||||
<echo message=" geant clean"/>
|
||||
<echo message=" geant clobber"/>
|
||||
</target>
|
||||
|
||||
<target name="compile" >
|
||||
<echo message="- Compile ise_library" />
|
||||
<geant target="_build_tpl_" arguments="compile" />
|
||||
</target>
|
||||
|
||||
<target name="clean" >
|
||||
<echo message="- Clean ise_library" />
|
||||
<geant target="_build_tpl_" arguments="clean" />
|
||||
</target>
|
||||
|
||||
<target name="clobber" >
|
||||
<echo message="- Clobber ise_library" />
|
||||
<geant target="_build_tpl_" arguments="clobber" />
|
||||
</target>
|
||||
|
||||
<target name="_build_tpl_" >
|
||||
<argument name="_target_name" />
|
||||
<geant target="${_target_name}" dir="cURL" file="build.eant" reuse_variables="true" />
|
||||
</target>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,82 @@
|
||||
note
|
||||
description: "Summary description for {TCP_STREAM_SOCKET}."
|
||||
date: "$Date: 2015-02-16 19:53:13 +0100 (lun., 16 févr. 2015) $"
|
||||
revision: "$Revision: 96642 $"
|
||||
|
||||
class
|
||||
TCP_STREAM_SOCKET
|
||||
|
||||
inherit
|
||||
NETWORK_STREAM_SOCKET
|
||||
redefine
|
||||
make
|
||||
end
|
||||
|
||||
create
|
||||
make_server_by_address_and_port,
|
||||
make_server_by_port
|
||||
|
||||
create {NETWORK_STREAM_SOCKET}
|
||||
make_from_descriptor_and_address
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Create a network stream socket.
|
||||
do
|
||||
Precursor
|
||||
set_reuse_address
|
||||
end
|
||||
|
||||
make_server_by_address_and_port (an_address: INET_ADDRESS; a_port: INTEGER)
|
||||
-- Create server socket on `an_address' and `a_port'.
|
||||
require
|
||||
valid_port: a_port >= 0
|
||||
do
|
||||
make
|
||||
create address.make_from_address_and_port (an_address, a_port)
|
||||
bind
|
||||
end
|
||||
|
||||
feature -- Basic operation
|
||||
|
||||
send_message (a_msg: STRING)
|
||||
local
|
||||
a_package : PACKET
|
||||
a_data : MANAGED_POINTER
|
||||
c_string : C_STRING
|
||||
do
|
||||
create c_string.make (a_msg)
|
||||
create a_data.make_from_pointer (c_string.item, a_msg.count + 1)
|
||||
create a_package.make_from_managed_pointer (a_data)
|
||||
send (a_package, 1)
|
||||
end
|
||||
|
||||
feature -- Output
|
||||
|
||||
put_readable_string_8 (s: READABLE_STRING_8)
|
||||
-- Write readable string `s' to socket.
|
||||
local
|
||||
ext: C_STRING
|
||||
do
|
||||
create ext.make (s)
|
||||
put_managed_pointer (ext.managed_data, 0, s.count)
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
try_ready_for_reading: BOOLEAN
|
||||
-- Is data available for reading from the socket right now?
|
||||
require
|
||||
socket_exists: exists
|
||||
local
|
||||
retval: INTEGER
|
||||
do
|
||||
retval := c_select_poll_with_timeout (descriptor, True, 0)
|
||||
Result := (retval > 0)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2015, Javier Velilla and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
@@ -17,7 +17,8 @@ create
|
||||
make_server_by_port
|
||||
|
||||
create {NETWORK_STREAM_SOCKET}
|
||||
make_from_descriptor_and_address
|
||||
make_from_descriptor_and_address,
|
||||
make_empty
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
@@ -77,6 +78,6 @@ feature -- Status report
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Javier Velilla and others"
|
||||
copyright: "2011-2015, Javier Velilla and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="nino" uuid="32C1D67D-33DE-4F1E-864B-D45388F2E3E6" library_target="nino">
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-12-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-12-0 http://www.eiffel.com/developers/xml/configuration-1-12-0.xsd" name="nino" uuid="32C1D67D-33DE-4F1E-864B-D45388F2E3E6" library_target="nino">
|
||||
<target name="nino">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
@@ -8,13 +8,28 @@
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" is_attached_by_default="true" void_safety="all">
|
||||
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="all" syntax="transitional">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="net" location="$ISE_LIBRARY\library\net\net-safe.ecf"/>
|
||||
<library name="thread" location="$ISE_LIBRARY\library\thread\thread-safe.ecf"/>
|
||||
<cluster name="nino" location=".\library\" recursive="true"/>
|
||||
<cluster name="nino" location=".\library\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>spec</exclude>
|
||||
</file_rule>
|
||||
<file_rule>
|
||||
<exclude>tcp_stream_socket.e</exclude>
|
||||
<condition>
|
||||
<version type="compiler" max="15.01.9.6506"/>
|
||||
</condition>
|
||||
</file_rule>
|
||||
</cluster>
|
||||
<cluster name="spec_before_15_01" location=".\library\spec\before_15_01\" recursive="true">
|
||||
<condition>
|
||||
<version type="compiler" max="15.01.9.6506"/>
|
||||
</condition>
|
||||
</cluster>
|
||||
</target>
|
||||
</system>
|
||||
|
||||
@@ -15,6 +15,21 @@
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
<library name="net" location="$ISE_LIBRARY\library\net\net.ecf"/>
|
||||
<library name="thread" location="$ISE_LIBRARY\library\thread\thread.ecf"/>
|
||||
<cluster name="nino" location=".\library\" recursive="true"/>
|
||||
<cluster name="nino" location=".\library\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>spec</exclude>
|
||||
</file_rule>
|
||||
<file_rule>
|
||||
<exclude>tcp_stream_socket.e</exclude>
|
||||
<condition>
|
||||
<version type="compiler" max="15.01.9.6506"/>
|
||||
</condition>
|
||||
</file_rule>
|
||||
</cluster>
|
||||
<cluster name="spec_before_15_01" location=".\library\spec\before_15_01\" recursive="true">
|
||||
<condition>
|
||||
<version type="compiler" max="15.01.9.6506"/>
|
||||
</condition>
|
||||
</cluster>
|
||||
</target>
|
||||
</system>
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
15
contrib/library/network/server/nino/package.iron
Normal file
15
contrib/library/network/server/nino/package.iron
Normal file
@@ -0,0 +1,15 @@
|
||||
package nino
|
||||
|
||||
project
|
||||
nino = "nino-safe.ecf"
|
||||
nino = "nino.ecf"
|
||||
|
||||
note
|
||||
title: Eiffel Nino Web Server
|
||||
description: Simple HTTPd server written in Eiffel
|
||||
tags: web, httpd, server
|
||||
copyright: Javier Velilla, Jocelyn Fiat and Eiffel Software.
|
||||
license: Eiffel Forum v2
|
||||
link[license]: http://www.eiffel.com/licensing/forum.txt
|
||||
|
||||
end
|
||||
2
contrib/library/text/parser/json/.gitignore
vendored
2
contrib/library/text/parser/json/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
*.swp
|
||||
EIFGENs
|
||||
@@ -1,26 +0,0 @@
|
||||
History file for EJSON
|
||||
======================
|
||||
|
||||
team: ""
|
||||
date: "2011-07-06"
|
||||
revision: "0.3.0"
|
||||
|
||||
|
||||
+++++++++++++++++++++Important Changes since 0.2.0 version++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
*Updated skip_white_spaces, now check %U and %T codes
|
||||
|
||||
*Undo changes to is_a_valid_number, because it's doesn't follow the
|
||||
JSON spec. Tests : fail13.json, fail29.json and fail30.json are valid
|
||||
with this implementation, so we go back to the previous
|
||||
implementation.
|
||||
|
||||
*Added autotest test suite
|
||||
|
||||
*Added getest based test program
|
||||
|
||||
*Updated Eiffel configuration file, updated to the new clusters
|
||||
|
||||
*Added converters and factory classes
|
||||
|
||||
*Added new top level directories; library, test, build and example
|
||||
@@ -1,20 +0,0 @@
|
||||
Copyright (c) 2010 Javier Velilla and others, http://ejson.origo.ethz.ch
|
||||
|
||||
|
||||
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,97 +0,0 @@
|
||||
Readme file for eJSON
|
||||
=====================
|
||||
|
||||
team: "Javier Velilla,Jocelyn Fiat, Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
1. Introduction
|
||||
---------------
|
||||
|
||||
eJSON stands for Eiffel JSON library and is a small Eiffel library for dealing
|
||||
with the JSON format. The objective of the library is to provide two basic
|
||||
features Eiffel2JSON and JSON2Eiffel.
|
||||
|
||||
2. Legal stuff
|
||||
--------------
|
||||
|
||||
eJSON is copyrighted by the author Javier Velilla and others. It is licensed
|
||||
under the MIT License. See the file license.txt in the same directory as this
|
||||
readme file.
|
||||
|
||||
3. Versioning scheme
|
||||
--------------------
|
||||
|
||||
eJSON version numbers has the form:
|
||||
|
||||
«major number».«minor number».«patch level»
|
||||
|
||||
eJSON will retain the major number 0 as long as it has beta status. A change in
|
||||
major number indicates that a release is not backward compatible. A change in
|
||||
minor number indicates that a release is backward compatible (within that major
|
||||
number) but that new useful features may have been added. A change in patch
|
||||
level simply indicates that the release contains bug fixes for the previous
|
||||
release. Note that as long as eJSON is in beta status (0.Y.Z) backward
|
||||
compatibility is not guranteed for changes in minor numbers!
|
||||
|
||||
4. Documentation
|
||||
---------------
|
||||
|
||||
Currently the only documentation on eJSON is available at:
|
||||
|
||||
https://github.com/eiffelhub/json/wiki/User-guide
|
||||
|
||||
5. Requirements and installation
|
||||
--------------------------------
|
||||
|
||||
EJSON requires that you have:
|
||||
|
||||
1. Gobo 3.9 installed or later
|
||||
2. One of the following compiler combinations installed:
|
||||
* ISE Eiffel 6.5 or later.
|
||||
* gec [try to test]
|
||||
* tecomp [try to test]
|
||||
|
||||
eJSON probably works fine with other versions of the above compilers.
|
||||
There are no known platform dependencies (Windows, Linux).
|
||||
|
||||
To install eJSON simply extract the ejson-X.Y.Z.zip file to some appropriate
|
||||
place on your hard disk. There are no requirements on environment variables or
|
||||
registry variables.
|
||||
|
||||
To verify that everything works you should compile the example programs and/or
|
||||
the test program.
|
||||
|
||||
6. Contents of eJSON
|
||||
--------------------
|
||||
|
||||
All directory names below are relative to the root directory of your ejson
|
||||
installation.
|
||||
|
||||
Directory Description
|
||||
--------- -----------
|
||||
doc Contains the eJSON.pdf documentation file.
|
||||
examples Contains the two example programs.
|
||||
ejson Contains the actual eJSON library classes.
|
||||
test Contains a test program for eJSON.
|
||||
|
||||
7. Contacting the Team
|
||||
----------------------
|
||||
|
||||
Contact the team:
|
||||
|
||||
Javier Velilla «javier.hector@gmail.com»
|
||||
Paul Cohen «paco@seibostudios.se»
|
||||
Jocelyn Fiat «jfiat@eiffel.com»
|
||||
|
||||
8. Releases
|
||||
-----------
|
||||
|
||||
For more information on what was changed in each release look in the file
|
||||
history.txt.
|
||||
|
||||
Version Date Description
|
||||
------- ---- -----------
|
||||
0.3.0 2011-07-06 JSON Factory Converters
|
||||
0.2.0 2010-02-07 Adapted to EiffelStudio 6.4 or later, supports void-safety
|
||||
0.1.0 2010-02-07 First release, Adapted to SmartEiffel 1.2r7 and EiffelStudio 6.2 or previous
|
||||
@@ -1,38 +0,0 @@
|
||||
note
|
||||
description: "Objects that ..."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
JSON_FILE_READER
|
||||
|
||||
feature -- Access
|
||||
|
||||
read_json_from (a_path: STRING): detachable STRING
|
||||
local
|
||||
l_file: PLAIN_TEXT_FILE
|
||||
template_content: STRING
|
||||
l_last_string: detachable STRING
|
||||
do
|
||||
create l_file.make (a_path)
|
||||
-- We perform several checks until we make a real attempt to open the file.
|
||||
if not l_file.exists then
|
||||
print ("error: '" + a_path + "' does not exist%N")
|
||||
else
|
||||
if not l_file.is_readable then
|
||||
print ("error: '" + a_path + "' is not readable.%N")
|
||||
else
|
||||
l_file.open_read
|
||||
create template_content.make_empty
|
||||
l_file.read_stream (l_file.count)
|
||||
l_last_string := l_file.last_string
|
||||
check l_last_string /= Void end -- implied by postcondition of `l_file.read_stream'
|
||||
template_content.append (l_last_string.string)
|
||||
Result := template_content
|
||||
l_file.close
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,175 +0,0 @@
|
||||
note
|
||||
description: "JSON_PRETTY_STRING_VISITOR Generates the JSON-String for a JSON_VALUE"
|
||||
revision: "0.1"
|
||||
|
||||
class
|
||||
JSON_PRETTY_STRING_VISITOR
|
||||
|
||||
inherit
|
||||
JSON_VISITOR
|
||||
|
||||
create
|
||||
make,
|
||||
make_custom
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make (a_output: like output)
|
||||
-- Create a new instance
|
||||
do
|
||||
make_custom (a_output, 1, 1)
|
||||
end
|
||||
|
||||
make_custom (a_output: like output; a_object_count_inlining, a_array_count_inlining: INTEGER)
|
||||
-- Create a new instance
|
||||
do
|
||||
output := a_output
|
||||
create indentation.make_empty
|
||||
indentation_step := "%T"
|
||||
|
||||
object_count_inlining := a_object_count_inlining
|
||||
array_count_inlining := a_array_count_inlining
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
output: STRING_32
|
||||
-- JSON representation
|
||||
|
||||
indentation: like output
|
||||
|
||||
indentation_step: like indentation
|
||||
|
||||
line_number: INTEGER
|
||||
|
||||
indent
|
||||
do
|
||||
indentation.append (indentation_step)
|
||||
end
|
||||
|
||||
exdent
|
||||
do
|
||||
indentation.remove_tail (indentation_step.count)
|
||||
end
|
||||
|
||||
new_line
|
||||
do
|
||||
output.append ("%N")
|
||||
output.append (indentation)
|
||||
line_number := line_number + 1
|
||||
end
|
||||
|
||||
object_count_inlining: INTEGER
|
||||
array_count_inlining: INTEGER
|
||||
|
||||
feature -- Visitor Pattern
|
||||
|
||||
visit_json_array (a_json_array: JSON_ARRAY)
|
||||
-- Visit `a_json_array'.
|
||||
local
|
||||
value: JSON_VALUE
|
||||
l_json_array: ARRAYED_LIST [JSON_VALUE]
|
||||
l_line: like line_number
|
||||
l_multiple_lines: BOOLEAN
|
||||
do
|
||||
l_json_array := a_json_array.array_representation
|
||||
l_multiple_lines := l_json_array.count >= array_count_inlining or across l_json_array as p some attached {JSON_OBJECT} p.item or attached {JSON_ARRAY} p.item end
|
||||
output.append ("[")
|
||||
l_line := line_number
|
||||
indent
|
||||
from
|
||||
l_json_array.start
|
||||
until
|
||||
l_json_array.off
|
||||
loop
|
||||
if
|
||||
line_number > l_line or
|
||||
l_multiple_lines
|
||||
then
|
||||
new_line
|
||||
end
|
||||
value := l_json_array.item
|
||||
value.accept (Current)
|
||||
l_json_array.forth
|
||||
if not l_json_array.after then
|
||||
output.append (", ")
|
||||
end
|
||||
end
|
||||
exdent
|
||||
if
|
||||
line_number > l_line or
|
||||
l_json_array.count >= array_count_inlining
|
||||
then
|
||||
new_line
|
||||
end
|
||||
output.append ("]")
|
||||
end
|
||||
|
||||
visit_json_boolean (a_json_boolean: JSON_BOOLEAN)
|
||||
-- Visit `a_json_boolean'.
|
||||
do
|
||||
output.append (a_json_boolean.item.out)
|
||||
end
|
||||
|
||||
visit_json_null (a_json_null: JSON_NULL)
|
||||
-- Visit `a_json_null'.
|
||||
do
|
||||
output.append ("null")
|
||||
end
|
||||
|
||||
visit_json_number (a_json_number: JSON_NUMBER)
|
||||
-- Visit `a_json_number'.
|
||||
do
|
||||
output.append (a_json_number.item)
|
||||
end
|
||||
|
||||
visit_json_object (a_json_object: JSON_OBJECT)
|
||||
-- Visit `a_json_object'.
|
||||
local
|
||||
l_pairs: HASH_TABLE [JSON_VALUE, JSON_STRING]
|
||||
l_line: like line_number
|
||||
l_multiple_lines: BOOLEAN
|
||||
do
|
||||
l_pairs := a_json_object.map_representation
|
||||
l_multiple_lines := l_pairs.count >= object_count_inlining or across l_pairs as p some attached {JSON_OBJECT} p.item or attached {JSON_ARRAY} p.item end
|
||||
output.append ("{")
|
||||
l_line := line_number
|
||||
indent
|
||||
from
|
||||
l_pairs.start
|
||||
until
|
||||
l_pairs.off
|
||||
loop
|
||||
if
|
||||
line_number > l_line or
|
||||
l_multiple_lines
|
||||
then
|
||||
new_line
|
||||
end
|
||||
l_pairs.key_for_iteration.accept (Current)
|
||||
output.append (": ")
|
||||
l_pairs.item_for_iteration.accept (Current)
|
||||
l_pairs.forth
|
||||
if not l_pairs.after then
|
||||
output.append (", ")
|
||||
end
|
||||
end
|
||||
exdent
|
||||
if
|
||||
line_number > l_line or
|
||||
l_pairs.count >= object_count_inlining
|
||||
then
|
||||
new_line
|
||||
end
|
||||
output.append ("}")
|
||||
end
|
||||
|
||||
visit_json_string (a_json_string: JSON_STRING)
|
||||
-- Visit `a_json_string'.
|
||||
do
|
||||
output.append ("%"")
|
||||
output.append (a_json_string.item)
|
||||
output.append ("%"")
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,59 +0,0 @@
|
||||
note
|
||||
description:
|
||||
|
||||
"JSON Visitor"
|
||||
|
||||
pattern: "Visitor"
|
||||
author: "Javier Velilla"
|
||||
license:"MIT (see http://www.opensource.org/licenses/mit-license.php)"
|
||||
date: "2008/08/24"
|
||||
revision: "Revision 0.1"
|
||||
|
||||
deferred class
|
||||
JSON_VISITOR
|
||||
|
||||
feature -- Visitor Pattern
|
||||
|
||||
visit_json_array (a_json_array: JSON_ARRAY)
|
||||
-- Visit `a_json_array'.
|
||||
require
|
||||
a_json_array_not_void: a_json_array /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
visit_json_boolean (a_json_boolean: JSON_BOOLEAN)
|
||||
-- Visit `a_json_boolean'.
|
||||
require
|
||||
a_json_boolean_not_void: a_json_boolean /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
visit_json_null (a_json_null: JSON_NULL)
|
||||
-- Visit `a_json_null'.
|
||||
require
|
||||
a_json_null_not_void: a_json_null /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
visit_json_number (a_json_number: JSON_NUMBER)
|
||||
-- Visit `a_json_number'.
|
||||
require
|
||||
a_json_number_not_void: a_json_number /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
visit_json_object (a_json_object: JSON_OBJECT)
|
||||
-- Visit `a_json_object'.
|
||||
require
|
||||
a_json_object_not_void: a_json_object /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
visit_json_string (a_json_string: JSON_STRING)
|
||||
-- Visit `a_json_string'.
|
||||
require
|
||||
a_json_string_not_void: a_json_string /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,102 +0,0 @@
|
||||
note
|
||||
description: "PRINT_JSON_VISITOR Generates the JSON-String for a JSON_VALUE"
|
||||
author: "jvelilla"
|
||||
date: "2008/08/24"
|
||||
revision: "0.1"
|
||||
|
||||
class
|
||||
PRINT_JSON_VISITOR
|
||||
|
||||
inherit
|
||||
JSON_VISITOR
|
||||
|
||||
create make
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make
|
||||
-- Create a new instance
|
||||
do
|
||||
create to_json.make_empty
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
to_json: STRING
|
||||
-- JSON representation
|
||||
|
||||
feature -- Visitor Pattern
|
||||
|
||||
visit_json_array (a_json_array: JSON_ARRAY)
|
||||
-- Visit `a_json_array'.
|
||||
local
|
||||
value: JSON_VALUE
|
||||
l_json_array: ARRAYED_LIST [JSON_VALUE]
|
||||
do
|
||||
l_json_array:=a_json_array.array_representation
|
||||
to_json.append ("[")
|
||||
from
|
||||
l_json_array.start
|
||||
until
|
||||
l_json_array.off
|
||||
loop
|
||||
value := l_json_array.item
|
||||
value.accept (Current)
|
||||
l_json_array.forth
|
||||
if not l_json_array.after then
|
||||
to_json.append(",")
|
||||
end
|
||||
end
|
||||
to_json.append ("]")
|
||||
end
|
||||
|
||||
visit_json_boolean (a_json_boolean: JSON_BOOLEAN)
|
||||
-- Visit `a_json_boolean'.
|
||||
do
|
||||
to_json.append (a_json_boolean.item.out)
|
||||
end
|
||||
|
||||
visit_json_null (a_json_null: JSON_NULL)
|
||||
-- Visit `a_json_null'.
|
||||
do
|
||||
to_json.append ("null")
|
||||
end
|
||||
|
||||
visit_json_number (a_json_number: JSON_NUMBER)
|
||||
-- Visit `a_json_number'.
|
||||
do
|
||||
to_json.append (a_json_number.item)
|
||||
end
|
||||
|
||||
visit_json_object (a_json_object: JSON_OBJECT)
|
||||
-- Visit `a_json_object'.
|
||||
local
|
||||
l_pairs: HASH_TABLE[JSON_VALUE,JSON_STRING]
|
||||
do
|
||||
l_pairs := a_json_object.map_representation
|
||||
to_json.append ("{")
|
||||
from
|
||||
l_pairs.start
|
||||
until
|
||||
l_pairs.off
|
||||
loop
|
||||
l_pairs.key_for_iteration.accept (Current)
|
||||
to_json.append (":")
|
||||
l_pairs.item_for_iteration.accept (Current)
|
||||
l_pairs.forth
|
||||
if not l_pairs.after then
|
||||
to_json.append (",")
|
||||
end
|
||||
end
|
||||
to_json.append ("}")
|
||||
end
|
||||
|
||||
visit_json_string (a_json_string: JSON_STRING)
|
||||
-- Visit `a_json_string'.
|
||||
do
|
||||
to_json.append ("%"")
|
||||
to_json.append (a_json_string.item)
|
||||
to_json.append ("%"")
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,85 +0,0 @@
|
||||
note
|
||||
description: "A JSON converter for DS_HASH_TABLE [ANY, HASHABLE]"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date: $"
|
||||
revision: "$Revision: $"
|
||||
file: "$HeadURL: $"
|
||||
|
||||
class JSON_DS_HASH_TABLE_CONVERTER
|
||||
|
||||
inherit
|
||||
JSON_CONVERTER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
do
|
||||
create object.make (0)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
value: JSON_OBJECT
|
||||
|
||||
object: DS_HASH_TABLE [ANY, HASHABLE]
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
from_json (j: like value): detachable like object
|
||||
local
|
||||
keys: ARRAY [JSON_STRING]
|
||||
i: INTEGER
|
||||
h: HASHABLE
|
||||
a: ANY
|
||||
do
|
||||
keys := j.current_keys
|
||||
create Result.make (keys.count)
|
||||
from
|
||||
i := 1
|
||||
until
|
||||
i > keys.count
|
||||
loop
|
||||
h ?= json.object (keys [i], void)
|
||||
check h /= Void end
|
||||
a := json.object (j.item (keys [i]), Void)
|
||||
Result.put (a, h)
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
|
||||
to_json (o: like object): like value
|
||||
local
|
||||
c: DS_HASH_TABLE_CURSOR [ANY, HASHABLE]
|
||||
js: JSON_STRING
|
||||
jv: JSON_VALUE
|
||||
failed: BOOLEAN
|
||||
do
|
||||
create Result.make
|
||||
from
|
||||
c := o.new_cursor
|
||||
c.start
|
||||
until
|
||||
c.after
|
||||
loop
|
||||
if attached {JSON_STRING} json.value (c.key) as l_key then
|
||||
js := l_key
|
||||
else
|
||||
create js.make_json (c.key.out)
|
||||
end
|
||||
jv := json.value (c.item)
|
||||
if jv /= Void then
|
||||
Result.put (jv, js)
|
||||
else
|
||||
failed := True
|
||||
end
|
||||
c.forth
|
||||
end
|
||||
if failed then
|
||||
Result := Void
|
||||
end
|
||||
end
|
||||
|
||||
end -- class JSON_DS_HASH_TABLE_CONVERTER
|
||||
@@ -1,62 +0,0 @@
|
||||
note
|
||||
description: "A JSON converter for DS_LINKED_LIST [ANY]"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date: $"
|
||||
revision: "$Revision: $"
|
||||
file: "$HeadURL: $"
|
||||
|
||||
class JSON_DS_LINKED_LIST_CONVERTER
|
||||
|
||||
inherit
|
||||
JSON_CONVERTER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
do
|
||||
create object.make
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
value: JSON_ARRAY
|
||||
|
||||
object: DS_LINKED_LIST [ANY]
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
from_json (j: like value): detachable like object
|
||||
local
|
||||
i: INTEGER
|
||||
do
|
||||
create Result.make
|
||||
from
|
||||
i := 1
|
||||
until
|
||||
i > j.count
|
||||
loop
|
||||
Result.put_last (json.object (j [i], Void))
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
|
||||
to_json (o: like object): like value
|
||||
local
|
||||
c: DS_LIST_CURSOR [ANY]
|
||||
do
|
||||
create Result.make_array
|
||||
from
|
||||
c := o.new_cursor
|
||||
c.start
|
||||
until
|
||||
c.after
|
||||
loop
|
||||
Result.add (json.value (c.item))
|
||||
c.forth
|
||||
end
|
||||
end
|
||||
|
||||
end -- class JSON_DS_LINKED_LIST_CONVERTER
|
||||
@@ -1,32 +0,0 @@
|
||||
note
|
||||
description: "[
|
||||
Shared factory class for creating JSON objects. Maps JSON
|
||||
objects to Gobo DS_HASH_TABLEs and JSON arrays to Gobo
|
||||
DS_LINKED_LISTs. Use non-conforming inheritance from this
|
||||
class to ensure that your classes share the same
|
||||
JSON_FACTORY instance.
|
||||
]"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
file: "$HeadURL: $"
|
||||
|
||||
class SHARED_GOBO_EJSON
|
||||
|
||||
feature
|
||||
|
||||
json: EJSON
|
||||
-- A shared EJSON instance with default converters for
|
||||
-- DS_LINKED_LIST [ANY] and DS_HASH_TABLE [ANY, HASHABLE]
|
||||
local
|
||||
jllc: JSON_DS_LINKED_LIST_CONVERTER
|
||||
jhtc: JSON_DS_HASH_TABLE_CONVERTER
|
||||
once
|
||||
create Result
|
||||
create jllc.make
|
||||
Result.add_converter (jllc)
|
||||
create jhtc.make
|
||||
Result.add_converter (jhtc)
|
||||
end
|
||||
|
||||
end -- class SHARED_GOBO_EJSON
|
||||
@@ -1,28 +0,0 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="json" uuid="4E21C3BD-7951-4C6E-A673-431E762D7414" library_target="json">
|
||||
<target name="json">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option trace="false" profile="false" debug="false" warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard" namespace="EJSON.Library">
|
||||
<assertions/>
|
||||
<warning name="export_class_missing" enabled="false"/>
|
||||
<warning name="old_verbatim_strings" enabled="false"/>
|
||||
<warning name="syntax" enabled="false"/>
|
||||
<warning name="vjrv" enabled="false"/>
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf" readonly="true"/>
|
||||
<cluster name="json" location=".\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>^/gobo$</exclude>
|
||||
<exclude>^/kernel$</exclude>
|
||||
<exclude>^/extras$</exclude>
|
||||
</file_rule>
|
||||
<cluster name="kernel" location=".\kernel\" recursive="true"/>
|
||||
<cluster name="extras" location=".\extras\" recursive="true"/>
|
||||
</cluster>
|
||||
</target>
|
||||
</system>
|
||||
@@ -1,28 +0,0 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="json" uuid="4E21C3BD-7951-4C6E-A673-431E762D7414" library_target="json">
|
||||
<target name="json">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option trace="false" profile="false" debug="false" warning="true" full_class_checking="true" void_safety="none" syntax="standard" namespace="EJSON.Library">
|
||||
<assertions/>
|
||||
<warning name="export_class_missing" enabled="false"/>
|
||||
<warning name="old_verbatim_strings" enabled="false"/>
|
||||
<warning name="syntax" enabled="false"/>
|
||||
<warning name="vjrv" enabled="false"/>
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf" readonly="true"/>
|
||||
<cluster name="json" location=".\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>^/gobo$</exclude>
|
||||
<exclude>^/kernel$</exclude>
|
||||
<exclude>^/extras$</exclude>
|
||||
</file_rule>
|
||||
<cluster name="kernel" location=".\kernel\" recursive="true"/>
|
||||
<cluster name="extras" location=".\extras\" recursive="true"/>
|
||||
</cluster>
|
||||
</target>
|
||||
</system>
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="json_gobo" uuid="437195AB-8B3C-4238-8998-A932A1423449" library_target="json_gobo">
|
||||
<target name="json_gobo">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option trace="false" profile="false" debug="false" warning="true" full_class_checking="true" void_safety="none" syntax="standard" namespace="EJSON.Library">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf" readonly="true"/>
|
||||
<library name="json" location="json.ecf" readonly="true"/>
|
||||
<library name="gobo_structure" location="$ISE_LIBRARY\library\gobo\gobo_structure.ecf"/>
|
||||
<cluster name="json_gobo" location=".\gobo" recursive="true" />
|
||||
</target>
|
||||
</system>
|
||||
@@ -1,30 +0,0 @@
|
||||
note
|
||||
description: "A JSON converter for ARRAYED_LIST [ANY]"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
file: "$HeadURL: $"
|
||||
|
||||
class JSON_ARRAYED_LIST_CONVERTER
|
||||
|
||||
inherit
|
||||
JSON_LIST_CONVERTER
|
||||
redefine
|
||||
object
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Access
|
||||
|
||||
object: ARRAYED_LIST [detachable ANY]
|
||||
|
||||
feature {NONE} -- Factory
|
||||
|
||||
new_object (nb: INTEGER): like object
|
||||
do
|
||||
create Result.make (nb)
|
||||
end
|
||||
|
||||
end -- class JSON_ARRAYED_LIST_CONVERTER
|
||||
@@ -1,36 +0,0 @@
|
||||
note
|
||||
description: "A JSON converter"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
file: "$HeadURL: $"
|
||||
|
||||
deferred class JSON_CONVERTER
|
||||
|
||||
inherit
|
||||
SHARED_EJSON
|
||||
|
||||
feature -- Access
|
||||
|
||||
object: ANY
|
||||
-- Eiffel object
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
from_json (j: attached like to_json): detachable like object
|
||||
-- Convert from JSON value.
|
||||
-- Returns Void if unable to convert
|
||||
deferred
|
||||
end
|
||||
|
||||
to_json (o: like object): detachable JSON_VALUE
|
||||
-- Convert to JSON value
|
||||
deferred
|
||||
end
|
||||
|
||||
invariant
|
||||
has_eiffel_object: object /= Void -- An empty object must be created at creation time!
|
||||
|
||||
end
|
||||
@@ -1,92 +0,0 @@
|
||||
note
|
||||
description: "A JSON converter for HASH_TABLE [ANY, HASHABLE]"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
file: "$HeadURL: $"
|
||||
|
||||
class JSON_HASH_TABLE_CONVERTER
|
||||
|
||||
inherit
|
||||
JSON_CONVERTER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
do
|
||||
create object.make (0)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
object: HASH_TABLE [ANY, HASHABLE]
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
from_json (j: attached like to_json): like object
|
||||
local
|
||||
keys: ARRAY [JSON_STRING]
|
||||
i: INTEGER
|
||||
h: detachable HASHABLE
|
||||
jv: detachable JSON_VALUE
|
||||
a: detachable ANY
|
||||
do
|
||||
keys := j.current_keys
|
||||
create Result.make (keys.count)
|
||||
from
|
||||
i := 1
|
||||
until
|
||||
i > keys.count
|
||||
loop
|
||||
h ?= json.object (keys [i], Void)
|
||||
check h /= Void end
|
||||
jv := j.item (keys [i])
|
||||
if jv /= Void then
|
||||
a := json.object (jv, Void)
|
||||
if a /= Void then
|
||||
Result.put (a, h)
|
||||
else
|
||||
check a_attached: a /= Void end
|
||||
end
|
||||
else
|
||||
check j_has_item: False end
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
|
||||
to_json (o: like object): detachable JSON_OBJECT
|
||||
local
|
||||
c: HASH_TABLE_ITERATION_CURSOR [ANY, HASHABLE]
|
||||
js: JSON_STRING
|
||||
jv: detachable JSON_VALUE
|
||||
failed: BOOLEAN
|
||||
do
|
||||
create Result.make
|
||||
from
|
||||
c := o.new_cursor
|
||||
until
|
||||
c.after
|
||||
loop
|
||||
if attached {JSON_STRING} json.value (c.key) as l_key then
|
||||
js := l_key
|
||||
else
|
||||
create js.make_json (c.key.out)
|
||||
end
|
||||
jv := json.value (c.item)
|
||||
if jv /= Void then
|
||||
Result.put (jv, js)
|
||||
else
|
||||
failed := True
|
||||
end
|
||||
c.forth
|
||||
end
|
||||
if failed then
|
||||
Result := Void
|
||||
end
|
||||
end
|
||||
|
||||
end -- class JSON_HASH_TABLE_CONVERTER
|
||||
@@ -1,30 +0,0 @@
|
||||
note
|
||||
description: "A JSON converter for LINKED_LIST [ANY]"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
file: "$HeadURL: $"
|
||||
|
||||
class JSON_LINKED_LIST_CONVERTER
|
||||
|
||||
inherit
|
||||
JSON_LIST_CONVERTER
|
||||
redefine
|
||||
object
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Access
|
||||
|
||||
object: LINKED_LIST [detachable ANY]
|
||||
|
||||
feature {NONE} -- Factory
|
||||
|
||||
new_object (nb: INTEGER): like object
|
||||
do
|
||||
create Result.make
|
||||
end
|
||||
|
||||
end -- class JSON_LINKED_LIST_CONVERTER
|
||||
@@ -1,74 +0,0 @@
|
||||
note
|
||||
description: "A JSON converter for LIST [ANY]"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
file: "$HeadURL: $"
|
||||
|
||||
deferred class JSON_LIST_CONVERTER
|
||||
|
||||
inherit
|
||||
JSON_CONVERTER
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
do
|
||||
object := new_object (0)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
object: LIST [detachable ANY]
|
||||
|
||||
feature {NONE} -- Factory
|
||||
|
||||
new_object (nb: INTEGER): like object
|
||||
deferred
|
||||
ensure
|
||||
Result /= Void
|
||||
end
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
from_json (j: attached like to_json): detachable like object
|
||||
local
|
||||
i: INTEGER
|
||||
do
|
||||
Result := new_object (j.count)
|
||||
from
|
||||
i := 1
|
||||
until
|
||||
i > j.count
|
||||
loop
|
||||
Result.extend (json.object (j [i], Void))
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
|
||||
to_json (o: like object): detachable JSON_ARRAY
|
||||
local
|
||||
c: ITERATION_CURSOR [detachable ANY]
|
||||
jv: detachable JSON_VALUE
|
||||
failed: BOOLEAN
|
||||
do
|
||||
create Result.make_array
|
||||
from
|
||||
c := o.new_cursor
|
||||
until
|
||||
c.after
|
||||
loop
|
||||
jv := json.value (c.item)
|
||||
if jv /= Void then
|
||||
Result.add (jv)
|
||||
else
|
||||
failed := True
|
||||
end
|
||||
c.forth
|
||||
end
|
||||
if failed then
|
||||
Result := Void
|
||||
end
|
||||
end
|
||||
|
||||
end -- class JSON_ARRAYED_LIST_CONVERTER
|
||||
@@ -1,268 +0,0 @@
|
||||
note
|
||||
description: "Core factory class for creating JSON objects and corresponding Eiffel objects."
|
||||
author: "Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
file: "$HeadURL: $"
|
||||
|
||||
class EJSON
|
||||
|
||||
inherit
|
||||
EXCEPTIONS
|
||||
|
||||
feature -- Access
|
||||
|
||||
value (an_object: detachable ANY): detachable JSON_VALUE
|
||||
-- JSON value from Eiffel object. Raises an "eJSON exception" if
|
||||
-- unable to convert value.
|
||||
local
|
||||
i: INTEGER
|
||||
ja: JSON_ARRAY
|
||||
do
|
||||
-- Try to convert from basic Eiffel types. Note that we check with
|
||||
-- `conforms_to' since the client may have subclassed the base class
|
||||
-- that these basic types are derived from.
|
||||
if an_object = Void then
|
||||
create {JSON_NULL} Result
|
||||
elseif attached {BOOLEAN} an_object as b then
|
||||
create {JSON_BOOLEAN} Result.make_boolean (b)
|
||||
elseif attached {INTEGER_8} an_object as i8 then
|
||||
create {JSON_NUMBER} Result.make_integer (i8)
|
||||
elseif attached {INTEGER_16} an_object as i16 then
|
||||
create {JSON_NUMBER} Result.make_integer (i16)
|
||||
elseif attached {INTEGER_32} an_object as i32 then
|
||||
create {JSON_NUMBER} Result.make_integer (i32)
|
||||
elseif attached {INTEGER_64} an_object as i64 then
|
||||
create {JSON_NUMBER} Result.make_integer (i64)
|
||||
elseif attached {NATURAL_8} an_object as n8 then
|
||||
create {JSON_NUMBER} Result.make_natural (n8)
|
||||
elseif attached {NATURAL_16} an_object as n16 then
|
||||
create {JSON_NUMBER} Result.make_natural (n16)
|
||||
elseif attached {NATURAL_32} an_object as n32 then
|
||||
create {JSON_NUMBER} Result.make_natural (n32)
|
||||
elseif attached {NATURAL_64} an_object as n64 then
|
||||
create {JSON_NUMBER} Result.make_natural (n64)
|
||||
elseif attached {REAL_32} an_object as r32 then
|
||||
create {JSON_NUMBER} Result.make_real (r32)
|
||||
elseif attached {REAL_64} an_object as r64 then
|
||||
create {JSON_NUMBER} Result.make_real (r64)
|
||||
elseif attached {ARRAY [detachable ANY]} an_object as a then
|
||||
create ja.make_array
|
||||
from
|
||||
i := a.lower
|
||||
until
|
||||
i > a.upper
|
||||
loop
|
||||
if attached value (a @ i) as v then
|
||||
ja.add (v)
|
||||
else
|
||||
check value_attached: False end
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
Result := ja
|
||||
elseif attached {CHARACTER_8} an_object as c8 then
|
||||
create {JSON_STRING} Result.make_json (c8.out)
|
||||
elseif attached {CHARACTER_32} an_object as c32 then
|
||||
create {JSON_STRING} Result.make_json (c32.out)
|
||||
|
||||
elseif attached {STRING_8} an_object as s8 then
|
||||
create {JSON_STRING} Result.make_json (s8)
|
||||
elseif attached {STRING_32} an_object as s32 then
|
||||
create {JSON_STRING} Result.make_json_from_string_32 (s32)
|
||||
end
|
||||
|
||||
if Result = Void then
|
||||
-- Now check the converters
|
||||
if an_object /= Void and then attached converter_for (an_object) as jc then
|
||||
Result := jc.to_json (an_object)
|
||||
else
|
||||
raise (exception_failed_to_convert_to_json (an_object))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
object (a_value: detachable JSON_VALUE; base_class: detachable STRING): detachable ANY
|
||||
-- Eiffel object from JSON value. If `base_class' /= Void an eiffel
|
||||
-- object based on `base_class' will be returned. Raises an "eJSON
|
||||
-- exception" if unable to convert value.
|
||||
local
|
||||
i: INTEGER
|
||||
ll: LINKED_LIST [detachable ANY]
|
||||
t: HASH_TABLE [detachable ANY, STRING_GENERAL]
|
||||
keys: ARRAY [JSON_STRING]
|
||||
do
|
||||
if a_value = Void then
|
||||
Result := Void
|
||||
else
|
||||
if base_class = Void then
|
||||
if a_value = Void then
|
||||
Result := Void
|
||||
elseif attached {JSON_NULL} a_value then
|
||||
Result := Void
|
||||
elseif attached {JSON_BOOLEAN} a_value as jb then
|
||||
Result := jb.item
|
||||
elseif attached {JSON_NUMBER} a_value as jn then
|
||||
if jn.item.is_integer_8 then
|
||||
Result := jn.item.to_integer_8
|
||||
elseif jn.item.is_integer_16 then
|
||||
Result := jn.item.to_integer_16
|
||||
elseif jn.item.is_integer_32 then
|
||||
Result := jn.item.to_integer_32
|
||||
elseif jn.item.is_integer_64 then
|
||||
Result := jn.item.to_integer_64
|
||||
elseif jn.item.is_natural_64 then
|
||||
Result := jn.item.to_natural_64
|
||||
elseif jn.item.is_double then
|
||||
Result := jn.item.to_double
|
||||
end
|
||||
elseif attached {JSON_STRING} a_value as js then
|
||||
create {STRING_32} Result.make_from_string (js.unescaped_string_32)
|
||||
elseif attached {JSON_ARRAY} a_value as ja then
|
||||
from
|
||||
create ll.make
|
||||
i := 1
|
||||
until
|
||||
i > ja.count
|
||||
loop
|
||||
ll.extend (object (ja [i], Void))
|
||||
i := i + 1
|
||||
end
|
||||
Result := ll
|
||||
elseif attached {JSON_OBJECT} a_value as jo then
|
||||
keys := jo.current_keys
|
||||
create t.make (keys.count)
|
||||
from
|
||||
i := keys.lower
|
||||
until
|
||||
i > keys.upper
|
||||
loop
|
||||
if attached {STRING_GENERAL} object (keys [i], Void) as s then
|
||||
t.put (object (jo.item (keys [i]), Void), s)
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
Result := t
|
||||
end
|
||||
else
|
||||
if converters.has_key (base_class) and then attached converters.found_item as jc then
|
||||
Result := jc.from_json (a_value)
|
||||
else
|
||||
raise (exception_failed_to_convert_to_eiffel (a_value, base_class))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
object_from_json (json: STRING; base_class: detachable STRING): detachable ANY
|
||||
-- Eiffel object from JSON representation. If `base_class' /= Void an
|
||||
-- Eiffel object based on `base_class' will be returned. Raises an
|
||||
-- "eJSON exception" if unable to convert value.
|
||||
require
|
||||
json_not_void: json /= Void
|
||||
local
|
||||
jv: detachable JSON_VALUE
|
||||
do
|
||||
json_parser.set_representation (json)
|
||||
jv := json_parser.parse
|
||||
if jv /= Void then
|
||||
Result := object (jv, base_class)
|
||||
end
|
||||
end
|
||||
|
||||
converter_for (an_object: ANY): detachable JSON_CONVERTER
|
||||
-- Converter for objects. Returns Void if none found.
|
||||
require
|
||||
an_object_not_void: an_object /= Void
|
||||
do
|
||||
if converters.has_key (an_object.generator) then
|
||||
Result := converters.found_item
|
||||
end
|
||||
end
|
||||
|
||||
json_reference (s: STRING): JSON_OBJECT
|
||||
-- A JSON (Dojo style) reference object using `s' as the
|
||||
-- reference value. The caller is responsable for ensuring
|
||||
-- the validity of `s' as a json reference.
|
||||
require
|
||||
s_not_void: s /= Void
|
||||
local
|
||||
js_key, js_value: JSON_STRING
|
||||
do
|
||||
create Result.make
|
||||
create js_key.make_json ("$ref")
|
||||
create js_value.make_json (s)
|
||||
Result.put (js_value, js_key)
|
||||
end
|
||||
|
||||
json_references (l: LIST [STRING]): JSON_ARRAY
|
||||
-- A JSON array of JSON (Dojo style) reference objects using the
|
||||
-- strings in `l' as reference values. The caller is responsable
|
||||
-- for ensuring the validity of all strings in `l' as json
|
||||
-- references.
|
||||
require
|
||||
l_not_void: l /= Void
|
||||
local
|
||||
c: ITERATION_CURSOR [STRING]
|
||||
do
|
||||
create Result.make_array
|
||||
from
|
||||
c := l.new_cursor
|
||||
until
|
||||
c.after
|
||||
loop
|
||||
Result.add (json_reference (c.item))
|
||||
c.forth
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Change
|
||||
|
||||
add_converter (jc: JSON_CONVERTER)
|
||||
-- Add the converter `jc'.
|
||||
require
|
||||
jc_not_void: jc /= Void
|
||||
do
|
||||
converters.force (jc, jc.object.generator)
|
||||
ensure
|
||||
has_converter: converter_for (jc.object) /= Void
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
converters: HASH_TABLE [JSON_CONVERTER, STRING]
|
||||
-- Converters hashed by generator (base class)
|
||||
once
|
||||
create Result.make (10)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation (Exceptions)
|
||||
|
||||
exception_prefix: STRING = "eJSON exception: "
|
||||
|
||||
exception_failed_to_convert_to_eiffel (a_value: JSON_VALUE; base_class: detachable STRING): STRING
|
||||
-- Exception message for failing to convert a JSON_VALUE to an instance of `a'.
|
||||
do
|
||||
Result := exception_prefix + "Failed to convert JSON_VALUE to an Eiffel object: " + a_value.generator
|
||||
if base_class /= Void then
|
||||
Result.append (" -> {" + base_class + "}")
|
||||
end
|
||||
end
|
||||
|
||||
exception_failed_to_convert_to_json (an_object: detachable ANY): STRING
|
||||
-- Exception message for failing to convert `a' to a JSON_VALUE.
|
||||
do
|
||||
Result := exception_prefix + "Failed to convert Eiffel object to a JSON_VALUE"
|
||||
if an_object /= Void then
|
||||
Result.append (" : {" + an_object.generator + "}")
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation (JSON parser)
|
||||
|
||||
json_parser: JSON_PARSER
|
||||
once
|
||||
create Result.make_parser ("")
|
||||
end
|
||||
|
||||
end -- class EJSON
|
||||
@@ -1,141 +0,0 @@
|
||||
note
|
||||
description: "[
|
||||
JSON_ARRAY represent an array in JSON.
|
||||
An array in JSON is an ordered set of names.
|
||||
Examples
|
||||
array
|
||||
[]
|
||||
[elements]
|
||||
]"
|
||||
|
||||
author: "Javier Velilla"
|
||||
date: "2008/08/24"
|
||||
revision: "Revision 0.1"
|
||||
|
||||
class
|
||||
JSON_ARRAY
|
||||
|
||||
inherit
|
||||
JSON_VALUE
|
||||
|
||||
DEBUG_OUTPUT
|
||||
|
||||
create
|
||||
make_array
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make_array
|
||||
-- Initialize JSON Array
|
||||
do
|
||||
create values.make (10)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
i_th alias "[]" (i: INTEGER): JSON_VALUE
|
||||
-- Item at `i'-th position
|
||||
require
|
||||
is_valid_index: valid_index (i)
|
||||
do
|
||||
Result := values.i_th (i)
|
||||
end
|
||||
|
||||
representation: STRING
|
||||
local
|
||||
i: INTEGER
|
||||
do
|
||||
Result := "["
|
||||
from
|
||||
i := 1
|
||||
until
|
||||
i > count
|
||||
loop
|
||||
Result.append (i_th (i).representation)
|
||||
i := i + 1
|
||||
if i <= count then
|
||||
Result.append_character (',')
|
||||
end
|
||||
end
|
||||
Result.append_character (']')
|
||||
end
|
||||
|
||||
feature -- Visitor pattern
|
||||
|
||||
accept (a_visitor: JSON_VISITOR)
|
||||
-- Accept `a_visitor'.
|
||||
-- (Call `visit_json_array' procedure on `a_visitor'.)
|
||||
do
|
||||
a_visitor.visit_json_array (Current)
|
||||
end
|
||||
|
||||
feature -- Mesurement
|
||||
|
||||
count: INTEGER
|
||||
-- Number of items.
|
||||
do
|
||||
Result := values.count
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
valid_index (i: INTEGER): BOOLEAN
|
||||
-- Is `i' a valid index?
|
||||
do
|
||||
Result := (1 <= i) and (i <= count)
|
||||
end
|
||||
|
||||
feature -- Change Element
|
||||
|
||||
add (value: JSON_VALUE)
|
||||
require
|
||||
value_not_null: value /= void
|
||||
do
|
||||
values.extend (value)
|
||||
ensure
|
||||
has_new_value: old values.count + 1 = values.count and
|
||||
values.has (value)
|
||||
end
|
||||
|
||||
feature -- Report
|
||||
|
||||
hash_code: INTEGER
|
||||
-- Hash code value
|
||||
do
|
||||
from
|
||||
values.start
|
||||
Result := values.item.hash_code
|
||||
until
|
||||
values.off
|
||||
loop
|
||||
Result:= ((Result \\ 8388593) |<< 8) + values.item.hash_code
|
||||
values.forth
|
||||
end
|
||||
Result := Result \\ values.count
|
||||
end
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
array_representation: ARRAYED_LIST [JSON_VALUE]
|
||||
-- Representation as a sequences of values
|
||||
do
|
||||
Result := values
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
debug_output: STRING
|
||||
-- String that should be displayed in debugger to represent `Current'.
|
||||
do
|
||||
Result := count.out
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
values: ARRAYED_LIST [JSON_VALUE]
|
||||
-- Value container
|
||||
|
||||
invariant
|
||||
value_not_void: values /= Void
|
||||
|
||||
end
|
||||
@@ -1,61 +0,0 @@
|
||||
note
|
||||
description: "JSON Truth values"
|
||||
author: "Javier Velilla"
|
||||
date: "2008/08/24"
|
||||
revision: "Revision 0.1"
|
||||
|
||||
class
|
||||
JSON_BOOLEAN
|
||||
|
||||
inherit
|
||||
JSON_VALUE
|
||||
|
||||
create
|
||||
make_boolean
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make_boolean (an_item: BOOLEAN)
|
||||
--Initialize.
|
||||
do
|
||||
item := an_item
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
item: BOOLEAN
|
||||
-- Content
|
||||
|
||||
hash_code: INTEGER
|
||||
-- Hash code value
|
||||
do
|
||||
Result := item.hash_code
|
||||
end
|
||||
|
||||
representation: STRING
|
||||
do
|
||||
if item then
|
||||
Result := "true"
|
||||
else
|
||||
Result := "false"
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Visitor pattern
|
||||
|
||||
accept (a_visitor: JSON_VISITOR)
|
||||
-- Accept `a_visitor'.
|
||||
-- (Call `visit_json_boolean' procedure on `a_visitor'.)
|
||||
do
|
||||
a_visitor.visit_json_boolean (Current)
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
debug_output: STRING
|
||||
-- String that should be displayed in debugger to represent `Current'.
|
||||
do
|
||||
Result := item.out
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,47 +0,0 @@
|
||||
note
|
||||
description: "JSON Null Values"
|
||||
author: "Javier Velilla"
|
||||
date: "2008/08/24"
|
||||
revision: "Revision 0.1"
|
||||
|
||||
class
|
||||
JSON_NULL
|
||||
|
||||
inherit
|
||||
JSON_VALUE
|
||||
|
||||
feature --Access
|
||||
|
||||
hash_code: INTEGER
|
||||
-- Hash code value
|
||||
do
|
||||
Result := null_value.hash_code
|
||||
end
|
||||
|
||||
representation: STRING
|
||||
do
|
||||
Result := "null"
|
||||
end
|
||||
|
||||
feature -- Visitor pattern
|
||||
|
||||
accept (a_visitor: JSON_VISITOR)
|
||||
-- Accept `a_visitor'.
|
||||
-- (Call `visit_element_a' procedure on `a_visitor'.)
|
||||
do
|
||||
a_visitor.visit_json_null (Current)
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
debug_output: STRING
|
||||
-- String that should be displayed in debugger to represent `Current'.
|
||||
do
|
||||
Result := null_value
|
||||
end
|
||||
|
||||
feature {NONE}-- Implementation
|
||||
|
||||
null_value: STRING = "null"
|
||||
|
||||
end
|
||||
@@ -1,99 +0,0 @@
|
||||
note
|
||||
|
||||
description: "JSON Numbers, octal and hexadecimal formats are not used."
|
||||
author: "Javier Velilla"
|
||||
date: "2008/08/24"
|
||||
revision: "Revision 0.1"
|
||||
license:"MIT (see http://www.opensource.org/licenses/mit-license.php)"
|
||||
|
||||
class
|
||||
JSON_NUMBER
|
||||
|
||||
inherit
|
||||
JSON_VALUE
|
||||
redefine
|
||||
is_equal
|
||||
end
|
||||
|
||||
create
|
||||
make_integer,
|
||||
make_natural,
|
||||
make_real
|
||||
|
||||
feature {NONE} -- initialization
|
||||
|
||||
make_integer (an_argument: INTEGER_64)
|
||||
-- Initialize an instance of JSON_NUMBER from the integer value of `an_argument'.
|
||||
do
|
||||
item := an_argument.out
|
||||
numeric_type := INTEGER_TYPE
|
||||
end
|
||||
|
||||
make_natural (an_argument: NATURAL_64)
|
||||
-- Initialize an instance of JSON_NUMBER from the unsigned integer value of `an_argument'.
|
||||
do
|
||||
item := an_argument.out
|
||||
numeric_type := NATURAL_TYPE
|
||||
end
|
||||
|
||||
make_real (an_argument: DOUBLE)
|
||||
-- Initialize an instance of JSON_NUMBER from the floating point value of `an_argument'.
|
||||
do
|
||||
item := an_argument.out
|
||||
numeric_type := DOUBLE_TYPE
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
item: STRING
|
||||
-- Content
|
||||
|
||||
hash_code: INTEGER
|
||||
--Hash code value
|
||||
do
|
||||
Result := item.hash_code
|
||||
end
|
||||
|
||||
representation: STRING
|
||||
do
|
||||
Result := item
|
||||
end
|
||||
|
||||
feature -- Visitor pattern
|
||||
|
||||
accept (a_visitor: JSON_VISITOR)
|
||||
-- Accept `a_visitor'.
|
||||
-- (Call `visit_json_number' procedure on `a_visitor'.)
|
||||
do
|
||||
a_visitor.visit_json_number (Current)
|
||||
end
|
||||
|
||||
feature -- Status
|
||||
|
||||
is_equal (other: like Current): BOOLEAN
|
||||
-- Is `other' attached to an object of the same type
|
||||
-- as current object and identical to it?
|
||||
do
|
||||
Result := item.is_equal (other.item)
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
debug_output: STRING
|
||||
-- String that should be displayed in debugger to represent `Current'.
|
||||
do
|
||||
Result := item
|
||||
end
|
||||
|
||||
feature -- Implementation
|
||||
|
||||
INTEGER_TYPE: INTEGER = 1
|
||||
DOUBLE_TYPE: INTEGER = 2
|
||||
NATURAL_TYPE: INTEGER = 3
|
||||
|
||||
numeric_type: INTEGER
|
||||
|
||||
invariant
|
||||
item_not_void: item /= Void
|
||||
|
||||
end
|
||||
@@ -1,191 +0,0 @@
|
||||
note
|
||||
|
||||
description: "[
|
||||
An JSON_OBJECT represent an object in JSON.
|
||||
An object is an unordered set of name/value pairs
|
||||
|
||||
Examples:
|
||||
|
||||
object
|
||||
{}
|
||||
{"key","value"}
|
||||
|
||||
]"
|
||||
author: "Javier Velilla"
|
||||
date: "2008/08/24"
|
||||
revision: "Revision 0.1"
|
||||
license:"MIT (see http://www.opensource.org/licenses/mit-license.php)"
|
||||
|
||||
class
|
||||
JSON_OBJECT
|
||||
|
||||
inherit
|
||||
JSON_VALUE
|
||||
|
||||
TABLE_ITERABLE [JSON_VALUE, JSON_STRING]
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Initialize
|
||||
do
|
||||
create object.make (10)
|
||||
end
|
||||
|
||||
feature -- Change Element
|
||||
|
||||
put (value: detachable JSON_VALUE; key: JSON_STRING)
|
||||
-- Assuming there is no item of key `key',
|
||||
-- insert `value' with `key'.
|
||||
require
|
||||
key_not_present: not has_key (key)
|
||||
local
|
||||
l_value: like value
|
||||
do
|
||||
l_value := value
|
||||
if l_value = Void then
|
||||
create {JSON_NULL} l_value
|
||||
end
|
||||
object.extend (l_value, key)
|
||||
end
|
||||
|
||||
replace (value: detachable JSON_VALUE; key: JSON_STRING)
|
||||
-- Assuming there is no item of key `key',
|
||||
-- insert `value' with `key'.
|
||||
local
|
||||
l_value: like value
|
||||
do
|
||||
l_value := value
|
||||
if l_value = Void then
|
||||
create {JSON_NULL} l_value
|
||||
end
|
||||
object.force (l_value, key)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
has_key (key: JSON_STRING): BOOLEAN
|
||||
-- has the JSON_OBJECT contains a specific key 'key'.
|
||||
do
|
||||
Result := object.has (key)
|
||||
end
|
||||
|
||||
has_item (value: JSON_VALUE): BOOLEAN
|
||||
-- has the JSON_OBJECT contain a specfic item 'value'
|
||||
do
|
||||
Result := object.has_item (value)
|
||||
end
|
||||
|
||||
item (key: JSON_STRING): detachable JSON_VALUE
|
||||
-- the json_value associated with a key.
|
||||
do
|
||||
Result := object.item (key)
|
||||
end
|
||||
|
||||
current_keys: ARRAY [JSON_STRING]
|
||||
-- array containing actually used keys
|
||||
do
|
||||
Result := object.current_keys
|
||||
end
|
||||
|
||||
representation: STRING
|
||||
local
|
||||
t: HASH_TABLE [JSON_VALUE, JSON_STRING]
|
||||
do
|
||||
Result := "{"
|
||||
from
|
||||
t := map_representation
|
||||
t.start
|
||||
until
|
||||
t.after
|
||||
loop
|
||||
Result.append (t.key_for_iteration.representation)
|
||||
Result.append (":")
|
||||
Result.append (t.item_for_iteration.representation)
|
||||
t.forth
|
||||
if not t.after then
|
||||
Result.append_character (',')
|
||||
end
|
||||
end
|
||||
Result.append_character ('}')
|
||||
end
|
||||
|
||||
feature -- Mesurement
|
||||
|
||||
count: INTEGER
|
||||
-- Number of field
|
||||
do
|
||||
Result := object.count
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
new_cursor: TABLE_ITERATION_CURSOR [JSON_VALUE, JSON_STRING]
|
||||
-- Fresh cursor associated with current structure
|
||||
do
|
||||
Result := object.new_cursor
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_empty: BOOLEAN
|
||||
-- Is empty object?
|
||||
do
|
||||
Result := object.is_empty
|
||||
end
|
||||
|
||||
feature -- Visitor pattern
|
||||
|
||||
accept (a_visitor: JSON_VISITOR)
|
||||
-- Accept `a_visitor'.
|
||||
-- (Call `visit_json_object' procedure on `a_visitor'.)
|
||||
do
|
||||
a_visitor.visit_json_object (Current)
|
||||
end
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
map_representation: HASH_TABLE [JSON_VALUE, JSON_STRING]
|
||||
--A representation that maps keys to values
|
||||
do
|
||||
Result := object
|
||||
end
|
||||
|
||||
feature -- Report
|
||||
|
||||
hash_code: INTEGER
|
||||
-- Hash code value
|
||||
do
|
||||
from
|
||||
object.start
|
||||
Result := object.out.hash_code
|
||||
until
|
||||
object.off
|
||||
loop
|
||||
Result := ((Result \\ 8388593) |<< 8) + object.item_for_iteration.hash_code
|
||||
object.forth
|
||||
end
|
||||
-- Ensure it is a positive value.
|
||||
Result := Result.hash_code
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
debug_output: STRING
|
||||
-- String that should be displayed in debugger to represent `Current'.
|
||||
do
|
||||
Result := object.count.out
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
object: HASH_TABLE [JSON_VALUE, JSON_STRING]
|
||||
-- Value container
|
||||
|
||||
invariant
|
||||
object_not_null: object /= Void
|
||||
|
||||
end
|
||||
@@ -1,329 +0,0 @@
|
||||
note
|
||||
|
||||
description: "[
|
||||
A JSON_STRING represent a string in JSON.
|
||||
A string is a collection of zero or more Unicodes characters, wrapped in double
|
||||
quotes, using blackslash espaces.
|
||||
]"
|
||||
|
||||
author: "Javier Velilla"
|
||||
date: "2008/08/24"
|
||||
revision: "Revision 0.1"
|
||||
license:"MIT (see http://www.opensource.org/licenses/mit-license.php)"
|
||||
|
||||
|
||||
class
|
||||
JSON_STRING
|
||||
|
||||
inherit
|
||||
JSON_VALUE
|
||||
redefine
|
||||
is_equal
|
||||
end
|
||||
|
||||
create
|
||||
make_json,
|
||||
make_json_from_string_32,
|
||||
make_with_escaped_json
|
||||
|
||||
convert
|
||||
make_json ({READABLE_STRING_8, STRING_8, IMMUTABLE_STRING_8}),
|
||||
make_json_from_string_32 ({READABLE_STRING_32, STRING_32, IMMUTABLE_STRING_32})
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make_json (s: READABLE_STRING_8)
|
||||
-- Initialize.
|
||||
require
|
||||
item_not_void: s /= Void
|
||||
do
|
||||
make_with_escaped_json (escaped_json_string (s))
|
||||
end
|
||||
|
||||
make_json_from_string_32 (s: READABLE_STRING_32)
|
||||
-- Initialize from STRING_32 `s'.
|
||||
require
|
||||
item_not_void: s /= Void
|
||||
do
|
||||
make_with_escaped_json (escaped_json_string_32 (s))
|
||||
end
|
||||
|
||||
make_with_escaped_json (s: READABLE_STRING_8)
|
||||
-- Initialize with an_item already escaped
|
||||
require
|
||||
item_not_void: s /= Void
|
||||
do
|
||||
item := s
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
item: STRING
|
||||
-- Contents with escaped entities if any
|
||||
|
||||
unescaped_string_8: STRING_8
|
||||
-- Unescaped string from `item'
|
||||
local
|
||||
s: like item
|
||||
i, n: INTEGER
|
||||
c: CHARACTER
|
||||
do
|
||||
s := item
|
||||
n := s.count
|
||||
create Result.make (n)
|
||||
from i := 1 until i > n loop
|
||||
c := s[i]
|
||||
if c = '\' then
|
||||
if i < n then
|
||||
inspect s[i+1]
|
||||
when '\' then
|
||||
Result.append_character ('\')
|
||||
i := i + 2
|
||||
when '%"' then
|
||||
Result.append_character ('%"')
|
||||
i := i + 2
|
||||
when 'n' then
|
||||
Result.append_character ('%N')
|
||||
i := i + 2
|
||||
when 'r' then
|
||||
Result.append_character ('%R')
|
||||
i := i + 2
|
||||
when 'u' then
|
||||
--| Leave unicode \uXXXX unescaped
|
||||
Result.append_character ('\')
|
||||
i := i + 1
|
||||
else
|
||||
Result.append_character ('\')
|
||||
i := i + 1
|
||||
end
|
||||
else
|
||||
Result.append_character ('\')
|
||||
i := i + 1
|
||||
end
|
||||
else
|
||||
Result.append_character (c)
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
unescaped_string_32: STRING_32
|
||||
-- Unescaped string 32 from `item'
|
||||
local
|
||||
s: like item
|
||||
i, n: INTEGER
|
||||
c: CHARACTER
|
||||
hex: STRING
|
||||
do
|
||||
s := item
|
||||
n := s.count
|
||||
create Result.make (n)
|
||||
from i := 1 until i > n loop
|
||||
c := s[i]
|
||||
if c = '\' then
|
||||
if i < n then
|
||||
inspect s[i+1]
|
||||
when '\' then
|
||||
Result.append_character ('\')
|
||||
i := i + 2
|
||||
when '%"' then
|
||||
Result.append_character ('%"')
|
||||
i := i + 2
|
||||
when 'n' then
|
||||
Result.append_character ('%N')
|
||||
i := i + 2
|
||||
when 'r' then
|
||||
Result.append_character ('%R')
|
||||
i := i + 2
|
||||
when 'u' then
|
||||
hex := s.substring (i+2, i+2+4 - 1)
|
||||
if hex.count = 4 then
|
||||
Result.append_code (hexadecimal_to_natural_32 (hex))
|
||||
end
|
||||
i := i + 2 + 4
|
||||
else
|
||||
Result.append_character ('\')
|
||||
i := i + 1
|
||||
end
|
||||
else
|
||||
Result.append_character ('\')
|
||||
i := i + 1
|
||||
end
|
||||
else
|
||||
Result.append_character (c.to_character_32)
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
representation: STRING
|
||||
-- String representation of `item' with escaped entities if any
|
||||
do
|
||||
create Result.make (item.count + 2)
|
||||
Result.append_character ('%"')
|
||||
Result.append (item)
|
||||
Result.append_character ('%"')
|
||||
end
|
||||
|
||||
feature -- Visitor pattern
|
||||
|
||||
accept (a_visitor: JSON_VISITOR)
|
||||
-- Accept `a_visitor'.
|
||||
-- (Call `visit_json_string' procedure on `a_visitor'.)
|
||||
do
|
||||
a_visitor.visit_json_string (Current)
|
||||
end
|
||||
|
||||
feature -- Comparison
|
||||
|
||||
is_equal (other: like Current): BOOLEAN
|
||||
-- Is JSON_STRING made of same character sequence as `other'
|
||||
-- (possibly with a different capacity)?
|
||||
do
|
||||
Result := item.same_string (other.item)
|
||||
end
|
||||
|
||||
feature -- Change Element
|
||||
|
||||
append (a_string: STRING)
|
||||
-- Add a_string
|
||||
require
|
||||
a_string_not_void: a_string /= Void
|
||||
do
|
||||
item.append_string (a_string)
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
hash_code: INTEGER
|
||||
-- Hash code value
|
||||
do
|
||||
Result := item.hash_code
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
debug_output: STRING
|
||||
-- String that should be displayed in debugger to represent `Current'.
|
||||
do
|
||||
Result := item
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
is_hexadecimal (s: READABLE_STRING_8): BOOLEAN
|
||||
-- Is `s' an hexadecimal value?
|
||||
do
|
||||
Result := across s as scur all scur.item.is_hexa_digit end
|
||||
end
|
||||
|
||||
hexadecimal_to_natural_32 (s: READABLE_STRING_8): NATURAL_32
|
||||
-- Hexadecimal string `s' converted to NATURAL_32 value
|
||||
require
|
||||
s_not_void: s /= Void
|
||||
is_hexadecimal: is_hexadecimal (s)
|
||||
local
|
||||
i, nb: INTEGER
|
||||
char: CHARACTER
|
||||
do
|
||||
nb := s.count
|
||||
|
||||
if nb >= 2 and then s.item (2) = 'x' then
|
||||
i := 3
|
||||
else
|
||||
i := 1
|
||||
end
|
||||
|
||||
from
|
||||
until
|
||||
i > nb
|
||||
loop
|
||||
Result := Result * 16
|
||||
char := s.item (i)
|
||||
if char >= '0' and then char <= '9' then
|
||||
Result := Result + (char |-| '0').to_natural_32
|
||||
else
|
||||
Result := Result + (char.lower |-| 'a' + 10).to_natural_32
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
|
||||
escaped_json_string (s: READABLE_STRING_8): STRING_8
|
||||
-- JSON string with '"' and '\' characters escaped
|
||||
require
|
||||
s_not_void: s /= Void
|
||||
local
|
||||
i, n: INTEGER
|
||||
c: CHARACTER_8
|
||||
do
|
||||
n := s.count
|
||||
create Result.make (n + n // 10)
|
||||
from i := 1 until i > n loop
|
||||
c := s.item (i)
|
||||
inspect c
|
||||
when '%"' then Result.append_string ("\%"")
|
||||
when '\' then Result.append_string ("\\")
|
||||
when '%R' then Result.append_string ("\r")
|
||||
when '%N' then Result.append_string ("\n")
|
||||
else
|
||||
Result.extend (c)
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
|
||||
escaped_json_string_32 (s: READABLE_STRING_32): STRING_8
|
||||
-- JSON string with '"' and '\' characters and unicode escaped
|
||||
require
|
||||
s_not_void: s /= Void
|
||||
local
|
||||
i, j, n: INTEGER
|
||||
uc: CHARACTER_32
|
||||
c: CHARACTER_8
|
||||
h: STRING_8
|
||||
do
|
||||
n := s.count
|
||||
create Result.make (n + n // 10)
|
||||
from i := 1 until i > n loop
|
||||
uc := s.item (i)
|
||||
if uc.is_character_8 then
|
||||
c := uc.to_character_8
|
||||
inspect c
|
||||
when '%"' then Result.append_string ("\%"")
|
||||
when '\' then Result.append_string ("\\")
|
||||
when '%R' then Result.append_string ("\r")
|
||||
when '%N' then Result.append_string ("\n")
|
||||
else
|
||||
Result.extend (c)
|
||||
end
|
||||
else
|
||||
Result.append ("\u")
|
||||
h := uc.code.to_hex_string
|
||||
-- Remove first 0 and keep 4 hexa digit
|
||||
from
|
||||
j := 1
|
||||
until
|
||||
h.count = 4 or (j <= h.count and then h.item (j) /= '0')
|
||||
loop
|
||||
j := j + 1
|
||||
end
|
||||
h := h.substring (j, h.count)
|
||||
|
||||
from
|
||||
until
|
||||
h.count >= 4
|
||||
loop
|
||||
h.prepend_integer (0)
|
||||
end
|
||||
check h.count = 4 end
|
||||
Result.append (h)
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
|
||||
invariant
|
||||
item_not_void: item /= Void
|
||||
|
||||
end
|
||||
@@ -1,43 +0,0 @@
|
||||
note
|
||||
description:"[
|
||||
JSON_VALUE represent a value in JSON.
|
||||
A value can be
|
||||
* a string in double quotes
|
||||
* a number
|
||||
* boolean value(true, false )
|
||||
* null
|
||||
* an object
|
||||
* an array
|
||||
]"
|
||||
author: "Javier Velilla"
|
||||
date: "2008/05/19"
|
||||
revision: "Revision 0.1"
|
||||
license:"MIT (see http://www.opensource.org/licenses/mit-license.php)"
|
||||
|
||||
|
||||
deferred class
|
||||
JSON_VALUE
|
||||
|
||||
inherit
|
||||
HASHABLE
|
||||
|
||||
DEBUG_OUTPUT
|
||||
|
||||
feature -- Access
|
||||
|
||||
representation: STRING
|
||||
-- UTF-8 encoded Unicode string representation of Current
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Visitor pattern
|
||||
|
||||
accept (a_visitor: JSON_VISITOR)
|
||||
-- Accept `a_visitor'.
|
||||
-- (Call `visit_*' procedure on `a_visitor'.)
|
||||
require
|
||||
a_visitor_not_void: a_visitor /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,513 +0,0 @@
|
||||
note
|
||||
|
||||
description: "Parse serialized JSON data"
|
||||
author: "jvelilla"
|
||||
date: "2008/08/24"
|
||||
revision: "Revision 0.1"
|
||||
|
||||
class
|
||||
JSON_PARSER
|
||||
|
||||
inherit
|
||||
JSON_READER
|
||||
JSON_TOKENS
|
||||
|
||||
create
|
||||
make_parser
|
||||
|
||||
feature {NONE} -- Initialize
|
||||
|
||||
make_parser (a_json: STRING)
|
||||
-- Initialize.
|
||||
require
|
||||
json_not_empty: a_json /= Void and then not a_json.is_empty
|
||||
do
|
||||
make (a_json)
|
||||
is_parsed := True
|
||||
create errors.make
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_parsed: BOOLEAN
|
||||
-- Is parsed?
|
||||
|
||||
errors: LINKED_LIST [STRING]
|
||||
-- Current errors
|
||||
|
||||
current_errors: STRING
|
||||
-- Current errors as string
|
||||
do
|
||||
create Result.make_empty
|
||||
from
|
||||
errors.start
|
||||
until
|
||||
errors.after
|
||||
loop
|
||||
Result.append_string (errors.item + "%N")
|
||||
errors.forth
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
report_error (e: STRING)
|
||||
-- Report error `e'
|
||||
require
|
||||
e_not_void: e /= Void
|
||||
do
|
||||
errors.force (e)
|
||||
end
|
||||
|
||||
feature -- Commands
|
||||
|
||||
parse_json: detachable JSON_VALUE
|
||||
-- Parse JSON data `representation'
|
||||
-- start ::= object | array
|
||||
do
|
||||
if is_valid_start_symbol then
|
||||
Result := parse
|
||||
if extra_elements then
|
||||
is_parsed := False
|
||||
end
|
||||
else
|
||||
is_parsed := False
|
||||
report_error ("Syntax error unexpected token, expecting `{' or `['")
|
||||
end
|
||||
end
|
||||
|
||||
parse: detachable JSON_VALUE
|
||||
-- Parse JSON data `representation'
|
||||
local
|
||||
c: CHARACTER
|
||||
do
|
||||
if is_parsed then
|
||||
skip_white_spaces
|
||||
c := actual
|
||||
inspect c
|
||||
when j_OBJECT_OPEN then
|
||||
Result := parse_object
|
||||
when j_STRING then
|
||||
Result := parse_string
|
||||
when j_ARRAY_OPEN then
|
||||
Result := parse_array
|
||||
else
|
||||
if c.is_digit or c = j_MINUS then
|
||||
Result := parse_number
|
||||
elseif is_null then
|
||||
Result := create {JSON_NULL}
|
||||
next
|
||||
next
|
||||
next
|
||||
elseif is_true then
|
||||
Result := create {JSON_BOOLEAN}.make_boolean (True)
|
||||
next
|
||||
next
|
||||
next
|
||||
elseif is_false then
|
||||
Result := create {JSON_BOOLEAN}.make_boolean (False)
|
||||
next
|
||||
next
|
||||
next
|
||||
next
|
||||
else
|
||||
is_parsed := False
|
||||
report_error ("JSON is not well formed in parse")
|
||||
Result := Void
|
||||
end
|
||||
end
|
||||
end
|
||||
ensure
|
||||
is_parsed_implies_result_not_void: is_parsed implies Result /= Void
|
||||
end
|
||||
|
||||
parse_object: JSON_OBJECT
|
||||
-- object
|
||||
-- {}
|
||||
-- {"key" : "value" [,]}
|
||||
local
|
||||
has_more: BOOLEAN
|
||||
l_json_string: detachable JSON_STRING
|
||||
l_value: detachable JSON_VALUE
|
||||
do
|
||||
create Result.make
|
||||
-- check if is an empty object {}
|
||||
next
|
||||
skip_white_spaces
|
||||
if actual = j_OBJECT_CLOSE then
|
||||
--is an empty object
|
||||
else
|
||||
-- a complex object {"key" : "value"}
|
||||
previous
|
||||
from has_more := True until not has_more loop
|
||||
next
|
||||
skip_white_spaces
|
||||
l_json_string := parse_string
|
||||
next
|
||||
skip_white_spaces
|
||||
if actual = ':' then
|
||||
next
|
||||
skip_white_spaces
|
||||
else
|
||||
is_parsed := False
|
||||
report_error ("%N Input string is a not well formed JSON, expected: : found: " + actual.out)
|
||||
has_more := False
|
||||
end
|
||||
|
||||
l_value := parse
|
||||
if is_parsed and then (l_value /= Void and l_json_string /= Void) then
|
||||
Result.put (l_value, l_json_string)
|
||||
next
|
||||
skip_white_spaces
|
||||
if actual = j_OBJECT_CLOSE then
|
||||
has_more := False
|
||||
elseif actual /= ',' then
|
||||
has_more := False
|
||||
is_parsed := False
|
||||
report_error ("JSON Object syntactically malformed expected , found: [" + actual.out + "]")
|
||||
end
|
||||
else
|
||||
has_more := False
|
||||
-- explain the error
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
parse_string: detachable JSON_STRING
|
||||
-- Parsed string
|
||||
local
|
||||
has_more: BOOLEAN
|
||||
l_json_string: STRING
|
||||
l_unicode: STRING
|
||||
c: like actual
|
||||
do
|
||||
create l_json_string.make_empty
|
||||
if actual = j_STRING then
|
||||
from
|
||||
has_more := True
|
||||
until
|
||||
not has_more
|
||||
loop
|
||||
next
|
||||
c := actual
|
||||
if c = j_STRING then
|
||||
has_more := False
|
||||
elseif c = '%H' then
|
||||
next
|
||||
c := actual
|
||||
if c = 'u' then
|
||||
create l_unicode.make_from_string ("\u")
|
||||
l_unicode.append (read_unicode)
|
||||
c := actual
|
||||
if is_valid_unicode (l_unicode) then
|
||||
l_json_string.append (l_unicode)
|
||||
else
|
||||
has_more := False
|
||||
is_parsed := False
|
||||
report_error ("Input String is not well formed JSON, expected a Unicode value, found [" + c.out + " ]")
|
||||
end
|
||||
elseif (not is_special_character (c) and not is_special_control (c)) or c = '%N' then
|
||||
has_more := False
|
||||
is_parsed := False
|
||||
report_error ("Input String is not well formed JSON, found [" + c.out + " ]")
|
||||
else
|
||||
l_json_string.append_character ('\')
|
||||
l_json_string.append_character (c)
|
||||
end
|
||||
else
|
||||
if is_special_character (c) and c /= '/' then
|
||||
has_more := False
|
||||
is_parsed := False
|
||||
report_error ("Input String is not well formed JSON, found [" + c.out + " ]")
|
||||
else
|
||||
l_json_string.append_character (c)
|
||||
end
|
||||
end
|
||||
end
|
||||
create Result.make_with_escaped_json (l_json_string)
|
||||
else
|
||||
Result := Void
|
||||
end
|
||||
end
|
||||
|
||||
parse_array: JSON_ARRAY
|
||||
-- array
|
||||
-- []
|
||||
-- [elements [,]]
|
||||
local
|
||||
flag: BOOLEAN
|
||||
l_value: detachable JSON_VALUE
|
||||
c: like actual
|
||||
do
|
||||
create Result.make_array
|
||||
--check if is an empty array []
|
||||
next
|
||||
skip_white_spaces
|
||||
if actual = j_array_close then
|
||||
--is an empty array
|
||||
else
|
||||
previous
|
||||
from
|
||||
flag := True
|
||||
until
|
||||
not flag
|
||||
loop
|
||||
next
|
||||
skip_white_spaces
|
||||
l_value := parse
|
||||
if is_parsed and then l_value /= Void then
|
||||
Result.add (l_value)
|
||||
next
|
||||
skip_white_spaces
|
||||
c := actual
|
||||
if c = j_ARRAY_CLOSE then
|
||||
flag := False
|
||||
elseif c /= ',' then
|
||||
flag := False
|
||||
is_parsed := False
|
||||
report_error ("Array is not well formed JSON, found [" + c.out + " ]")
|
||||
end
|
||||
else
|
||||
flag := False
|
||||
report_error ("Array is not well formed JSON, found [" + actual.out + " ]")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
parse_number: detachable JSON_NUMBER
|
||||
-- Parsed number
|
||||
local
|
||||
sb: STRING
|
||||
flag: BOOLEAN
|
||||
is_integer: BOOLEAN
|
||||
c: like actual
|
||||
do
|
||||
create sb.make_empty
|
||||
sb.append_character (actual)
|
||||
|
||||
from
|
||||
flag := True
|
||||
until
|
||||
not flag
|
||||
loop
|
||||
next
|
||||
c := actual
|
||||
if not has_next or is_close_token (c)
|
||||
or c = ',' or c = '%N' or c = '%R'
|
||||
then
|
||||
flag := False
|
||||
previous
|
||||
else
|
||||
sb.append_character (c)
|
||||
end
|
||||
end
|
||||
|
||||
if is_valid_number (sb) then
|
||||
if sb.is_integer then
|
||||
create Result.make_integer (sb.to_integer)
|
||||
is_integer := True
|
||||
elseif sb.is_double and not is_integer then
|
||||
create Result.make_real (sb.to_double)
|
||||
end
|
||||
else
|
||||
is_parsed := False
|
||||
report_error ("Expected a number, found: [ " + sb + " ]")
|
||||
end
|
||||
end
|
||||
|
||||
is_null: BOOLEAN
|
||||
-- Word at index represents null?
|
||||
local
|
||||
l_null: STRING
|
||||
l_string: STRING
|
||||
do
|
||||
l_null := null_id
|
||||
l_string := json_substring (index,index + l_null.count - 1)
|
||||
if l_string.is_equal (l_null) then
|
||||
Result := True
|
||||
end
|
||||
end
|
||||
|
||||
is_false: BOOLEAN
|
||||
-- Word at index represents false?
|
||||
local
|
||||
l_false: STRING
|
||||
l_string: STRING
|
||||
do
|
||||
l_false := false_id
|
||||
l_string := json_substring (index, index + l_false.count - 1)
|
||||
if l_string.is_equal (l_false) then
|
||||
Result := True
|
||||
end
|
||||
end
|
||||
|
||||
is_true: BOOLEAN
|
||||
-- Word at index represents true?
|
||||
local
|
||||
l_true: STRING
|
||||
l_string: STRING
|
||||
do
|
||||
l_true := true_id
|
||||
l_string := json_substring (index,index + l_true.count - 1)
|
||||
if l_string.is_equal (l_true) then
|
||||
Result := True
|
||||
end
|
||||
end
|
||||
|
||||
read_unicode: STRING
|
||||
-- Read unicode and return value
|
||||
local
|
||||
i: INTEGER
|
||||
do
|
||||
create Result.make_empty
|
||||
from
|
||||
i := 1
|
||||
until
|
||||
i > 4 or not has_next
|
||||
loop
|
||||
next
|
||||
Result.append_character (actual)
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
is_valid_number (a_number: STRING): BOOLEAN
|
||||
-- is 'a_number' a valid number based on this regular expression
|
||||
-- "-?(?: 0|[1-9]\d+)(?: \.\d+)?(?: [eE][+-]?\d+)?\b"?
|
||||
local
|
||||
s: detachable STRING
|
||||
c: CHARACTER
|
||||
i,n: INTEGER
|
||||
do
|
||||
create s.make_empty
|
||||
n := a_number.count
|
||||
if n = 0 then
|
||||
Result := False
|
||||
else
|
||||
Result := True
|
||||
i := 1
|
||||
--| "-?"
|
||||
c := a_number[i]
|
||||
if c = '-' then
|
||||
s.extend (c); i := i + 1; c := a_number[i]
|
||||
end
|
||||
--| "0|[1-9]\d*
|
||||
if c.is_digit then
|
||||
if c = '0' then
|
||||
--| "0"
|
||||
s.extend (c); i := i + 1; c := a_number[i]
|
||||
else
|
||||
--| "[1-9]"
|
||||
s.extend (c); i := i + 1; c := a_number[i]
|
||||
--| "\d*"
|
||||
from until i > n or not c.is_digit loop
|
||||
s.extend (c); i := i + 1; c := a_number[i]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if Result then
|
||||
--| "(\.\d+)?"
|
||||
if c = '.' then
|
||||
--| "\.\d+" = "\.\d\d*"
|
||||
s.extend (c); i := i + 1; c := a_number[i]
|
||||
if c.is_digit then
|
||||
from until i > n or not c.is_digit loop
|
||||
s.extend (c); i := i + 1; c := a_number[i]
|
||||
end
|
||||
else
|
||||
Result := False --| expecting digit
|
||||
end
|
||||
end
|
||||
end
|
||||
if Result then --| "(?:[eE][+-]?\d+)?\b"
|
||||
if c = 'e' or c = 'E' then
|
||||
--| "[eE][+-]?\d+"
|
||||
s.extend (c); i := i + 1; c := a_number[i]
|
||||
if c = '+' or c = '-' then
|
||||
s.extend (c); i := i + 1; c := a_number[i]
|
||||
end
|
||||
if c.is_digit then
|
||||
from until i > n or not c.is_digit loop
|
||||
s.extend (c); i := i + 1; c := a_number[i]
|
||||
end
|
||||
else
|
||||
Result := False --| expecting digit
|
||||
end
|
||||
end
|
||||
end
|
||||
if Result then --| "\b"
|
||||
from until i > n or not c.is_space loop
|
||||
s.extend (c); i := i + 1; c := a_number[i]
|
||||
end
|
||||
Result := i > n and then s.same_string (a_number)
|
||||
end
|
||||
end
|
||||
|
||||
is_valid_unicode (a_unicode: STRING): BOOLEAN
|
||||
-- is 'a_unicode' a valid unicode based on this regular expression
|
||||
-- "\\u[0-9a-fA-F]{4}"
|
||||
local
|
||||
i: INTEGER
|
||||
do
|
||||
if
|
||||
a_unicode.count = 6 and then
|
||||
a_unicode[1] = '\' and then
|
||||
a_unicode[2] = 'u'
|
||||
then
|
||||
from
|
||||
Result := True
|
||||
i := 3
|
||||
until
|
||||
i > 6 or Result = False
|
||||
loop
|
||||
inspect a_unicode[i]
|
||||
when '0'..'9', 'a'..'f', 'A'..'F' then
|
||||
else
|
||||
Result := False
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
extra_elements: BOOLEAN
|
||||
-- has more elements?
|
||||
local
|
||||
c: like actual
|
||||
do
|
||||
if has_next then
|
||||
next
|
||||
end
|
||||
from
|
||||
c := actual
|
||||
until
|
||||
c /= ' ' or c /= '%R' or c /= '%U' or c /= '%T' or c /= '%N' or not has_next
|
||||
loop
|
||||
next
|
||||
end
|
||||
Result := has_next
|
||||
end
|
||||
|
||||
is_valid_start_symbol : BOOLEAN
|
||||
-- expecting `{' or `[' as start symbol
|
||||
do
|
||||
if attached representation as s and then s.count > 0 then
|
||||
Result := s[1] = '{' or s[1] = '['
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Constants
|
||||
|
||||
false_id: STRING = "false"
|
||||
|
||||
true_id: STRING = "true"
|
||||
|
||||
null_id: STRING = "null"
|
||||
|
||||
|
||||
end
|
||||
@@ -1,118 +0,0 @@
|
||||
note
|
||||
description: "Objects that ..."
|
||||
author: "jvelilla"
|
||||
date: "2008/08/24"
|
||||
revision: "0.1"
|
||||
|
||||
class
|
||||
JSON_READER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_json: STRING)
|
||||
-- Initialize Reader
|
||||
do
|
||||
set_representation (a_json)
|
||||
end
|
||||
|
||||
feature -- Commands
|
||||
|
||||
set_representation (a_json: STRING)
|
||||
-- Set `representation'.
|
||||
do
|
||||
a_json.left_adjust
|
||||
a_json.right_adjust
|
||||
representation := a_json
|
||||
index := 1
|
||||
end
|
||||
|
||||
read: CHARACTER
|
||||
-- Read character
|
||||
do
|
||||
if not representation.is_empty then
|
||||
Result := representation.item (index)
|
||||
end
|
||||
end
|
||||
|
||||
next
|
||||
-- Move to next index
|
||||
require
|
||||
has_more_elements: has_next
|
||||
do
|
||||
index := index + 1
|
||||
ensure
|
||||
incremented: old index + 1 = index
|
||||
end
|
||||
|
||||
previous
|
||||
-- Move to previous index
|
||||
require
|
||||
not_is_first: has_previous
|
||||
do
|
||||
index := index - 1
|
||||
ensure
|
||||
incremented: old index - 1 = index
|
||||
end
|
||||
|
||||
skip_white_spaces
|
||||
-- Remove white spaces
|
||||
local
|
||||
c: like actual
|
||||
do
|
||||
from
|
||||
c := actual
|
||||
until
|
||||
(c /= ' ' and c /= '%N' and c /= '%R' and c /= '%U' and c /= '%T' ) or not has_next
|
||||
loop
|
||||
next
|
||||
c := actual
|
||||
end
|
||||
end
|
||||
|
||||
json_substring (start_index, end_index: INTEGER_32): STRING
|
||||
-- JSON representation between `start_index' and `end_index'
|
||||
do
|
||||
Result := representation.substring (start_index, end_index)
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
has_next: BOOLEAN
|
||||
-- Has a next character?
|
||||
do
|
||||
Result := index <= representation.count
|
||||
end
|
||||
|
||||
has_previous: BOOLEAN
|
||||
-- Has a previous character?
|
||||
do
|
||||
Result := index >= 1
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
representation: STRING
|
||||
-- Serialized representation of the original JSON string
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
actual: CHARACTER
|
||||
-- Current character or '%U' if none
|
||||
do
|
||||
if index > representation.count then
|
||||
Result := '%U'
|
||||
else
|
||||
Result := representation.item (index)
|
||||
end
|
||||
end
|
||||
|
||||
index: INTEGER
|
||||
-- Actual index
|
||||
|
||||
invariant
|
||||
representation_not_void: representation /= Void
|
||||
|
||||
end
|
||||
@@ -1,77 +0,0 @@
|
||||
note
|
||||
description: ""
|
||||
author: "jvelilla"
|
||||
date: "2008/08/24"
|
||||
revision: "0.1"
|
||||
|
||||
class
|
||||
JSON_TOKENS
|
||||
|
||||
feature -- Access
|
||||
|
||||
j_OBJECT_OPEN: CHARACTER = '{'
|
||||
j_ARRAY_OPEN: CHARACTER = '['
|
||||
j_OBJECT_CLOSE: CHARACTER = '}'
|
||||
j_ARRAY_CLOSE: CHARACTER = ']'
|
||||
|
||||
j_STRING: CHARACTER = '"'
|
||||
j_PLUS: CHARACTER = '+'
|
||||
j_MINUS: CHARACTER = '-'
|
||||
j_DOT: CHARACTER = '.'
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_open_token (c: CHARACTER): BOOLEAN
|
||||
-- Characters which open a type
|
||||
do
|
||||
inspect c
|
||||
when j_OBJECT_OPEN, j_ARRAY_OPEN, j_STRING, j_PLUS, j_MINUS, j_DOT then
|
||||
Result := True
|
||||
else
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
is_close_token (c: CHARACTER): BOOLEAN
|
||||
-- Characters which close a type
|
||||
do
|
||||
inspect c
|
||||
when j_OBJECT_CLOSE, j_ARRAY_CLOSE, j_STRING then
|
||||
Result := True
|
||||
else
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
is_special_character (c: CHARACTER): BOOLEAN
|
||||
-- Control Characters
|
||||
-- %F Form feed
|
||||
-- %H backslasH
|
||||
-- %N Newline
|
||||
-- %R carriage Return
|
||||
-- %T horizontal Tab
|
||||
-- %B Backspace
|
||||
-- / Solidus
|
||||
-- " Quotation
|
||||
do
|
||||
inspect c
|
||||
when '%F', '%H', '%N', '%R', '%T', '%B', '/', '"' then
|
||||
Result := True
|
||||
else
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
is_special_control (c: CHARACTER): BOOLEAN
|
||||
--Control Characters
|
||||
-- \b\f\n\r\t
|
||||
do
|
||||
inspect c
|
||||
when 'b', 'f', 'n', 'r', 't' then
|
||||
Result := True
|
||||
else
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,38 +0,0 @@
|
||||
note
|
||||
description: "[
|
||||
Shared factory class for creating JSON objects. Maps JSON
|
||||
objects to ELKS HASH_TABLEs and JSON arrays to ELKS
|
||||
LINKED_LISTs. Use non-conforming inheritance from this
|
||||
class to ensure that your classes share the same
|
||||
JSON_FACTORY instance.
|
||||
]"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision: 89185 $"
|
||||
file: "$HeadURL: $"
|
||||
|
||||
class SHARED_EJSON
|
||||
|
||||
feature
|
||||
|
||||
json: EJSON
|
||||
-- A shared EJSON instance with default converters for
|
||||
--LINKED_LIST [ANY] and HASH_TABLE [ANY, HASHABLE]
|
||||
local
|
||||
jalc: JSON_ARRAYED_LIST_CONVERTER
|
||||
jllc: JSON_LINKED_LIST_CONVERTER
|
||||
jhtc: JSON_HASH_TABLE_CONVERTER
|
||||
once
|
||||
create Result
|
||||
|
||||
create jalc.make
|
||||
Result.add_converter (jalc)
|
||||
|
||||
create jllc.make
|
||||
Result.add_converter (jllc)
|
||||
|
||||
create jhtc.make
|
||||
Result.add_converter (jhtc)
|
||||
end
|
||||
|
||||
end -- class SHARED_EJSON
|
||||
@@ -1,24 +0,0 @@
|
||||
note
|
||||
description : "test_suite application root class"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
|
||||
class
|
||||
APPLICATION
|
||||
|
||||
inherit
|
||||
ARGUMENTS
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Run application.
|
||||
do
|
||||
--| Add your code here
|
||||
print ("Hello Eiffel World!%N")
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,24 +0,0 @@
|
||||
class AUTHOR
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_name: STRING_32)
|
||||
do
|
||||
set_name (a_name)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
name: STRING_32
|
||||
|
||||
feature -- Status setting
|
||||
|
||||
set_name (a_name: STRING_32)
|
||||
do
|
||||
name := a_name
|
||||
end
|
||||
|
||||
end -- class AUTHOR
|
||||
@@ -1,40 +0,0 @@
|
||||
class BOOK
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_title: STRING_32; an_author: AUTHOR; an_isbn: STRING_32)
|
||||
do
|
||||
set_title (a_title)
|
||||
set_author (an_author)
|
||||
set_isbn (an_isbn)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
title: STRING_32
|
||||
|
||||
isbn: STRING_32
|
||||
|
||||
author: AUTHOR
|
||||
|
||||
feature -- Status setting
|
||||
|
||||
set_title (a_title: STRING_32)
|
||||
do
|
||||
title := a_title
|
||||
end
|
||||
|
||||
set_author (an_author: AUTHOR)
|
||||
do
|
||||
author := an_author
|
||||
end
|
||||
|
||||
set_isbn (an_isbn: STRING_32)
|
||||
do
|
||||
isbn := an_isbn
|
||||
end
|
||||
|
||||
end -- class BOOK
|
||||
@@ -1,80 +0,0 @@
|
||||
class BOOK_COLLECTION
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_name: STRING_32)
|
||||
do
|
||||
set_name (a_name)
|
||||
create book_index.make (10)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
name: STRING_32
|
||||
|
||||
books: LIST [BOOK]
|
||||
do
|
||||
from
|
||||
create {LINKED_LIST [BOOK]} Result.make
|
||||
book_index.start
|
||||
until
|
||||
book_index.after
|
||||
loop
|
||||
Result.append (book_index.item_for_iteration)
|
||||
book_index.forth
|
||||
end
|
||||
end
|
||||
|
||||
books_by_author (an_author: STRING_32): detachable LIST [BOOK]
|
||||
do
|
||||
if book_index.has (an_author) then
|
||||
Result := book_index @ an_author
|
||||
else
|
||||
create {LINKED_LIST [BOOK]} Result.make
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Status setting
|
||||
|
||||
set_name (a_name: STRING_32)
|
||||
do
|
||||
name := a_name
|
||||
end
|
||||
|
||||
add_book (a_book: BOOK)
|
||||
local
|
||||
l: detachable LIST [BOOK]
|
||||
do
|
||||
if book_index.has (a_book.author.name) then
|
||||
l := book_index.at ( a_book.author.name )
|
||||
else
|
||||
create {LINKED_LIST [BOOK]} l.make
|
||||
book_index.put (l, a_book.author.name)
|
||||
end
|
||||
if attached l as la then
|
||||
la.force (a_book)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
add_books (book_list: like books)
|
||||
|
||||
do
|
||||
from
|
||||
book_list.start
|
||||
until
|
||||
book_list.after
|
||||
loop
|
||||
add_book (book_list.item)
|
||||
book_list.forth
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
book_index: HASH_TABLE [LIST [BOOK], STRING_32]
|
||||
|
||||
end -- class BOOK_COLLECTION
|
||||
@@ -1 +0,0 @@
|
||||
"A JSON payload should be an object or array, not a string."
|
||||
@@ -1 +0,0 @@
|
||||
{"Extra value after close": true} "misplaced quoted value"
|
||||
@@ -1 +0,0 @@
|
||||
{"Illegal expression": 1 + 2}
|
||||
@@ -1 +0,0 @@
|
||||
{"Illegal invocation": alert()}
|
||||
@@ -1 +0,0 @@
|
||||
{"Numbers cannot have leading zeroes": 013}
|
||||
@@ -1 +0,0 @@
|
||||
{"Numbers cannot be hex": 0x14}
|
||||
@@ -1 +0,0 @@
|
||||
["Illegal backslash escape: \x15"]
|
||||
@@ -1 +0,0 @@
|
||||
[\naked]
|
||||
@@ -1 +0,0 @@
|
||||
["Illegal backslash escape: \017"]
|
||||
@@ -1 +0,0 @@
|
||||
[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]
|
||||
@@ -1 +0,0 @@
|
||||
{"Missing colon" null}
|
||||
@@ -1 +0,0 @@
|
||||
["Unclosed array"
|
||||
@@ -1 +0,0 @@
|
||||
{"Double colon":: null}
|
||||
@@ -1 +0,0 @@
|
||||
{"Comma instead of colon", null}
|
||||
@@ -1 +0,0 @@
|
||||
["Colon instead of comma": false]
|
||||
@@ -1 +0,0 @@
|
||||
["Bad value", truth]
|
||||
@@ -1 +0,0 @@
|
||||
['single quote']
|
||||
@@ -1 +0,0 @@
|
||||
[" tab character in string "]
|
||||
@@ -1 +0,0 @@
|
||||
["tab\ character\ in\ string\ "]
|
||||
@@ -1,2 +0,0 @@
|
||||
["line
|
||||
break"]
|
||||
@@ -1,2 +0,0 @@
|
||||
["line\
|
||||
break"]
|
||||
@@ -1 +0,0 @@
|
||||
[0e]
|
||||
@@ -1 +0,0 @@
|
||||
{unquoted_key: "keys must be quoted"}
|
||||
@@ -1 +0,0 @@
|
||||
[0e+]
|
||||
@@ -1 +0,0 @@
|
||||
[0e+-1]
|
||||
@@ -1 +0,0 @@
|
||||
{"Comma instead if closing brace": true,
|
||||
@@ -1 +0,0 @@
|
||||
["mismatch"}
|
||||
@@ -1 +0,0 @@
|
||||
["extra comma",]
|
||||
@@ -1 +0,0 @@
|
||||
["double extra comma",,]
|
||||
@@ -1 +0,0 @@
|
||||
[ , "<-- missing value"]
|
||||
@@ -1 +0,0 @@
|
||||
["Comma after the close"],
|
||||
@@ -1 +0,0 @@
|
||||
["Extra close"]]
|
||||
@@ -1 +0,0 @@
|
||||
{"Extra comma": true,}
|
||||
@@ -1,53 +0,0 @@
|
||||
note
|
||||
description: "A JSON converter for AUTHOR"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class JSON_AUTHOR_CONVERTER
|
||||
|
||||
inherit
|
||||
JSON_CONVERTER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
local
|
||||
ucs: STRING_32
|
||||
do
|
||||
create ucs.make_from_string ("")
|
||||
create object.make (ucs)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
object: AUTHOR
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
from_json (j: like to_json): detachable like object
|
||||
local
|
||||
ucs: detachable STRING_32
|
||||
do
|
||||
ucs ?= json.object (j.item (name_key), Void)
|
||||
check ucs /= Void end
|
||||
create Result.make (ucs)
|
||||
end
|
||||
|
||||
to_json (o: like object): JSON_OBJECT
|
||||
do
|
||||
create Result.make
|
||||
Result.put (json.value (o.name), name_key)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
name_key: JSON_STRING
|
||||
once
|
||||
create Result.make_json ("name")
|
||||
end
|
||||
|
||||
end -- class JSON_AUTHOR_CONVERTER
|
||||
@@ -1,78 +0,0 @@
|
||||
note
|
||||
description: "A JSON converter for BOOK_COLLECTION"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class JSON_BOOK_COLLECTION_CONVERTER
|
||||
|
||||
inherit
|
||||
JSON_CONVERTER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
local
|
||||
ucs: STRING_32
|
||||
do
|
||||
create ucs.make_from_string ("")
|
||||
create object.make (ucs)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
object: BOOK_COLLECTION
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
from_json (j: like to_json): detachable like object
|
||||
local
|
||||
ucs: detachable STRING_32
|
||||
ll: LINKED_LIST [BOOK]
|
||||
b: detachable BOOK
|
||||
ja: detachable JSON_ARRAY
|
||||
i: INTEGER
|
||||
do
|
||||
ucs ?= json.object (j.item (name_key), Void)
|
||||
check ucs /= Void end
|
||||
create Result.make (ucs)
|
||||
ja ?= j.item (books_key)
|
||||
check ja /= Void end
|
||||
from
|
||||
i := 1
|
||||
create ll.make
|
||||
until
|
||||
i > ja.count
|
||||
loop
|
||||
b ?= json.object (ja [i], "BOOK")
|
||||
check b /= Void end
|
||||
ll.force (b)
|
||||
i := i + 1
|
||||
end
|
||||
check ll /= Void end
|
||||
Result.add_books (ll)
|
||||
end
|
||||
|
||||
to_json (o: like object): JSON_OBJECT
|
||||
do
|
||||
create Result.make
|
||||
Result.put (json.value (o.name), name_key)
|
||||
Result.put (json.value (o.books), books_key)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
name_key: JSON_STRING
|
||||
once
|
||||
create Result.make_json ("name")
|
||||
end
|
||||
|
||||
books_key: JSON_STRING
|
||||
once
|
||||
create Result.make_json ("books")
|
||||
end
|
||||
|
||||
end -- class JSON_BOOK_COLLECTION_CONVERTER
|
||||
@@ -1,72 +0,0 @@
|
||||
note
|
||||
description: "A JSON converter for BOOK"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class JSON_BOOK_CONVERTER
|
||||
|
||||
inherit
|
||||
JSON_CONVERTER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
local
|
||||
ucs: STRING_32
|
||||
a: AUTHOR
|
||||
do
|
||||
create ucs.make_from_string ("")
|
||||
create a.make (ucs)
|
||||
create object.make (ucs, a, ucs)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
object: BOOK
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
from_json (j: like to_json): detachable like object
|
||||
local
|
||||
ucs1, ucs2: detachable STRING_32
|
||||
a: detachable AUTHOR
|
||||
do
|
||||
ucs1 ?= json.object (j.item (title_key), Void)
|
||||
check ucs1 /= Void end
|
||||
ucs2 ?= json.object (j.item (isbn_key), Void)
|
||||
check ucs2 /= Void end
|
||||
a ?= json.object (j.item (author_key), "AUTHOR")
|
||||
check a /= Void end
|
||||
create Result.make (ucs1, a, ucs2)
|
||||
end
|
||||
|
||||
to_json (o: like object): JSON_OBJECT
|
||||
do
|
||||
create Result.make
|
||||
Result.put (json.value (o.title), title_key)
|
||||
Result.put (json.value (o.isbn), isbn_key)
|
||||
Result.put (json.value (o.author), author_key)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
title_key: JSON_STRING
|
||||
once
|
||||
create Result.make_json ("title")
|
||||
end
|
||||
|
||||
isbn_key: JSON_STRING
|
||||
once
|
||||
create Result.make_json ("isbn")
|
||||
end
|
||||
|
||||
author_key: JSON_STRING
|
||||
once
|
||||
create Result.make_json ("author")
|
||||
end
|
||||
|
||||
end -- class JSON_BOOK_CONVERTER
|
||||
@@ -1,11 +0,0 @@
|
||||
{"menu": {
|
||||
"id": "file",
|
||||
"value": "File",
|
||||
"popup": {
|
||||
"menuitem": [
|
||||
{"value": "New", "onclick": "CreateNewDoc()"},
|
||||
{"value": "Open", "onclick": "OpenDoc()"},
|
||||
{"value": "Close", "onclick": "CloseDoc()"}
|
||||
]
|
||||
}
|
||||
}}
|
||||
@@ -1,58 +0,0 @@
|
||||
[
|
||||
"JSON Test Pattern pass1",
|
||||
{"object with 1 member":["array with 1 element"]},
|
||||
{},
|
||||
[],
|
||||
-42,
|
||||
true,
|
||||
false,
|
||||
null,
|
||||
{
|
||||
"integer": 1234567890,
|
||||
"real": -9876.543210,
|
||||
"e": 0.123456789e-12,
|
||||
"E": 1.234567890E+34,
|
||||
"": 23456789012E66,
|
||||
"zero": 0,
|
||||
"one": 1,
|
||||
"space": " ",
|
||||
"quote": "\"",
|
||||
"backslash": "\\",
|
||||
"controls": "\b\f\n\r\t",
|
||||
"slash": "/ & \/",
|
||||
"alpha": "abcdefghijklmnopqrstuvwyz",
|
||||
"ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",
|
||||
"digit": "0123456789",
|
||||
"0123456789": "digit",
|
||||
"special": "`1~!@#$%^&*()_+-={':[,]}|;.</>?",
|
||||
"hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A",
|
||||
"true": true,
|
||||
"false": false,
|
||||
"null": null,
|
||||
"array":[ ],
|
||||
"object":{ },
|
||||
"address": "50 St. James Street",
|
||||
"url": "http://www.JSON.org/",
|
||||
"comment": "// /* <!-- --",
|
||||
"# -- --> */": " ",
|
||||
" s p a c e d " :[1,2 , 3
|
||||
|
||||
,
|
||||
|
||||
4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7],
|
||||
"jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}",
|
||||
"quotes": "" \u0022 %22 0x22 034 "",
|
||||
"\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"
|
||||
: "A key can be any string"
|
||||
},
|
||||
0.5 ,98.6
|
||||
,
|
||||
99.44
|
||||
,
|
||||
|
||||
1066,
|
||||
1e1,
|
||||
0.1e1,
|
||||
1e-1,
|
||||
1e00,2e+00,2e-00
|
||||
,"rosebud"]
|
||||
@@ -1 +0,0 @@
|
||||
[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]]
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"JSON Test Pattern pass3": {
|
||||
"The outermost value": "must be an object or array.",
|
||||
"In this test": "It is an object."
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
class TEST_DS
|
||||
|
||||
inherit
|
||||
SHARED_EJSON
|
||||
rename default_create as shared_default_create end
|
||||
EQA_TEST_SET
|
||||
select default_create end
|
||||
|
||||
|
||||
feature -- Test
|
||||
|
||||
test_linked_list_converter
|
||||
local
|
||||
jc: JSON_LINKED_LIST_CONVERTER
|
||||
l: LINKED_LIST [STRING]
|
||||
l2: detachable LINKED_LIST [detachable ANY]
|
||||
s: STRING
|
||||
jv: detachable JSON_VALUE
|
||||
do
|
||||
create jc.make
|
||||
json.add_converter (jc)
|
||||
create l.make
|
||||
s := "foo"
|
||||
l.force (s)
|
||||
s := "bar"
|
||||
l.force (s)
|
||||
jv := json.value (l)
|
||||
assert ("jv /= Void", jv /= Void)
|
||||
if attached jv as l_jv then
|
||||
s := jv.representation
|
||||
l2 ?= json.object (jv, "LINKED_LIST")
|
||||
assert ("l2 /= Void", l2 /= Void)
|
||||
end
|
||||
end
|
||||
|
||||
test_hash_table_converter
|
||||
local
|
||||
tc: JSON_HASH_TABLE_CONVERTER
|
||||
t: HASH_TABLE [STRING, STRING]
|
||||
t2: detachable HASH_TABLE [ANY, HASHABLE]
|
||||
s: STRING
|
||||
ucs_key, ucs_value: detachable STRING_32
|
||||
jv: detachable JSON_VALUE
|
||||
do
|
||||
create tc.make
|
||||
json.add_converter (tc)
|
||||
create t.make (2)
|
||||
t.put ("foo", "1")
|
||||
t.put ("bar", "2")
|
||||
jv := json.value (t)
|
||||
assert ("jv /= Void", jv /= Void)
|
||||
if attached jv as l_jv then
|
||||
s := l_jv.representation
|
||||
t2 ?= json.object (l_jv, "HASH_TABLE")
|
||||
assert ("t2 /= Void", t2 /= Void)
|
||||
end
|
||||
create ucs_key.make_from_string ("1")
|
||||
if attached t2 as l_t2 then
|
||||
ucs_value ?= t2 @ ucs_key
|
||||
assert ("ucs_value /= Void", ucs_value /= Void)
|
||||
if attached ucs_value as l_ucs_value then
|
||||
assert ("ucs_value.string.is_equal (%"foo%")", l_ucs_value.string.is_equal ("foo"))
|
||||
end
|
||||
create ucs_key.make_from_string ("2")
|
||||
ucs_value ?= t2 @ ucs_key
|
||||
assert ("ucs_value /= Void", ucs_value /= Void)
|
||||
if attached ucs_value as l_ucs_value then
|
||||
assert ("ucs_value.string.is_equal (%"bar%")", l_ucs_value.string.is_equal ("bar"))
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end -- class TEST_DS
|
||||
@@ -1,833 +0,0 @@
|
||||
class TEST_JSON_CORE
|
||||
|
||||
inherit
|
||||
SHARED_EJSON
|
||||
rename default_create as shared_default_create end
|
||||
EQA_TEST_SET
|
||||
select default_create end
|
||||
|
||||
feature -- Test
|
||||
|
||||
test_json_number_and_integer
|
||||
local
|
||||
i: INTEGER
|
||||
jn: JSON_NUMBER
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
i := 42
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create jn.make_integer (i)
|
||||
assert ("jn.representation.same_string (%"42%")", jn.representation.same_string ("42"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
if attached {JSON_NUMBER} json.value (i) as l_jn then
|
||||
assert ("l_jn.representation.same_string (%"42%")", jn.representation.same_string ("42"))
|
||||
else
|
||||
assert ("json.value (i) is a JSON_NUMBER", False)
|
||||
end
|
||||
|
||||
-- JSON representation-> JSON value -> Eiffel value
|
||||
-- Note: The JSON_FACTORY will return the smallest INTEGER_* object
|
||||
-- that can represent the value of the JSON number, in this case
|
||||
-- we know it is INTEGER_8 since the value is 42
|
||||
jrep := "42"
|
||||
create parser.make_parser (jrep)
|
||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
||||
if attached {INTEGER_8} json.object (jn, Void) as l_i8 then
|
||||
assert ("l_i8 = 42", l_i8 = 42)
|
||||
else
|
||||
assert ("json.object (jn, Void) is a INTEGER_8", False)
|
||||
end
|
||||
else
|
||||
assert ("parser.parse is a JSON_NUMBER", False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_number_and_integer_8
|
||||
local
|
||||
i8: INTEGER_8
|
||||
jn: JSON_NUMBER
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
i8 := 42
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create jn.make_integer (i8)
|
||||
assert ("jn.representation.same_string (%"42%")", jn.representation.same_string ("42"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
if attached {JSON_NUMBER} json.value (i8) as l_jn then
|
||||
assert ("l_jn.representation.same_string (%"42%")", jn.representation.same_string ("42"))
|
||||
else
|
||||
assert ("json.value (i8) is a JSON_NUMBER", False)
|
||||
end
|
||||
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
-- Note: The JSON_FACTORY will return the smallest INTEGER_* object
|
||||
-- that can represent the value of the JSON number, in this case
|
||||
-- we know it is INTEGER_8 since the value is 42
|
||||
jrep := "42"
|
||||
create parser.make_parser (jrep)
|
||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
||||
if attached {INTEGER_8} json.object (jn, Void) as l_i8 then
|
||||
assert ("l_i8 = 42", l_i8 = 42)
|
||||
else
|
||||
assert ("json.object (jn, Void) is a INTEGER_8", False)
|
||||
end
|
||||
else
|
||||
assert ("parser.parse is a JSON_NUMBER", False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_number_and_integer_16
|
||||
local
|
||||
i16: INTEGER_16
|
||||
jn: JSON_NUMBER
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
i16 := 300
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create jn.make_integer (i16)
|
||||
assert ("jn.representation.same_string (%"300%")", jn.representation.same_string ("300"))
|
||||
-- Eiffel value -> JSON with factory
|
||||
if attached {JSON_NUMBER} json.value (i16) as l_jn then
|
||||
assert ("l_jn.representation.same_string (%"300%")", l_jn.representation.same_string ("300"))
|
||||
else
|
||||
assert ("json.value (i16) is a JSON_NUMBER", False)
|
||||
end
|
||||
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
-- Note: The JSON_FACTORY will return the smallest INTEGER_* object
|
||||
-- that can represent the value of the JSON number, in this case
|
||||
-- we know it is INTEGER_16 since the value is 300
|
||||
jrep := "300"
|
||||
create parser.make_parser (jrep)
|
||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
||||
if attached {INTEGER_16} json.object (jn, Void) as l_i16 then
|
||||
assert ("l_i16 = 300", l_i16 = 300)
|
||||
else
|
||||
assert ("json.object (jn, Void) is a INTEGER_16", False)
|
||||
end
|
||||
else
|
||||
assert ("parser.parse is a JSON_NUMBER", False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_number_and_integer_32
|
||||
local
|
||||
i32: INTEGER_32
|
||||
jn: JSON_NUMBER
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
i32 := 100000
|
||||
-- Eiffel value -> JSON representation -> JSON value
|
||||
create jn.make_integer (i32)
|
||||
assert ("jn.representation.same_string (%"100000%")", jn.representation.same_string ("100000"))
|
||||
-- Eiffel value -> JSON representation -> JSON value with factory
|
||||
if attached {JSON_NUMBER} json.value (i32) as l_jn then
|
||||
assert ("l_jn.representation.same_string (%"100000%")", l_jn.representation.same_string ("100000"))
|
||||
else
|
||||
assert ("json.value (i32) is a JSON_NUMBER", False)
|
||||
end
|
||||
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
-- Note: The JSON_FACTORY will return the smallest INTEGER_* object
|
||||
-- that can represent the value of the JSON number, in this case
|
||||
-- we know it is INTEGER_32 since the value is 100000
|
||||
jrep := "100000"
|
||||
create parser.make_parser (jrep)
|
||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
||||
if attached {INTEGER_32} json.object (jn, Void) as l_i32 then
|
||||
assert ("l_i32 = 100000", l_i32 = 100000)
|
||||
else
|
||||
assert ("json.object (jn, Void) is a INTEGER_32", False)
|
||||
end
|
||||
else
|
||||
assert ("parser.parse is a JSON_NUMBER", False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_number_and_integer_64
|
||||
local
|
||||
i64: INTEGER_64
|
||||
jn: JSON_NUMBER
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
i64 := 42949672960
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create jn.make_integer (i64)
|
||||
assert ("jn.representation.same_string (%"42949672960%")", jn.representation.same_string ("42949672960"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
if attached {JSON_NUMBER} json.value (i64) as l_jn then
|
||||
assert ("l_jn.representation.same_string (%"42949672960%")", l_jn.representation.same_string ("42949672960"))
|
||||
else
|
||||
assert ("json.value (i64) is a JSON_NUMBER", False)
|
||||
end
|
||||
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
-- Note: The JSON_FACTORY will return the smallest INTEGER_* object
|
||||
-- that can represent the value of the JSON number, in this case
|
||||
-- we know it is INTEGER_32 since the value is 42949672960
|
||||
jrep := "42949672960"
|
||||
create parser.make_parser (jrep)
|
||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
||||
if attached {INTEGER_64} json.object (jn, Void) as l_i64 then
|
||||
assert ("l_i64 = 42949672960", l_i64 = 42949672960)
|
||||
else
|
||||
assert ("json.object (jn, Void) is a INTEGER_64", False)
|
||||
end
|
||||
else
|
||||
assert ("parser.parse is a JSON_NUMBER", False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_number_and_natural_8
|
||||
local
|
||||
n8: NATURAL_8
|
||||
jn: JSON_NUMBER
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
n8 := 200
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create jn.make_natural (n8)
|
||||
assert ("jn.representation.same_string (%"200%")", jn.representation.same_string ("200"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
if attached {JSON_NUMBER} json.value (n8) as l_jn then
|
||||
assert ("l_jn.representation.same_string (%"200%")", l_jn.representation.same_string ("200"))
|
||||
else
|
||||
assert ("json.value (n8) is a JSON_NUMBER}", False)
|
||||
end
|
||||
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
-- Note: The JSON_FACTORY will return the smallest INTEGER_* object
|
||||
-- that can represent the value of the JSON number, in this case
|
||||
-- we know it is INTEGER_16 since the value is 200
|
||||
jrep := "200"
|
||||
create parser.make_parser (jrep)
|
||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
||||
if attached {INTEGER_16} json.object (jn, Void) as i16 then
|
||||
assert ("i16 = 200", i16 = 200)
|
||||
else
|
||||
assert ("json.object (jn, Void) is an INTEGER_16", False)
|
||||
end
|
||||
else
|
||||
assert ("parser.parse is a JSON_NUMBER", False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_number_and_natural_16
|
||||
local
|
||||
n16: NATURAL_16
|
||||
jn: JSON_NUMBER
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
n16 := 32768
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create jn.make_natural (n16)
|
||||
assert ("jn.representation.same_string (%"32768%")", jn.representation.same_string ("32768"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
if attached {JSON_NUMBER} json.value (n16) as l_jn then
|
||||
assert ("l_jn.representation.same_string (%"32768%")", l_jn.representation.same_string ("32768"))
|
||||
else
|
||||
assert ("json.value (n16) is a JSON_NUMBER", False)
|
||||
end
|
||||
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
-- Note: The JSON_FACTORY will return the smallest INTEGER_* object
|
||||
-- that can represent the value of the JSON number, in this case
|
||||
-- we know it is INTEGER_32 since the value is 32768
|
||||
jrep := "32768"
|
||||
create parser.make_parser (jrep)
|
||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
||||
if attached {INTEGER_32} json.object (jn, Void) as i32 then
|
||||
assert ("i32 = 32768", i32 = 32768)
|
||||
else
|
||||
assert ("json.object (jn, Void) is a INTEGER_32", False)
|
||||
end
|
||||
else
|
||||
assert ("parser.parse is a JSON_NUMBER", False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_number_and_natural_32
|
||||
local
|
||||
n32: NATURAL_32
|
||||
jn: JSON_NUMBER
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
n32 := 2147483648
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create jn.make_natural (n32)
|
||||
assert ("jn.representation.same_string (%"2147483648%")", jn.representation.same_string ("2147483648"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
if attached json.value (n32) as l_jn then
|
||||
assert ("l_jn.representation.same_string (%"2147483648%")", l_jn.representation.same_string ("2147483648"))
|
||||
else
|
||||
assert ("json.value (n32) is a JSON_NUMBER", False)
|
||||
end
|
||||
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
-- Note: The JSON_FACTORY will return the smallest INTEGER_* object
|
||||
-- that can represent the value of the JSON number, in this case
|
||||
-- we know it is INTEGER_64 since the value is 2147483648
|
||||
jrep := "2147483648"
|
||||
create parser.make_parser (jrep)
|
||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
||||
if attached {INTEGER_64} json.object (jn, Void) as i64 then
|
||||
assert ("i64 = 2147483648", i64 = 2147483648)
|
||||
else
|
||||
assert ("json.object (jn, Void) is a INTEGER_64", False)
|
||||
end
|
||||
else
|
||||
assert ("parser.parse is a JSON_NUMBER", False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_number_and_large_integers
|
||||
local
|
||||
jrep: STRING
|
||||
n64: NATURAL_64
|
||||
jn: JSON_NUMBER
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
n64 := 9223372036854775808
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create jn.make_natural (n64)
|
||||
assert ("jn.representation.same_string (%"9223372036854775808%")", jn.representation.same_string ("9223372036854775808"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
if attached {JSON_NUMBER} json.value (n64) as l_jn then
|
||||
assert ("l_jn.representation.same_string (%"9223372036854775808%")", l_jn.representation.same_string ("9223372036854775808"))
|
||||
else
|
||||
assert ("json.value (n64) is a JSON_NUMBER", False)
|
||||
end
|
||||
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
-- Note: The JSON_FACTORY will return the smallest INTEGER_* object
|
||||
-- that can represent the value of the JSON number, in this case
|
||||
-- we know it is INTEGER_32 since the value is 42949672960
|
||||
jrep := "9223372036854775808" -- 1 higher than largest positive number that can be represented by INTEGER 64
|
||||
create parser.make_parser (jrep)
|
||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
||||
if attached {NATURAL_64} json.object (jn, Void) as l_n64 then
|
||||
assert ("l_n64 = 9223372036854775808", l_n64 = 9223372036854775808)
|
||||
else
|
||||
assert ("json.object (jn, Void) is a NATURAL_64", False)
|
||||
end
|
||||
else
|
||||
assert ("parser.parse is a JSON_NUMBER", False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_number_and_eiffel_real
|
||||
local
|
||||
r: REAL
|
||||
jn: JSON_NUMBER
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
r := 3.14
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create jn.make_real (r)
|
||||
assert ("jn.representation.same_string (%"3.1400001049041748%")", jn.representation.same_string ("3.1400001049041748"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
if attached {JSON_NUMBER} json.value (r) as l_jn then
|
||||
assert ("l_jn.representation.same_string (%"3.1400001049041748%")", l_jn.representation.same_string ("3.1400001049041748"))
|
||||
else
|
||||
assert ("json.value (r) is a JSON_NUMBER", False)
|
||||
end
|
||||
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
-- Note: The JSON_FACTORY will always return a REAL_64 if the value
|
||||
-- of the JSON number is a floating point number
|
||||
jrep := "3.14"
|
||||
create parser.make_parser (jrep)
|
||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
||||
if attached {REAL_64} json.object (jn, Void) as r64 then
|
||||
assert ("3.14 <= r64 and r64 <= 3.141", 3.14 <= r64 and r64 <= 3.141)
|
||||
else
|
||||
assert ("json.object (jn, Void) is a REAL_64", False)
|
||||
end
|
||||
else
|
||||
assert ("parser.parse is a JSON_NUMBER", False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_number_and_eiffel_real_32
|
||||
local
|
||||
r32: REAL_32
|
||||
jn: JSON_NUMBER
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
r32 := 3.14
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create jn.make_real (r32)
|
||||
assert ("jn.representation.same_string (%"3.1400001049041748%")", jn.representation.same_string ("3.1400001049041748"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
if attached {JSON_NUMBER} json.value (r32) as l_jn then
|
||||
assert ("l_jn.representation.same_string (%"3.1400001049041748%")", l_jn.representation.same_string ("3.1400001049041748"))
|
||||
else
|
||||
assert ("json.value (r32) is a JSON_NUMBER", False)
|
||||
end
|
||||
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
jrep := "3.1400001049041748"
|
||||
create parser.make_parser (jrep)
|
||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
||||
if attached {REAL_64} json.object (l_jn, Void) as r64 then
|
||||
assert ("r64 = 3.1400001049041748", r64 = 3.1400001049041748)
|
||||
else
|
||||
assert ("json.object (l_jn, Void) is a REAL_64", False)
|
||||
end
|
||||
else
|
||||
assert ("parser.parse is a JSON_NUMBER", False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_number_and_eiffel_real_64
|
||||
local
|
||||
r64: REAL_64
|
||||
jn: JSON_NUMBER
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
r64 := 3.1415926535897931
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create jn.make_real (r64)
|
||||
assert ("jn.representation.same_string (%"3.1415926535897931%")", jn.representation.same_string ("3.1415926535897931"))
|
||||
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
if attached {JSON_NUMBER} json.value (r64) as l_jn then
|
||||
assert ("l_jn.representation.same_string (%"3.1415926535897931%")", l_jn.representation.same_string ("3.1415926535897931"))
|
||||
else
|
||||
assert ("json.value (r64) is a JSON_NUMBER", False)
|
||||
end
|
||||
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
jrep := "3.1415926535897931"
|
||||
create parser.make_parser (jrep)
|
||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
||||
if attached {REAL_64} json.object (jn, Void) as l_r64 then
|
||||
assert ("l_r64 = 3.1415926535897931", l_r64 = 3.1415926535897931)
|
||||
else
|
||||
assert ("json.object (jn, Void) is a REAL_64", False)
|
||||
end
|
||||
else
|
||||
assert ("parser.parse is a JSON_NUMBER", False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_boolean
|
||||
local
|
||||
parser: JSON_PARSER
|
||||
jb: JSON_BOOLEAN
|
||||
b: BOOLEAN
|
||||
do
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
b := True
|
||||
create jb.make_boolean (b)
|
||||
assert ("jb.representation.is_equal (%"true%")", jb.representation.is_equal ("true"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
if attached {JSON_BOOLEAN} json.value (b) as l_jb then
|
||||
assert ("l_jb.representation.same_string (%"true%")", l_jb.representation.same_string ("true"))
|
||||
else
|
||||
assert ("l_jb /= Void", False)
|
||||
end
|
||||
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
create parser.make_parser ("true")
|
||||
if attached {JSON_BOOLEAN} parser.parse as l_jb then
|
||||
if attached {BOOLEAN} json.object (l_jb, Void) as l_b then
|
||||
assert ("l_b = True", l_b = True)
|
||||
else
|
||||
assert ("json.object (l_jb, Void) is BOOLEAN", False)
|
||||
end
|
||||
else
|
||||
assert ("parser.parse is a JSON_BOOLEAN", False)
|
||||
end
|
||||
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
b := False
|
||||
create jb.make_boolean (b)
|
||||
assert ("jb.representation.same_string (%"false%")", jb.representation.same_string ("false"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
if attached {JSON_BOOLEAN} json.value (b) as l_jb then
|
||||
assert ("l_jb.representation.same_string (%"false%")", l_jb.representation.same_string ("false"))
|
||||
else
|
||||
assert ("json.value (b) is a JSON_BOOLEAN", False)
|
||||
end
|
||||
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
create parser.make_parser ("false")
|
||||
if attached {JSON_BOOLEAN} parser.parse as l_jb then
|
||||
if attached {BOOLEAN} json.object (l_jb, Void) as l_b then
|
||||
assert ("l_b = False", l_b = False)
|
||||
else
|
||||
assert ("json.object (l_jb, Void) is a BOOLEAN", False)
|
||||
end
|
||||
else
|
||||
assert ("parser.parse is a JSON_BOOLEAN", False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_null
|
||||
local
|
||||
a: detachable ANY
|
||||
dummy_object: STRING
|
||||
jn: detachable JSON_NULL
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create jn
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"%"null%"%")", jn.representation.is_equal ("null"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
jn ?= json.value (Void)
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
if attached jn as l_jn then
|
||||
assert ("jn.representation.is_equal (%"null%")", l_jn.representation.is_equal ("null"))
|
||||
end
|
||||
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
jrep := "null"
|
||||
create parser.make_parser (jrep)
|
||||
jn := Void
|
||||
jn ?= parser.parse
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
create dummy_object.make_empty
|
||||
a := dummy_object
|
||||
a ?= json.object (jn, Void)
|
||||
assert ("a = Void", a = Void)
|
||||
end
|
||||
|
||||
test_json_string_and_character
|
||||
local
|
||||
c: CHARACTER
|
||||
js: detachable JSON_STRING
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
c := 'a'
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create js.make_json (c.out)
|
||||
assert ("js /= Void", js /= Void)
|
||||
assert ("js.representation.is_equal (%"%"a%"%")", js.representation.is_equal ("%"a%""))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
js ?= json.value (c)
|
||||
assert ("js /= Void", js /= Void)
|
||||
if attached js as l_js then
|
||||
assert ("js.representation.is_equal (%"%"a%"%")", l_js.representation.is_equal ("%"a%""))
|
||||
end
|
||||
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
jrep := "%"a%""
|
||||
create parser.make_parser (jrep)
|
||||
js := Void
|
||||
js ?= parser.parse
|
||||
assert ("js /= Void", js /= Void)
|
||||
if attached {STRING_32} json.object (js, Void) as ucs then
|
||||
assert ("ucs.string.is_equal (%"a%")", ucs.string.is_equal ("a"))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
test_json_string_and_string
|
||||
local
|
||||
s: STRING
|
||||
js: detachable JSON_STRING
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
s := "foobar"
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create js.make_json (s)
|
||||
assert ("js /= Void", js /= Void)
|
||||
assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal ("%"foobar%""))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
js ?= json.value (s)
|
||||
assert ("js /= Void", js /= Void)
|
||||
if attached js as l_js then
|
||||
assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal ("%"foobar%""))
|
||||
end
|
||||
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
jrep := "%"foobar%""
|
||||
create parser.make_parser (jrep)
|
||||
js := Void
|
||||
js ?= parser.parse
|
||||
assert ("js /= Void", js /= Void)
|
||||
if attached {STRING_32} json.object (js, Void) as l_ucs then
|
||||
assert ("ucs.string.is_equal (%"foobar%")", l_ucs.string.is_equal ("foobar"))
|
||||
end
|
||||
end
|
||||
|
||||
test_json_string_and_uc_string
|
||||
local
|
||||
js: detachable JSON_STRING
|
||||
ucs: detachable STRING_32
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
create ucs.make_from_string ("foobar")
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create js.make_json (ucs)
|
||||
assert ("js /= Void", js /= Void)
|
||||
assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal ("%"foobar%""))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
js ?= json.value (ucs)
|
||||
assert ("js /= Void", js /= Void)
|
||||
if attached js as l_js then
|
||||
assert ("js.representation.is_equal (%"%"foobar%"%")", l_js.representation.is_equal ("%"foobar%""))
|
||||
end
|
||||
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
jrep := "%"foobar%""
|
||||
create parser.make_parser (jrep)
|
||||
js := Void
|
||||
js ?= parser.parse
|
||||
assert ("js /= Void", js /= Void)
|
||||
ucs := Void
|
||||
ucs ?= json.object (js, Void)
|
||||
if attached ucs as l_ucs then
|
||||
assert ("ucs.string.is_equal (%"foobar%")", l_ucs.string.is_equal ("foobar"))
|
||||
end
|
||||
end
|
||||
|
||||
test_json_string_and_special_characters
|
||||
local
|
||||
js: detachable JSON_STRING
|
||||
s: detachable STRING_8
|
||||
ucs: detachable STRING_32
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
create s.make_from_string ("foo\bar")
|
||||
create js.make_json (s)
|
||||
|
||||
assert ("js.representation.same_string (%"%"foo\\bar%"%")", js.representation.same_string ("%"foo\\bar%""))
|
||||
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
js ?= json.value (s)
|
||||
assert ("js /= Void", js /= Void)
|
||||
if js /= Void then
|
||||
assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.same_string ("%"foo\\bar%""))
|
||||
end
|
||||
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
jrep := "%"foo\\bar%""
|
||||
create parser.make_parser (jrep)
|
||||
js ?= parser.parse
|
||||
assert ("js /= Void", js /= Void)
|
||||
ucs ?= json.object (js, Void)
|
||||
if ucs /= Void then
|
||||
assert ("ucs.same_string (%"foo\bar%")", ucs.same_string ("foo\bar"))
|
||||
end
|
||||
|
||||
jrep := "%"foo\\bar%""
|
||||
create parser.make_parser (jrep)
|
||||
if attached {JSON_STRING} parser.parse as jstring then
|
||||
assert ("unescaped string %"foo\\bar%" to %"foo\bar%"", jstring.unescaped_string_8.same_string ("foo\bar"))
|
||||
end
|
||||
|
||||
create js.make_json_from_string_32 ({STRING_32}"%/20320/%/22909/")
|
||||
assert ("escaping unicode string32 %"%%/20320/%%/22909/%" %"\u4F60\u597D%"", js.item.same_string ("\u4F60\u597D"))
|
||||
|
||||
jrep := "%"\u4F60\u597D%"" --| Ni hao
|
||||
create parser.make_parser (jrep)
|
||||
if attached {JSON_STRING} parser.parse as jstring then
|
||||
assert ("same unicode string32 %"%%/20320/%%/22909/%"", jstring.unescaped_string_32.same_string ({STRING_32}"%/20320/%/22909/"))
|
||||
end
|
||||
end
|
||||
|
||||
test_json_array
|
||||
local
|
||||
ll: LINKED_LIST [INTEGER_8]
|
||||
ll2: detachable LINKED_LIST [detachable ANY]
|
||||
ja: detachable JSON_ARRAY
|
||||
jn: JSON_NUMBER
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create ll.make
|
||||
ll.extend (0)
|
||||
ll.extend (1)
|
||||
ll.extend (1)
|
||||
ll.extend (2)
|
||||
ll.extend (3)
|
||||
ll.extend (5)
|
||||
-- Note: Currently there is no simple way of creating a JSON_ARRAY
|
||||
-- from an LINKED_LIST.
|
||||
create ja.make_array
|
||||
from
|
||||
ll.start
|
||||
until
|
||||
ll.after
|
||||
loop
|
||||
create jn.make_integer (ll.item)
|
||||
ja.add (jn)
|
||||
ll.forth
|
||||
end
|
||||
assert ("ja /= Void", ja /= Void)
|
||||
assert ("ja.representation.is_equal (%"[0,1,1,2,3,5]%")", ja.representation.is_equal ("[0,1,1,2,3,5]"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
ja := Void
|
||||
ja ?= json.value (ll)
|
||||
assert ("ja /= Void", ja /= Void)
|
||||
if attached ja as l_ja then
|
||||
assert ("ja.representation.is_equal (%"[0,1,1,2,3,5]%")", l_ja.representation.is_equal ("[0,1,1,2,3,5]"))
|
||||
end
|
||||
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
-- Note: The JSON_FACTORY will return the smallest INTEGER_* object
|
||||
-- that can represent the value of the JSON number, in this case
|
||||
-- it means we will get an LINKED_LIST [ANY] containing the INTEGER_8
|
||||
-- values 0, 1, 1, 2, 3, 5
|
||||
jrep := "[0,1,1,2,3,5]"
|
||||
create parser.make_parser (jrep)
|
||||
ja := Void
|
||||
ja ?= parser.parse
|
||||
assert ("ja /= Void", ja /= Void)
|
||||
ll2 ?= json.object (ja, Void)
|
||||
assert ("ll2 /= Void", ll2 /= Void)
|
||||
--ll.compare_objects
|
||||
--ll2.compare_objects
|
||||
if attached ll2 as l_ll2 then
|
||||
assert ("ll2.is_equal (ll)", l_ll2.is_equal (ll))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
test_json_object
|
||||
local
|
||||
t, t2: detachable HASH_TABLE [detachable ANY, STRING_GENERAL]
|
||||
i: INTEGER
|
||||
ucs_key, ucs: STRING_32
|
||||
a: ARRAY [INTEGER]
|
||||
jo: detachable JSON_OBJECT
|
||||
jn: JSON_NUMBER
|
||||
js_key, js: JSON_STRING
|
||||
ja: JSON_ARRAY
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
-- Note: Currently there is now way of creating a JSON_OBJECT from
|
||||
-- a HASH_TABLE, so we do it manually.
|
||||
-- t = {"name": "foobar", "size": 42, "contents", [0, 1, 1, 2, 3, 5]}
|
||||
create jo.make
|
||||
create js_key.make_json ("name")
|
||||
create js.make_json ("foobar")
|
||||
jo.put (js, js_key)
|
||||
create js_key.make_json ("size")
|
||||
create jn.make_integer (42)
|
||||
jo.put (jn, js_key)
|
||||
create js_key.make_json ("contents")
|
||||
create ja.make_array
|
||||
create jn.make_integer (0)
|
||||
ja.add (jn)
|
||||
create jn.make_integer (1)
|
||||
ja.add (jn)
|
||||
create jn.make_integer (1)
|
||||
ja.add (jn)
|
||||
create jn.make_integer (2)
|
||||
ja.add (jn)
|
||||
create jn.make_integer (3)
|
||||
ja.add (jn)
|
||||
create jn.make_integer (5)
|
||||
ja.add (jn)
|
||||
jo.put (ja, js_key)
|
||||
assert ("jo /= Void", jo /= Void)
|
||||
assert ("jo.representation.is_equal (%"{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}%")", jo.representation.is_equal ("{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
create t.make (3)
|
||||
create ucs_key.make_from_string ("name")
|
||||
create ucs.make_from_string ("foobar")
|
||||
t.put (ucs, ucs_key)
|
||||
create ucs_key.make_from_string ("size")
|
||||
i := 42
|
||||
t.put (i, ucs_key)
|
||||
create ucs_key.make_from_string ("contents")
|
||||
a := <<0, 1, 1, 2, 3, 5>>
|
||||
t.put (a, ucs_key)
|
||||
jo := Void
|
||||
jo ?= json.value (t)
|
||||
assert ("jo /= Void", jo /= Void)
|
||||
if attached jo as l_jo then
|
||||
assert ("jo.representation.is_equal (%"{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}%")", l_jo.representation.is_equal ("{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}"))
|
||||
end
|
||||
-- JSON representation -> JSON value -> Eiffel value -> JSON value -> JSON representation
|
||||
jrep := "{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}"
|
||||
create parser.make_parser (jrep)
|
||||
jo := Void
|
||||
jo ?= parser.parse
|
||||
assert ("jo /= Void", jo /= Void)
|
||||
t2 ?= json.object (jo, Void)
|
||||
assert ("t2 /= Void", t2 /= Void)
|
||||
jo ?= json.value (t2)
|
||||
assert ("jo /= Void", jo /= Void)
|
||||
if attached jo as l_jo then
|
||||
assert ("jrep.is_equal (jo.representation)", jrep.is_equal (jo.representation))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
test_json_object_hash_code
|
||||
local
|
||||
ht: HASH_TABLE [ANY, JSON_VALUE]
|
||||
jo: JSON_OBJECT
|
||||
do
|
||||
create ht.make (1)
|
||||
create jo.make
|
||||
ht.force ("", jo)
|
||||
assert ("ht.has_key (jo)", ht.has_key (jo))
|
||||
end
|
||||
|
||||
test_json_failed_json_conversion
|
||||
-- Test converting an Eiffel object to JSON that is based on a class
|
||||
-- for which no JSON converter has been registered.
|
||||
local
|
||||
gv: OPERATING_ENVIRONMENT
|
||||
jv: detachable JSON_VALUE
|
||||
exception: BOOLEAN
|
||||
do
|
||||
if not exception then
|
||||
create gv
|
||||
jv := json.value (gv)
|
||||
else
|
||||
assert ("exceptions.is_developer_exception", json.is_developer_exception)
|
||||
-- assert ("exceptions.is_developer_exception_of_name", json.is_developer_exception_of_name ("eJSON exception: Failed to convert Eiffel object to a JSON_VALUE: OPERATING_ENVIRONMENT"))
|
||||
end
|
||||
rescue
|
||||
exception := True
|
||||
retry
|
||||
end
|
||||
|
||||
test_json_failed_eiffel_conversion
|
||||
-- Test converting from a JSON value to an Eiffel object based on a
|
||||
-- class for which no JSON converter has been registered.
|
||||
local
|
||||
gv : detachable OPERATING_ENVIRONMENT
|
||||
jo: JSON_OBJECT
|
||||
exception: BOOLEAN
|
||||
do
|
||||
if not exception then
|
||||
create jo.make
|
||||
gv ?= json.object (jo, "OPERATING_ENVIRONMENT")
|
||||
else
|
||||
assert ("exceptions.is_developer_exception", json.is_developer_exception)
|
||||
-- assert ("exceptions.is_developer_exception_of_name", json.is_developer_exception_of_name ("eJSON exception: Failed to convert JSON_VALUE to an Eiffel object: JSON_OBJECT -> OPERATING_ENVIRONMENT"))
|
||||
|
||||
end
|
||||
rescue
|
||||
exception := True
|
||||
retry
|
||||
end
|
||||
|
||||
end -- class TEST_JSON_CORE
|
||||
@@ -1,42 +0,0 @@
|
||||
class TEST_JSON_CUSTOM_CLASSES
|
||||
|
||||
inherit
|
||||
SHARED_EJSON
|
||||
rename default_create as shared_default_create end
|
||||
EQA_TEST_SET
|
||||
select default_create end
|
||||
feature -- Test
|
||||
|
||||
test_custom_classes
|
||||
local
|
||||
bc: detachable BOOK_COLLECTION
|
||||
jbc: JSON_BOOK_CONVERTER
|
||||
jbcc: JSON_BOOK_COLLECTION_CONVERTER
|
||||
jac: JSON_AUTHOR_CONVERTER
|
||||
jo: detachable JSON_OBJECT
|
||||
parser: JSON_PARSER
|
||||
jrep: STRING
|
||||
do
|
||||
create jbc.make
|
||||
json.add_converter (jbc)
|
||||
create jbcc.make
|
||||
json.add_converter (jbcc)
|
||||
create jac.make
|
||||
json.add_converter (jac)
|
||||
jrep := "{%"name%":%"Test collection%",%"books%":[{%"title%":%"eJSON: The Definitive Guide%",%"isbn%":%"123123-413243%",%"author%":{%"name%":%"Foo Bar%"}}]}"
|
||||
create parser.make_parser (jrep)
|
||||
jo := Void
|
||||
jo ?= parser.parse
|
||||
assert ("jo /= Void", jo /= Void)
|
||||
bc := Void
|
||||
bc ?= json.object (jo, "BOOK_COLLECTION")
|
||||
assert ("bc /= Void", bc /= Void)
|
||||
jo ?= json.value (bc)
|
||||
assert ("jo /= Void", jo /= Void)
|
||||
if attached jo as l_jo then
|
||||
assert ("JSON representation is correct", l_jo.representation.same_string ("{%"name%":%"Test collection%",%"books%":[{%"title%":%"eJSON: The Definitive Guide%",%"isbn%":%"123123-413243%",%"author%":{%"name%":%"Foo Bar%"}}]}"))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end -- class TEST_JSON_CUSTOM_CLASS
|
||||
@@ -1,514 +0,0 @@
|
||||
note
|
||||
description: "[
|
||||
Eiffel tests that can be executed by testing tool.
|
||||
]"
|
||||
author: "EiffelStudio test wizard"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
testing: "type/manual"
|
||||
|
||||
class
|
||||
TEST_JSON_SUITE
|
||||
|
||||
inherit
|
||||
EQA_TEST_SET
|
||||
redefine
|
||||
on_prepare
|
||||
end
|
||||
|
||||
feature {NONE} -- Events
|
||||
|
||||
on_prepare
|
||||
-- <Precursor>
|
||||
do
|
||||
create file_reader
|
||||
end
|
||||
|
||||
feature -- Tests Pass
|
||||
|
||||
test_json_pass1
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("pass1.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("pass1.json",parse_json.is_parsed = True)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_pass2
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("pass2.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("pass2.json",parse_json.is_parsed = True)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_pass3
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("pass3.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("pass3.json",parse_json.is_parsed = True)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Tests Failures
|
||||
test_json_fail1
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail1.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail1.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail2
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail2.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail2.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail3
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail3.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail3.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail4
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail4.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail4.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail5
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail5.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail5.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test_json_fail6
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail6.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail6.json",parse_json.is_parsed = False )
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail7
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail7.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail7.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail8
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail8.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail8.json",parse_json.is_parsed = False )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test_json_fail9
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail9.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail9.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test_json_fail10
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail10.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail10.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail11
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail11.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail11.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail12
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail12.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail12.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail13
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail13.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail13.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail14
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail14.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail14.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail15
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail15.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail15.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail16
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail16.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail16.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail17
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail17.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail17.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail18
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail18.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail18.json",parse_json.is_parsed = True)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail19
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail19.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail19.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail20
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail20.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail20.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail21
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail21.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail21.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test_json_fail22
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail22.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail22.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail23
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail23.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail23.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail24
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail24.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail24.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail25
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail25.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail25.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test_json_fail26
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail26.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail26.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test_json_fail27
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail27.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail27.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test_json_fail28
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail28.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail28.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test_json_fail29
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail29.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail29.json",parse_json.is_parsed = False )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
test_json_fail30
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail30.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail30.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail31
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail31.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail31.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail32
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail32.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail32.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
test_json_fail33
|
||||
--
|
||||
local
|
||||
parse_json: like new_json_parser
|
||||
do
|
||||
if attached json_file_from ("fail33.json") as json_file then
|
||||
parse_json := new_json_parser (json_file)
|
||||
json_value := parse_json.parse_json
|
||||
assert ("fail33.json",parse_json.is_parsed = False)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- JSON_FROM_FILE
|
||||
|
||||
file_reader: JSON_FILE_READER
|
||||
|
||||
json_value: detachable JSON_VALUE
|
||||
|
||||
json_file_from (fn: STRING): detachable STRING
|
||||
do
|
||||
Result := file_reader.read_json_from (test_dir + fn)
|
||||
assert ("File contains json data", Result /= Void)
|
||||
end
|
||||
|
||||
new_json_parser (a_string: STRING): JSON_PARSER
|
||||
do
|
||||
create Result.make_parser (a_string)
|
||||
end
|
||||
|
||||
test_dir: STRING
|
||||
local
|
||||
i: INTEGER
|
||||
do
|
||||
Result := (create {EXECUTION_ENVIRONMENT}).current_working_directory
|
||||
Result.append_character ((create {OPERATING_ENVIRONMENT}).directory_separator)
|
||||
-- The should looks like
|
||||
-- ..json\test\autotest\test_suite\EIFGENs\test_suite\Testing\execution\TEST_JSON_SUITE.test_json_fail1\..\..\..\..\..\fail1.json
|
||||
from
|
||||
i := 5
|
||||
until
|
||||
i = 0
|
||||
loop
|
||||
Result.append_character ('.')
|
||||
Result.append_character ('.')
|
||||
Result.append_character ((create {OPERATING_ENVIRONMENT}).directory_separator)
|
||||
i := i - 1
|
||||
end
|
||||
-- Result := "/home/jvelilla/work/project/Eiffel/ejson_dev/trunk/test/autotest/test_suite/"
|
||||
end
|
||||
|
||||
invariant
|
||||
file_reader /= Void
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="test_suite" uuid="EA141B17-6A21-4781-8B5F-E9939BAE968A">
|
||||
<target name="test_suite">
|
||||
<root cluster="test_suite" class="APPLICATION" feature="make"/>
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="standard">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="json" location="..\..\..\library\json-safe.ecf"/>
|
||||
<library name="testing" location="$ISE_LIBRARY\library\testing\testing-safe.ecf"/>
|
||||
<cluster name="test_suite" location=".\" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
@@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-5-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-5-0 http://www.eiffel.com/developers/xml/configuration-1-5-0.xsd" name="test_suite" uuid="EA141B17-6A21-4781-8B5F-E9939BAE968A">
|
||||
<target name="test_suite">
|
||||
<root cluster="test_suite" class="APPLICATION" feature="make"/>
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<precompile name="base_pre" location="$ISE_PRECOMP\base.ecf"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
<library name="json" location="..\..\..\library\json.ecf"/>
|
||||
<library name="testing" location="$ISE_LIBRARY\library\testing\testing.ecf"/>
|
||||
<cluster name="test_suite" location=".\" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
@@ -1,24 +0,0 @@
|
||||
class AUTHOR
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_name: UC_STRING) is
|
||||
do
|
||||
set_name (a_name)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
name: UC_STRING
|
||||
|
||||
feature -- Status setting
|
||||
|
||||
set_name (a_name: UC_STRING) is
|
||||
do
|
||||
name := a_name
|
||||
end
|
||||
|
||||
end -- class AUTHOR
|
||||
@@ -1,40 +0,0 @@
|
||||
class BOOK
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_title: UC_STRING; an_author: AUTHOR; an_isbn: UC_STRING) is
|
||||
do
|
||||
set_title (a_title)
|
||||
set_author (an_author)
|
||||
set_isbn (an_isbn)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
title: UC_STRING
|
||||
|
||||
isbn: UC_STRING
|
||||
|
||||
author: AUTHOR
|
||||
|
||||
feature -- Status setting
|
||||
|
||||
set_title (a_title: UC_STRING) is
|
||||
do
|
||||
title := a_title
|
||||
end
|
||||
|
||||
set_author (an_author: AUTHOR) is
|
||||
do
|
||||
author := an_author
|
||||
end
|
||||
|
||||
set_isbn (an_isbn: UC_STRING) is
|
||||
do
|
||||
isbn := an_isbn
|
||||
end
|
||||
|
||||
end -- class BOOK
|
||||
@@ -1,82 +0,0 @@
|
||||
class BOOK_COLLECTION
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_name: UC_STRING) is
|
||||
do
|
||||
set_name (a_name)
|
||||
create book_index.make (10)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
name: UC_STRING
|
||||
|
||||
books: DS_LIST [BOOK] is
|
||||
local
|
||||
c: DS_HASH_TABLE_CURSOR [DS_LIST [BOOK], UC_STRING]
|
||||
do
|
||||
from
|
||||
create {DS_LINKED_LIST [BOOK]} Result.make
|
||||
c := book_index.new_cursor
|
||||
c.start
|
||||
until
|
||||
c.after
|
||||
loop
|
||||
Result.append_last (c.item)
|
||||
c.forth
|
||||
end
|
||||
end
|
||||
|
||||
books_by_author (an_author: UC_STRING): DS_LIST [BOOK] is
|
||||
do
|
||||
if book_index.has (an_author) then
|
||||
Result := book_index @ an_author
|
||||
else
|
||||
create {DS_LINKED_LIST [BOOK]} Result.make
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Status setting
|
||||
|
||||
set_name (a_name: UC_STRING) is
|
||||
do
|
||||
name := a_name
|
||||
end
|
||||
|
||||
add_book (a_book: BOOK) is
|
||||
local
|
||||
l: DS_LIST [BOOK]
|
||||
do
|
||||
if book_index.has (a_book.author.name) then
|
||||
l := book_index @ a_book.author.name
|
||||
else
|
||||
create {DS_LINKED_LIST [BOOK]} l.make
|
||||
book_index.put (l, a_book.author.name)
|
||||
end
|
||||
l.put_last (a_book)
|
||||
end
|
||||
|
||||
add_books (book_list: like books) is
|
||||
local
|
||||
c: DS_LIST_CURSOR [BOOK]
|
||||
do
|
||||
from
|
||||
c := book_list.new_cursor
|
||||
c.start
|
||||
until
|
||||
c.after
|
||||
loop
|
||||
add_book (c.item)
|
||||
c.forth
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
book_index: DS_HASH_TABLE [DS_LIST [BOOK], UC_STRING]
|
||||
|
||||
end -- class BOOK_COLLECTION
|
||||
@@ -1,11 +0,0 @@
|
||||
echo Compiling ejson_test (finalized)
|
||||
ecb -finalize -c_compile -config ejson_test.ecf -batch -clean > NUL 2>&1
|
||||
IF %ERRORLEVEL% EQU -1 goto ERROR
|
||||
copy EIFGENs\ejson_test\F_code\ejson_test.exe ejson_test.exe
|
||||
goto EOF
|
||||
|
||||
:ERROR
|
||||
echo Error occurred during ejson_test compilation
|
||||
goto EOF
|
||||
|
||||
:EOF
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user