Compare commits
575 Commits
0.26.4
...
0.28.1-rc1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b417b9d51 | ||
|
|
cc05e5727d | ||
|
|
764a8f2644 | ||
|
|
a15785eb64 | ||
|
|
688f8c5f3f | ||
|
|
dde5ccf7fa | ||
|
|
d5a6313c71 | ||
|
|
f030aab759 | ||
|
|
4393f98a2c | ||
|
|
c377d6c94b | ||
|
|
16aa015682 | ||
|
|
9cded76cf0 | ||
|
|
4ad07bb6b2 | ||
|
|
d0b28a6700 | ||
|
|
18299c3f7a | ||
|
|
ca07a1230b | ||
|
|
e0ad66d967 | ||
|
|
5615c4a2a7 | ||
|
|
d7fbef6764 | ||
|
|
e95bda3bdf | ||
|
|
c010a85ef5 | ||
|
|
798d36efcf | ||
|
|
2d44c8568f | ||
|
|
7232bdb40c | ||
|
|
45f092488a | ||
|
|
4244e1070d | ||
|
|
5a7fa8cfa9 | ||
|
|
daf4f8fcde | ||
|
|
d182d1455e | ||
|
|
dc2260adbe | ||
|
|
83a01e0c7d | ||
|
|
53c1269ebd | ||
|
|
f8bfe3a550 | ||
|
|
90bb53af20 | ||
|
|
c77a2f335a | ||
|
|
8e34a1f6a7 | ||
|
|
2564b62f5c | ||
|
|
a7598c5610 | ||
|
|
8377f2516b | ||
|
|
7efd0ab0d6 | ||
|
|
14d38a1a8d | ||
|
|
c8447c190c | ||
|
|
aa5d16b3d8 | ||
|
|
fd1135315c | ||
|
|
98c915b2ca | ||
|
|
9114f3d2e6 | ||
|
|
5b0109055d | ||
|
|
5a3168c9ff | ||
|
|
a14f29f84f | ||
|
|
6c1190a361 | ||
|
|
100a76f0e8 | ||
|
|
47482acf83 | ||
|
|
54ef4ee6ef | ||
|
|
2389abc295 | ||
|
|
67c666b033 | ||
|
|
5ce3ed3555 | ||
|
|
d30b32fcde | ||
|
|
568e4cebda | ||
|
|
29d644e9d3 | ||
|
|
2dbb7301fb | ||
|
|
d2cba1c54f | ||
|
|
6a0c26a709 | ||
|
|
e44ae6af93 | ||
|
|
837b0799ac | ||
|
|
bc85a8b24f | ||
|
|
15d68649d5 | ||
|
|
e0d96ae807 | ||
|
|
3aa39ced60 | ||
|
|
1f1c0618e1 | ||
|
|
7788aa25b5 | ||
|
|
d5b460a85c | ||
|
|
9019f3a4f2 | ||
|
|
dfda0d566a | ||
|
|
99c2fac143 | ||
|
|
4c5308da8d | ||
|
|
4d0ed3d857 | ||
|
|
0b5582ed0d | ||
|
|
17734f833c | ||
|
|
98a9d5d424 | ||
|
|
6d74f36449 | ||
|
|
47a5bf6aa5 | ||
|
|
2805e9eb3b | ||
|
|
72a1a86886 | ||
|
|
ec190bae33 | ||
|
|
83003e43d7 | ||
|
|
3b20dc2994 | ||
|
|
a7198298e7 | ||
|
|
f3d76d5780 | ||
|
|
e2305c3c5e | ||
|
|
ba737d7e58 | ||
|
|
88f69204c8 | ||
|
|
bb4561c2b8 | ||
|
|
4710f764e4 | ||
|
|
11a59a767e | ||
|
|
4cf3157aad | ||
|
|
b1f6cb349b | ||
|
|
0c134582ca | ||
|
|
acf2833362 | ||
|
|
20f9971096 | ||
|
|
cefeaceef0 | ||
|
|
1ba7c4b6ee | ||
|
|
1b49776819 | ||
|
|
41c68f4bbc | ||
|
|
56ac830405 | ||
|
|
ebcf821d81 | ||
|
|
e874a2624f | ||
|
|
03d1c0ed21 | ||
|
|
1b8c77eee0 | ||
|
|
d575cd50b1 | ||
|
|
2b040569e7 | ||
|
|
7a53f86fff | ||
|
|
a90bb53cd2 | ||
|
|
b450d62138 | ||
|
|
1a9d65c52a | ||
|
|
05f4746bbe | ||
|
|
1c587723fa | ||
|
|
b2a9c79de5 | ||
|
|
64259c7bcb | ||
|
|
a7efdb4e52 | ||
|
|
091ff0cce0 | ||
|
|
7e25a3a942 | ||
|
|
b3254e2b18 | ||
|
|
9a0fa79144 | ||
|
|
352db260b2 | ||
|
|
f072b5b679 | ||
|
|
b4058a813b | ||
|
|
b27e152ead | ||
|
|
936e83759d | ||
|
|
18fdc175c6 | ||
|
|
47c6ab0ced | ||
|
|
4868135d47 | ||
|
|
5e70db651d | ||
|
|
1fedede771 | ||
|
|
00596f1436 | ||
|
|
db840b5604 | ||
|
|
45070d0e51 | ||
|
|
8a1081f9ef | ||
|
|
ac84e44161 | ||
|
|
836dfb6503 | ||
|
|
35a8ce2349 | ||
|
|
bb7d68b3b9 | ||
|
|
1979846e5e | ||
|
|
a61ffab3f9 | ||
|
|
698fe73608 | ||
|
|
0083c32629 | ||
|
|
f313caaa73 | ||
|
|
6e3f07ddce | ||
|
|
11d28c4856 | ||
|
|
e9394ca85a | ||
|
|
9445a30e72 | ||
|
|
185b1a3d36 | ||
|
|
1c2f5d60a5 | ||
|
|
2f32910bef | ||
|
|
8de1b20bb5 | ||
|
|
60a7abcef6 | ||
|
|
e44e75fa6b | ||
|
|
ff7dc0b446 | ||
|
|
f813cb2310 | ||
|
|
cba19d7e23 | ||
|
|
9479c0e12d | ||
|
|
65c9c45ec6 | ||
|
|
6d79004d4f | ||
|
|
97623d20c5 | ||
|
|
d37802a42f | ||
|
|
9b837a24aa | ||
|
|
d0ef2f7dd8 | ||
|
|
c7cfd23580 | ||
|
|
7cf1ec3f89 | ||
|
|
9708a12607 | ||
|
|
92812fe723 | ||
|
|
79417ac59a | ||
|
|
984f66e083 | ||
|
|
ef2a436769 | ||
|
|
7f1a95550f | ||
|
|
803f5b5613 | ||
|
|
8ca9fa1c26 | ||
|
|
3b3b897193 | ||
|
|
6c364f63cc | ||
|
|
6b9e842ddd | ||
|
|
8f88d915ba | ||
|
|
eaa1f47f00 | ||
|
|
cbeae85731 | ||
|
|
84e618b3f2 | ||
|
|
382a16ff07 | ||
|
|
7bd339b645 | ||
|
|
70d8b2c4b7 | ||
|
|
3764a83c6b | ||
|
|
c3d200ddcd | ||
|
|
44c5e337ab | ||
|
|
040982e321 | ||
|
|
6c81ea846c | ||
|
|
d082a0696d | ||
|
|
f999839e59 | ||
|
|
f1bc662a24 | ||
|
|
232693419a | ||
|
|
ed66b951c6 | ||
|
|
70c2854f7c | ||
|
|
e9381ddeb2 | ||
|
|
1b46e003c3 | ||
|
|
4611d5a35f | ||
|
|
2e59378ab7 | ||
|
|
fc8bf39043 | ||
|
|
2cccd8ab28 | ||
|
|
d537ceedd6 | ||
|
|
ac7243b309 | ||
|
|
607e983f37 | ||
|
|
02f7326b7e | ||
|
|
b688f69031 | ||
|
|
df41329df9 | ||
|
|
0825bd7076 | ||
|
|
e9b7003cf5 | ||
|
|
c5d673c426 | ||
|
|
9cc8eec773 | ||
|
|
0b45535061 | ||
|
|
9f64ad8d89 | ||
|
|
e5b0b7e9a7 | ||
|
|
9c3522cb70 | ||
|
|
b357390215 | ||
|
|
c66fc2f656 | ||
|
|
64554aca6d | ||
|
|
f1df9a02fa | ||
|
|
f3725bdd2e | ||
|
|
cb92b94d55 | ||
|
|
ef01f82e0c | ||
|
|
4ba7ee8c92 | ||
|
|
c59633a588 | ||
|
|
f56e37398c | ||
|
|
e43ffa6f2b | ||
|
|
6991bc9723 | ||
|
|
9d6106a80b | ||
|
|
9e70404411 | ||
|
|
bc48d299b6 | ||
|
|
a8db5650a5 | ||
|
|
91871b418b | ||
|
|
aaf98082e9 | ||
|
|
ac228deeda | ||
|
|
fc661c83ef | ||
|
|
a2acffdfa3 | ||
|
|
79ce4ed226 | ||
|
|
e3a7aa0033 | ||
|
|
95973ba3e8 | ||
|
|
fde6303ae6 | ||
|
|
b4a1948951 | ||
|
|
b927028416 | ||
|
|
fe5d1ff6c5 | ||
|
|
1308656000 | ||
|
|
ec1e6b9385 | ||
|
|
315a8b6b60 | ||
|
|
558c6b621b | ||
|
|
6d91d02c62 | ||
|
|
436ded68b7 | ||
|
|
3ec88b3665 | ||
|
|
2caedb38a6 | ||
|
|
49378ab7fe | ||
|
|
982dc6aa8c | ||
|
|
33175187b7 | ||
|
|
0339904920 | ||
|
|
8bda9487c6 | ||
|
|
617d84c0ef | ||
|
|
ac64731d55 | ||
|
|
5dc064e971 | ||
|
|
c24732ed4e | ||
|
|
ba710bee86 | ||
|
|
c20392ca80 | ||
|
|
8eb05d0950 | ||
|
|
b11ad375cd | ||
|
|
7a6d533014 | ||
|
|
be44f75d2d | ||
|
|
ab14123aed | ||
|
|
a963a6d10d | ||
|
|
69b4cd22a2 | ||
|
|
958325653f | ||
|
|
c5dc419f9e | ||
|
|
2a201f9525 | ||
|
|
b7ba509618 | ||
|
|
f946d7b447 | ||
|
|
e2a5535ed6 | ||
|
|
0f94e2c0c3 | ||
|
|
a25508b98d | ||
|
|
e825433a38 | ||
|
|
d1c08889fe | ||
|
|
0b82b5a0d6 | ||
|
|
a33d0d4fb6 | ||
|
|
ba42334d36 | ||
|
|
2e62641aa4 | ||
|
|
dad460dcfc | ||
|
|
3ae23b6a54 | ||
|
|
97126f18b1 | ||
|
|
3838d222c2 | ||
|
|
96c3292210 | ||
|
|
b0fd92cb3f | ||
|
|
62c5b5e570 | ||
|
|
feaa0871ac | ||
|
|
9f41976926 | ||
|
|
1784f24c5f | ||
|
|
fc47d9fc4d | ||
|
|
eade9f8f2b | ||
|
|
6276c55cc9 | ||
|
|
afa6ff7c4b | ||
|
|
f4dcbe3a84 | ||
|
|
9c02cc1b17 | ||
|
|
0cc3ef8f90 | ||
|
|
4cbbacc946 | ||
|
|
9a0c71d4a7 | ||
|
|
0f1b831de7 | ||
|
|
37a7a2aacd | ||
|
|
635b157b11 | ||
|
|
c3ae4da83a | ||
|
|
c3809ece67 | ||
|
|
bfc436dccd | ||
|
|
71d6874236 | ||
|
|
9bf1f994ae | ||
|
|
bb4127a6fb | ||
|
|
a691632995 | ||
|
|
5d6ea3d75f | ||
|
|
43873b1b2c | ||
|
|
9430f3665b | ||
|
|
f3c1f63444 | ||
|
|
b5c7232d6f | ||
|
|
2f3677d593 | ||
|
|
1e0efaffe8 | ||
|
|
fc79754750 | ||
|
|
0e4de42be8 | ||
|
|
4e389127b5 | ||
|
|
47593730d6 | ||
|
|
e742da73bd | ||
|
|
890bf3cce1 | ||
|
|
60eb312e3b | ||
|
|
06207da185 | ||
|
|
4dc2cf8a6b | ||
|
|
44450bf644 | ||
|
|
312aec79ca | ||
|
|
a8578c73f8 | ||
|
|
c522ffa6db | ||
|
|
93b7599b1c | ||
|
|
3ccbd7c9b2 | ||
|
|
385a87db31 | ||
|
|
5530353eef | ||
|
|
d1193093ef | ||
|
|
b203db27a4 | ||
|
|
0a3e1af04c | ||
|
|
c6c8e5d70c | ||
|
|
fa354ec8d9 | ||
|
|
d0375f697d | ||
|
|
33c8257d25 | ||
|
|
f389bc33c3 | ||
|
|
4d5dca71ce | ||
|
|
a9c44a1b9c | ||
|
|
4144f800a1 | ||
|
|
6ef9a81017 | ||
|
|
8c6722f3c5 | ||
|
|
40e138627b | ||
|
|
a470dda4e6 | ||
|
|
b725410623 | ||
|
|
a9dfb33126 | ||
|
|
8b848770dc | ||
|
|
94629edb9b | ||
|
|
2a3f2ca28d | ||
|
|
8ab1e7d432 | ||
|
|
b2ba6a0c85 | ||
|
|
cca5421aed | ||
|
|
799d9a73e6 | ||
|
|
b0781622b2 | ||
|
|
0d0eec6345 | ||
|
|
1af79f7960 | ||
|
|
15b570bbdd | ||
|
|
7aa5599cc2 | ||
|
|
676293ec42 | ||
|
|
abc4fb81b1 | ||
|
|
53a16f354f | ||
|
|
6ab1ecd836 | ||
|
|
e7b16e7b47 | ||
|
|
14804f81a8 | ||
|
|
9a61b8d77d | ||
|
|
f42c2763d5 | ||
|
|
98d4e0e1b5 | ||
|
|
9156633baf | ||
|
|
bcf4f836b4 | ||
|
|
dbc1d70f99 | ||
|
|
78bc190a85 | ||
|
|
02855d7fed | ||
|
|
6fdd5d32be | ||
|
|
d7f32b105b | ||
|
|
0ac480a0bd | ||
|
|
417996de02 | ||
|
|
6c2d60cec2 | ||
|
|
743bd6c917 | ||
|
|
ab61aa41d9 | ||
|
|
36396ae29e | ||
|
|
749e083e6e | ||
|
|
67b9cf9e82 | ||
|
|
27fb20f3ab | ||
|
|
1c71b274f0 | ||
|
|
fcd20b63fe | ||
|
|
8ec344ac1b | ||
|
|
df966a9ac6 | ||
|
|
f634666dc6 | ||
|
|
e2f9f5d7e5 | ||
|
|
d078b0d143 | ||
|
|
0ccdea3cd8 | ||
|
|
df54b47cd0 | ||
|
|
2e595830b3 | ||
|
|
96fbcc9a5a | ||
|
|
6283801981 | ||
|
|
9a3214d46e | ||
|
|
9eb7c8344f | ||
|
|
4140bbb1f7 | ||
|
|
ea44497136 | ||
|
|
07737c6e5b | ||
|
|
98d5eefc86 | ||
|
|
4f2d93bb65 | ||
|
|
a5df3f1747 | ||
|
|
7f5f73887d | ||
|
|
91ce7807b9 | ||
|
|
d26fae9875 | ||
|
|
60bdc79ec4 | ||
|
|
253ddf2998 | ||
|
|
9fa15b390a | ||
|
|
e7d6fe6c8b | ||
|
|
9650b1aa70 | ||
|
|
eafa6f960f | ||
|
|
c62ccf4870 | ||
|
|
ef34439a79 | ||
|
|
b328ec2462 | ||
|
|
60f27178b8 | ||
|
|
e3fbb83ad0 | ||
|
|
28b70a7b9a | ||
|
|
dcdc341d0f | ||
|
|
fce77c9372 | ||
|
|
a360c481c2 | ||
|
|
c72db5fa5f | ||
|
|
fc9a23d6d4 | ||
|
|
167f4666e2 | ||
|
|
1cbcc7be21 | ||
|
|
8053598069 | ||
|
|
7cfac1a91a | ||
|
|
192cdd028e | ||
|
|
029c143922 | ||
|
|
00298cc68c | ||
|
|
d9c7db51af | ||
|
|
f12b15d22b | ||
|
|
409b8bac00 | ||
|
|
28b09bde4b | ||
|
|
2f6af906f4 | ||
|
|
628e3ac1eb | ||
|
|
fbf5785e35 | ||
|
|
eeea2b1ff8 | ||
|
|
32062e439f | ||
|
|
930a0beaf1 | ||
|
|
4a49fefdd9 | ||
|
|
8e792855e0 | ||
|
|
69f5c6987a | ||
|
|
85fc9e4ecf | ||
|
|
d5c3f0c9cf | ||
|
|
a48120e675 | ||
|
|
36f8e4f2ad | ||
|
|
1084a39a45 | ||
|
|
86df482842 | ||
|
|
b0d47ebcc6 | ||
|
|
fffdf1dfba | ||
|
|
3273ed2616 | ||
|
|
aa7b0a31b0 | ||
|
|
fb0d44d403 | ||
|
|
cd8ec89cbb | ||
|
|
252f271dc5 | ||
|
|
62d400c3a9 | ||
|
|
f9aa3e0da5 | ||
|
|
685fe5b0fb | ||
|
|
5180e71a0d | ||
|
|
55637f7508 | ||
|
|
7d72dfe0be | ||
|
|
02529a0fc2 | ||
|
|
b44974677e | ||
|
|
d4fd5e4fce | ||
|
|
30123eaa4a | ||
|
|
454ec97d51 | ||
|
|
c2ac331e78 | ||
|
|
be4a35af11 | ||
|
|
445b29ad0d | ||
|
|
64d0f7fffd | ||
|
|
baf0d09455 | ||
|
|
08a81a0ab9 | ||
|
|
31110c7fd9 | ||
|
|
0e1dd92d9b | ||
|
|
a3204a4df7 | ||
|
|
2288ab48b9 | ||
|
|
670401884c | ||
|
|
37181c341e | ||
|
|
be7e677448 | ||
|
|
b2eeb49a45 | ||
|
|
9aa040d917 | ||
|
|
c2043a223b | ||
|
|
f24e859f17 | ||
|
|
737b33f9d1 | ||
|
|
00791d2151 | ||
|
|
b141598f9b | ||
|
|
d1618d79b0 | ||
|
|
00c84dfe5c | ||
|
|
95f31b98a8 | ||
|
|
10d74ed100 | ||
|
|
8a7f612d5b | ||
|
|
0829ee9234 | ||
|
|
b22e33444b | ||
|
|
d115a12cbe | ||
|
|
b7b744de94 | ||
|
|
68e46e406a | ||
|
|
a46ae4efec | ||
|
|
62777a794e | ||
|
|
329a969761 | ||
|
|
30170bc394 | ||
|
|
f193302e15 | ||
|
|
7c4870d641 | ||
|
|
8b84a76d5d | ||
|
|
a4cd761372 | ||
|
|
63d2cfd6ba | ||
|
|
bb44bdd047 | ||
|
|
6904e66384 | ||
|
|
fbffe2367e | ||
|
|
e442a2846d | ||
|
|
f6985586ea | ||
|
|
2bae5b0959 | ||
|
|
1e58809fcc | ||
|
|
6b1d213cc2 | ||
|
|
42bec13a83 | ||
|
|
4415a179b3 | ||
|
|
5d42604efd | ||
|
|
b134b7d3f6 | ||
|
|
788219fe05 | ||
|
|
9a7f66cfe9 | ||
|
|
daa4d16e61 | ||
|
|
cf05f87795 | ||
|
|
c2f2f83b7c | ||
|
|
b30b2a523f | ||
|
|
150a3810a8 | ||
|
|
ac0eaa912b | ||
|
|
e37d4043f6 | ||
|
|
d073425b44 | ||
|
|
825b18cf71 | ||
|
|
549ad3204f | ||
|
|
35f9499b67 | ||
|
|
db82c35c17 | ||
|
|
73c74f753c | ||
|
|
a38fb2a5dc | ||
|
|
38e99e01f9 | ||
|
|
a1f46e84b8 | ||
|
|
6540804571 | ||
|
|
ffe6707595 | ||
|
|
9b21740c9f | ||
|
|
bd12e2ab95 | ||
|
|
bffb5ef8b4 | ||
|
|
e4c9822d78 | ||
|
|
73187d8832 | ||
|
|
8101154d5e | ||
|
|
c02937fd6f | ||
|
|
3430be4075 | ||
|
|
3f2b6f771f | ||
|
|
6e39b49cc2 | ||
|
|
71c34ed4e0 | ||
|
|
477178675c | ||
|
|
dbdf68b248 | ||
|
|
2fd139b307 | ||
|
|
a6c2657062 | ||
|
|
78a0bc0e2c | ||
|
|
d7116d6867 | ||
|
|
edc15b9fa2 | ||
|
|
93d4b73b2f | ||
|
|
8e3849e591 | ||
|
|
acaa1098f7 | ||
|
|
c1a5e88752 | ||
|
|
74b99014d2 | ||
|
|
9cba944d21 | ||
|
|
8c1c2f5d05 | ||
|
|
bf0fa8c562 | ||
|
|
3e1fc9ba6c | ||
|
|
4ceba603e4 |
6
.gitignore
vendored
@@ -31,6 +31,7 @@ Release/*.*
|
||||
tmp
|
||||
|
||||
# Ignore database directory.
|
||||
db/
|
||||
db/*.db
|
||||
db/*.db-*
|
||||
|
||||
@@ -75,4 +76,7 @@ My Amplifier XE Results - RippleD
|
||||
/out.txt
|
||||
|
||||
# Build Log
|
||||
rippled-build.log
|
||||
rippled-build.log
|
||||
|
||||
# Profiling data
|
||||
gmon.out
|
||||
|
||||
17
.travis.yml
@@ -6,20 +6,10 @@ before_install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq python-software-properties
|
||||
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
- sudo add-apt-repository -y ppa:boost-latest/ppa
|
||||
- sudo add-apt-repository -y ppa:afrank/boost
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq g++-4.8
|
||||
- sudo apt-get install -qq libboost1.55-all-dev
|
||||
# We want debug symbols for boost as we install gdb later
|
||||
- sudo apt-get install -qq libboost1.55-dbg
|
||||
- | # Setup the BOOST_ROOT
|
||||
export BOOST_ROOT=$HOME/boost_root
|
||||
mkdir -p $BOOST_ROOT/stage
|
||||
ln -s /usr/lib/x86_64-linux-gnu $BOOST_ROOT/stage/lib
|
||||
ln -s /usr/include/boost $BOOST_ROOT/boost
|
||||
- | # Try to patch boost
|
||||
sudo patch /usr/include/boost/bimap/detail/debug/static_error.hpp Builds/travis/static_error.boost.patch
|
||||
sudo patch /usr/include/boost/config/compiler/clang.hpp Builds/travis/clang.boost.patch
|
||||
- sudo apt-get install -qq libboost1.57-all-dev
|
||||
- sudo apt-get install -qq mlocate
|
||||
- sudo updatedb
|
||||
- sudo locate libboost | grep /lib | grep -e ".a$"
|
||||
@@ -44,6 +34,9 @@ before_install:
|
||||
script:
|
||||
# Set so any failing command will abort the build
|
||||
- set -e
|
||||
# Make sure vcxproj is up to date
|
||||
- scons vcxproj
|
||||
- git diff --exit-code
|
||||
# $CC will be either `clang` or `gcc` (If only we could do -j12 ;)
|
||||
- scons $CC.debug
|
||||
# We can be sure we're using the build/$CC.debug variant (-f so never err)
|
||||
|
||||
23
Builds/Docker/Dockerfile-testnet
Normal file
@@ -0,0 +1,23 @@
|
||||
FROM ubuntu
|
||||
MAINTAINER Torrie Fischer <torrie@ripple.com>
|
||||
|
||||
RUN apt-get update -qq &&\
|
||||
apt-get install -qq software-properties-common &&\
|
||||
apt-add-repository -y ppa:ubuntu-toolchain-r/test &&\
|
||||
apt-add-repository -y ppa:afrank/boost &&\
|
||||
apt-get update -qq
|
||||
|
||||
RUN apt-get purge -qq libboost1.48-dev &&\
|
||||
apt-get install -qq libprotobuf8 libboost1.57-all-dev
|
||||
|
||||
RUN mkdir -p /srv/rippled/data
|
||||
|
||||
VOLUME /srv/rippled/data/
|
||||
|
||||
ENTRYPOINT ["/srv/rippled/bin/rippled"]
|
||||
CMD ["--conf", "/srv/rippled/data/rippled.cfg"]
|
||||
EXPOSE 51235/udp
|
||||
EXPOSE 5005/tcp
|
||||
|
||||
ADD ./rippled.cfg /srv/rippled/data/rippled.cfg
|
||||
ADD ./rippled /srv/rippled/bin/
|
||||
180
Builds/Test.py
Executable file
@@ -0,0 +1,180 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of rippled: https://github.com/ripple/rippled
|
||||
# Copyright (c) 2012 - 2015 Ripple Labs Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
"""
|
||||
Invocation:
|
||||
./Builds/Test.py - builds and tests all configurations
|
||||
|
||||
#
|
||||
# The build must succeed without shell aliases for this to work.
|
||||
#
|
||||
# Common problems:
|
||||
# 1) Boost not found. Solution: export BOOST_ROOT=[path to boost folder]
|
||||
# 2) OpenSSL not found. Solution: export OPENSSL_ROOT=[path to OpenSSL folder]
|
||||
# 3) scons is an alias. Solution: Create a script named "scons" somewhere in
|
||||
# your $PATH (eg. ~/bin/scons will often work).
|
||||
# #!/bin/sh
|
||||
# python /C/Python27/Scripts/scons.py "${@}"
|
||||
"""
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
import argparse
|
||||
import itertools
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
IS_WINDOWS = platform.system().lower() == 'windows'
|
||||
|
||||
if IS_WINDOWS:
|
||||
BINARY_RE = re.compile(r'build\\([^\\]+)\\rippled.exe')
|
||||
|
||||
else:
|
||||
BINARY_RE = re.compile(r'build/([^/]+)/rippled')
|
||||
|
||||
ALL_TARGETS = ['debug', 'release']
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Test.py - run ripple tests'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--all', '-a',
|
||||
action='store_true',
|
||||
help='Build all configurations.',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--keep_going', '-k',
|
||||
action='store_true',
|
||||
help='Keep going after one configuration has failed.',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--silent', '-s',
|
||||
action='store_true',
|
||||
help='Silence all messages except errors',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--verbose', '-v',
|
||||
action='store_true',
|
||||
help=('Report more information about which commands are executed and the '
|
||||
'results.'),
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--test', '-t',
|
||||
default='',
|
||||
help='Add a prefix for unit tests',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'scons_args',
|
||||
default=(),
|
||||
nargs='*'
|
||||
)
|
||||
|
||||
ARGS = parser.parse_args()
|
||||
|
||||
def shell(*cmd, **kwds):
|
||||
"Execute a shell command and return the output."
|
||||
silent = kwds.pop('silent', ARGS.silent)
|
||||
verbose = not silent and kwds.pop('verbose', ARGS.verbose)
|
||||
if verbose:
|
||||
print('$', ' '.join(cmd))
|
||||
kwds['shell'] = IS_WINDOWS
|
||||
|
||||
process = subprocess.Popen(
|
||||
cmd,
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
**kwds)
|
||||
lines = []
|
||||
count = 0
|
||||
for line in process.stdout:
|
||||
lines.append(line)
|
||||
if verbose:
|
||||
print(line, end='')
|
||||
elif not silent:
|
||||
count += 1
|
||||
if count >= 80:
|
||||
print()
|
||||
count = 0
|
||||
else:
|
||||
print('.', end='')
|
||||
|
||||
if not verbose and count:
|
||||
print()
|
||||
process.wait()
|
||||
return process.returncode, lines
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = list(ARGS.scons_args)
|
||||
if ARGS.all:
|
||||
for a in ALL_TARGETS:
|
||||
if a not in args:
|
||||
args.append(a)
|
||||
print('Building:', *(args or ['(default)']))
|
||||
|
||||
# Build everything.
|
||||
resultcode, lines = shell('scons', *args)
|
||||
if resultcode:
|
||||
print('Build FAILED:')
|
||||
if not ARGS.verbose:
|
||||
print(*lines, sep='')
|
||||
exit(1)
|
||||
|
||||
# Now extract the executable names and corresponding targets.
|
||||
failed = []
|
||||
_, lines = shell('scons', '-n', '--tree=derived', *args, silent=True)
|
||||
for line in lines:
|
||||
match = BINARY_RE.search(line)
|
||||
if match:
|
||||
executable, target = match.group(0, 1)
|
||||
|
||||
print('Unit tests for', target)
|
||||
testflag = '--unittest'
|
||||
if ARGS.test:
|
||||
testflag += ('=' + ARGS.test)
|
||||
|
||||
resultcode, lines = shell(executable, testflag)
|
||||
if resultcode:
|
||||
print('ERROR:', *lines, sep='')
|
||||
failed.append([target, 'unittest'])
|
||||
if not ARGS.keep_going:
|
||||
break
|
||||
ARGS.verbose and print(*lines, sep='')
|
||||
|
||||
print('npm tests for', target)
|
||||
resultcode, lines = shell('npm', 'test', '--rippled=' + executable)
|
||||
if resultcode:
|
||||
print('ERROR:\n', *lines, sep='')
|
||||
failed.append([target, 'npm'])
|
||||
if not ARGS.keep_going:
|
||||
break
|
||||
else:
|
||||
ARGS.verbose and print(*lines, sep='')
|
||||
|
||||
if failed:
|
||||
print('FAILED:', *(':'.join(f) for f in failed))
|
||||
exit(1)
|
||||
else:
|
||||
print('Success')
|
||||
@@ -1,24 +1,26 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Express 2013 for Windows Desktop
|
||||
VisualStudioVersion = 12.0.30110.0
|
||||
VisualStudioVersion = 12.0.31101.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RippleD", "RippleD.vcxproj", "{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
debug.classic|x64 = debug.classic|x64
|
||||
debug|x64 = debug|x64
|
||||
release.classic|x64 = release.classic|x64
|
||||
release|x64 = release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.Debug|Win32.ActiveCfg = debug|x64
|
||||
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.Debug|x64.ActiveCfg = debug|x64
|
||||
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.Debug|x64.Build.0 = debug|x64
|
||||
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.Release|Win32.ActiveCfg = release|x64
|
||||
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.Release|x64.ActiveCfg = release|x64
|
||||
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.Release|x64.Build.0 = release|x64
|
||||
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.debug.classic|x64.ActiveCfg = debug.classic|x64
|
||||
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.debug.classic|x64.Build.0 = debug.classic|x64
|
||||
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.debug|x64.ActiveCfg = debug|x64
|
||||
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.debug|x64.Build.0 = debug|x64
|
||||
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.release.classic|x64.ActiveCfg = release.classic|x64
|
||||
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.release.classic|x64.Build.0 = release.classic|x64
|
||||
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.release|x64.ActiveCfg = release|x64
|
||||
{26B7D9AC-1A80-8EF8-6703-D061F1BECB75}.release|x64.Build.0 = release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Name: rippled
|
||||
Version: 0.26.4
|
||||
Version: 0.28.1-rc1
|
||||
Release: 1%{?dist}
|
||||
Summary: Ripple peer-to-peer network daemon
|
||||
|
||||
@@ -50,4 +50,3 @@ rm -rf %{buildroot}
|
||||
/usr/bin/rippled
|
||||
/usr/share/rippled/LICENSE
|
||||
/etc/rippled/rippled-example.cfg
|
||||
|
||||
|
||||
85
README.md
@@ -1,3 +1,77 @@
|
||||

|
||||
|
||||
#The World’s Fastest and Most Secure Payment System
|
||||
|
||||
**What is Ripple?**
|
||||
|
||||
Ripple is the open-source, distributed payment protocol that enables instant
|
||||
payments with low fees, no chargebacks, and currency flexibility (for example
|
||||
dollars, yen, euros, bitcoins, or even loyalty points). Businesses of any size
|
||||
can easily build payment solutions such as banking or remittance apps, and
|
||||
accelerate the movement of money. Ripple enables the world to move value the
|
||||
way it moves information on the Internet.
|
||||
|
||||

|
||||
|
||||
**What is a Gateway?**
|
||||
|
||||
Ripple works with gateways: independent businesses which hold customer
|
||||
deposits in various currencies such as U.S. dollars (USD) or Euros (EUR),
|
||||
in exchange for providing cryptographically-signed issuances that users can
|
||||
send and trade with one another in seconds on the Ripple network. Within the
|
||||
protocol, exchanges between multiple currencies can occur atomically without
|
||||
any central authority to monitor them. Later, customers can withdraw their
|
||||
Ripple balances from the gateways that created those issuances.
|
||||
|
||||
**How do Ripple payments work?**
|
||||
|
||||
A sender specifies the amount and currency the recipient should receive and
|
||||
Ripple automatically converts the sender’s available currencies using the
|
||||
distributed order books integrated into the Ripple protocol. Independent third
|
||||
parties acting as market makers provide liquidity in these order books.
|
||||
|
||||
Ripple uses a pathfinding algorithm that considers currency pairs when
|
||||
converting from the source to the destination currency. This algorithm searches
|
||||
for a series of currency swaps that gives the user the lowest cost. Since
|
||||
anyone can participate as a market maker, market forces drive fees to the
|
||||
lowest practical level.
|
||||
|
||||
**What can you do with Ripple?**
|
||||
|
||||
The protocol is entirely open-source and the network’s shared ledger is public
|
||||
information, so no central authority prevents anyone from participating. Anyone
|
||||
can become a market maker, create a wallet or a gateway, or monitor network
|
||||
behavior. Competition drives down spreads and fees, making the network useful
|
||||
to everyone.
|
||||
|
||||
|
||||
###Key Protocol Features
|
||||
1. XRP is Ripple’s native [cryptocurrency]
|
||||
(http://en.wikipedia.org/wiki/Cryptocurrency) with a fixed supply that
|
||||
decreases slowly over time, with no mining. XRP acts as a bridge currency, and
|
||||
pays for transaction fees that protect the network against spam.
|
||||

|
||||
|
||||
2. Pathfinding discovers cheap and efficient payment paths through multiple
|
||||
[order books](https://www.ripplecharts.com) allowing anyone to [trade](https://www.rippletrade.com) anything. When two accounts aren’t linked by relationships of trust, the Ripple pathfinding engine considers intermediate links and order books to produce a set of possible paths the transaction can take. When the payment is processed, the liquidity along these paths is iteratively consumed in best-first order.
|
||||

|
||||
|
||||
3. [Consensus](https://www.youtube.com/watch?v=pj1QVb1vlC0) confirms
|
||||
transactions in an atomic fashion, without mining, ensuring efficient use of
|
||||
resources.
|
||||
|
||||
[transact]: https://ripple.com/files/ripple-FIs.pdf
|
||||
[build]: https://ripple.com/build/
|
||||
|
||||
[transact.png]: /images/transact.png
|
||||
[build.png]: /images/build.png
|
||||
[contribute.png]: /images/contribute.png
|
||||
|
||||
###Join The Ripple Community
|
||||
|![Transact][transact.png]|![Build][build.png]|![Contribute][contribute.png]|
|
||||
|:-----------------------:|:-----------------:|:---------------------------:|
|
||||
|[Transact on the fastest payment infrastructure][transact]|[Build Imaginative Apps][build]|Contribute to the Ripple Protocol Implementation|
|
||||
|
||||
#rippled - Ripple P2P server
|
||||
|
||||
##[](https://travis-ci.org/ripple/rippled)
|
||||
@@ -10,6 +84,9 @@ This is the repository for Ripple's `rippled`, reference P2P server.
|
||||
###Setup instructions:
|
||||
* https://ripple.com/wiki/Rippled_setup_instructions
|
||||
|
||||
###Issues
|
||||
* https://ripplelabs.atlassian.net/browse/RIPD
|
||||
|
||||
### Repository Contents
|
||||
|
||||
#### ./bin
|
||||
@@ -37,5 +114,9 @@ Ripple is open source and permissively licensed under the ISC license. See the
|
||||
LICENSE file for more details.
|
||||
|
||||
###For more information:
|
||||
* https://ripple.com
|
||||
* https://ripple.com/wiki
|
||||
* Ripple Wiki - https://ripple.com/wiki/
|
||||
* Ripple Primer - https://ripple.com/ripple_primer.pdf
|
||||
* Ripple Primer (Market Making) - https://ripple.com/ripple-mm.pdf
|
||||
* Ripple Gateway Primer - https://ripple.com/ripple-gateways.pdf
|
||||
* Consensus - https://wiki.ripple.com/Consensus
|
||||
|
||||
|
||||
500
SConstruct
@@ -11,14 +11,17 @@
|
||||
all All available variants
|
||||
debug All available debug variants
|
||||
release All available release variants
|
||||
profile All available profile variants
|
||||
|
||||
clang All clang variants
|
||||
clang.debug clang debug variant
|
||||
clang.release clang release variant
|
||||
clang.profile clang profile variant
|
||||
|
||||
gcc All gcc variants
|
||||
gcc.debug gcc debug variant
|
||||
gcc.release gcc release variant
|
||||
gcc.profile gcc profile variant
|
||||
|
||||
msvc All msvc variants
|
||||
msvc.debug MSVC debug variant
|
||||
@@ -26,10 +29,37 @@
|
||||
|
||||
vcxproj Generate Visual Studio 2013 project file
|
||||
|
||||
count Show line count metrics
|
||||
|
||||
Any individual target can also have ".nounity" appended for a classic,
|
||||
non unity build. Example:
|
||||
|
||||
scons gcc.debug.nounity
|
||||
|
||||
If the clang toolchain is detected, then the default target will use it, else
|
||||
the gcc toolchain will be used. On Windows environments, the MSVC toolchain is
|
||||
also detected.
|
||||
|
||||
The following environment variables modify the build environment:
|
||||
CLANG_CC
|
||||
CLANG_CXX
|
||||
CLANG_LINK
|
||||
If set, a clang toolchain will be used. These must all be set together.
|
||||
|
||||
GNU_CC
|
||||
GNU_CXX
|
||||
GNU_LINK
|
||||
If set, a gcc toolchain will be used (unless a clang toolchain is
|
||||
detected first). These must all be set together.
|
||||
|
||||
CXX
|
||||
If set, used to detect a toolchain.
|
||||
|
||||
BOOST_ROOT
|
||||
Path to the boost directory.
|
||||
OPENSSL_ROOT
|
||||
Path to the openssl directory.
|
||||
|
||||
'''
|
||||
#
|
||||
'''
|
||||
@@ -83,6 +113,29 @@ def check_openssl():
|
||||
(CHECK_LINE, CHECK_COMMAND))
|
||||
|
||||
|
||||
def set_implicit_cache():
|
||||
'''Use implicit_cache on some targets to improve build times.
|
||||
|
||||
By default, scons scans each file for include dependecies. The implicit
|
||||
cache flag lets you cache these dependencies for later builds, and will
|
||||
only rescan files that change.
|
||||
|
||||
Failure cases are:
|
||||
1) If the include search paths are changed (i.e. CPPPATH), then a file
|
||||
may not be rebuilt.
|
||||
2) If a same-named file has been added to a directory that is earlier in
|
||||
the search path than the directory in which the file was found.
|
||||
Turn on if this build is for a specific debug target (i.e. clang.debug)
|
||||
|
||||
If one of the failure cases applies, you can force a rescan of dependencies
|
||||
using the command line option `--implicit-deps-changed`
|
||||
'''
|
||||
if len(COMMAND_LINE_TARGETS) == 1:
|
||||
s = COMMAND_LINE_TARGETS[0].split('.')
|
||||
if len(s) > 1 and 'debug' in s:
|
||||
SetOption('implicit_cache', 1)
|
||||
|
||||
|
||||
def import_environ(env):
|
||||
'''Imports environment settings into the construction environment'''
|
||||
def set(keys):
|
||||
@@ -199,7 +252,11 @@ def config_base(env):
|
||||
)
|
||||
check_openssl()
|
||||
|
||||
env.Append(CPPDEFINES=['OPENSSL_NO_SSL2'])
|
||||
env.Append(CPPDEFINES=[
|
||||
'OPENSSL_NO_SSL2'
|
||||
,'DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER'
|
||||
,{'HAVE_USLEEP' : '1'}
|
||||
])
|
||||
|
||||
try:
|
||||
BOOST_ROOT = os.path.normpath(os.environ['BOOST_ROOT'])
|
||||
@@ -245,7 +302,7 @@ def config_env(toolchain, variant, env):
|
||||
if variant == 'debug':
|
||||
env.Append(CPPDEFINES=['DEBUG', '_DEBUG'])
|
||||
|
||||
elif variant == 'release':
|
||||
elif variant == 'release' or variant == 'profile':
|
||||
env.Append(CPPDEFINES=['NDEBUG'])
|
||||
|
||||
if toolchain in Split('clang gcc'):
|
||||
@@ -263,14 +320,32 @@ def config_env(toolchain, variant, env):
|
||||
'-g' # generate debug symbols
|
||||
])
|
||||
|
||||
env.Append(LINKFLAGS=[
|
||||
'-rdynamic',
|
||||
'-g',
|
||||
])
|
||||
|
||||
if variant == 'profile':
|
||||
env.Append(CCFLAGS=[
|
||||
'-p',
|
||||
'-pg',
|
||||
])
|
||||
env.Append(LINKFLAGS=[
|
||||
'-p',
|
||||
'-pg',
|
||||
])
|
||||
|
||||
if toolchain == 'clang':
|
||||
env.Append(CCFLAGS=['-Wno-redeclared-class-member'])
|
||||
env.Append(CPPDEFINES=['BOOST_ASIO_HAS_STD_ARRAY'])
|
||||
|
||||
env.Append(CXXFLAGS=[
|
||||
'-frtti',
|
||||
'-std=c++11',
|
||||
'-Wno-invalid-offsetof'])
|
||||
|
||||
env.Append(CPPDEFINES=['_FILE_OFFSET_BITS=64'])
|
||||
|
||||
if Beast.system.osx:
|
||||
env.Append(CPPDEFINES={
|
||||
'BEAST_COMPILE_OBJECTIVE_CPP': 1,
|
||||
@@ -298,11 +373,10 @@ def config_env(toolchain, variant, env):
|
||||
'boost_program_options',
|
||||
'boost_regex',
|
||||
'boost_system',
|
||||
'boost_thread'
|
||||
]
|
||||
# We prefer static libraries for boost
|
||||
if env.get('BOOST_ROOT'):
|
||||
# Need to add boost_thread. Not needed when dynamic linking is used.
|
||||
boost_libs += ['boost_thread']
|
||||
static_libs = ['%s/stage/lib/lib%s.a' % (env['BOOST_ROOT'], l) for
|
||||
l in boost_libs]
|
||||
if all(os.path.exists(f) for f in static_libs):
|
||||
@@ -324,22 +398,12 @@ def config_env(toolchain, variant, env):
|
||||
else:
|
||||
env.Append(LIBS=['rt'])
|
||||
|
||||
env.Append(LINKFLAGS=[
|
||||
'-rdynamic'
|
||||
])
|
||||
|
||||
if variant == 'release':
|
||||
env.Append(CCFLAGS=[
|
||||
'-O3',
|
||||
'-fno-strict-aliasing'
|
||||
])
|
||||
|
||||
if toolchain != 'msvc':
|
||||
git = Beast.Git(env)
|
||||
if git.exists:
|
||||
id = '%s+%s.%s' % (git.tags, git.user, git.branch)
|
||||
env.Append(CPPDEFINES={'GIT_COMMIT_ID' : '\'"%s"\'' % id })
|
||||
|
||||
if toolchain == 'clang':
|
||||
if Beast.system.osx:
|
||||
env.Replace(CC='clang', CXX='clang++', LINK='clang++')
|
||||
@@ -466,6 +530,7 @@ def config_env(toolchain, variant, env):
|
||||
# Configure the base construction environment
|
||||
root_dir = Dir('#').srcnode().get_abspath() # Path to this SConstruct file
|
||||
build_dir = os.path.join('build')
|
||||
|
||||
base = Environment(
|
||||
toolpath=[os.path.join ('src', 'beast', 'site_scons', 'site_tools')],
|
||||
tools=['default', 'Protoc', 'VSProject'],
|
||||
@@ -477,10 +542,14 @@ base.Append(CPPPATH=[
|
||||
'src',
|
||||
os.path.join('src', 'beast'),
|
||||
os.path.join(build_dir, 'proto'),
|
||||
os.path.join('src','soci','src'),
|
||||
])
|
||||
|
||||
base.Decider('MD5-timestamp')
|
||||
set_implicit_cache()
|
||||
|
||||
# Configure the toolchains, variants, default toolchain, and default target
|
||||
variants = ['debug', 'release']
|
||||
variants = ['debug', 'release', 'profile']
|
||||
all_toolchains = ['clang', 'gcc', 'msvc']
|
||||
if Beast.system.osx:
|
||||
toolchains = ['clang']
|
||||
@@ -501,6 +570,8 @@ else:
|
||||
default_toolchain = 'clang'
|
||||
else:
|
||||
raise ValueError("Don't understand toolchains in " + str(toolchains))
|
||||
|
||||
default_tu_style = 'unity'
|
||||
default_variant = 'release'
|
||||
default_target = None
|
||||
|
||||
@@ -527,144 +598,273 @@ class ObjectBuilder(object):
|
||||
if kwds:
|
||||
env = env.Clone()
|
||||
env.Prepend(**kwds)
|
||||
path = UNITY_BUILD_DIRECTORY + filename
|
||||
o = env.Object(Beast.variantFile(path, self.variant_dirs))
|
||||
o = env.Object(Beast.variantFile(filename, self.variant_dirs))
|
||||
self.objects.append(o)
|
||||
|
||||
def list_sources(base, suffixes):
|
||||
def _iter(base):
|
||||
for parent, dirs, files in os.walk(base):
|
||||
files = [f for f in files if not f[0] == '.']
|
||||
dirs[:] = [d for d in dirs if not d[0] == '.']
|
||||
for path in files:
|
||||
path = os.path.join(parent, path)
|
||||
r = os.path.splitext(path)
|
||||
if r[1] and r[1] in suffixes:
|
||||
yield os.path.normpath(path)
|
||||
return list(_iter(base))
|
||||
|
||||
|
||||
def append_sources(result, *filenames, **kwds):
|
||||
result.append([filenames, kwds])
|
||||
|
||||
|
||||
def get_soci_sources(style):
|
||||
result = []
|
||||
cpp_path = [
|
||||
'src/soci/src/core',
|
||||
'src/sqlite', ]
|
||||
append_sources(result,
|
||||
'src/ripple/unity/soci.cpp',
|
||||
CPPPATH=cpp_path)
|
||||
if style == 'unity':
|
||||
append_sources(result,
|
||||
'src/ripple/unity/soci_ripple.cpp',
|
||||
CPPPATH=cpp_path)
|
||||
return result
|
||||
|
||||
|
||||
def get_classic_sources():
|
||||
result = []
|
||||
append_sources(
|
||||
result,
|
||||
*list_sources('src/ripple/app', '.cpp'),
|
||||
CPPPATH=[
|
||||
'src/soci/src/core',
|
||||
'src/sqlite']
|
||||
)
|
||||
append_sources(result, *list_sources('src/ripple/basics', '.cpp'))
|
||||
append_sources(result, *list_sources('src/ripple/core', '.cpp'))
|
||||
append_sources(result, *list_sources('src/ripple/crypto', '.cpp'))
|
||||
append_sources(result, *list_sources('src/ripple/json', '.cpp'))
|
||||
append_sources(result, *list_sources('src/ripple/legacy', '.cpp'))
|
||||
append_sources(result, *list_sources('src/ripple/net', '.cpp'))
|
||||
append_sources(result, *list_sources('src/ripple/overlay', '.cpp'))
|
||||
append_sources(result, *list_sources('src/ripple/peerfinder', '.cpp'))
|
||||
append_sources(result, *list_sources('src/ripple/protocol', '.cpp'))
|
||||
append_sources(result, *list_sources('src/ripple/shamap', '.cpp'))
|
||||
append_sources(
|
||||
result,
|
||||
*list_sources('src/ripple/nodestore', '.cpp'),
|
||||
CPPPATH=[
|
||||
'src/rocksdb2/include',
|
||||
'src/snappy/snappy',
|
||||
'src/snappy/config',
|
||||
])
|
||||
|
||||
result += get_soci_sources('classic')
|
||||
return result
|
||||
|
||||
|
||||
def get_unity_sources():
|
||||
result = []
|
||||
append_sources(
|
||||
result,
|
||||
'src/ripple/unity/app.cpp',
|
||||
'src/ripple/unity/app1.cpp',
|
||||
'src/ripple/unity/app2.cpp',
|
||||
'src/ripple/unity/app3.cpp',
|
||||
'src/ripple/unity/app4.cpp',
|
||||
'src/ripple/unity/app5.cpp',
|
||||
'src/ripple/unity/app6.cpp',
|
||||
'src/ripple/unity/app7.cpp',
|
||||
'src/ripple/unity/app8.cpp',
|
||||
'src/ripple/unity/app9.cpp',
|
||||
'src/ripple/unity/core.cpp',
|
||||
'src/ripple/unity/basics.cpp',
|
||||
'src/ripple/unity/crypto.cpp',
|
||||
'src/ripple/unity/net.cpp',
|
||||
'src/ripple/unity/overlay.cpp',
|
||||
'src/ripple/unity/peerfinder.cpp',
|
||||
'src/ripple/unity/json.cpp',
|
||||
'src/ripple/unity/protocol.cpp',
|
||||
'src/ripple/unity/shamap.cpp',
|
||||
'src/ripple/unity/legacy.cpp',
|
||||
)
|
||||
|
||||
result += get_soci_sources('unity')
|
||||
|
||||
append_sources(
|
||||
result,
|
||||
'src/ripple/unity/nodestore.cpp',
|
||||
CPPPATH=[
|
||||
'src/rocksdb2/include',
|
||||
'src/snappy/snappy',
|
||||
'src/snappy/config',
|
||||
])
|
||||
|
||||
return result
|
||||
|
||||
# Declare the targets
|
||||
aliases = collections.defaultdict(list)
|
||||
msvc_configs = []
|
||||
for toolchain in all_toolchains:
|
||||
for variant in variants:
|
||||
# Configure this variant's construction environment
|
||||
env = base.Clone()
|
||||
config_env(toolchain, variant, env)
|
||||
variant_name = '%s.%s' % (toolchain, variant)
|
||||
variant_dir = os.path.join(build_dir, variant_name)
|
||||
variant_dirs = {
|
||||
os.path.join(variant_dir, 'src') :
|
||||
'src',
|
||||
os.path.join(variant_dir, 'proto') :
|
||||
os.path.join (build_dir, 'proto'),
|
||||
}
|
||||
for dest, source in variant_dirs.iteritems():
|
||||
env.VariantDir(dest, source, duplicate=0)
|
||||
|
||||
object_builder = ObjectBuilder(env, variant_dirs)
|
||||
object_builder.add_source_files(
|
||||
'app.cpp',
|
||||
'app1.cpp',
|
||||
'app2.cpp',
|
||||
'app3.cpp',
|
||||
'app4.cpp',
|
||||
'app5.cpp',
|
||||
'app6.cpp',
|
||||
'app7.cpp',
|
||||
'app8.cpp',
|
||||
'app9.cpp',
|
||||
'basics.cpp',
|
||||
'beast.cpp',
|
||||
'common.cpp',
|
||||
'core.cpp',
|
||||
'data.cpp',
|
||||
'http.cpp',
|
||||
'json.cpp',
|
||||
'net.cpp',
|
||||
'overlay.cpp',
|
||||
'peerfinder.cpp',
|
||||
'protobuf.cpp',
|
||||
'ripple.proto.cpp',
|
||||
'resource.cpp',
|
||||
'rpcx.cpp',
|
||||
'sitefiles.cpp',
|
||||
'sslutil.cpp',
|
||||
'types.cpp',
|
||||
'validators.cpp',
|
||||
'websocket.cpp',
|
||||
)
|
||||
|
||||
object_builder.add_source_files(
|
||||
'beastc.c',
|
||||
CCFLAGS=['-Wno-array-bounds'])
|
||||
def should_prepare_target(cl_target,
|
||||
style, toolchain, variant):
|
||||
if not cl_target:
|
||||
# default target
|
||||
return (style == default_tu_style and
|
||||
toolchain == default_toolchain and
|
||||
variant == default_variant)
|
||||
if 'vcxproj' in cl_target:
|
||||
return toolchain == 'msvc'
|
||||
s = cl_target.split('.')
|
||||
if style == 'unity' and 'nounity' in s:
|
||||
return False
|
||||
if len(s) == 1:
|
||||
return ('all' in cl_target or
|
||||
variant in cl_target or
|
||||
toolchain in cl_target)
|
||||
if len(s) == 2 or len(s) == 3:
|
||||
return s[0] == toolchain and s[1] == variant
|
||||
|
||||
object_builder.add_source_files(
|
||||
'nodestore.cpp',
|
||||
CPPPATH=[
|
||||
'src/leveldb/include',
|
||||
#'src/hyperleveldb/include', # hyper
|
||||
'src/rocksdb2/include',
|
||||
]
|
||||
)
|
||||
return True # A target we don't know about, better prepare to build it
|
||||
|
||||
if 'gcc' in toolchain:
|
||||
no_uninitialized_warning = {'CCFLAGS': ['-Wno-maybe-uninitialized']}
|
||||
else:
|
||||
no_uninitialized_warning = {}
|
||||
|
||||
object_builder.add_source_files(
|
||||
'leveldb.cpp',
|
||||
CPPPATH=[
|
||||
'src/leveldb/',
|
||||
'src/leveldb/include',
|
||||
'src/snappy/snappy',
|
||||
'src/snappy/config',
|
||||
],
|
||||
**no_uninitialized_warning
|
||||
)
|
||||
def should_prepare_targets(style, toolchain, variant):
|
||||
if not COMMAND_LINE_TARGETS:
|
||||
return should_prepare_target(None, style, toolchain, variant)
|
||||
for t in COMMAND_LINE_TARGETS:
|
||||
if should_prepare_target(t, style, toolchain, variant):
|
||||
return True
|
||||
|
||||
object_builder.add_source_files(
|
||||
'hyperleveldb.cpp',
|
||||
CPPPATH=[
|
||||
'src/hyperleveldb',
|
||||
'src/snappy/snappy',
|
||||
'src/snappy/config',
|
||||
],
|
||||
**no_uninitialized_warning
|
||||
)
|
||||
for tu_style in ['classic', 'unity']:
|
||||
if tu_style == 'classic':
|
||||
sources = get_classic_sources()
|
||||
else:
|
||||
sources = get_unity_sources()
|
||||
for toolchain in all_toolchains:
|
||||
for variant in variants:
|
||||
if not should_prepare_targets(tu_style, toolchain, variant):
|
||||
continue
|
||||
if variant == 'profile' and toolchain == 'msvc':
|
||||
continue
|
||||
# Configure this variant's construction environment
|
||||
env = base.Clone()
|
||||
config_env(toolchain, variant, env)
|
||||
variant_name = '%s.%s' % (toolchain, variant)
|
||||
if tu_style == 'classic':
|
||||
variant_name += '.nounity'
|
||||
variant_dir = os.path.join(build_dir, variant_name)
|
||||
variant_dirs = {
|
||||
os.path.join(variant_dir, 'src') :
|
||||
'src',
|
||||
os.path.join(variant_dir, 'proto') :
|
||||
os.path.join (build_dir, 'proto'),
|
||||
}
|
||||
for dest, source in variant_dirs.iteritems():
|
||||
env.VariantDir(dest, source, duplicate=0)
|
||||
|
||||
object_builder.add_source_files(
|
||||
'rocksdb.cpp',
|
||||
CPPPATH=[
|
||||
'src/rocksdb2',
|
||||
'src/rocksdb2/include',
|
||||
'src/snappy/snappy',
|
||||
'src/snappy/config',
|
||||
],
|
||||
**no_uninitialized_warning
|
||||
)
|
||||
object_builder = ObjectBuilder(env, variant_dirs)
|
||||
|
||||
object_builder.add_source_files(
|
||||
'snappy.cpp',
|
||||
CCFLAGS=['-Wno-unused-function'],
|
||||
CPPPATH=[
|
||||
'src/snappy/snappy',
|
||||
'src/snappy/config',
|
||||
]
|
||||
)
|
||||
for s, k in sources:
|
||||
object_builder.add_source_files(*s, **k)
|
||||
|
||||
if toolchain == "clang" and Beast.system.osx:
|
||||
object_builder.add_source_files('beastobjc.mm')
|
||||
git_commit_tag = {}
|
||||
if toolchain != 'msvc':
|
||||
git = Beast.Git(env)
|
||||
if git.exists:
|
||||
id = '%s+%s.%s' % (git.tags, git.user, git.branch)
|
||||
git_commit_tag = {'CPPDEFINES':
|
||||
{'GIT_COMMIT_ID' : '\'"%s"\'' % id }}
|
||||
|
||||
target = env.Program(
|
||||
target=os.path.join(variant_dir, 'rippled'),
|
||||
source=object_builder.objects
|
||||
object_builder.add_source_files(
|
||||
'src/ripple/unity/git_id.cpp',
|
||||
**git_commit_tag)
|
||||
|
||||
object_builder.add_source_files(
|
||||
'src/beast/beast/unity/hash_unity.cpp',
|
||||
'src/ripple/unity/beast.cpp',
|
||||
'src/ripple/unity/lz4.c',
|
||||
'src/ripple/unity/protobuf.cpp',
|
||||
'src/ripple/unity/ripple.proto.cpp',
|
||||
'src/ripple/unity/resource.cpp',
|
||||
'src/ripple/unity/rpcx.cpp',
|
||||
'src/ripple/unity/server.cpp',
|
||||
'src/ripple/unity/validators.cpp',
|
||||
'src/ripple/unity/websocket02.cpp'
|
||||
)
|
||||
|
||||
if toolchain == default_toolchain and variant == default_variant:
|
||||
default_target = target
|
||||
install_target = env.Install (build_dir, source=default_target)
|
||||
env.Alias ('install', install_target)
|
||||
env.Default (install_target)
|
||||
aliases['all'].extend(install_target)
|
||||
if toolchain == 'msvc':
|
||||
config = env.VSProjectConfig(variant, 'x64', target, env)
|
||||
msvc_configs.append(config)
|
||||
if toolchain in toolchains:
|
||||
aliases['all'].extend(target)
|
||||
aliases[variant].extend(target)
|
||||
aliases[toolchain].extend(target)
|
||||
env.Alias(variant_name, target)
|
||||
object_builder.add_source_files(
|
||||
'src/ripple/unity/beastc.c',
|
||||
CCFLAGS = ([] if toolchain == 'msvc' else ['-Wno-array-bounds']))
|
||||
|
||||
if 'gcc' in toolchain:
|
||||
no_uninitialized_warning = {'CCFLAGS': ['-Wno-maybe-uninitialized']}
|
||||
else:
|
||||
no_uninitialized_warning = {}
|
||||
|
||||
object_builder.add_source_files(
|
||||
'src/ripple/unity/ed25519.c',
|
||||
CPPPATH=[
|
||||
'src/ed25519-donna',
|
||||
]
|
||||
)
|
||||
|
||||
object_builder.add_source_files(
|
||||
'src/ripple/unity/rocksdb.cpp',
|
||||
CPPPATH=[
|
||||
'src/rocksdb2',
|
||||
'src/rocksdb2/include',
|
||||
'src/snappy/snappy',
|
||||
'src/snappy/config',
|
||||
],
|
||||
**no_uninitialized_warning
|
||||
)
|
||||
|
||||
object_builder.add_source_files(
|
||||
'src/ripple/unity/snappy.cpp',
|
||||
CCFLAGS=([] if toolchain == 'msvc' else ['-Wno-unused-function']),
|
||||
CPPPATH=[
|
||||
'src/snappy/snappy',
|
||||
'src/snappy/config',
|
||||
]
|
||||
)
|
||||
|
||||
object_builder.add_source_files(
|
||||
'src/ripple/unity/websocket04.cpp',
|
||||
CPPPATH='src/websocketpp',
|
||||
)
|
||||
|
||||
if toolchain == "clang" and Beast.system.osx:
|
||||
object_builder.add_source_files('src/ripple/unity/beastobjc.mm')
|
||||
|
||||
target = env.Program(
|
||||
target=os.path.join(variant_dir, 'rippled'),
|
||||
source=object_builder.objects
|
||||
)
|
||||
|
||||
if tu_style == default_tu_style:
|
||||
if toolchain == default_toolchain and (
|
||||
variant == default_variant):
|
||||
default_target = target
|
||||
install_target = env.Install (build_dir, source=default_target)
|
||||
env.Alias ('install', install_target)
|
||||
env.Default (install_target)
|
||||
aliases['all'].extend(install_target)
|
||||
if toolchain == 'msvc':
|
||||
config = env.VSProjectConfig(variant, 'x64', target, env)
|
||||
msvc_configs.append(config)
|
||||
if toolchain in toolchains:
|
||||
aliases['all'].extend(target)
|
||||
aliases[toolchain].extend(target)
|
||||
elif toolchain == 'msvc':
|
||||
config = env.VSProjectConfig(variant + ".classic", 'x64', target, env)
|
||||
msvc_configs.append(config)
|
||||
|
||||
if toolchain in toolchains:
|
||||
aliases[variant].extend(target)
|
||||
env.Alias(variant_name, target)
|
||||
|
||||
for key, value in aliases.iteritems():
|
||||
env.Alias(key, value)
|
||||
@@ -675,3 +875,33 @@ vcxproj = base.VSProject(
|
||||
VSPROJECT_ROOT_DIRS = ['src/beast', 'src', '.'],
|
||||
VSPROJECT_CONFIGS = msvc_configs)
|
||||
base.Alias('vcxproj', vcxproj)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
# Adds a phony target to the environment that always builds
|
||||
# See: http://www.scons.org/wiki/PhonyTargets
|
||||
def PhonyTargets(env = None, **kw):
|
||||
if not env: env = DefaultEnvironment()
|
||||
for target, action in kw.items():
|
||||
env.AlwaysBuild(env.Alias(target, [], action))
|
||||
|
||||
# Build the list of rippled source files that hold unit tests
|
||||
def do_count(target, source, env):
|
||||
def list_testfiles(base, suffixes):
|
||||
def _iter(base):
|
||||
for parent, _, files in os.walk(base):
|
||||
for path in files:
|
||||
path = os.path.join(parent, path)
|
||||
r = os.path.splitext(path)
|
||||
if r[1] in suffixes:
|
||||
if r[0].endswith('.test'):
|
||||
yield os.path.normpath(path)
|
||||
return list(_iter(base))
|
||||
testfiles = list_testfiles(os.path.join('src', 'ripple'), env.get('CPPSUFFIXES'))
|
||||
lines = 0
|
||||
for f in testfiles:
|
||||
lines = lines + sum(1 for line in open(f))
|
||||
print "Total unit test lines: %d" % lines
|
||||
|
||||
PhonyTargets(env, count = do_count)
|
||||
|
||||
|
||||
77
appveyor.yml
Normal file
@@ -0,0 +1,77 @@
|
||||
# Set environment variables.
|
||||
environment:
|
||||
PYTHON: C:/Python27-x64
|
||||
|
||||
# We bundle up protoc.exe and only the parts of boost and openssl we need so
|
||||
# that it's a small download. We also use appveyor's free cache, avoiding fees
|
||||
# downloading from S3 each time.
|
||||
# TODO: script to create this package.
|
||||
RIPPLED_DEPS_URL: https://s3-ap-northeast-1.amazonaws.com/history-replay/rippled_deps.zip
|
||||
|
||||
# Other dependencies we just download each time.
|
||||
PIP_URL: https://bootstrap.pypa.io/get-pip.py
|
||||
PYWIN32_URL: https://downloads.sourceforge.net/project/pywin32/pywin32/Build%20219/pywin32-219.win-amd64-py2.7.exe
|
||||
|
||||
# Scons honours these environment variables, setting the include/lib paths.
|
||||
BOOST_ROOT: C:/rippled_deps/boost
|
||||
OPENSSL_ROOT: C:/rippled_deps/openssl
|
||||
|
||||
# At the end of each successful build we cache this directory. It must be less
|
||||
# than 100MB total compressed.
|
||||
cache:
|
||||
- "C:\\rippled_deps"
|
||||
|
||||
# This means we'll download a zip of the branch we want, rather than the full
|
||||
# history.
|
||||
shallow_clone: true
|
||||
|
||||
install:
|
||||
# We want easy_install, python and protoc.exe on PATH.
|
||||
- SET PATH=%PYTHON%;%PYTHON%/Scripts;C:/rippled_deps;%PATH%
|
||||
|
||||
# `ps` prefix means the command is executed by powershell.
|
||||
- ps: Start-FileDownload $env:PIP_URL
|
||||
- ps: Start-FileDownload $env:PYWIN32_URL
|
||||
|
||||
# Installing pip will install setuptools/easy_install.
|
||||
- python get-pip.py
|
||||
|
||||
# Pip has some problems installing scons on windows so we use easy install.
|
||||
- easy_install scons
|
||||
|
||||
# Scons has problems with parallel builds on windows without pywin32.
|
||||
- easy_install pywin32-219.win-amd64-py2.7.exe
|
||||
# (easy_install can do headless installs of .exe wizards)
|
||||
|
||||
# Download dependencies if appveyor didn't restore them from the cache.
|
||||
# Use 7zip to unzip.
|
||||
- ps: |
|
||||
if (-not(Test-Path 'C:/rippled_deps')) {
|
||||
Start-FileDownload "$env:RIPPLED_DEPS_URL"
|
||||
7z x rippled_deps.zip -oC:\ -y > $null
|
||||
}
|
||||
|
||||
# TODO: This is giving me grief
|
||||
# artifacts:
|
||||
# # Save rippled.exe in the cloud after each build.
|
||||
# - path: "build\\rippled.exe"
|
||||
|
||||
build_script:
|
||||
# We set the environment variables needed to put compilers on the PATH.
|
||||
- '"%VS120COMNTOOLS%../../VC/vcvarsall.bat" x86_amd64'
|
||||
# Show which version of the compiler we are using.
|
||||
- cl
|
||||
- scons msvc.debug -j%NUMBER_OF_PROCESSORS%
|
||||
|
||||
after_build:
|
||||
# Put our executable in a place where npm test can find it.
|
||||
- ps: cp build/msvc.debug/rippled.exe build
|
||||
- ps: ls build
|
||||
|
||||
test_script:
|
||||
# Run the unit tests
|
||||
- build\\rippled --unittest
|
||||
|
||||
# Run the integration tests
|
||||
- npm install
|
||||
- npm test
|
||||
133
bin/stop-test.js
Normal file
@@ -0,0 +1,133 @@
|
||||
/* -------------------------------- REQUIRES -------------------------------- */
|
||||
|
||||
var child = require("child_process");
|
||||
var assert = require("assert");
|
||||
|
||||
/* --------------------------------- CONFIG --------------------------------- */
|
||||
|
||||
if (process.argv[2] == null) {
|
||||
[
|
||||
'Usage: ',
|
||||
'',
|
||||
' `node bin/stop-test.js i,j [rippled_path] [rippled_conf]`',
|
||||
'',
|
||||
' Launch rippled and stop it after n seconds for all n in [i, j}',
|
||||
' For all even values of n launch rippled with `--fg`',
|
||||
' For values of n where n % 3 == 0 launch rippled with `--fg`\n',
|
||||
'Examples: ',
|
||||
'',
|
||||
' $ node bin/stop-test.js 5,10',
|
||||
(' $ node bin/stop-test.js 1,4 ' +
|
||||
'build/clang.debug/rippled $HOME/.confs/rippled.cfg')
|
||||
]
|
||||
.forEach(function(l){console.log(l)});
|
||||
|
||||
process.exit();
|
||||
} else {
|
||||
var testRange = process.argv[2].split(',').map(Number);
|
||||
var rippledPath = process.argv[3] || 'build/rippled'
|
||||
var rippledConf = process.argv[4] || 'rippled.cfg'
|
||||
}
|
||||
|
||||
var options = {
|
||||
env: process.env,
|
||||
stdio: 'ignore' // we could dump the child io when it fails abnormally
|
||||
};
|
||||
|
||||
// default args
|
||||
var conf_args = ['--conf='+rippledConf];
|
||||
var start_args = conf_args.concat([/*'--net'*/])
|
||||
var stop_args = conf_args.concat(['stop']);
|
||||
|
||||
/* --------------------------------- HELPERS -------------------------------- */
|
||||
|
||||
function start(args) {
|
||||
return child.spawn(rippledPath, args, options);
|
||||
}
|
||||
function stop(rippled) { child.execFile(rippledPath, stop_args, options)}
|
||||
function secs_l8r(ms, f) {setTimeout(f, ms * 1000); }
|
||||
|
||||
function show_results_and_exit(results) {
|
||||
console.log(JSON.stringify(results, undefined, 2));
|
||||
process.exit();
|
||||
}
|
||||
|
||||
var timeTakes = function (range) {
|
||||
function sumRange(n) {return (n+1) * n /2}
|
||||
var ret = sumRange(range[1]);
|
||||
if (range[0] > 1) {
|
||||
ret = ret - sumRange(range[0] - 1)
|
||||
}
|
||||
var stopping = (range[1] - range[0]) * 0.5;
|
||||
return ret + stopping;
|
||||
}
|
||||
|
||||
/* ---------------------------------- TEST ---------------------------------- */
|
||||
|
||||
console.log("Test will take ~%s seconds", timeTakes(testRange));
|
||||
|
||||
(function oneTest(n /* seconds */, results) {
|
||||
if (n >= testRange[1]) {
|
||||
// show_results_and_exit(results);
|
||||
console.log(JSON.stringify(results, undefined, 2));
|
||||
oneTest(testRange[0], []);
|
||||
return;
|
||||
}
|
||||
|
||||
var args = start_args;
|
||||
if (n % 2 == 0) {args = args.concat(['--fg'])}
|
||||
if (n % 3 == 0) {args = args.concat(['--net'])}
|
||||
|
||||
var result = {args: args, alive_for: n};
|
||||
results.push(result);
|
||||
|
||||
console.log("\nLaunching `%s` with `%s` for %d seconds",
|
||||
rippledPath, JSON.stringify(args), n);
|
||||
|
||||
rippled = start(args);
|
||||
console.log("Rippled pid: %d", rippled.pid);
|
||||
|
||||
// defaults
|
||||
var b4StopSent = false;
|
||||
var stopSent = false;
|
||||
var stop_took = null;
|
||||
|
||||
rippled.once('exit', function(){
|
||||
if (!stopSent && !b4StopSent) {
|
||||
console.warn('\nRippled exited itself b4 stop issued');
|
||||
process.exit();
|
||||
};
|
||||
|
||||
// The io handles close AFTER exit, may have implications for
|
||||
// `stdio:'inherit'` option to `child.spawn`.
|
||||
rippled.once('close', function() {
|
||||
result.stop_took = (+new Date() - stop_took) / 1000; // seconds
|
||||
console.log("Stopping after %d seconds took %s seconds",
|
||||
n, result.stop_took);
|
||||
oneTest(n+1, results);
|
||||
});
|
||||
});
|
||||
|
||||
secs_l8r(n, function(){
|
||||
console.log("Stopping rippled after %d seconds", n);
|
||||
|
||||
// possible race here ?
|
||||
// seems highly unlikely, but I was having issues at one point
|
||||
b4StopSent=true;
|
||||
stop_took = (+new Date());
|
||||
// when does `exit` actually get sent?
|
||||
stop();
|
||||
stopSent=true;
|
||||
|
||||
// Sometimes we want to attach with a debugger.
|
||||
if (process.env.ABORT_TESTS_ON_STALL != null) {
|
||||
// We wait 30 seconds, and if it hasn't stopped, we abort the process
|
||||
secs_l8r(30, function() {
|
||||
if (result.stop_took == null) {
|
||||
console.log("rippled has stalled");
|
||||
process.exit();
|
||||
};
|
||||
});
|
||||
}
|
||||
})
|
||||
}(testRange[0], []));
|
||||
52
circle.yml
Normal file
@@ -0,0 +1,52 @@
|
||||
machine:
|
||||
services:
|
||||
- docker
|
||||
dependencies:
|
||||
pre:
|
||||
- sudo apt-add-repository -y 'deb http://llvm.org/apt/precise/ llvm-toolchain-precise-3.4 main'
|
||||
- sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test
|
||||
- sudo add-apt-repository -y ppa:afrank/boost
|
||||
- wget -q -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get purge -qq libboost1.48-dev
|
||||
- sudo apt-get install -qq libboost1.57-all-dev
|
||||
- sudo apt-get install -qq clang-3.4 gcc-4.8 libobjc-4.8-dev libgcc-4.8-dev libstdc++-4.8-dev libclang1-3.4 libgcc1 libgomp1 libstdc++6 scons protobuf-compiler libprotobuf-dev libssl-dev exuberant-ctags
|
||||
- sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 99 --slave /usr/bin/g++ g++ /usr/bin/g++-4.8
|
||||
- sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-3.4 99 --slave /usr/bin/clang++ clang++ /usr/bin/clang++-3.4
|
||||
- gcc --version
|
||||
- clang --version
|
||||
test:
|
||||
pre:
|
||||
- scons clang.debug
|
||||
override:
|
||||
- | # create gdb script
|
||||
echo "set env MALLOC_CHECK_=3" > script.gdb
|
||||
echo "run" >> script.gdb
|
||||
echo "backtrace full" >> script.gdb
|
||||
# gdb --help
|
||||
- cat script.gdb | gdb --ex 'set print thread-events off' --return-child-result --args build/clang.debug/rippled --unittest
|
||||
- npm install
|
||||
# Use build/(gcc|clang).debug/rippled
|
||||
- |
|
||||
echo "exports.default_server_config = {\"rippled_path\" : \"$HOME/rippled/build/clang.debug/rippled\"};" > test/config.js
|
||||
|
||||
# Run integration tests
|
||||
- npm test
|
||||
post:
|
||||
- mkdir -p build/docker/
|
||||
- cp doc/rippled-example.cfg build/clang.debug/rippled build/docker/
|
||||
- cp Builds/Docker/Dockerfile-testnet build/docker/Dockerfile
|
||||
- mv build/docker/rippled-example.cfg build/docker/rippled.cfg
|
||||
- strip build/docker/rippled
|
||||
- docker build -t ripple/rippled:$CIRCLE_SHA1 build/docker/
|
||||
- docker tag ripple/rippled:$CIRCLE_SHA1 ripple/rippled:latest
|
||||
- docker tag ripple/rippled:$CIRCLE_SHA1 ripple/rippled:$CIRCLE_BRANCH
|
||||
- docker images
|
||||
deployment:
|
||||
docker:
|
||||
branch: /.*/
|
||||
commands:
|
||||
- docker login -e $DOCKER_EMAIL -u $DOCKER_USERNAME -p $DOCKER_PASSWORD
|
||||
- docker push ripple/rippled:$CIRCLE_SHA1
|
||||
- docker push ripple/rippled:$CIRCLE_BRANCH
|
||||
- docker push ripple/rippled:latest
|
||||
@@ -1,19 +1,16 @@
|
||||
VFALCO NOTE - This file appears to be unmaintained.
|
||||
A list of rippled version numbers, and the Github pull requests they contain.
|
||||
|
||||
Critical protocol changes
|
||||
-------------------------
|
||||
|
||||
Mon Apr 8 16:13:12 PDT 2013
|
||||
* The JSON field "inLedger" changing to "ledger_index"
|
||||
|
||||
Previous
|
||||
* The JSON field "metaData" changing to "meta".
|
||||
* RPC ledger will no longer take "ledger", use "ledger_hash" or "ledger_index".
|
||||
* "ledgerClose" events:
|
||||
** "hash" DEPRECATED: use "ledger_hash"
|
||||
** "seqNum" DEPRECATED: use "ledger_index"
|
||||
** "closeTime" DEPRECATED: use "close" or "close_human"
|
||||
* stream "rt_accounts" --> "accounts_proposed"
|
||||
* stream "rt_transactions" --> "transactions_proposed"
|
||||
* subscribe "username" --> "url_username"
|
||||
* subscribe "password" --> "url_password"
|
||||
0.28.0-b12: Includes pulls 836, 887, 902, 903 and 904.
|
||||
0.28.0-b13: Includes pulls 906, 912, 913, 914 and 915.
|
||||
0.28.0-b14: Includes pulls 907, 910, 922 and 923.
|
||||
0.28.0-b15: Includes pulls 832, 870, 879, 883, 911, 916, 919, 920, 924, 925 and 928. FAILED pulls 909 and 926.
|
||||
0.28.0-b16: Includes pulls 909, 926, 929, 931, 932, 935 and 934.
|
||||
0.28.0-b17: Includes pulls 927, 939, 940, 943, 944, 945 and 949.
|
||||
0.28.0-b18: Includes pulls 930, 946, 947, 948, 951, 952, 953, 954, 955, 956, 959, 960 and 962.
|
||||
0.29.0-b19: Includes pulls 967, 969 and 971.
|
||||
0.29.0-b20: Includes pulls 935, 942, 957, 958, 963, 964, 965, 966, 968, 972, 973, 974 and 975.
|
||||
0.29.0-b21: Includes pulls 970 and 976.
|
||||
0.28.1-b4: Includes pulls 968, 998, 1005, 1008, 1010, 1011 and 1012.
|
||||
0.28.1-b6: Includes pulls 983, 984, 1013, 1023 and 1024.
|
||||
0.28.1-b8: Includes pulls 988, 1009, 1014, 1019, 1029, 1031, 1033, 1034 and 1035.
|
||||
0.28.1-b9: Includes pulls 1026, 1030, 1036, 1037, 1038, 1040, and 1041.
|
||||
|
||||
16
doc/Docker.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Rippled Docker Image
|
||||
|
||||
Rippled has a continuous deployment pipeline that turns every git commit into a
|
||||
docker image for quick testing and deployment.
|
||||
|
||||
To run the tip of the latest release via docker:
|
||||
|
||||
```$ docker run -P -v /srv/rippled/ ripple/rippled:latest```
|
||||
|
||||
To run the tip of active development:
|
||||
|
||||
```$ docker run -P -v /srv/rippled/ ripple/rippled:develop```
|
||||
|
||||
Where ```/srv/rippled``` points to a directory containing a rippled.cfg and
|
||||
database files. By default, port 5005/tcp maps to the RPC port and 51235/udp to
|
||||
the peer port.
|
||||
@@ -6,23 +6,21 @@
|
||||
#
|
||||
# Contents
|
||||
#
|
||||
# 1. Peer Networking
|
||||
# 1. Server
|
||||
#
|
||||
# 2. Websocket Networking
|
||||
# 2. Peer Protocol
|
||||
#
|
||||
# 3. RPC Networking
|
||||
# 3. Ripple Protocol
|
||||
#
|
||||
# 4. SMS Gateway
|
||||
# 4. HTTPS Client
|
||||
#
|
||||
# 5. Ripple Protcol
|
||||
# 5. Database
|
||||
#
|
||||
# 6. HTTPS Client
|
||||
# 6. Diagnostics
|
||||
#
|
||||
# 7. Database
|
||||
# 7. Voting
|
||||
#
|
||||
# 8. Diagnostics
|
||||
#
|
||||
# 9. Voting
|
||||
# 8. Example Settings
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
@@ -44,19 +42,234 @@
|
||||
# or Mac style end of lines. Blank lines and lines beginning with '#' are
|
||||
# ignored. Undefined sections are reserved. No escapes are currently defined.
|
||||
#
|
||||
# Notation
|
||||
#
|
||||
# In this document a simple BNF notation is used. Angle brackets denote
|
||||
# required elements, square brackets denote optional elements, and single
|
||||
# quotes indicate string literals. A vertical bar separating 1 or more
|
||||
# elements is a logical "or"; Any one of the elements may be chosen.
|
||||
# Parenthesis are notational only, and used to group elements, they are not
|
||||
# part of the syntax unless they appear in quotes. White space may always
|
||||
# appear between elements, it has no effect on values.
|
||||
#
|
||||
# <key> A required identifier
|
||||
# '=' The equals sign character
|
||||
# | Logical "or"
|
||||
# ( ) Used for grouping
|
||||
#
|
||||
#
|
||||
# An identifier is a string of upper or lower case letters, digits, or
|
||||
# underscores subject to the requirement that the first character of an
|
||||
# identifier must be a letter. Identifiers are not case sensitive (but
|
||||
# values may be).
|
||||
#
|
||||
# Some configuration sections contain key/value pairs. A line containing
|
||||
# a key/value pair has this syntax:
|
||||
#
|
||||
# <identifier> '=' <value>
|
||||
#
|
||||
# Depending on the section and key, different value types are possible:
|
||||
#
|
||||
# <integer> A signed integer
|
||||
# <unsigned> An unsigned integer
|
||||
# <flag> A boolean. 1 = true/yes/on, 0 = false/no/off.
|
||||
#
|
||||
# Consult the documentation on the key in question to determine the possible
|
||||
# value types.
|
||||
#
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# 1. Peer Networking
|
||||
# 1. Server
|
||||
#
|
||||
#-------------------
|
||||
#----------
|
||||
#
|
||||
#
|
||||
#
|
||||
# rippled offers various server protocols to clients making inbound
|
||||
# connections. The listening ports rippled uses are "universal" ports
|
||||
# which may be configured to handshake in one or more of the available
|
||||
# supported protocols. These universal ports simplify administration:
|
||||
# A single open port can be used for multiple protocols.
|
||||
#
|
||||
# NOTE At least one server port must be defined in order
|
||||
# to accept incoming network connections.
|
||||
#
|
||||
#
|
||||
# [server]
|
||||
#
|
||||
# A list of port names and key/value pairs. A port name must start with a
|
||||
# letter and contain only letters and numbers. The name is not case-sensitive.
|
||||
# For each name in this list, rippled will look for a configuration file
|
||||
# section with the same name and use it to create a listening port. The
|
||||
# name is informational only; the choice of name does not affect the function
|
||||
# of the listening port.
|
||||
#
|
||||
# Key/value pairs specified in this section are optional, and apply to all
|
||||
# listening ports unless the port overrides the value in its section. They
|
||||
# may be considered default values.
|
||||
#
|
||||
# Suggestion:
|
||||
#
|
||||
# To avoid a conflict with port names and future configuration sections,
|
||||
# we recommend prepending "port_" to the port name. This prefix is not
|
||||
# required, but suggested.
|
||||
#
|
||||
# This example defines two ports with different port numbers and settings:
|
||||
#
|
||||
# [server]
|
||||
# port_public
|
||||
# port_private
|
||||
# port = 80
|
||||
#
|
||||
# [port_public]
|
||||
# ip=0.0.0.0
|
||||
# port = 443
|
||||
# protocol=peer,https
|
||||
#
|
||||
# [port_private]
|
||||
# ip=127.0.0.1
|
||||
# protocol=http
|
||||
#
|
||||
# When rippled is used as a command line client (for example, issuing a
|
||||
# server stop command), the first port advertising the http or https
|
||||
# protocol will be used to make the connection.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [<name>]
|
||||
#
|
||||
# A series of key/value pairs that define the settings for the port with
|
||||
# the corresponding name. These keys are possible:
|
||||
#
|
||||
# ip = <IP-address>
|
||||
#
|
||||
# Required. Determines the IP address of the network interface to bind
|
||||
# to. To bind to all available interfaces, uses 0.0.0.0
|
||||
#
|
||||
# port = <number>
|
||||
#
|
||||
# Required. Sets the port number to use for this port.
|
||||
#
|
||||
# protocol = [ http, https, peer ]
|
||||
#
|
||||
# Required. A comma-separated list of protocols to support:
|
||||
#
|
||||
# http JSON-RPC over HTTP
|
||||
# https JSON-RPC over HTTPS
|
||||
# ws Websockets
|
||||
# wss Secure Websockets
|
||||
# peer Peer Protocol
|
||||
#
|
||||
# Restrictions:
|
||||
#
|
||||
# Only one port may be configured to support the peer protocol.
|
||||
# A port cannot have websocket and non websocket protocols at the
|
||||
# same time. It is possible have both Websockets and Secure Websockets
|
||||
# together in one port.
|
||||
#
|
||||
# NOTE If no ports support the peer protocol, rippled cannot
|
||||
# receive incoming peer connections or become a superpeer.
|
||||
#
|
||||
# user = <text>
|
||||
# password = <text>
|
||||
#
|
||||
# When set, these credentials will be required on HTTP/S requests.
|
||||
# The credentials must be provided using HTTP's Basic Authentication
|
||||
# headers. If either or both fields are empty, then no credentials are
|
||||
# required. IP address restrictions, if any, will be checked in addition
|
||||
# to the credentials specified here.
|
||||
#
|
||||
# When acting in the client role, rippled will supply these credentials
|
||||
# using HTTP's Basic Authentication headers when making outbound HTTP/S
|
||||
# requests.
|
||||
#
|
||||
# admin = [ IP, IP, IP, ... ]
|
||||
#
|
||||
# A comma-separated list of IP addresses.
|
||||
#
|
||||
# When set, grants administrative command access to the specified IP
|
||||
# addresses. These commands may be issued over http, https, ws, or wss
|
||||
# if configured on the port. If unspecified, the default is to not allow
|
||||
# administrative commands.
|
||||
#
|
||||
# *SECURITY WARNING*
|
||||
# 0.0.0.0 may be specified to allow access from any IP address. It must
|
||||
# be the only address specified and cannot be combined with other IPs.
|
||||
# Use of this address can compromise server security, please consider its
|
||||
# use carefully.
|
||||
#
|
||||
# admin_user = <text>
|
||||
# admin_password = <text>
|
||||
#
|
||||
# When set, clients must provide these credentials in the submitted
|
||||
# JSON for any administrative command requests submitted to the HTTP/S,
|
||||
# WS, or WSS protocol interfaces. If administrative commands are
|
||||
# disabled for a port, these credentials have no effect.
|
||||
#
|
||||
# When acting in the client role, rippled will supply these credentials
|
||||
# in the submitted JSON for any administrative command requests when
|
||||
# invoking JSON-RPC commands on remote servers.
|
||||
#
|
||||
# ssl_key = <filename>
|
||||
# ssl_cert = <filename>
|
||||
# ssl_chain = <filename>
|
||||
#
|
||||
# Use the specified files when configuring SSL on the port.
|
||||
#
|
||||
# NOTE If no files are specified and secure protocols are selected,
|
||||
# rippled will generate an internal self-signed certificate.
|
||||
#
|
||||
# The files have these meanings:
|
||||
#
|
||||
# ssl_key
|
||||
#
|
||||
# Specifies the filename holding the SSL key in PEM format.
|
||||
#
|
||||
# ssl_cert
|
||||
#
|
||||
# Specifies the path to the SSL certificate file in PEM format.
|
||||
# This is not needed if the chain includes it.
|
||||
#
|
||||
# ssl_chain
|
||||
#
|
||||
# If you need a certificate chain, specify the path to the
|
||||
# certificate chain here. The chain may include the end certificate.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_startup]
|
||||
#
|
||||
# Specify a list of RPC commands to run at startup.
|
||||
#
|
||||
# Examples:
|
||||
# { "command" : "server_info" }
|
||||
# { "command" : "log_level", "partition" : "ripplecalc", "severity" : "trace" }
|
||||
#
|
||||
#
|
||||
#
|
||||
# [websocket_ping_frequency]
|
||||
#
|
||||
# <number>
|
||||
#
|
||||
# The amount of time to wait in seconds, before sending a websocket 'ping'
|
||||
# message. Ping messages are used to determine if the remote end of the
|
||||
# connection is no longer available.
|
||||
#
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# 2. Peer Protocol
|
||||
#
|
||||
#-----------------
|
||||
#
|
||||
# These settings control security and access attributes of the Peer to Peer
|
||||
# server section of the rippled process. Peer Networking implements the
|
||||
# server section of the rippled process. Peer Protocol implements the
|
||||
# Ripple Payment protocol. It is over peer connections that transactions
|
||||
# and validations are passed from to machine to machine, to make up the
|
||||
# components of closed ledgers.
|
||||
# and validations are passed from to machine to machine, to determine the
|
||||
# contents of validated ledgers.
|
||||
#
|
||||
#
|
||||
#
|
||||
@@ -95,40 +308,6 @@
|
||||
#
|
||||
#
|
||||
#
|
||||
# [peer_ip]
|
||||
#
|
||||
# IP address or domain to bind to allow external connections from peers.
|
||||
# Defaults to not binding, which disallows external connections from peers.
|
||||
#
|
||||
# Examples: 0.0.0.0 - Bind on all interfaces.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [peer_port]
|
||||
#
|
||||
# If peer_ip is supplied, corresponding port to bind to for peer connections.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [peer_port_proxy]
|
||||
#
|
||||
# An optional, additional listening port number for peers. Incoming
|
||||
# connections on this port will be required to provide a PROXY Protocol
|
||||
# handshake, described in this document (external link):
|
||||
#
|
||||
# http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt
|
||||
#
|
||||
# The PROXY Protocol is a popular method used by elastic load balancing
|
||||
# service providers such as Amazon, to identify the true IP address and
|
||||
# port number of external incoming connections.
|
||||
#
|
||||
# In addition to enabling this setting, it will also be required to
|
||||
# use your provider-specific control panel or administrative web page
|
||||
# to configure your server instance to receive PROXY Protocol handshakes,
|
||||
# and also to restrict access to your instance to the Elastic Load Balancer.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [peer_private]
|
||||
#
|
||||
# 0 or 1.
|
||||
@@ -147,19 +326,6 @@
|
||||
#
|
||||
#
|
||||
#
|
||||
# [peer_ssl_cipher_list]
|
||||
#
|
||||
# A colon delimited string with the allowed SSL cipher modes for peer. The
|
||||
# choices for for ciphers are defined by the OpenSSL API function
|
||||
# SSL_CTX_set_cipher_list, documented here (external link):
|
||||
#
|
||||
# http://pic.dhe.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=%2Fcom.ibm.ztpf-ztpfdf.doc_put.cur%2Fgtpc2%2Fcpp_ssl_ctx_set_cipher_list.html
|
||||
#
|
||||
# The default setting is "ALL:!LOW:!EXP:!MD5:@STRENGTH", which allows
|
||||
# non-authenticated peer connections (they are, however, secure).
|
||||
#
|
||||
#
|
||||
#
|
||||
# [node_seed]
|
||||
#
|
||||
# This is used for clustering. To force a particular node seed or key, the
|
||||
@@ -193,283 +359,45 @@
|
||||
#
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
# [overlay] EXPERIMENTAL
|
||||
#
|
||||
# 2. Websocket Networking
|
||||
# This section is EXPERIMENTAL, and should not be
|
||||
# present for production configuration settings.
|
||||
#
|
||||
#------------------------
|
||||
# A set of key/value pair parameters to configure the overlay.
|
||||
#
|
||||
# These settings control security and access attributes of the Websocket
|
||||
# server section of the rippled process, primarily used to service
|
||||
# client requests and backend applications.
|
||||
# auto_connect = 0 | 1
|
||||
#
|
||||
# When set, activates the autoconnect feature. This maintains outgoing
|
||||
# connections using PeerFinder's "Outgoing Connection Strategy."
|
||||
#
|
||||
# become_superpeer = 'never' | 'always' | 'auto'
|
||||
#
|
||||
# [websocket_public_ip]
|
||||
# Controls the selection of peer roles:
|
||||
#
|
||||
# IP address or domain to bind to allow untrusted connections from clients.
|
||||
# In the future, this option will go away and the peer_ip will accept
|
||||
# websocket client connections.
|
||||
# 'never' Always handshake in the leaf role.
|
||||
# 'always' Always handshake in the superpeer role.
|
||||
# 'auto' Start as a leaf, promote to superpeer after
|
||||
# passing capability check (default).
|
||||
#
|
||||
# Examples: 0.0.0.0 - Bind on all interfaces.
|
||||
# 127.0.0.1 - Bind on localhost interface. Only local programs may connect.
|
||||
# In the leaf role, a peer does not advertise its IP and port for
|
||||
# the purpose of receiving incoming connections. The peer also does
|
||||
# not forward transactions and validations received from other peers.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [websocket_public_port]
|
||||
#
|
||||
# Port to bind to allow untrusted connections from clients. In the future,
|
||||
# this option will go away and the peer_ip will accept websocket client
|
||||
# connections.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [websocket_public_secure]
|
||||
#
|
||||
# 0, 1 or 2.
|
||||
# 0: Provide ws service for websocket_public_ip/websocket_public_port.
|
||||
# 1: Provide both ws and wss service for websocket_public_ip/websocket_public_port. [default]
|
||||
# 2: Provide wss service only for websocket_public_ip/websocket_public_port.
|
||||
#
|
||||
# Browser pages like the Ripple client will not be able to connect to a secure
|
||||
# websocket connection if a self-signed certificate is used. As the Ripple
|
||||
# reference client currently shares secrets with its server, this should be
|
||||
# enabled.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [websocket_ping_frequency]
|
||||
#
|
||||
# <number>
|
||||
#
|
||||
# The amount of time to wait in seconds, before sending a websocket 'ping'
|
||||
# message. Ping messages are used to determine if the remote end of the
|
||||
# connection is no longer available.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [websocket_ip]
|
||||
#
|
||||
# IP address or domain to bind to allow trusted ADMIN connections from backend
|
||||
# applications.
|
||||
#
|
||||
# Examples: 0.0.0.0 - Bind on all interfaces.
|
||||
# 127.0.0.1 - Bind on localhost interface. Only local programs may connect.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [websocket_port]
|
||||
#
|
||||
# Port to bind to allow trusted ADMIN connections from backend applications.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [websocket_secure]
|
||||
#
|
||||
# 0, 1, or 2.
|
||||
# 0: Provide ws service only for websocket_ip/websocket_port. [default]
|
||||
# 1: Provide ws and wss service for websocket_ip/websocket_port
|
||||
# 2: Provide wss service for websocket_ip/websocket_port.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [websocket_ssl_cert]
|
||||
#
|
||||
# Specify the path to the SSL certificate file in PEM format.
|
||||
# This is not needed if the chain includes it.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [websocket_ssl_chain]
|
||||
#
|
||||
# If you need a certificate chain, specify the path to the certificate chain
|
||||
# here. The chain may include the end certificate.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [websocket_ssl_key]
|
||||
#
|
||||
# Specify the filename holding the SSL key in PEM format.
|
||||
# In the superpeer role, a peer advertises its IP and port for
|
||||
# receiving incoming connections after passing an incoming connection
|
||||
# test. Superpeers forward transactions and protocol messages to all
|
||||
# other peers. Superpeers do not forward validations to other superpeers.
|
||||
# Instead, a validation received by a superpeer from a leaf is forwarded
|
||||
# only to other leaf connections.
|
||||
#
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# 3. RPC Networking
|
||||
# 3. Ripple Protocol
|
||||
#
|
||||
#------------------
|
||||
#
|
||||
# This group of settings configures security and access attributes of the
|
||||
# RPC server section of the rippled process, used to service both local
|
||||
# and optional remote clients.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_allow_remote]
|
||||
#
|
||||
# 0 or 1.
|
||||
#
|
||||
# 0: Allow RPC connections only from 127.0.0.1. [default]
|
||||
# 1: Allow RPC connections from any IP.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_admin_allow]
|
||||
#
|
||||
# Specify a list of IP addresses allowed to have admin access. One per line.
|
||||
# If you want to test the output of non-admin commands add this section and
|
||||
# just put an ip address not under your control.
|
||||
# Defaults to 127.0.0.1.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_admin_user]
|
||||
#
|
||||
# As a server, require this as the admin user to be specified. Also, require
|
||||
# rpc_admin_user and rpc_admin_password to be checked for RPC admin functions.
|
||||
# The request must specify these as the admin_user and admin_password in the
|
||||
# request object.
|
||||
#
|
||||
# As a client, supply this to the server in the request object.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_admin_password]
|
||||
#
|
||||
# As a server, require this as the admin password to be specified. Also,
|
||||
# require rpc_admin_user and rpc_admin_password to be checked for RPC admin
|
||||
# functions. The request must specify these as the admin_user and
|
||||
# admin_password in the request object.
|
||||
#
|
||||
# As a client, supply this to the server in the request object.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_ip]
|
||||
#
|
||||
# IP address or domain to bind to allow insecure RPC connections.
|
||||
# Defaults to not binding, which disallows RPC connections.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_port]
|
||||
#
|
||||
# If rpc_ip is supplied, corresponding port to bind to for peer connections.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_user]
|
||||
#
|
||||
# As a server, require this user to be specified and require rpc_password to
|
||||
# be checked for RPC access via the rpc_ip and rpc_port. The user and password
|
||||
# must be specified via HTTP's basic authentication method.
|
||||
# As a client, supply this to the server via HTTP's basic authentication
|
||||
# method.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_password]
|
||||
#
|
||||
# As a server, require this password to be specified and require rpc_user to
|
||||
# be checked for RPC access via the rpc_ip and rpc_port. The user and password
|
||||
# must be specified via HTTP's basic authentication method.
|
||||
# As a client, supply this to the server via HTTP's basic authentication
|
||||
# method.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_startup]
|
||||
#
|
||||
# Specify a list of RPC commands to run at startup.
|
||||
#
|
||||
# Examples:
|
||||
# { "command" : "server_info" }
|
||||
# { "command" : "log_level", "partition" : "ripplecalc", "severity" : "trace" }
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_secure]
|
||||
#
|
||||
# 0 or 1.
|
||||
#
|
||||
# 0: Server certificates are not provided for RPC clients using SSL [default]
|
||||
# 1: Client RPC connections wil be provided with SSL certificates.
|
||||
#
|
||||
# Note that if rpc_secure is enabled, it will also be necessary to configure
|
||||
# the certificate file settings located in rpc_ssl_cert, rpc_ssl_chain, and
|
||||
# rpc_ssl_key
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_ssl_cert]
|
||||
#
|
||||
# <pathname>
|
||||
#
|
||||
# A file system path leading to the SSL certificate file to use for secure
|
||||
# RPC. The file is in PEM format. The file is not needed if the chain
|
||||
# includes it.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_ssl_chain]
|
||||
#
|
||||
# <pathname>
|
||||
#
|
||||
# A file system path leading to the file with the certificate chain.
|
||||
# The chain may include the end certificate.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_ssl_key]
|
||||
#
|
||||
# <pathname>
|
||||
#
|
||||
# A file system path leading to the file with the SSL key.
|
||||
# The file is in PEM format.
|
||||
#
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# 4. SMS Gateway
|
||||
#
|
||||
#---------------
|
||||
#
|
||||
# If you have a certain SMS messaging provider you can configure these
|
||||
# settings to allow the rippled server instance to send an SMS text to the
|
||||
# configured gateway in response to an admin-level RPC command "sms" with
|
||||
# one parameter, 'text' containing the message to send. This allows backend
|
||||
# applications to use the rippled instance to securely notify administrators
|
||||
# of custom events or information via SMS gateway.
|
||||
#
|
||||
# When the 'sms' RPC command is issued, the configured SMS gateway will be
|
||||
# contacted via HTTPS GET at the URL indicated by sms_url. The URI formed
|
||||
# will be in this format:
|
||||
#
|
||||
# [sms_url]?from=[sms_from]&to=[sms_to]&api_key=[sms_key]&api_secret=[sms_secret]&text=['text']
|
||||
#
|
||||
# Where [...] are the corresponding values from the configuration file, and
|
||||
# ['test'] is the value of the JSON field with name 'text'.
|
||||
#
|
||||
# [sms_url]
|
||||
#
|
||||
# The URL to contact via HTTPS when sending SMS messages
|
||||
#
|
||||
# [sms_from]
|
||||
# [sms_to]
|
||||
# [sms_key]
|
||||
# [sms_secret]
|
||||
#
|
||||
# These are all strings passed directly in the URI as query parameters
|
||||
# to the provider of the SMS gateway.
|
||||
#
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# 5. Ripple Protocol
|
||||
#
|
||||
#------------------
|
||||
#-------------------
|
||||
#
|
||||
# These settings affect the behavior of the server instance with respect
|
||||
# to Ripple payment protocol level activities such as validating and
|
||||
@@ -504,6 +432,8 @@
|
||||
# need to serve clients can set this to "none". Servers that want complete
|
||||
# history can set this to "full".
|
||||
#
|
||||
# This must be less than or equal to online_delete (if online_delete is used)
|
||||
#
|
||||
# The default is: 256
|
||||
#
|
||||
#
|
||||
@@ -598,7 +528,7 @@
|
||||
# [path_search_old]
|
||||
#
|
||||
# For clients that use the legacy path finding interfaces, the search
|
||||
# agressivness to use. The default is 7.
|
||||
# aggressiveness to use. The default is 7.
|
||||
#
|
||||
#
|
||||
#
|
||||
@@ -611,21 +541,23 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# 6. HTTPS Client
|
||||
# 4. HTTPS Client
|
||||
#
|
||||
#----------------
|
||||
#
|
||||
# The rippled server instance uses HTTPS GET requests in a variety of
|
||||
# circumstances, including but not limited to the SMS Messaging Gateway
|
||||
# feature and also for contacting trusted domains to fetch information
|
||||
# such as mapping an email address to a Ripple Payment Network address.
|
||||
# circumstances, including but not limited to contacting trusted domains to
|
||||
# fetch information such as mapping an email address to a Ripple Payment
|
||||
# Network address.
|
||||
#
|
||||
# [ssl_verify]
|
||||
#
|
||||
# 0 or 1.
|
||||
#
|
||||
# 0. HTTPS client connections will not verify certificates.
|
||||
# 1. Certificates will be checked for HTTPS client connections .
|
||||
# 1. Certificates will be checked for HTTPS client connections.
|
||||
#
|
||||
# If not specified, this parameter defaults to 1.
|
||||
#
|
||||
#
|
||||
#
|
||||
@@ -651,7 +583,7 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# 7. Database
|
||||
# 5. Database
|
||||
#
|
||||
#------------
|
||||
#
|
||||
@@ -684,22 +616,27 @@
|
||||
# ...
|
||||
#
|
||||
# Examples:
|
||||
# type=HyperLevelDB
|
||||
# path=db/hyperldb
|
||||
# compression=0
|
||||
# type=rocksdb
|
||||
# path=db/rocksdb
|
||||
#
|
||||
# Choices for 'type' (not case-sensitive)
|
||||
# RocksDB Use Facebook's RocksDB database (preferred)
|
||||
# HyperLevelDB Use an improved version of LevelDB
|
||||
# SQLite Use SQLite
|
||||
# LevelDB Use Google's LevelDB database (deprecated)
|
||||
# none Use no backend
|
||||
# NuDB Use Ripple Labs' NuDB (Windows preferred)
|
||||
# SQLite (Deprecated)
|
||||
# none (No backend)
|
||||
#
|
||||
# Required keys:
|
||||
# path Location to store the database (all types)
|
||||
#
|
||||
# Optional keys:
|
||||
# compression 0 for none, 1 for Snappy compression
|
||||
# online_delete Minimum value of 256. Enable automatic purging
|
||||
# of older ledger information. Maintain at least this
|
||||
# number of ledger records online. Must be greater
|
||||
# than or equal to ledger_history.
|
||||
# advisory_delete 0 for disabled, 1 for enabled. If set, then
|
||||
# require administrative RPC call "can_delete"
|
||||
# to enable online deletion of ledger records.
|
||||
#
|
||||
# Notes:
|
||||
# The 'node_db' entry configures the primary, persistent storage.
|
||||
@@ -718,13 +655,14 @@
|
||||
# There are 4 book-keeping SQLite database that the server creates and
|
||||
# maintains. If you omit this configuration setting, it will default to
|
||||
# creating a directory called "db" located in the same place as your
|
||||
# rippled.cfg file.
|
||||
# rippled.cfg file. Partial pathnames will be considered relative to
|
||||
# the location of the rippled executable.
|
||||
#
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# 8. Diagnostics
|
||||
# 6. Diagnostics
|
||||
#
|
||||
#---------------
|
||||
#
|
||||
@@ -745,10 +683,10 @@
|
||||
#
|
||||
# [insight]
|
||||
#
|
||||
# Configuration parameters for the Beast.Insight stats collection module.
|
||||
# Configuration parameters for the Beast. Insight stats collection module.
|
||||
#
|
||||
# Insight is a module that collects information from the areas of rippled
|
||||
# that have instrumentation. The configuration paramters control where the
|
||||
# that have instrumentation. The configuration parameters control where the
|
||||
# collection metrics are sent. The parameters are expressed as key = value
|
||||
# pairs with no white space. The main parameter is the choice of server:
|
||||
#
|
||||
@@ -780,7 +718,7 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# 9. Voting
|
||||
# 7. Voting
|
||||
#
|
||||
#----------
|
||||
#
|
||||
@@ -807,7 +745,7 @@
|
||||
#
|
||||
# account_reserve = <drops>
|
||||
#
|
||||
# The account reserve requirement specified in drops. The portion of an
|
||||
# The account reserve requirement is specified in drops. The portion of an
|
||||
# account's XRP balance that is at or below the reserve may only be
|
||||
# spent on transaction fees, and not transferred out of the account.
|
||||
#
|
||||
@@ -830,41 +768,84 @@
|
||||
# owner_reserve = 5000000 # 5 XRP
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
# Allow other peers to connect to this server.
|
||||
#
|
||||
[peer_ip]
|
||||
0.0.0.0
|
||||
|
||||
[peer_port]
|
||||
51235
|
||||
|
||||
# Allow untrusted clients to connect to this server.
|
||||
# 8. Example Settings
|
||||
#
|
||||
[websocket_public_ip]
|
||||
0.0.0.0
|
||||
|
||||
[websocket_public_port]
|
||||
5006
|
||||
|
||||
# Provide trusted websocket ADMIN access to the localhost.
|
||||
#--------------------
|
||||
#
|
||||
[websocket_ip]
|
||||
127.0.0.1
|
||||
|
||||
[websocket_port]
|
||||
6006
|
||||
|
||||
# Provide trusted json-rpc ADMIN access to the localhost.
|
||||
# Administrators can use these values as a starting point for configuring
|
||||
# their instance of rippled, but each value should be checked to make sure
|
||||
# it meets the business requirements for the organization.
|
||||
#
|
||||
[rpc_ip]
|
||||
127.0.0.1
|
||||
# Server
|
||||
#
|
||||
# These example configuration settings create these ports:
|
||||
#
|
||||
# "peer"
|
||||
#
|
||||
# Peer protocol open to everyone. This is required to accept
|
||||
# incoming rippled connections. This does not affect automatic
|
||||
# or manual outgoing Peer protocol connections.
|
||||
#
|
||||
# "rpc"
|
||||
#
|
||||
# Administrative RPC commands over HTTPS, when originating from
|
||||
# the same machine (via the loopback adapter at 127.0.0.1).
|
||||
#
|
||||
# "wss_admin"
|
||||
#
|
||||
# Admin level API commands over Secure Websockets, when originating
|
||||
# from the same machine (via the loopback adapter at 127.0.0.1).
|
||||
#
|
||||
# This port is commented out but can be enabled by removing
|
||||
# the '#' from each corresponding line including the entry under [server]
|
||||
#
|
||||
# "wss_public"
|
||||
#
|
||||
# Guest level API commands over Secure Websockets, open to everyone.
|
||||
#
|
||||
# For HTTPS and Secure Websockets ports, if no certificate and key file
|
||||
# are specified then a self-signed certificate will be generated on startup.
|
||||
# If you have a certificate and key file, uncomment the corresponding lines
|
||||
# and ensure the paths to the files are correct.
|
||||
#
|
||||
# NOTE
|
||||
#
|
||||
# To accept connections on well known ports such as 80 (HTTP) or
|
||||
# 443 (HTTPS), most operating systems will require rippled to
|
||||
# run with administrator privileges, or else rippled will not start.
|
||||
|
||||
[rpc_port]
|
||||
5005
|
||||
[server]
|
||||
port_rpc
|
||||
port_peer
|
||||
port_wss_admin
|
||||
#port_ws_public
|
||||
#ssl_key = /etc/ssl/private/server.key
|
||||
#ssl_cert = /etc/ssl/certs/server.crt
|
||||
|
||||
[rpc_allow_remote]
|
||||
0
|
||||
[port_rpc]
|
||||
port = 5005
|
||||
ip = 127.0.0.1
|
||||
admin = 127.0.0.1
|
||||
protocol = https
|
||||
|
||||
[port_peer]
|
||||
port = 51235
|
||||
ip = 0.0.0.0
|
||||
protocol = peer
|
||||
|
||||
[port_wss_admin]
|
||||
port = 6006
|
||||
ip = 127.0.0.1
|
||||
admin = 127.0.0.1
|
||||
protocol = wss
|
||||
|
||||
#[port_ws_public]
|
||||
#port = 5005
|
||||
#ip = 127.0.0.1
|
||||
#protocol = wss
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
[node_size]
|
||||
medium
|
||||
@@ -872,6 +853,8 @@ medium
|
||||
# This is primary persistent datastore for rippled. This includes transaction
|
||||
# metadata, account states, and ledger headers. Helpful information can be
|
||||
# found here: https://ripple.com/wiki/NodeBackEnd
|
||||
# delete old ledgers while maintaining at least 2000. Do not require an
|
||||
# external administrative command to initiate deletion.
|
||||
[node_db]
|
||||
type=RocksDB
|
||||
path=/var/lib/rippled/db/rocksdb
|
||||
@@ -880,6 +863,8 @@ filter_bits=12
|
||||
cache_mb=256
|
||||
file_size_mb=8
|
||||
file_size_mult=2
|
||||
online_delete=2000
|
||||
advisory_delete=0
|
||||
|
||||
[database_path]
|
||||
/var/lib/rippled/db
|
||||
@@ -919,22 +904,7 @@ n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA RL5
|
||||
[rpc_startup]
|
||||
{ "command": "log_level", "severity": "warning" }
|
||||
|
||||
# Configure SSL for WebSockets. Not enabled by default because not everybody
|
||||
# has an SSL cert on their server, but if you uncomment the following lines and
|
||||
# set the path to the SSL certificate and private key the WebSockets protocol
|
||||
# will be protected by SSL/TLS.
|
||||
#[websocket_secure]
|
||||
#1
|
||||
|
||||
#[websocket_ssl_cert]
|
||||
#/etc/ssl/certs/server.crt
|
||||
|
||||
#[websocket_ssl_key]
|
||||
#/etc/ssl/private/server.key
|
||||
|
||||
# Defaults to 0 ("no") so that you can use self-signed SSL certificates for
|
||||
# development, or internally.
|
||||
# Defaults to 1 ("yes") so that certificates will be validated. To allow the use
|
||||
# of self-signed certificates for development or internal use, set to 0 ("no").
|
||||
#[ssl_verify]
|
||||
#0
|
||||
|
||||
|
||||
|
||||
BIN
images/build.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
images/contribute.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
images/network.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
images/pathfinding.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
images/ripple.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
images/transact.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
images/vehicle_currency.png
Normal file
|
After Width: | Height: | Size: 71 KiB |
19
package.json
@@ -2,33 +2,30 @@
|
||||
"name": "rippled",
|
||||
"version": "0.0.1",
|
||||
"description": "Rippled Server",
|
||||
|
||||
"private": true,
|
||||
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
|
||||
"dependencies": {
|
||||
"ripple-lib": "0.8.2",
|
||||
"async": "~0.2.9",
|
||||
"deep-equal": "0.0.0",
|
||||
"extend": "~1.2.0",
|
||||
"simple-jsonrpc": "~0.0.2",
|
||||
"deep-equal": "0.0.0"
|
||||
"lodash": "^3.5.0",
|
||||
"request": "^2.47.0",
|
||||
"ripple-lib": "0.10.0",
|
||||
"simple-jsonrpc": "~0.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"coffee-script": "~1.6.3",
|
||||
"mocha": "~1.13.0"
|
||||
"assert-diff": "^1.0.1",
|
||||
"coffee-script": "^1.8.0",
|
||||
"mocha": "^2.1.0"
|
||||
},
|
||||
|
||||
"scripts": {
|
||||
"test": "mocha test/websocket-test.js test/server-test.js test/*-test.{js,coffee}"
|
||||
},
|
||||
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/ripple/rippled.git"
|
||||
},
|
||||
|
||||
"readmeFilename": "README.md"
|
||||
}
|
||||
|
||||
@@ -59,24 +59,11 @@
|
||||
|
||||
/** Config: BEAST_CHECK_MEMORY_LEAKS
|
||||
Enables a memory-leak check for certain objects when the app terminates.
|
||||
See the LeakChecked class for more details about enabling leak checking for
|
||||
specific classes.
|
||||
*/
|
||||
#ifndef BEAST_CHECK_MEMORY_LEAKS
|
||||
//#define BEAST_CHECK_MEMORY_LEAKS 0
|
||||
#endif
|
||||
|
||||
/** Config: BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
|
||||
Setting this option makes Socket-derived classes generate compile errors
|
||||
if they forget any of the virtual overrides As some Socket-derived classes
|
||||
intentionally omit member functions that are not applicable, this macro
|
||||
should only be enabled temporarily when writing your own Socket-derived
|
||||
class, to make sure that the function signatures match as expected.
|
||||
*/
|
||||
#ifndef BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
|
||||
//#define BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES 1
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Libraries
|
||||
@@ -193,13 +180,6 @@
|
||||
#define RIPPLE_PROPOSE_AMENDMENTS 0
|
||||
#endif
|
||||
|
||||
/** Config: RIPPLE_ENABLE_AUTOBRIDGING
|
||||
This determines whether ripple implements offer autobridging via XRP.
|
||||
*/
|
||||
#ifndef RIPPLE_ENABLE_AUTOBRIDGING
|
||||
#define RIPPLE_ENABLE_AUTOBRIDGING 0
|
||||
#endif
|
||||
|
||||
/** Config: RIPPLE_SINGLE_IO_SERVICE_THREAD
|
||||
When set, restricts the number of threads calling io_service::run to one.
|
||||
This is useful when debugging.
|
||||
@@ -208,17 +188,18 @@
|
||||
#define RIPPLE_SINGLE_IO_SERVICE_THREAD 0
|
||||
#endif
|
||||
|
||||
/** Config: RIPPLE_STRUCTURED_OVERLAY_CLIENT
|
||||
RIPPLE_STRUCTURED_OVERLAY_SERVER
|
||||
Enables Structured Overlay support for the client or server roles.
|
||||
This feature is currently in development:
|
||||
https://ripplelabs.atlassian.net/browse/RIPD-157
|
||||
/** Config: RIPPLE_HOOK_VALIDATORS
|
||||
Activates code for handling validations and validators (work in progress).
|
||||
*/
|
||||
#ifndef RIPPLE_STRUCTURED_OVERLAY_CLIENT
|
||||
#define RIPPLE_STRUCTURED_OVERLAY_CLIENT 0
|
||||
#ifndef RIPPLE_HOOK_VALIDATORS
|
||||
#define RIPPLE_HOOK_VALIDATORS 0
|
||||
#endif
|
||||
#ifndef RIPPLE_STRUCTURED_OVERLAY_SERVER
|
||||
#define RIPPLE_STRUCTURED_OVERLAY_SERVER 1
|
||||
|
||||
/** Config: RIPPLE_ENABLE_TICKETS
|
||||
Enables processing of ticket transactions
|
||||
*/
|
||||
#ifndef RIPPLE_ENABLE_TICKETS
|
||||
#define RIPPLE_ENABLE_TICKETS 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -64,17 +64,6 @@
|
||||
//#define BEAST_CHECK_MEMORY_LEAKS 0
|
||||
#endif
|
||||
|
||||
/** Config: BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
|
||||
Setting this option makes Socket-derived classes generate compile errors
|
||||
if they forget any of the virtual overrides As some Socket-derived classes
|
||||
intentionally omit member functions that are not applicable, this macro
|
||||
should only be enabled temporarily when writing your own Socket-derived
|
||||
class, to make sure that the function signatures match as expected.
|
||||
*/
|
||||
#ifndef BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
|
||||
//#define BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES 1
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Libraries
|
||||
|
||||
@@ -1,429 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Portions of this file are from JUCE.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
Please visit http://www.juce.com
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ATOMIC_H_INCLUDED
|
||||
#define BEAST_ATOMIC_H_INCLUDED
|
||||
|
||||
#include <beast/Config.h>
|
||||
|
||||
#include <beast/utility/noexcept.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace beast {
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Simple class to hold a primitive value and perform atomic operations on it.
|
||||
|
||||
The type used must be a 32 or 64 bit primitive, like an int, pointer, etc.
|
||||
There are methods to perform most of the basic atomic operations.
|
||||
*/
|
||||
template <typename Type>
|
||||
class Atomic
|
||||
{
|
||||
// This class can only be used for types which are 32 or 64 bits in size.
|
||||
static_assert (sizeof (Type) == 4 || sizeof (Type) == 8,
|
||||
"Atomic arguments must be 32- or 64-bit long primitive types.");
|
||||
|
||||
public:
|
||||
/** Creates a new value, initialised to zero. */
|
||||
inline Atomic() noexcept
|
||||
: value (0)
|
||||
{
|
||||
}
|
||||
|
||||
/** Creates a new value, with a given initial value. */
|
||||
inline Atomic (const Type initialValue) noexcept
|
||||
: value (initialValue)
|
||||
{
|
||||
}
|
||||
|
||||
/** Copies another value (atomically). */
|
||||
inline Atomic (const Atomic& other) noexcept
|
||||
: value (other.get())
|
||||
{
|
||||
}
|
||||
|
||||
/** Destructor. */
|
||||
inline ~Atomic() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
/** Atomically reads and returns the current value. */
|
||||
Type get() const noexcept;
|
||||
|
||||
/** Copies another value onto this one (atomically). */
|
||||
Atomic& operator= (const Atomic& other) noexcept
|
||||
{ exchange (other.get()); return *this; }
|
||||
|
||||
/** Copies another value onto this one (atomically). */
|
||||
Atomic& operator= (const Type newValue) noexcept
|
||||
{ exchange (newValue); return *this; }
|
||||
|
||||
/** Atomically sets the current value. */
|
||||
void set (Type newValue) noexcept
|
||||
{ exchange (newValue); }
|
||||
|
||||
/** Atomically sets the current value, returning the value that was replaced. */
|
||||
Type exchange (Type value) noexcept;
|
||||
|
||||
/** Atomically adds a number to this value, returning the new value. */
|
||||
Type operator+= (Type amountToAdd) noexcept;
|
||||
|
||||
/** Atomically subtracts a number from this value, returning the new value. */
|
||||
Type operator-= (Type amountToSubtract) noexcept;
|
||||
|
||||
/** Atomically increments this value, returning the new value. */
|
||||
Type operator++() noexcept;
|
||||
|
||||
/** Atomically decrements this value, returning the new value. */
|
||||
Type operator--() noexcept;
|
||||
|
||||
/** Atomically compares this value with a target value, and if it is equal, sets
|
||||
this to be equal to a new value.
|
||||
|
||||
This operation is the atomic equivalent of doing this:
|
||||
@code
|
||||
bool compareAndSetBool (Type newValue, Type valueToCompare)
|
||||
{
|
||||
if (get() == valueToCompare)
|
||||
{
|
||||
set (newValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@returns true if the comparison was true and the value was replaced; false if
|
||||
the comparison failed and the value was left unchanged.
|
||||
@see compareAndSetValue
|
||||
*/
|
||||
bool compareAndSetBool (Type newValue, Type valueToCompare) noexcept;
|
||||
|
||||
/** Atomically compares this value with a target value, and if it is equal, sets
|
||||
this to be equal to a new value.
|
||||
|
||||
This operation is the atomic equivalent of doing this:
|
||||
@code
|
||||
Type compareAndSetValue (Type newValue, Type valueToCompare)
|
||||
{
|
||||
Type oldValue = get();
|
||||
if (oldValue == valueToCompare)
|
||||
set (newValue);
|
||||
|
||||
return oldValue;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@returns the old value before it was changed.
|
||||
@see compareAndSetBool
|
||||
*/
|
||||
Type compareAndSetValue (Type newValue, Type valueToCompare) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
#if BEAST_64BIT
|
||||
BEAST_ALIGN (8)
|
||||
#else
|
||||
BEAST_ALIGN (4)
|
||||
#endif
|
||||
|
||||
/** The raw value that this class operates on.
|
||||
This is exposed publically in case you need to manipulate it directly
|
||||
for performance reasons.
|
||||
*/
|
||||
volatile Type value;
|
||||
|
||||
private:
|
||||
template <typename Dest, typename Source>
|
||||
static inline Dest castTo (Source value) noexcept { union { Dest d; Source s; } u; u.s = value; return u.d; }
|
||||
|
||||
static inline Type castFrom32Bit (std::int32_t value) noexcept { return castTo <Type, std::int32_t> (value); }
|
||||
static inline Type castFrom64Bit (std::int64_t value) noexcept { return castTo <Type, std::int64_t> (value); }
|
||||
static inline std::int32_t castTo32Bit (Type value) noexcept { return castTo <std::int32_t, Type> (value); }
|
||||
static inline std::int64_t castTo64Bit (Type value) noexcept { return castTo <std::int64_t, Type> (value); }
|
||||
|
||||
|
||||
Type operator++ (int); // better to just use pre-increment with atomics..
|
||||
Type operator-- (int);
|
||||
|
||||
/** This templated negate function will negate pointers as well as integers */
|
||||
template <typename ValueType>
|
||||
inline ValueType negateValue (ValueType n) noexcept
|
||||
{
|
||||
return sizeof (ValueType) == 1 ? (ValueType) -(signed char) n
|
||||
: (sizeof (ValueType) == 2 ? (ValueType) -(short) n
|
||||
: (sizeof (ValueType) == 4 ? (ValueType) -(int) n
|
||||
: ((ValueType) -(std::int64_t) n)));
|
||||
}
|
||||
|
||||
/** This templated negate function will negate pointers as well as integers */
|
||||
template <typename PointerType>
|
||||
inline PointerType* negateValue (PointerType* n) noexcept
|
||||
{
|
||||
return reinterpret_cast <PointerType*> (-reinterpret_cast <std::intptr_t> (n));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/*
|
||||
The following code is in the header so that the atomics can be inlined where possible...
|
||||
*/
|
||||
#if BEAST_IOS || (BEAST_MAC && (BEAST_PPC || BEAST_CLANG || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2)))
|
||||
#define BEAST_ATOMICS_MAC 1 // Older OSX builds using gcc4.1 or earlier
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
|
||||
#define BEAST_MAC_ATOMICS_VOLATILE
|
||||
#else
|
||||
#define BEAST_MAC_ATOMICS_VOLATILE volatile
|
||||
#endif
|
||||
|
||||
#if BEAST_PPC || BEAST_IOS
|
||||
// None of these atomics are available for PPC or for iOS 3.1 or earlier!!
|
||||
template <typename Type> static Type OSAtomicAdd64Barrier (Type b, BEAST_MAC_ATOMICS_VOLATILE Type* a) noexcept { bassertfalse; return *a += b; }
|
||||
template <typename Type> static Type OSAtomicIncrement64Barrier (BEAST_MAC_ATOMICS_VOLATILE Type* a) noexcept { bassertfalse; return ++*a; }
|
||||
template <typename Type> static Type OSAtomicDecrement64Barrier (BEAST_MAC_ATOMICS_VOLATILE Type* a) noexcept { bassertfalse; return --*a; }
|
||||
template <typename Type> static bool OSAtomicCompareAndSwap64Barrier (Type old, Type newValue, BEAST_MAC_ATOMICS_VOLATILE Type* value) noexcept
|
||||
{ bassertfalse; if (old == *value) { *value = newValue; return true; } return false; }
|
||||
#define BEAST_64BIT_ATOMICS_UNAVAILABLE 1
|
||||
#endif
|
||||
|
||||
#elif BEAST_CLANG && BEAST_LINUX
|
||||
#define BEAST_ATOMICS_GCC 1
|
||||
|
||||
//==============================================================================
|
||||
#elif BEAST_GCC
|
||||
#define BEAST_ATOMICS_GCC 1 // GCC with intrinsics
|
||||
|
||||
#if BEAST_IOS || BEAST_ANDROID // (64-bit ops will compile but not link on these mobile OSes)
|
||||
#define BEAST_64BIT_ATOMICS_UNAVAILABLE 1
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
#else
|
||||
#define BEAST_ATOMICS_WINDOWS 1 // Windows with intrinsics
|
||||
|
||||
#if BEAST_USE_INTRINSICS
|
||||
#ifndef __INTEL_COMPILER
|
||||
#pragma intrinsic (_InterlockedExchange, _InterlockedIncrement, _InterlockedDecrement, _InterlockedCompareExchange, \
|
||||
_InterlockedCompareExchange64, _InterlockedExchangeAdd, _ReadWriteBarrier)
|
||||
#endif
|
||||
#define beast_InterlockedExchange(a, b) _InterlockedExchange(a, b)
|
||||
#define beast_InterlockedIncrement(a) _InterlockedIncrement(a)
|
||||
#define beast_InterlockedDecrement(a) _InterlockedDecrement(a)
|
||||
#define beast_InterlockedExchangeAdd(a, b) _InterlockedExchangeAdd(a, b)
|
||||
#define beast_InterlockedCompareExchange(a, b, c) _InterlockedCompareExchange(a, b, c)
|
||||
#define beast_InterlockedCompareExchange64(a, b, c) _InterlockedCompareExchange64(a, b, c)
|
||||
#define beast_MemoryBarrier _ReadWriteBarrier
|
||||
#else
|
||||
long beast_InterlockedExchange (volatile long* a, long b) noexcept;
|
||||
long beast_InterlockedIncrement (volatile long* a) noexcept;
|
||||
long beast_InterlockedDecrement (volatile long* a) noexcept;
|
||||
long beast_InterlockedExchangeAdd (volatile long* a, long b) noexcept;
|
||||
long beast_InterlockedCompareExchange (volatile long* a, long b, long c) noexcept;
|
||||
__int64 beast_InterlockedCompareExchange64 (volatile __int64* a, __int64 b, __int64 c) noexcept;
|
||||
inline void beast_MemoryBarrier() noexcept { long x = 0; beast_InterlockedIncrement (&x); }
|
||||
#endif
|
||||
|
||||
#if BEAST_64BIT
|
||||
#ifndef __INTEL_COMPILER
|
||||
#pragma intrinsic (_InterlockedExchangeAdd64, _InterlockedExchange64, _InterlockedIncrement64, _InterlockedDecrement64)
|
||||
#endif
|
||||
#define beast_InterlockedExchangeAdd64(a, b) _InterlockedExchangeAdd64(a, b)
|
||||
#define beast_InterlockedExchange64(a, b) _InterlockedExchange64(a, b)
|
||||
#define beast_InterlockedIncrement64(a) _InterlockedIncrement64(a)
|
||||
#define beast_InterlockedDecrement64(a) _InterlockedDecrement64(a)
|
||||
#else
|
||||
// None of these atomics are available in a 32-bit Windows build!!
|
||||
template <typename Type> static Type beast_InterlockedExchangeAdd64 (volatile Type* a, Type b) noexcept { bassertfalse; Type old = *a; *a += b; return old; }
|
||||
template <typename Type> static Type beast_InterlockedExchange64 (volatile Type* a, Type b) noexcept { bassertfalse; Type old = *a; *a = b; return old; }
|
||||
template <typename Type> static Type beast_InterlockedIncrement64 (volatile Type* a) noexcept { bassertfalse; return ++*a; }
|
||||
template <typename Type> static Type beast_InterlockedDecrement64 (volatile Type* a) noexcept { bassertfalse; return --*a; }
|
||||
#define BEAST_64BIT_ATOMICS_UNAVAILABLE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BEAST_MSVC
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4311) // (truncation warning)
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
template <typename Type>
|
||||
inline Type Atomic<Type>::get() const noexcept
|
||||
{
|
||||
#if BEAST_ATOMICS_MAC
|
||||
return sizeof (Type) == 4 ? castFrom32Bit ((std::int32_t) OSAtomicAdd32Barrier ((int32_t) 0, (BEAST_MAC_ATOMICS_VOLATILE int32_t*) &value))
|
||||
: castFrom64Bit ((std::int64_t) OSAtomicAdd64Barrier ((int64_t) 0, (BEAST_MAC_ATOMICS_VOLATILE int64_t*) &value));
|
||||
#elif BEAST_ATOMICS_WINDOWS
|
||||
return sizeof (Type) == 4 ? castFrom32Bit ((std::int32_t) beast_InterlockedExchangeAdd ((volatile long*) &value, (long) 0))
|
||||
: castFrom64Bit ((std::int64_t) beast_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) 0));
|
||||
#elif BEAST_ATOMICS_GCC
|
||||
return sizeof (Type) == 4 ? castFrom32Bit ((std::int32_t) __sync_add_and_fetch ((volatile std::int32_t*) &value, 0))
|
||||
: castFrom64Bit ((std::int64_t) __sync_add_and_fetch ((volatile std::int64_t*) &value, 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type Atomic<Type>::exchange (const Type newValue) noexcept
|
||||
{
|
||||
#if BEAST_ATOMICS_MAC || BEAST_ATOMICS_GCC
|
||||
Type currentVal = value;
|
||||
while (! compareAndSetBool (newValue, currentVal)) { currentVal = value; }
|
||||
return currentVal;
|
||||
#elif BEAST_ATOMICS_WINDOWS
|
||||
return sizeof (Type) == 4 ? castFrom32Bit ((std::int32_t) beast_InterlockedExchange ((volatile long*) &value, (long) castTo32Bit (newValue)))
|
||||
: castFrom64Bit ((std::int64_t) beast_InterlockedExchange64 ((volatile __int64*) &value, (__int64) castTo64Bit (newValue)));
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type Atomic<Type>::operator+= (const Type amountToAdd) noexcept
|
||||
{
|
||||
#if BEAST_ATOMICS_MAC
|
||||
# ifdef __clang__
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"
|
||||
# pragma clang diagnostic ignored "-Wint-to-pointer-cast"
|
||||
# endif
|
||||
return sizeof (Type) == 4 ? (Type) OSAtomicAdd32Barrier ((int32_t) castTo32Bit (amountToAdd), (BEAST_MAC_ATOMICS_VOLATILE int32_t*) &value)
|
||||
: (Type) OSAtomicAdd64Barrier ((int64_t) amountToAdd, (BEAST_MAC_ATOMICS_VOLATILE int64_t*) &value);
|
||||
# ifdef __clang__
|
||||
# pragma clang diagnostic pop
|
||||
# endif
|
||||
#elif BEAST_ATOMICS_WINDOWS
|
||||
return sizeof (Type) == 4 ? (Type) (beast_InterlockedExchangeAdd ((volatile long*) &value, (long) amountToAdd) + (long) amountToAdd)
|
||||
: (Type) (beast_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) amountToAdd) + (__int64) amountToAdd);
|
||||
#elif BEAST_ATOMICS_GCC
|
||||
return (Type) __sync_add_and_fetch (&value, amountToAdd);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type Atomic<Type>::operator-= (const Type amountToSubtract) noexcept
|
||||
{
|
||||
return operator+= (negateValue (amountToSubtract));
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type Atomic<Type>::operator++() noexcept
|
||||
{
|
||||
#if BEAST_ATOMICS_MAC
|
||||
# ifdef __clang__
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"
|
||||
# pragma clang diagnostic ignored "-Wint-to-pointer-cast"
|
||||
# endif
|
||||
return sizeof (Type) == 4 ? (Type) OSAtomicIncrement32Barrier ((BEAST_MAC_ATOMICS_VOLATILE int32_t*) &value)
|
||||
: (Type) OSAtomicIncrement64Barrier ((BEAST_MAC_ATOMICS_VOLATILE int64_t*) &value);
|
||||
# ifdef __clang__
|
||||
# pragma clang diagnostic pop
|
||||
# endif
|
||||
#elif BEAST_ATOMICS_WINDOWS
|
||||
return sizeof (Type) == 4 ? (Type) beast_InterlockedIncrement ((volatile long*) &value)
|
||||
: (Type) beast_InterlockedIncrement64 ((volatile __int64*) &value);
|
||||
#elif BEAST_ATOMICS_GCC
|
||||
return (Type) __sync_add_and_fetch (&value, (Type) 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type Atomic<Type>::operator--() noexcept
|
||||
{
|
||||
#if BEAST_ATOMICS_MAC
|
||||
# ifdef __clang__
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"
|
||||
# pragma clang diagnostic ignored "-Wint-to-pointer-cast"
|
||||
# endif
|
||||
return sizeof (Type) == 4 ? (Type) OSAtomicDecrement32Barrier ((BEAST_MAC_ATOMICS_VOLATILE int32_t*) &value)
|
||||
: (Type) OSAtomicDecrement64Barrier ((BEAST_MAC_ATOMICS_VOLATILE int64_t*) &value);
|
||||
# ifdef __clang__
|
||||
# pragma clang diagnostic pop
|
||||
# endif
|
||||
#elif BEAST_ATOMICS_WINDOWS
|
||||
return sizeof (Type) == 4 ? (Type) beast_InterlockedDecrement ((volatile long*) &value)
|
||||
: (Type) beast_InterlockedDecrement64 ((volatile __int64*) &value);
|
||||
#elif BEAST_ATOMICS_GCC
|
||||
return (Type) __sync_add_and_fetch (&value, (Type) -1);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline bool Atomic<Type>::compareAndSetBool (const Type newValue, const Type valueToCompare) noexcept
|
||||
{
|
||||
#if BEAST_ATOMICS_MAC
|
||||
return sizeof (Type) == 4 ? OSAtomicCompareAndSwap32Barrier ((int32_t) castTo32Bit (valueToCompare), (int32_t) castTo32Bit (newValue), (BEAST_MAC_ATOMICS_VOLATILE int32_t*) &value)
|
||||
: OSAtomicCompareAndSwap64Barrier ((int64_t) castTo64Bit (valueToCompare), (int64_t) castTo64Bit (newValue), (BEAST_MAC_ATOMICS_VOLATILE int64_t*) &value);
|
||||
#elif BEAST_ATOMICS_WINDOWS
|
||||
return compareAndSetValue (newValue, valueToCompare) == valueToCompare;
|
||||
#elif BEAST_ATOMICS_GCC
|
||||
return sizeof (Type) == 4 ? __sync_bool_compare_and_swap ((volatile std::int32_t*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue))
|
||||
: __sync_bool_compare_and_swap ((volatile std::int64_t*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue));
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type Atomic<Type>::compareAndSetValue (const Type newValue, const Type valueToCompare) noexcept
|
||||
{
|
||||
#if BEAST_ATOMICS_MAC
|
||||
for (;;) // Annoying workaround for only having a bool CAS operation..
|
||||
{
|
||||
if (compareAndSetBool (newValue, valueToCompare))
|
||||
return valueToCompare;
|
||||
|
||||
const Type result = value;
|
||||
if (result != valueToCompare)
|
||||
return result;
|
||||
}
|
||||
|
||||
#elif BEAST_ATOMICS_WINDOWS
|
||||
return sizeof (Type) == 4 ? castFrom32Bit ((std::int32_t) beast_InterlockedCompareExchange ((volatile long*) &value, (long) castTo32Bit (newValue), (long) castTo32Bit (valueToCompare)))
|
||||
: castFrom64Bit ((std::int64_t) beast_InterlockedCompareExchange64 ((volatile __int64*) &value, (__int64) castTo64Bit (newValue), (__int64) castTo64Bit (valueToCompare)));
|
||||
#elif BEAST_ATOMICS_GCC
|
||||
return sizeof (Type) == 4 ? castFrom32Bit ((std::int32_t) __sync_val_compare_and_swap ((volatile std::int32_t*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue)))
|
||||
: castFrom64Bit ((std::int64_t) __sync_val_compare_and_swap ((volatile std::int64_t*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue)));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void memoryBarrier() noexcept
|
||||
{
|
||||
#if BEAST_ATOMICS_MAC
|
||||
OSMemoryBarrier();
|
||||
#elif BEAST_ATOMICS_GCC
|
||||
__sync_synchronize();
|
||||
#elif BEAST_ATOMICS_WINDOWS
|
||||
beast_MemoryBarrier();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if BEAST_MSVC
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -26,9 +26,6 @@
|
||||
|
||||
// VFALCO NOTE this is analogous to <boost/config.hpp>
|
||||
|
||||
// Assert to boost that we always have std::array support
|
||||
#define BOOST_ASIO_HAS_STD_ARRAY 1
|
||||
|
||||
#if !defined(BEAST_COMPILER_CONFIG) && !defined(BEAST_NO_COMPILER_CONFIG) && !defined(BEAST_NO_CONFIG)
|
||||
#include <beast/config/SelectCompilerConfig.h>
|
||||
#endif
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#ifndef BEAST_CRYPTO_H_INCLUDED
|
||||
#define BEAST_CRYPTO_H_INCLUDED
|
||||
|
||||
#include <beast/crypto/MurmurHash.h>
|
||||
#include <beast/crypto/Sha256.h>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -25,11 +25,9 @@
|
||||
#include <beast/threads/SharedLockGuard.h>
|
||||
#include <beast/threads/SharedMutexAdapter.h>
|
||||
#include <beast/threads/SharedData.h>
|
||||
#include <beast/threads/ServiceQueue.h>
|
||||
#include <beast/threads/SpinLock.h>
|
||||
#include <beast/threads/Stoppable.h>
|
||||
#include <beast/threads/Thread.h>
|
||||
#include <beast/threads/ThreadLocalValue.h>
|
||||
#include <beast/threads/WaitableEvent.h>
|
||||
#include <beast/threads/ScopedWrapperContext.h>
|
||||
|
||||
|
||||
@@ -22,5 +22,8 @@
|
||||
#endif
|
||||
|
||||
#include <beast/asio/impl/IPAddressConversion.cpp>
|
||||
#include <beast/asio/impl/error.cpp>
|
||||
#include <beast/asio/tests/bind_handler.test.cpp>
|
||||
#include <beast/asio/tests/streambuf.test.cpp>
|
||||
#include <beast/asio/tests/error_test.cpp>
|
||||
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_SSL_H_INCLUDED
|
||||
#define BEAST_ASIO_SSL_H_INCLUDED
|
||||
#ifndef BEAST_ASIO_ERROR_H_INCLUDED
|
||||
#define BEAST_ASIO_ERROR_H_INCLUDED
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/ssl/error.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
@@ -32,8 +32,12 @@ bool
|
||||
is_short_read (boost::system::error_code const& ec)
|
||||
{
|
||||
return (ec.category() == boost::asio::error::get_ssl_category())
|
||||
&& (ERR_GET_REASON(ec.value()) == SSL_R_SHORT_READ);
|
||||
&& (ERR_GET_REASON(ec.value()) == SSL_R_SHORT_READ);
|
||||
}
|
||||
|
||||
/** Returns a human readable message if the error code is SSL related. */
|
||||
std::string
|
||||
asio_message(boost::system::error_code const& ec);
|
||||
|
||||
}
|
||||
}
|
||||
59
src/beast/beast/asio/impl/error.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <beast/asio/error.h>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
|
||||
// This buffer must be at least 120 bytes, most examples use 256.
|
||||
// https://www.openssl.org/docs/crypto/ERR_error_string.html
|
||||
static std::uint32_t const errorBufferSize (256);
|
||||
|
||||
std::string
|
||||
asio_message (boost::system::error_code const& ec)
|
||||
{
|
||||
std::string error;
|
||||
|
||||
if (ec.category () == boost::asio::error::get_ssl_category ())
|
||||
{
|
||||
error = " ("
|
||||
+ boost::lexical_cast<std::string> (ERR_GET_LIB (ec.value ()))
|
||||
+ ","
|
||||
+ boost::lexical_cast<std::string> (ERR_GET_FUNC (ec.value ()))
|
||||
+ ","
|
||||
+ boost::lexical_cast<std::string> (ERR_GET_REASON (ec.value ()))
|
||||
+ ") ";
|
||||
|
||||
//
|
||||
char buf[errorBufferSize];
|
||||
::ERR_error_string_n (ec.value (), buf, errorBufferSize);
|
||||
error += buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = ec.message ();
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,9 @@
|
||||
#define BEAST_ASIO_SSL_BUNDLE_H_INCLUDED
|
||||
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
#include <boost/asio/ssl/stream.hpp>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
@@ -33,21 +35,33 @@ namespace asio {
|
||||
*/
|
||||
struct ssl_bundle
|
||||
{
|
||||
typedef boost::asio::ip::tcp::socket socket_type;
|
||||
typedef boost::asio::ssl::stream <socket_type&> stream_type;
|
||||
using socket_type = boost::asio::ip::tcp::socket;
|
||||
using stream_type = boost::asio::ssl::stream <socket_type&>;
|
||||
using shared_context = std::shared_ptr<boost::asio::ssl::context>;
|
||||
|
||||
template <class... Args>
|
||||
ssl_bundle (boost::asio::ssl::context& context, Args&&... args);
|
||||
ssl_bundle (shared_context const& context_, Args&&... args);
|
||||
|
||||
// DEPRECATED
|
||||
template <class... Args>
|
||||
ssl_bundle (boost::asio::ssl::context& context_, Args&&... args);
|
||||
|
||||
shared_context context;
|
||||
socket_type socket;
|
||||
stream_type stream;
|
||||
};
|
||||
|
||||
template <class... Args>
|
||||
ssl_bundle::ssl_bundle (boost::asio::ssl::context& context,
|
||||
Args&&... args)
|
||||
ssl_bundle::ssl_bundle (shared_context const& context_, Args&&... args)
|
||||
: socket(std::forward<Args>(args)...)
|
||||
, stream (socket, context)
|
||||
, stream (socket, *context_)
|
||||
{
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
ssl_bundle::ssl_bundle (boost::asio::ssl::context& context_, Args&&... args)
|
||||
: socket(std::forward<Args>(args)...)
|
||||
, stream (socket, context_)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
679
src/beast/beast/asio/streambuf.h
Normal file
@@ -0,0 +1,679 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_STREAMBUF_H_INCLUDED
|
||||
#define BEAST_ASIO_STREAMBUF_H_INCLUDED
|
||||
|
||||
#include <beast/utility/empty_base_optimization.h>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <exception>
|
||||
#include <beast/cxx14/type_traits.h> // <type_traits>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
|
||||
/** Implements asio::streambuf interface using multiple buffers. */
|
||||
template <class Allocator>
|
||||
class basic_streambuf
|
||||
: private empty_base_optimization<Allocator>
|
||||
{
|
||||
public:
|
||||
using size_type = typename std::allocator_traits<Allocator>::size_type;
|
||||
using const_buffer = boost::asio::const_buffer;
|
||||
using mutable_buffer = boost::asio::mutable_buffer;
|
||||
|
||||
private:
|
||||
class element;
|
||||
|
||||
using alloc_traits = std::allocator_traits<Allocator>;
|
||||
using list_type = typename boost::intrusive::make_list <element,
|
||||
boost::intrusive::constant_time_size <true>>::type;
|
||||
using iterator = typename list_type::iterator;
|
||||
using const_iterator = typename list_type::const_iterator;
|
||||
|
||||
/* These diagrams illustrate the layout and state variables.
|
||||
|
||||
Input and output contained entirely in one element:
|
||||
|
||||
0 out_
|
||||
|<-------------+------------------------------------------->|
|
||||
in_pos_ out_pos_ out_end_
|
||||
|
||||
|
||||
Output contained in first and second elements:
|
||||
|
||||
out_
|
||||
|<------+----------+------->| |<----------+-------------->|
|
||||
in_pos_ out_pos_ out_end_
|
||||
|
||||
|
||||
Output contained in the second element:
|
||||
|
||||
out_
|
||||
|<------------+------------>| |<----+-------------------->|
|
||||
in_pos_ out_pos_ out_end_
|
||||
|
||||
|
||||
Output contained in second and third elements:
|
||||
|
||||
out_
|
||||
|<-----+-------->| |<-------+------>| |<--------------->|
|
||||
in_pos_ out_pos_ out_end_
|
||||
|
||||
|
||||
Input sequence is empty:
|
||||
|
||||
out_
|
||||
|<------+------------------>| |<-----------+------------->|
|
||||
out_pos_ out_end_
|
||||
in_pos_
|
||||
|
||||
|
||||
Output sequence is empty:
|
||||
|
||||
out_
|
||||
|<------+------------------>| |<------+------------------>|
|
||||
in_pos_ out_pos_
|
||||
out_end_
|
||||
|
||||
|
||||
The end of output can point to the end of an element.
|
||||
But out_pos_ should never point to the end:
|
||||
|
||||
out_
|
||||
|<------+------------------>| |<------+------------------>|
|
||||
in_pos_ out_pos_ out_end_
|
||||
|
||||
|
||||
When the input sequence entirely fills the last element and
|
||||
the output sequence is empty, out_ will point to the end of
|
||||
the list of buffers, and out_pos_ and out_end_ will be 0:
|
||||
|
||||
|
||||
|<------+------------------>| out_ == list_.end()
|
||||
in_pos_ out_pos_ == 0
|
||||
out_end_ == 0
|
||||
*/
|
||||
|
||||
list_type list_;
|
||||
size_type block_size_;
|
||||
size_type block_size_next_;
|
||||
size_type in_size_ = 0; // size of the input sequence
|
||||
iterator out_; // element that contains out_pos_
|
||||
size_type in_pos_ = 0; // input offset in list_.front()
|
||||
size_type out_pos_ = 0; // output offset in *out_
|
||||
size_type out_end_ = 0; // output end offset in list_.back()
|
||||
|
||||
public:
|
||||
class const_buffers_type;
|
||||
class mutable_buffers_type;
|
||||
|
||||
basic_streambuf (basic_streambuf const& other) = delete;
|
||||
basic_streambuf& operator= (basic_streambuf const& other) = delete;
|
||||
basic_streambuf& operator= (basic_streambuf&& other) = delete;
|
||||
|
||||
~basic_streambuf();
|
||||
|
||||
explicit
|
||||
basic_streambuf(std::size_t block_size = 16*1024,
|
||||
Allocator const& alloc = Allocator{});
|
||||
|
||||
basic_streambuf (basic_streambuf&& other);
|
||||
|
||||
/** Get the maximum size of the basic_streambuf. */
|
||||
size_type
|
||||
max_size() const
|
||||
{
|
||||
return std::numeric_limits<std::size_t>::max();
|
||||
}
|
||||
|
||||
/** Get the size of the input sequence. */
|
||||
size_type
|
||||
size() const
|
||||
{
|
||||
return in_size_;
|
||||
}
|
||||
|
||||
/** Get a list of buffers that represents the output sequence, with the given size. */
|
||||
mutable_buffers_type
|
||||
prepare (size_type n);
|
||||
|
||||
/** Move bytes from the output sequence to the input sequence. */
|
||||
void
|
||||
commit (size_type n);
|
||||
|
||||
/** Get a list of buffers that represents the input sequence. */
|
||||
const_buffers_type
|
||||
data() const;
|
||||
|
||||
/** Remove bytes from the input sequence. */
|
||||
void
|
||||
consume (size_type n);
|
||||
|
||||
private:
|
||||
void
|
||||
debug_check() const;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class Allocator>
|
||||
class basic_streambuf<Allocator>::element
|
||||
: public boost::intrusive::list_base_hook <
|
||||
boost::intrusive::link_mode <boost::intrusive::normal_link>>
|
||||
{
|
||||
private:
|
||||
size_type const size_; // size of the allocation minus sizeof(element)
|
||||
|
||||
public:
|
||||
element (element const&) = delete;
|
||||
element& operator= (element const&) = delete;
|
||||
|
||||
explicit
|
||||
element (size_type block_size)
|
||||
: size_(block_size)
|
||||
{ }
|
||||
|
||||
size_type
|
||||
size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
size_type
|
||||
alloc_size() const
|
||||
{
|
||||
return size_ + sizeof(*this);
|
||||
}
|
||||
|
||||
char*
|
||||
data() const
|
||||
{
|
||||
return const_cast<char*>(
|
||||
reinterpret_cast<char const*>(this+1));
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class Allocator>
|
||||
class basic_streambuf<Allocator>::const_buffers_type
|
||||
{
|
||||
public:
|
||||
using value_type = const_buffer;
|
||||
|
||||
private:
|
||||
struct transform
|
||||
{
|
||||
using argument_type = element;
|
||||
using result_type = value_type;
|
||||
|
||||
basic_streambuf const* streambuf_ = nullptr;
|
||||
|
||||
transform() = default;
|
||||
|
||||
explicit
|
||||
transform (basic_streambuf const& streambuf)
|
||||
: streambuf_ (&streambuf)
|
||||
{
|
||||
}
|
||||
|
||||
value_type const
|
||||
operator() (element const& e) const;
|
||||
};
|
||||
|
||||
basic_streambuf const* streambuf_ = nullptr;
|
||||
|
||||
public:
|
||||
using const_iterator = boost::transform_iterator<
|
||||
transform, typename list_type::const_iterator,
|
||||
value_type, value_type>;
|
||||
|
||||
const_buffers_type() = default;
|
||||
const_buffers_type (const_buffers_type const&) = default;
|
||||
const_buffers_type& operator= (const_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const
|
||||
{
|
||||
return const_iterator (streambuf_->list_.begin(),
|
||||
transform(*streambuf_));
|
||||
}
|
||||
|
||||
const_iterator
|
||||
end() const
|
||||
{
|
||||
return const_iterator (streambuf_->out_ ==
|
||||
streambuf_->list_.end() ? streambuf_->list_.end() :
|
||||
std::next(streambuf_->out_), transform(*streambuf_));
|
||||
}
|
||||
|
||||
private:
|
||||
friend class basic_streambuf;
|
||||
|
||||
explicit
|
||||
const_buffers_type (basic_streambuf const& streambuf);
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
basic_streambuf<Allocator>::const_buffers_type::const_buffers_type (
|
||||
basic_streambuf const& streambuf)
|
||||
: streambuf_ (&streambuf)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Allocator>
|
||||
auto
|
||||
basic_streambuf<Allocator>::const_buffers_type::
|
||||
transform::operator() (element const& e) const ->
|
||||
value_type const
|
||||
{
|
||||
return value_type (e.data(),
|
||||
(streambuf_->out_ == streambuf_->list_.end() ||
|
||||
&e != &*streambuf_->out_) ? e.size() : streambuf_->out_pos_) +
|
||||
(&e == &*streambuf_->list_.begin() ?
|
||||
streambuf_->in_pos_ : 0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class Allocator>
|
||||
class basic_streambuf<Allocator>::mutable_buffers_type
|
||||
{
|
||||
public:
|
||||
using value_type = mutable_buffer;
|
||||
|
||||
private:
|
||||
struct transform
|
||||
{
|
||||
using argument_type = element;
|
||||
using result_type = value_type;
|
||||
|
||||
basic_streambuf const* streambuf_ = nullptr;
|
||||
|
||||
transform() = default;
|
||||
|
||||
explicit
|
||||
transform (basic_streambuf const& streambuf)
|
||||
: streambuf_ (&streambuf)
|
||||
{
|
||||
}
|
||||
|
||||
value_type const
|
||||
operator() (element const& e) const;
|
||||
};
|
||||
|
||||
basic_streambuf const* streambuf_;
|
||||
|
||||
public:
|
||||
using const_iterator = boost::transform_iterator<
|
||||
transform, typename list_type::const_iterator,
|
||||
value_type, value_type>;
|
||||
|
||||
mutable_buffers_type() = default;
|
||||
mutable_buffers_type (mutable_buffers_type const&) = default;
|
||||
mutable_buffers_type& operator= (mutable_buffers_type const&) = default;
|
||||
|
||||
const_iterator
|
||||
begin() const
|
||||
{
|
||||
return const_iterator (streambuf_->out_,
|
||||
transform(*streambuf_));
|
||||
}
|
||||
|
||||
const_iterator
|
||||
end() const
|
||||
{
|
||||
return const_iterator (streambuf_->list_.end(),
|
||||
transform(*streambuf_));
|
||||
}
|
||||
|
||||
private:
|
||||
friend class basic_streambuf;
|
||||
mutable_buffers_type (basic_streambuf const& streambuf);
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
basic_streambuf<Allocator>::mutable_buffers_type::mutable_buffers_type (
|
||||
basic_streambuf const& streambuf)
|
||||
: streambuf_ (&streambuf)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Allocator>
|
||||
auto
|
||||
basic_streambuf<Allocator>::mutable_buffers_type::
|
||||
transform::operator() (element const& e) const ->
|
||||
value_type const
|
||||
{
|
||||
return value_type (e.data(), &e == &*std::prev(streambuf_->list_.end()) ?
|
||||
streambuf_->out_end_ : e.size()) + (&e == &*streambuf_->out_ ?
|
||||
streambuf_->out_pos_ : 0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class Allocator>
|
||||
basic_streambuf<Allocator>::~basic_streambuf()
|
||||
{
|
||||
for(auto iter = list_.begin(); iter != list_.end();)
|
||||
{
|
||||
auto& e = *iter++;
|
||||
size_type const n = e.alloc_size();
|
||||
alloc_traits::destroy(this->member(), &e);
|
||||
alloc_traits::deallocate(this->member(),
|
||||
reinterpret_cast<char*>(&e), n);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Allocator>
|
||||
basic_streambuf<Allocator>::basic_streambuf(std::size_t block_size,
|
||||
Allocator const& alloc)
|
||||
: empty_base_optimization<Allocator>(alloc)
|
||||
, block_size_ (block_size)
|
||||
, block_size_next_ (block_size)
|
||||
, out_ (list_.end())
|
||||
{
|
||||
if (! (block_size > 0))
|
||||
throw std::invalid_argument(
|
||||
"basic_streambuf: invalid block_size");
|
||||
}
|
||||
|
||||
template <class Allocator>
|
||||
basic_streambuf<Allocator>::basic_streambuf (basic_streambuf&& other)
|
||||
: empty_base_optimization<Allocator>(other.member())
|
||||
, list_ (std::move(other.list_))
|
||||
, block_size_ (other.block_size_)
|
||||
, block_size_next_ (other.block_size_next_)
|
||||
, in_size_ (other.in_size_)
|
||||
, out_ (other.out_)
|
||||
, in_pos_ (other.in_pos_)
|
||||
, out_pos_ (other.out_pos_)
|
||||
, out_end_ (other.out_end_)
|
||||
{
|
||||
other.in_size_ = 0;
|
||||
other.out_ = other.list_.end();
|
||||
other.in_pos_ = 0;
|
||||
other.out_pos_ = 0;
|
||||
other.out_end_ = 0;
|
||||
}
|
||||
|
||||
template <class Allocator>
|
||||
auto
|
||||
basic_streambuf<Allocator>::prepare (size_type n) ->
|
||||
mutable_buffers_type
|
||||
{
|
||||
iterator pos = out_;
|
||||
if (pos != list_.end())
|
||||
{
|
||||
auto const avail = pos->size() - out_pos_;
|
||||
if (n > avail)
|
||||
{
|
||||
n -= avail;
|
||||
while (++pos != list_.end())
|
||||
{
|
||||
if (n < pos->size())
|
||||
{
|
||||
out_end_ = n;
|
||||
n = 0;
|
||||
++pos;
|
||||
break;
|
||||
}
|
||||
n -= pos->size();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++pos;
|
||||
out_end_ = out_pos_ + n;
|
||||
n = 0;
|
||||
}
|
||||
debug_check();
|
||||
}
|
||||
|
||||
if (n > 0)
|
||||
{
|
||||
assert(pos == list_.end());
|
||||
for(;;)
|
||||
{
|
||||
auto const avail = block_size_next_;
|
||||
auto& e = *reinterpret_cast<element*>(alloc_traits::allocate(
|
||||
this->member(), avail + sizeof(element)));
|
||||
alloc_traits::construct(this->member(), &e, avail);
|
||||
list_.push_back(e);
|
||||
if (out_ == list_.end())
|
||||
{
|
||||
out_ = list_.iterator_to(e);
|
||||
debug_check();
|
||||
}
|
||||
if (n <= avail)
|
||||
{
|
||||
out_end_ = n;
|
||||
debug_check();
|
||||
break;
|
||||
}
|
||||
n -= avail;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (pos != list_.end())
|
||||
{
|
||||
auto& e = *pos++;
|
||||
list_.erase(list_.iterator_to(e));
|
||||
auto const len = e.alloc_size();
|
||||
alloc_traits::destroy(this->member(), &e);
|
||||
alloc_traits::deallocate(this->member(),
|
||||
reinterpret_cast<char*>(&e), len);
|
||||
}
|
||||
debug_check();
|
||||
}
|
||||
|
||||
return mutable_buffers_type (*this);
|
||||
}
|
||||
|
||||
template <class Allocator>
|
||||
void
|
||||
basic_streambuf<Allocator>::commit (size_type n)
|
||||
{
|
||||
if (list_.empty())
|
||||
return;
|
||||
if (out_ == list_.end())
|
||||
return;
|
||||
auto const last = std::prev(list_.end());
|
||||
while (out_ != last)
|
||||
{
|
||||
auto const avail =
|
||||
out_->size() - out_pos_;
|
||||
if (n < avail)
|
||||
{
|
||||
out_pos_ += n;
|
||||
in_size_ += n;
|
||||
debug_check();
|
||||
return;
|
||||
}
|
||||
++out_;
|
||||
n -= avail;
|
||||
out_pos_ = 0;
|
||||
in_size_ += avail;
|
||||
debug_check();
|
||||
}
|
||||
|
||||
n = std::min (n, out_end_ - out_pos_);
|
||||
out_pos_ += n;
|
||||
in_size_ += n;
|
||||
if (out_pos_ == out_->size())
|
||||
{
|
||||
++out_;
|
||||
out_pos_ = 0;
|
||||
out_end_ = 0;
|
||||
}
|
||||
debug_check();
|
||||
}
|
||||
|
||||
template <class Allocator>
|
||||
auto
|
||||
basic_streambuf<Allocator>::data() const ->
|
||||
const_buffers_type
|
||||
{
|
||||
return const_buffers_type(*this);
|
||||
}
|
||||
|
||||
template <class Allocator>
|
||||
void
|
||||
basic_streambuf<Allocator>::consume (size_type n)
|
||||
{
|
||||
if (list_.empty())
|
||||
return;
|
||||
|
||||
auto pos = list_.begin();
|
||||
for(;;)
|
||||
{
|
||||
if (pos != out_)
|
||||
{
|
||||
auto const avail = pos->size() - in_pos_;
|
||||
if (n < avail)
|
||||
{
|
||||
in_size_ -= n;
|
||||
in_pos_ += n;
|
||||
debug_check();
|
||||
break;
|
||||
}
|
||||
n -= avail;
|
||||
in_size_ -= avail;
|
||||
in_pos_ = 0;
|
||||
debug_check();
|
||||
|
||||
element& e = *pos++;
|
||||
list_.erase(list_.iterator_to(e));
|
||||
size_type const len = e.alloc_size();
|
||||
alloc_traits::destroy(this->member(), &e);
|
||||
alloc_traits::deallocate(this->member(),
|
||||
reinterpret_cast<char*>(&e), len);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const avail = out_pos_ - in_pos_;
|
||||
if (n < avail)
|
||||
{
|
||||
in_size_ -= n;
|
||||
in_pos_ += n;
|
||||
}
|
||||
else
|
||||
{
|
||||
in_size_ -= avail;
|
||||
if (out_pos_ != out_end_||
|
||||
out_ != list_.iterator_to(list_.back()))
|
||||
{
|
||||
in_pos_ = out_pos_;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the whole buffer now.
|
||||
// Alternatively we could deallocate it.
|
||||
in_pos_ = 0;
|
||||
out_pos_ = 0;
|
||||
out_end_ = 0;
|
||||
}
|
||||
}
|
||||
debug_check();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class Allocator>
|
||||
void
|
||||
basic_streambuf<Allocator>::debug_check() const
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (list_.empty())
|
||||
{
|
||||
assert(in_pos_ == 0);
|
||||
assert(in_size_ == 0);
|
||||
assert(out_pos_ == 0);
|
||||
assert(out_end_ == 0);
|
||||
assert(out_ == list_.end());
|
||||
return;
|
||||
}
|
||||
|
||||
auto const& front = list_.front();
|
||||
|
||||
assert(in_pos_ < front.size());
|
||||
|
||||
if (out_ == list_.end())
|
||||
{
|
||||
assert(out_pos_ == 0);
|
||||
assert(out_end_ == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const& out = *out_;
|
||||
auto const& back = list_.back();
|
||||
|
||||
assert(out_end_ <= back.size());
|
||||
assert(out_pos_ < out.size());
|
||||
assert(&out != &front || out_pos_ >= in_pos_);
|
||||
assert(&out != &front || out_pos_ - in_pos_ == in_size_);
|
||||
assert(&out != &back || out_pos_ <= out_end_);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class Alloc, class T>
|
||||
basic_streambuf<Alloc>&
|
||||
operator<< (basic_streambuf<Alloc>& buf, T const& t)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << t;
|
||||
auto const& s = ss.str();
|
||||
buf.commit(boost::asio::buffer_copy(
|
||||
buf.prepare(s.size()), boost::asio::buffer(s)));
|
||||
return buf;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using streambuf = basic_streambuf<std::allocator<char>>;
|
||||
|
||||
/** Convert the entire basic_streambuf to a string.
|
||||
@note It is more efficient to deal directly in the streambuf instead.
|
||||
*/
|
||||
template <class Allocator>
|
||||
std::string
|
||||
to_string (basic_streambuf<Allocator> const& buf)
|
||||
{
|
||||
std::string s;
|
||||
s.resize(buf.size());
|
||||
boost::asio::buffer_copy(boost::asio::buffer(
|
||||
&s[0], s.size()), buf.data());
|
||||
return s;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -17,30 +17,28 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_BOOST_GET_POINTER_H_INCLUDED
|
||||
#define BEAST_BOOST_GET_POINTER_H_INCLUDED
|
||||
#include <beast/asio/error.h>
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <string>
|
||||
|
||||
#include <boost/get_pointer.hpp>
|
||||
|
||||
// Boost 1.55 incorrectly defines BOOST_NO_CXX11_SMART_PTR
|
||||
// when building with clang 3.4 and earlier. This workaround
|
||||
// gives beast its own overloads.
|
||||
|
||||
#ifdef BOOST_NO_CXX11_SMART_PTR
|
||||
#include <memory>
|
||||
namespace beast {
|
||||
template <class T>
|
||||
T* get_pointer (std::unique_ptr<T> const& p)
|
||||
{
|
||||
return p.get();
|
||||
}
|
||||
namespace asio {
|
||||
|
||||
template <class T>
|
||||
T* get_pointer (std::shared_ptr<T> const& p)
|
||||
class error_test : public unit_test::suite
|
||||
{
|
||||
return p.get();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
public:
|
||||
void run ()
|
||||
{
|
||||
{
|
||||
boost::system::error_code ec = boost::system::error_code (335544539,
|
||||
boost::asio::error::get_ssl_category ());
|
||||
std::string const s = beast::asio::asio_message (ec);
|
||||
expect(s == " (20,0,219) error:140000DB:SSL routines:SSL routines:short read");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
BEAST_DEFINE_TESTSUITE(error,asio,beast);
|
||||
|
||||
}
|
||||
}
|
||||
158
src/beast/beast/asio/tests/streambuf.test.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <beast/asio/streambuf.h>
|
||||
#include <beast/unit_test/suite.h>
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
|
||||
class streambuf_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
// Convert a buffer sequence to a string
|
||||
template <class Buffers>
|
||||
static
|
||||
std::string
|
||||
to_str (Buffers const& b)
|
||||
{
|
||||
std::string s;
|
||||
auto const n = boost::asio::buffer_size(b);
|
||||
s.resize(n);
|
||||
boost::asio::buffer_copy(
|
||||
boost::asio::buffer(&s[0], n), b);
|
||||
return s;
|
||||
}
|
||||
|
||||
// Fill a buffer sequence with predictable data
|
||||
template <class Buffers>
|
||||
static
|
||||
void
|
||||
fill (Buffers const& b)
|
||||
{
|
||||
char c = 0;
|
||||
auto first = boost::asio::buffers_begin(b);
|
||||
auto last = boost::asio::buffers_end(b);
|
||||
while (first != last)
|
||||
*first++ = c++;
|
||||
}
|
||||
|
||||
// Check that a buffer sequence has predictable data
|
||||
template <class Buffers>
|
||||
void
|
||||
check (Buffers const& b, char c = 0)
|
||||
{
|
||||
auto first = boost::asio::buffers_begin(b);
|
||||
auto last = boost::asio::buffers_end(b);
|
||||
while (first != last)
|
||||
expect (*first++ == c++);
|
||||
}
|
||||
|
||||
void
|
||||
test_prepare()
|
||||
{
|
||||
testcase << "prepare";
|
||||
beast::asio::streambuf b(11);
|
||||
for (std::size_t n = 0; n < 97; ++n)
|
||||
{
|
||||
fill(b.prepare(n));
|
||||
b.commit(n);
|
||||
check(b.data());
|
||||
b.consume(n);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_commit()
|
||||
{
|
||||
testcase << "commit";
|
||||
beast::asio::streambuf b(11);
|
||||
for (std::size_t n = 0; n < 97; ++n)
|
||||
{
|
||||
fill(b.prepare(n));
|
||||
char c = 0;
|
||||
for (int i = 1;; ++i)
|
||||
{
|
||||
b.commit(i);
|
||||
check(b.data(), c);
|
||||
b.consume(i);
|
||||
if (b.size() < 1)
|
||||
break;
|
||||
c += i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_consume()
|
||||
{
|
||||
testcase << "consume";
|
||||
beast::asio::streambuf b(11);
|
||||
for (std::size_t n = 0; n < 97; ++n)
|
||||
{
|
||||
fill(b.prepare(n));
|
||||
b.commit(n);
|
||||
char c = 0;
|
||||
for (int i = 1; b.size() > 0; ++i)
|
||||
{
|
||||
check(b.data(), c);
|
||||
b.consume(i);
|
||||
c += i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
{
|
||||
beast::asio::streambuf b(10);
|
||||
std::string const s = "1234567890";
|
||||
b << s;
|
||||
expect (to_str(b.data()) == s);
|
||||
b.prepare(5);
|
||||
}
|
||||
|
||||
{
|
||||
beast::asio::streambuf b(10);
|
||||
b.prepare(10);
|
||||
b.commit(10);
|
||||
b.consume(10);
|
||||
}
|
||||
|
||||
{
|
||||
beast::asio::streambuf b(5);
|
||||
boost::asio::buffer_copy(b.prepare(14),
|
||||
boost::asio::buffer(std::string("1234567890ABCD")));
|
||||
b.commit(4);
|
||||
expect(to_str(b.data()) == "1234");
|
||||
b.consume(4);
|
||||
b.commit(10);
|
||||
expect(to_str(b.data()) == "567890ABCD");
|
||||
}
|
||||
|
||||
test_prepare();
|
||||
test_commit();
|
||||
test_consume();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(streambuf,asio,beast);
|
||||
|
||||
}
|
||||
}
|
||||
315
src/beast/beast/asio/waitable_executor.h
Normal file
@@ -0,0 +1,315 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_WAITABLE_EXECUTOR_H_INCLUDED
|
||||
#define BEAST_ASIO_WAITABLE_EXECUTOR_H_INCLUDED
|
||||
|
||||
#include <boost/asio/handler_alloc_hook.hpp>
|
||||
#include <boost/asio/handler_continuation_hook.hpp>
|
||||
#include <boost/asio/handler_invoke_hook.hpp>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <beast/cxx14/type_traits.h> // <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class Owner, class Handler>
|
||||
class waitable_executor_wrapped_handler
|
||||
{
|
||||
private:
|
||||
static_assert (std::is_same <std::decay_t <Owner>, Owner>::value,
|
||||
"Owner cannot be a const or reference type");
|
||||
|
||||
Handler handler_;
|
||||
std::reference_wrapper <Owner> owner_;
|
||||
bool cont_;
|
||||
|
||||
public:
|
||||
waitable_executor_wrapped_handler (Owner& owner,
|
||||
Handler&& handler, bool continuation = false)
|
||||
: handler_ (std::move(handler))
|
||||
, owner_ (owner)
|
||||
{
|
||||
using boost::asio::asio_handler_is_continuation;
|
||||
cont_ = continuation ? true :
|
||||
asio_handler_is_continuation(
|
||||
std::addressof(handler_));
|
||||
owner_.get().increment();
|
||||
}
|
||||
|
||||
waitable_executor_wrapped_handler (Owner& owner,
|
||||
Handler const& handler, bool continuation = false)
|
||||
: handler_ (handler)
|
||||
, owner_ (owner)
|
||||
{
|
||||
using boost::asio::asio_handler_is_continuation;
|
||||
cont_ = continuation ? true :
|
||||
asio_handler_is_continuation(
|
||||
std::addressof(handler_));
|
||||
owner_.get().increment();
|
||||
}
|
||||
|
||||
~waitable_executor_wrapped_handler()
|
||||
{
|
||||
owner_.get().decrement();
|
||||
}
|
||||
|
||||
waitable_executor_wrapped_handler (
|
||||
waitable_executor_wrapped_handler const& other)
|
||||
: handler_ (other.handler_)
|
||||
, owner_ (other.owner_)
|
||||
, cont_ (other.cont_)
|
||||
{
|
||||
owner_.get().increment();
|
||||
}
|
||||
|
||||
waitable_executor_wrapped_handler (
|
||||
waitable_executor_wrapped_handler&& other)
|
||||
: handler_ (std::move(other.handler_))
|
||||
, owner_ (other.owner_)
|
||||
, cont_ (other.cont_)
|
||||
{
|
||||
owner_.get().increment();
|
||||
}
|
||||
|
||||
waitable_executor_wrapped_handler& operator=(
|
||||
waitable_executor_wrapped_handler const&) = delete;
|
||||
|
||||
template <class... Args>
|
||||
void
|
||||
operator()(Args&&... args)
|
||||
{
|
||||
handler_(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
void
|
||||
operator()(Args&&... args) const
|
||||
{
|
||||
handler_(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class Function>
|
||||
friend
|
||||
void
|
||||
asio_handler_invoke (Function& f,
|
||||
waitable_executor_wrapped_handler* h)
|
||||
{
|
||||
using boost::asio::asio_handler_invoke;
|
||||
asio_handler_invoke(f,
|
||||
std::addressof(h->handler_));
|
||||
}
|
||||
|
||||
template <class Function>
|
||||
friend
|
||||
void
|
||||
asio_handler_invoke (Function const& f,
|
||||
waitable_executor_wrapped_handler* h)
|
||||
{
|
||||
using boost::asio::asio_handler_invoke;
|
||||
asio_handler_invoke(f,
|
||||
std::addressof(h->handler_));
|
||||
}
|
||||
|
||||
friend
|
||||
void*
|
||||
asio_handler_allocate (std::size_t size,
|
||||
waitable_executor_wrapped_handler* h)
|
||||
{
|
||||
using boost::asio::asio_handler_allocate;
|
||||
return asio_handler_allocate(
|
||||
size, std::addressof(h->handler_));
|
||||
}
|
||||
|
||||
friend
|
||||
void
|
||||
asio_handler_deallocate (void* p, std::size_t size,
|
||||
waitable_executor_wrapped_handler* h)
|
||||
{
|
||||
using boost::asio::asio_handler_deallocate;
|
||||
asio_handler_deallocate(
|
||||
p, size, std::addressof(h->handler_));
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
asio_handler_is_continuation (
|
||||
waitable_executor_wrapped_handler* h)
|
||||
{
|
||||
return h->cont_;
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Executor which provides blocking until all handlers are called. */
|
||||
class waitable_executor
|
||||
{
|
||||
private:
|
||||
template <class, class>
|
||||
friend class detail::waitable_executor_wrapped_handler;
|
||||
|
||||
std::mutex mutex_;
|
||||
std::condition_variable cond_;
|
||||
std::size_t count_ = 0;
|
||||
std::vector<std::function<void(void)>> notify_;
|
||||
|
||||
public:
|
||||
/** Block until all handlers are called. */
|
||||
template <class = void>
|
||||
void
|
||||
wait();
|
||||
|
||||
/** Blocks until all handlers are called or time elapses.
|
||||
@return `true` if all handlers are done or `false` if the time elapses.
|
||||
*/
|
||||
template <class Rep, class Period>
|
||||
bool
|
||||
wait_for (std::chrono::duration<
|
||||
Rep, Period> const& elapsed_time);
|
||||
|
||||
/** Blocks until all handlers are called or a time is reached.
|
||||
@return `true` if all handlers are done or `false` on timeout.
|
||||
*/
|
||||
template <class Clock, class Duration>
|
||||
bool
|
||||
wait_until (std::chrono::time_point<
|
||||
Clock, Duration> const& timeout_time);
|
||||
|
||||
/** Call a function asynchronously after all handlers are called.
|
||||
The function may be called on the callers thread.
|
||||
*/
|
||||
template <class = void>
|
||||
void
|
||||
async_wait(std::function<void(void)> f);
|
||||
|
||||
/** Create a new handler that dispatches the wrapped handler on the Context. */
|
||||
template <class Handler>
|
||||
detail::waitable_executor_wrapped_handler<waitable_executor,
|
||||
std::remove_reference_t<Handler>>
|
||||
wrap (Handler&& handler);
|
||||
|
||||
private:
|
||||
template <class = void>
|
||||
void
|
||||
increment();
|
||||
|
||||
template <class = void>
|
||||
void
|
||||
decrement();
|
||||
};
|
||||
|
||||
template <class>
|
||||
void
|
||||
waitable_executor::wait()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
cond_.wait(lock,
|
||||
[this]() { return count_ == 0; });
|
||||
}
|
||||
|
||||
template <class Rep, class Period>
|
||||
bool
|
||||
waitable_executor::wait_for (std::chrono::duration<
|
||||
Rep, Period> const& elapsed_time)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
return cond_.wait_for(lock, elapsed_time,
|
||||
[this]() { return count_ == 0; }) ==
|
||||
std::cv_status::no_timeout;
|
||||
}
|
||||
|
||||
template <class Clock, class Duration>
|
||||
bool
|
||||
waitable_executor::wait_until (std::chrono::time_point<
|
||||
Clock, Duration> const& timeout_time)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
return cond_.wait_until(lock, timeout_time,
|
||||
[this]() { return count_ == 0; }) ==
|
||||
std::cv_status::no_timeout;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class>
|
||||
void
|
||||
waitable_executor::async_wait(std::function<void(void)> f)
|
||||
{
|
||||
bool busy;
|
||||
{
|
||||
std::lock_guard<std::mutex> _(mutex_);
|
||||
busy = count_ > 0;
|
||||
if (busy)
|
||||
notify_.emplace_back(std::move(f));
|
||||
}
|
||||
if (! busy)
|
||||
f();
|
||||
}
|
||||
|
||||
template <class Handler>
|
||||
detail::waitable_executor_wrapped_handler<waitable_executor,
|
||||
std::remove_reference_t<Handler>>
|
||||
waitable_executor::wrap (Handler&& handler)
|
||||
{
|
||||
return detail::waitable_executor_wrapped_handler<
|
||||
waitable_executor, std::remove_reference_t<Handler>>(
|
||||
*this, std::forward<Handler>(handler));
|
||||
}
|
||||
|
||||
template <class>
|
||||
void
|
||||
waitable_executor::increment()
|
||||
{
|
||||
std::lock_guard<std::mutex> _(mutex_);
|
||||
++count_;
|
||||
}
|
||||
|
||||
template <class>
|
||||
void
|
||||
waitable_executor::decrement()
|
||||
{
|
||||
bool notify;
|
||||
std::vector<std::function<void(void)>> list;
|
||||
{
|
||||
std::lock_guard<std::mutex> _(mutex_);
|
||||
notify = --count_ == 0;
|
||||
if (notify)
|
||||
std::swap(list, notify_);
|
||||
}
|
||||
if (notify)
|
||||
{
|
||||
cond_.notify_all();
|
||||
for(auto& _ : list)
|
||||
_();
|
||||
}
|
||||
}
|
||||
|
||||
} // asio
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -27,12 +27,12 @@ namespace beast {
|
||||
|
||||
/** Abstract interface to a clock.
|
||||
|
||||
The abstract clock interface allows a dependency injection to take
|
||||
place so that the choice of implementation can be made at run-time
|
||||
instead of compile time. The trade-off is that the Duration used to
|
||||
represent the clock must be chosen at compile time and cannot be
|
||||
changed. This includes both the choice of representation (integers
|
||||
for example) and the period in ticks corresponding to one second.
|
||||
This makes now() a member function instead of a static member, so
|
||||
an instance of the class can be dependency injected, facilitating
|
||||
unit tests where time may be controlled.
|
||||
|
||||
An abstract_clock inherits all the nested types of the Clock
|
||||
template parameter.
|
||||
|
||||
Example:
|
||||
|
||||
@@ -40,56 +40,37 @@ namespace beast {
|
||||
|
||||
struct Implementation
|
||||
{
|
||||
abstract_clock <std::chrono::seconds>& m_clock;
|
||||
|
||||
// Dependency injection
|
||||
//
|
||||
explicit Implementation (
|
||||
abstract_clock <std::chrono::seconds>& clock)
|
||||
: m_clock (clock)
|
||||
using clock_type = abstract_clock <std::chrono::steady_clock>;
|
||||
clock_type& clock_;
|
||||
explicit Implementation (clock_type& clock)
|
||||
: clock_(clock)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
@endcode
|
||||
|
||||
@tparam The length of time, in seconds, corresponding to one tick.
|
||||
@tparam Clock A type meeting these requirements:
|
||||
http://en.cppreference.com/w/cpp/concept/Clock
|
||||
*/
|
||||
template <class Duration>
|
||||
template <class Clock>
|
||||
class abstract_clock
|
||||
{
|
||||
public:
|
||||
typedef typename Duration::rep rep;
|
||||
typedef typename Duration::period period;
|
||||
typedef Duration duration;
|
||||
typedef std::chrono::time_point <
|
||||
abstract_clock, duration> time_point;
|
||||
using rep = typename Clock::rep;
|
||||
using period = typename Clock::period;
|
||||
using duration = typename Clock::duration;
|
||||
using time_point = typename Clock::time_point;
|
||||
|
||||
virtual ~abstract_clock () { }
|
||||
static bool const is_steady = Clock::is_steady;
|
||||
|
||||
/** Returns `true` if this is a steady clock. */
|
||||
virtual bool is_steady () const = 0;
|
||||
virtual ~abstract_clock() = default;
|
||||
|
||||
/** Returns the current time. */
|
||||
virtual time_point now () const = 0;
|
||||
|
||||
#if 0
|
||||
/** Convert the specified time point to a string. */
|
||||
/** @{ */
|
||||
//virtual std::string to_string (time_point const& tp) const = 0;
|
||||
|
||||
template <class Duration2>
|
||||
std::string to_string (
|
||||
std::chrono::time_point <abstract_clock, Duration2> const& tp) const
|
||||
{
|
||||
return to_string (
|
||||
std::chrono::time_point_cast <Duration> (tp));
|
||||
}
|
||||
/** @} */
|
||||
#endif
|
||||
virtual time_point now() const = 0;
|
||||
|
||||
/** Returning elapsed ticks since the epoch. */
|
||||
rep elapsed () const
|
||||
rep elapsed()
|
||||
{
|
||||
return now().time_since_epoch().count();
|
||||
}
|
||||
@@ -99,68 +80,34 @@ public:
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class TrivialClock, class Duration>
|
||||
struct basic_abstract_clock_wrapper : public abstract_clock <Duration>
|
||||
{
|
||||
using typename abstract_clock <Duration>::duration;
|
||||
using typename abstract_clock <Duration>::time_point;
|
||||
|
||||
bool is_steady () const
|
||||
{
|
||||
return TrivialClock::is_steady;
|
||||
}
|
||||
|
||||
time_point now () const
|
||||
{
|
||||
return time_point (duration (
|
||||
std::chrono::duration_cast <duration> (
|
||||
TrivialClock::now().time_since_epoch ()).count ()));
|
||||
}
|
||||
};
|
||||
|
||||
template <class TrivialClock, class Duration>
|
||||
template <class Facade, class Clock>
|
||||
struct abstract_clock_wrapper
|
||||
: public basic_abstract_clock_wrapper <TrivialClock, Duration>
|
||||
: public abstract_clock<Facade>
|
||||
{
|
||||
// generic conversion displays the duration
|
||||
/*
|
||||
std::string to_string (typename basic_abstract_clock_wrapper <
|
||||
TrivialClock, Duration>::time_point const& tp) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << tp.time_since_epoch();
|
||||
return ss.str ();
|
||||
}
|
||||
*/
|
||||
};
|
||||
using typename abstract_clock<Facade>::duration;
|
||||
using typename abstract_clock<Facade>::time_point;
|
||||
|
||||
/*
|
||||
template <class Duration>
|
||||
struct abstract_clock_wrapper <std::chrono::system_clock, Duration>
|
||||
: public basic_abstract_clock_wrapper <std::chrono::system_clock, Duration>
|
||||
{
|
||||
typedef std::chrono::system_clock clock_type;
|
||||
std::string to_string (time_point const& tp)
|
||||
time_point
|
||||
now() const override
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << clock_type::time_point (tp.time_since_epoch ());
|
||||
return ss.str ();
|
||||
return Clock::now();
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Retrieve a discrete clock for a type implementing the Clock concept.
|
||||
The interface is created as an object with static storage duration.
|
||||
/** Returns a global instance of an abstract clock.
|
||||
@tparam Facade A type meeting these requirements:
|
||||
http://en.cppreference.com/w/cpp/concept/Clock
|
||||
@tparam Clock The actual concrete clock to use.
|
||||
*/
|
||||
template <class TrivialClock, class Duration>
|
||||
abstract_clock <Duration>& get_abstract_clock ()
|
||||
template<class Facade, class Clock = Facade>
|
||||
abstract_clock<Facade>&
|
||||
get_abstract_clock()
|
||||
{
|
||||
static detail::abstract_clock_wrapper <
|
||||
TrivialClock, Duration> clock;
|
||||
static detail::abstract_clock_wrapper<Facade, Clock> clock;
|
||||
return clock;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,25 +45,25 @@ public:
|
||||
class seconds_clock_thread
|
||||
{
|
||||
public:
|
||||
typedef std::mutex mutex;
|
||||
typedef std::condition_variable cond_var;
|
||||
typedef std::lock_guard <mutex> lock_guard;
|
||||
typedef std::unique_lock <mutex> unique_lock;
|
||||
typedef std::chrono::steady_clock clock_type;
|
||||
typedef std::chrono::seconds seconds;
|
||||
typedef std::thread thread;
|
||||
typedef std::vector <seconds_clock_worker*> workers;
|
||||
using mutex = std::mutex;
|
||||
using cond_var = std::condition_variable;
|
||||
using lock_guard = std::lock_guard <mutex>;
|
||||
using unique_lock = std::unique_lock <mutex>;
|
||||
using clock_type = std::chrono::steady_clock;
|
||||
using seconds = std::chrono::seconds;
|
||||
using thread = std::thread;
|
||||
using workers = std::vector <seconds_clock_worker*>;
|
||||
|
||||
bool m_stop;
|
||||
mutex m_mutex;
|
||||
cond_var m_cond;
|
||||
workers m_workers;
|
||||
thread m_thread;
|
||||
bool stop_;
|
||||
mutex mutex_;
|
||||
cond_var cond_;
|
||||
workers workers_;
|
||||
thread thread_;
|
||||
|
||||
seconds_clock_thread ()
|
||||
: m_stop (false)
|
||||
: stop_ (false)
|
||||
{
|
||||
m_thread = thread (std::bind(
|
||||
thread_ = thread (std::bind(
|
||||
&seconds_clock_thread::run, this));
|
||||
}
|
||||
|
||||
@@ -74,37 +74,37 @@ public:
|
||||
|
||||
void add (seconds_clock_worker& w)
|
||||
{
|
||||
lock_guard lock (m_mutex);
|
||||
m_workers.push_back (&w);
|
||||
lock_guard lock (mutex_);
|
||||
workers_.push_back (&w);
|
||||
}
|
||||
|
||||
void remove (seconds_clock_worker& w)
|
||||
{
|
||||
lock_guard lock (m_mutex);
|
||||
m_workers.erase (std::find (
|
||||
m_workers.begin (), m_workers.end(), &w));
|
||||
lock_guard lock (mutex_);
|
||||
workers_.erase (std::find (
|
||||
workers_.begin (), workers_.end(), &w));
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
if (m_thread.joinable())
|
||||
if (thread_.joinable())
|
||||
{
|
||||
{
|
||||
lock_guard lock (m_mutex);
|
||||
m_stop = true;
|
||||
lock_guard lock (mutex_);
|
||||
stop_ = true;
|
||||
}
|
||||
m_cond.notify_all();
|
||||
m_thread.join();
|
||||
cond_.notify_all();
|
||||
thread_.join();
|
||||
}
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
unique_lock lock (m_mutex);;
|
||||
unique_lock lock (mutex_);;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (auto iter : m_workers)
|
||||
for (auto iter : workers_)
|
||||
iter->sample();
|
||||
|
||||
clock_type::time_point const when (
|
||||
@@ -112,7 +112,7 @@ public:
|
||||
clock_type::now().time_since_epoch()) +
|
||||
seconds (1));
|
||||
|
||||
if (m_cond.wait_until (lock, when, [this]{ return m_stop; }))
|
||||
if (cond_.wait_until (lock, when, [this]{ return stop_; }))
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -143,24 +143,26 @@ basic_seconds_clock_main_hook()
|
||||
}
|
||||
|
||||
/** A clock whose minimum resolution is one second.
|
||||
|
||||
The purpose of this class is to optimize the performance of the now()
|
||||
member function call. It uses a dedicated thread that wakes up at least
|
||||
once per second to sample the requested trivial clock.
|
||||
@tparam TrivialClock The clock to sample.
|
||||
|
||||
@tparam Clock A type meeting these requirements:
|
||||
http://en.cppreference.com/w/cpp/concept/Clock
|
||||
*/
|
||||
template <class TrivialClock>
|
||||
template <class Clock>
|
||||
class basic_seconds_clock
|
||||
{
|
||||
public:
|
||||
typedef std::chrono::seconds resolution;
|
||||
typedef typename resolution::rep rep;
|
||||
typedef typename resolution::period period;
|
||||
typedef std::chrono::duration <rep, period> duration;
|
||||
typedef std::chrono::time_point <basic_seconds_clock> time_point;
|
||||
using rep = typename Clock::rep;
|
||||
using period = typename Clock::period;
|
||||
using duration = typename Clock::duration;
|
||||
using time_point = typename Clock::time_point;
|
||||
|
||||
static bool const is_steady = TrivialClock::is_steady;
|
||||
static bool const is_steady = Clock::is_steady;
|
||||
|
||||
static time_point now ()
|
||||
static time_point now()
|
||||
{
|
||||
// Make sure the thread is constructed before the
|
||||
// worker otherwise we will crash during destruction
|
||||
@@ -176,45 +178,36 @@ public:
|
||||
|
||||
struct worker : detail::seconds_clock_worker
|
||||
{
|
||||
typedef std::mutex mutex;
|
||||
typedef std::lock_guard <mutex> lock_guard;
|
||||
|
||||
time_point m_now;
|
||||
mutex m_mutex;
|
||||
std::mutex mutex_;
|
||||
|
||||
static time_point get_now ()
|
||||
worker()
|
||||
: m_now(Clock::now())
|
||||
{
|
||||
return time_point (floor <resolution> (
|
||||
TrivialClock::now().time_since_epoch()));
|
||||
detail::seconds_clock_thread::instance().add(*this);
|
||||
}
|
||||
|
||||
worker ()
|
||||
: m_now (get_now ())
|
||||
~worker()
|
||||
{
|
||||
detail::seconds_clock_thread::instance().add (*this);
|
||||
}
|
||||
|
||||
~worker ()
|
||||
{
|
||||
detail::seconds_clock_thread::instance().remove (*this);
|
||||
detail::seconds_clock_thread::instance().remove(*this);
|
||||
}
|
||||
|
||||
time_point now()
|
||||
{
|
||||
lock_guard lock (m_mutex);
|
||||
std::lock_guard<std::mutex> lock (mutex_);
|
||||
return m_now;
|
||||
}
|
||||
|
||||
void sample ()
|
||||
void sample()
|
||||
{
|
||||
lock_guard lock (m_mutex);
|
||||
m_now = get_now ();
|
||||
std::lock_guard<std::mutex> lock (mutex_);
|
||||
m_now = Clock::now();
|
||||
}
|
||||
};
|
||||
|
||||
static worker w;
|
||||
|
||||
return w.now ();
|
||||
return w.now();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -32,8 +32,6 @@
|
||||
#include <beast/utility/noexcept.h>
|
||||
#include <ctime>
|
||||
#include <locale>
|
||||
|
||||
#define BEAST_CHRONO_NO_TIMEPOINT_IO 1
|
||||
|
||||
/*
|
||||
|
||||
@@ -798,292 +796,8 @@ time_fmt(timezone f)
|
||||
return __time_man(f);
|
||||
}
|
||||
|
||||
#if ! BEAST_CHRONO_NO_TIMEPOINT_IO
|
||||
} // chrono
|
||||
|
||||
template <class _CharT, class _Traits, class _Duration>
|
||||
basic_istream<_CharT, _Traits>&
|
||||
operator>>(basic_istream<_CharT, _Traits>& __is,
|
||||
time_point<steady_clock, _Duration>& __tp)
|
||||
{
|
||||
_Duration __d;
|
||||
__is >> __d;
|
||||
if (__is.good())
|
||||
{
|
||||
const _CharT __u[] = {' ', 's', 'i', 'n', 'c', 'e', ' ', 'b', 'o', 'o', 't'};
|
||||
const basic_string<_CharT> __units(__u, __u + sizeof(__u)/sizeof(__u[0]));
|
||||
ios_base::iostate __err = ios_base::goodbit;
|
||||
typedef istreambuf_iterator<_CharT, _Traits> _I;
|
||||
_I __i(__is);
|
||||
_I __e;
|
||||
ptrdiff_t __k = __scan_keyword(__i, __e,
|
||||
&__units, &__units + 1,
|
||||
use_facet<ctype<_CharT> >(__is.getloc()),
|
||||
__err) - &__units;
|
||||
if (__k == 1)
|
||||
{
|
||||
// failed to read epoch string
|
||||
__is.setstate(__err);
|
||||
return __is;
|
||||
}
|
||||
__tp = time_point<steady_clock, _Duration>(__d);
|
||||
}
|
||||
else
|
||||
__is.setstate(__is.failbit);
|
||||
return __is;
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Duration>
|
||||
basic_ostream<_CharT, _Traits>&
|
||||
operator<<(basic_ostream<_CharT, _Traits>& __os,
|
||||
const time_point<system_clock, _Duration>& __tp)
|
||||
{
|
||||
typename basic_ostream<_CharT, _Traits>::sentry ok(__os);
|
||||
if (ok)
|
||||
{
|
||||
bool failed = false;
|
||||
try
|
||||
{
|
||||
const _CharT* pb = nullptr;
|
||||
const _CharT* pe = pb;
|
||||
timezone tz = utc;
|
||||
typedef timepunct<_CharT> F;
|
||||
locale loc = __os.getloc();
|
||||
if (has_facet<F>(loc))
|
||||
{
|
||||
const F& f = use_facet<F>(loc);
|
||||
pb = f.fmt().data();
|
||||
pe = pb + f.fmt().size();
|
||||
tz = f.get_timezone();
|
||||
}
|
||||
time_t __t = system_clock::to_time_t(__tp);
|
||||
tm __tm;
|
||||
if (tz == local)
|
||||
{
|
||||
if (localtime_r(&__t, &__tm) == 0)
|
||||
failed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gmtime_r(&__t, &__tm) == 0)
|
||||
failed = true;
|
||||
}
|
||||
if (!failed)
|
||||
{
|
||||
const time_put<_CharT>& tp = use_facet<time_put<_CharT> >(loc);
|
||||
if (pb == pe)
|
||||
{
|
||||
_CharT pattern[] = {'%', 'F', 'T', '%', 'H', ':', '%', 'M', ':'};
|
||||
pb = pattern;
|
||||
pe = pb + sizeof(pattern) / sizeof(_CharT);
|
||||
failed = tp.put(__os, __os, __os.fill(), &__tm, pb, pe).failed();
|
||||
if (!failed)
|
||||
{
|
||||
duration<double> __d = __tp - system_clock::from_time_t(__t) +
|
||||
seconds(__tm.tm_sec);
|
||||
if (__d.count() < 10)
|
||||
__os << _CharT('0');
|
||||
ios::fmtflags __flgs = __os.flags();
|
||||
__os.setf(ios::fixed, ios::floatfield);
|
||||
__os << __d.count();
|
||||
__os.flags(__flgs);
|
||||
if (tz == local)
|
||||
{
|
||||
_CharT sub_pattern[] = {' ', '%', 'z'};
|
||||
pb = sub_pattern;
|
||||
pe = pb + + sizeof(sub_pattern) / sizeof(_CharT);
|
||||
failed = tp.put(__os, __os, __os.fill(), &__tm, pb, pe).failed();
|
||||
}
|
||||
else
|
||||
{
|
||||
_CharT sub_pattern[] = {' ', '+', '0', '0', '0', '0', 0};
|
||||
__os << sub_pattern;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
failed = tp.put(__os, __os, __os.fill(), &__tm, pb, pe).failed();
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
failed = true;
|
||||
}
|
||||
if (failed)
|
||||
__os.setstate(ios_base::failbit | ios_base::badbit);
|
||||
}
|
||||
return __os;
|
||||
}
|
||||
|
||||
template <class _CharT, class _InputIterator>
|
||||
minutes
|
||||
__extract_z(_InputIterator& __b, _InputIterator __e,
|
||||
ios_base::iostate& __err, const ctype<_CharT>& __ct)
|
||||
{
|
||||
int __minn = 0;
|
||||
if (__b != __e)
|
||||
{
|
||||
char __cn = __ct.narrow(*__b, 0);
|
||||
if (__cn != '+' && __cn != '-')
|
||||
{
|
||||
__err |= ios_base::failbit;
|
||||
return minutes(0);
|
||||
}
|
||||
int __sn = __cn == '-' ? -1 : 1;
|
||||
int __hr = 0;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
if (++__b == __e)
|
||||
{
|
||||
__err |= ios_base::eofbit | ios_base::failbit;
|
||||
return minutes(0);
|
||||
}
|
||||
__cn = __ct.narrow(*__b, 0);
|
||||
if (!('0' <= __cn && __cn <= '9'))
|
||||
{
|
||||
__err |= ios_base::failbit;
|
||||
return minutes(0);
|
||||
}
|
||||
__hr = __hr * 10 + __cn - '0';
|
||||
}
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
if (++__b == __e)
|
||||
{
|
||||
__err |= ios_base::eofbit | ios_base::failbit;
|
||||
return minutes(0);
|
||||
}
|
||||
__cn = __ct.narrow(*__b, 0);
|
||||
if (!('0' <= __cn && __cn <= '9'))
|
||||
{
|
||||
__err |= ios_base::failbit;
|
||||
return minutes(0);
|
||||
}
|
||||
__minn = __minn * 10 + __cn - '0';
|
||||
}
|
||||
if (++__b == __e)
|
||||
__err |= ios_base::eofbit;
|
||||
__minn += __hr * 60;
|
||||
__minn *= __sn;
|
||||
}
|
||||
else
|
||||
__err |= ios_base::eofbit | ios_base::failbit;
|
||||
return minutes(__minn);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Duration>
|
||||
basic_istream<_CharT, _Traits>&
|
||||
operator>>(basic_istream<_CharT, _Traits>& __is,
|
||||
time_point<system_clock, _Duration>& __tp)
|
||||
{
|
||||
typename basic_istream<_CharT,_Traits>::sentry ok(__is);
|
||||
if (ok)
|
||||
{
|
||||
ios_base::iostate err = ios_base::goodbit;
|
||||
try
|
||||
{
|
||||
const _CharT* pb = nullptr;
|
||||
const _CharT* pe = pb;
|
||||
typedef timepunct<_CharT> F;
|
||||
locale loc = __is.getloc();
|
||||
timezone tz = utc;
|
||||
if (has_facet<F>(loc))
|
||||
{
|
||||
const F& f = use_facet<F>(loc);
|
||||
pb = f.fmt().data();
|
||||
pe = pb + f.fmt().size();
|
||||
tz = f.get_timezone();
|
||||
}
|
||||
const time_get<_CharT>& tg = use_facet<time_get<_CharT> >(loc);
|
||||
const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(loc);
|
||||
tm __tm = {0};
|
||||
typedef istreambuf_iterator<_CharT, _Traits> _I;
|
||||
if (pb == pe)
|
||||
{
|
||||
_CharT pattern[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd',
|
||||
'T', '%', 'H', ':', '%', 'M', ':'};
|
||||
pb = pattern;
|
||||
pe = pb + sizeof(pattern) / sizeof(_CharT);
|
||||
tg.get(__is, 0, __is, err, &__tm, pb, pe);
|
||||
if (err & ios_base::failbit)
|
||||
goto __exit;
|
||||
double __sec;
|
||||
_CharT __c = _CharT();
|
||||
__is >> __sec;
|
||||
if (__is.fail())
|
||||
{
|
||||
err |= ios_base::failbit;
|
||||
goto __exit;
|
||||
}
|
||||
_I __i(__is);
|
||||
_I __eof;
|
||||
__c = *__i;
|
||||
if (++__i == __eof || __c != ' ')
|
||||
{
|
||||
err |= ios_base::failbit;
|
||||
goto __exit;
|
||||
}
|
||||
minutes __minn = __extract_z(__i, __eof, err, __ct);
|
||||
if (err & ios_base::failbit)
|
||||
goto __exit;
|
||||
time_t __t;
|
||||
__t = timegm(&__tm);
|
||||
__tp = system_clock::from_time_t(__t) - __minn
|
||||
+ round<microseconds>(duration<double>(__sec));
|
||||
}
|
||||
else
|
||||
{
|
||||
const _CharT __z[2] = {'%', 'z'};
|
||||
const _CharT* __fz = std::search(pb, pe, __z, __z+2);
|
||||
tg.get(__is, 0, __is, err, &__tm, pb, __fz);
|
||||
minutes __minn(0);
|
||||
if (__fz != pe)
|
||||
{
|
||||
if (err != ios_base::goodbit)
|
||||
{
|
||||
err |= ios_base::failbit;
|
||||
goto __exit;
|
||||
}
|
||||
_I __i(__is);
|
||||
_I __eof;
|
||||
__minn = __extract_z(__i, __eof, err, __ct);
|
||||
if (err & ios_base::failbit)
|
||||
goto __exit;
|
||||
if (__fz+2 != pe)
|
||||
{
|
||||
if (err != ios_base::goodbit)
|
||||
{
|
||||
err |= ios_base::failbit;
|
||||
goto __exit;
|
||||
}
|
||||
tg.get(__is, 0, __is, err, &__tm, __fz+2, pe);
|
||||
if (err & ios_base::failbit)
|
||||
goto __exit;
|
||||
}
|
||||
}
|
||||
__tm.tm_isdst = -1;
|
||||
time_t __t;
|
||||
if (tz == utc || __fz != pe)
|
||||
__t = timegm(&__tm);
|
||||
else
|
||||
__t = mktime(&__tm);
|
||||
__tp = system_clock::from_time_t(__t) - __minn;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
err |= ios_base::badbit | ios_base::failbit;
|
||||
}
|
||||
__exit:
|
||||
__is.setstate(err);
|
||||
}
|
||||
return __is;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // chrono
|
||||
|
||||
//_LIBCPP_END_NAMESPACE_STD
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_CHRONO_UTIL_H_INCLUDED
|
||||
#define BEAST_CHRONO_UTIL_H_INCLUDED
|
||||
#ifndef BEAST_CHRONO_CHRONO_UTIL_H_INCLUDED
|
||||
#define BEAST_CHRONO_CHRONO_UTIL_H_INCLUDED
|
||||
|
||||
// From Howard Hinnant
|
||||
// http://home.roadrunner.com/~hinnant/duration_io/chrono_util.html
|
||||
|
||||
@@ -25,68 +25,73 @@
|
||||
namespace beast {
|
||||
|
||||
/** Manual clock implementation.
|
||||
|
||||
This concrete class implements the @ref abstract_clock interface and
|
||||
allows the time to be advanced manually, mainly for the purpose of
|
||||
providing a clock in unit tests.
|
||||
@tparam The length of time, in seconds, corresponding to one tick.
|
||||
|
||||
@tparam Clock A type meeting these requirements:
|
||||
http://en.cppreference.com/w/cpp/concept/Clock
|
||||
*/
|
||||
template <class Duration, bool IsSteady = true>
|
||||
class manual_clock : public abstract_clock <Duration>
|
||||
template <class Clock>
|
||||
class manual_clock
|
||||
: public abstract_clock<Clock>
|
||||
{
|
||||
public:
|
||||
using typename abstract_clock <Duration>::rep;
|
||||
using typename abstract_clock <Duration>::duration;
|
||||
using typename abstract_clock <Duration>::time_point;
|
||||
|
||||
explicit manual_clock (time_point const& t = time_point (Duration (0)))
|
||||
: m_now (t)
|
||||
{
|
||||
}
|
||||
|
||||
bool is_steady () const
|
||||
{
|
||||
return IsSteady;
|
||||
}
|
||||
|
||||
time_point now () const
|
||||
{
|
||||
return m_now;
|
||||
}
|
||||
|
||||
#if 0
|
||||
std::string to_string (time_point const& tp) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << tp.time_since_epoch() << " from start";
|
||||
return ss.str ();
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Set the current time of the manual clock.
|
||||
Precondition:
|
||||
! IsSteady || t > now()
|
||||
*/
|
||||
void set (time_point const& t)
|
||||
{
|
||||
//if (IsSteady)
|
||||
m_now = t;
|
||||
}
|
||||
|
||||
/** Convenience for setting the time using a duration in @ref rep units. */
|
||||
void set (rep v)
|
||||
{
|
||||
set (time_point (duration (v)));
|
||||
}
|
||||
|
||||
/** Convenience for advancing the clock by one. */
|
||||
manual_clock& operator++ ()
|
||||
{
|
||||
m_now += duration (1);
|
||||
return *this;
|
||||
}
|
||||
using typename abstract_clock<Clock>::rep;
|
||||
using typename abstract_clock<Clock>::duration;
|
||||
using typename abstract_clock<Clock>::time_point;
|
||||
|
||||
private:
|
||||
time_point m_now;
|
||||
time_point now_;
|
||||
|
||||
public:
|
||||
explicit
|
||||
manual_clock (time_point const& now = time_point(duration(0)))
|
||||
: now_(now)
|
||||
{
|
||||
}
|
||||
|
||||
time_point
|
||||
now() const override
|
||||
{
|
||||
return now_;
|
||||
}
|
||||
|
||||
/** Set the current time of the manual clock. */
|
||||
void
|
||||
set (time_point const& when)
|
||||
{
|
||||
assert(! Clock::is_steady || when >= now_);
|
||||
now_ = when;
|
||||
}
|
||||
|
||||
/** Convenience for setting the time in seconds from epoch. */
|
||||
template <class Integer>
|
||||
void
|
||||
set(Integer seconds_from_epoch)
|
||||
{
|
||||
set(time_point(duration(
|
||||
std::chrono::seconds(seconds_from_epoch))));
|
||||
}
|
||||
|
||||
/** Advance the clock by a duration. */
|
||||
template <class Rep, class Period>
|
||||
void
|
||||
advance(std::chrono::duration<Rep, Period> const& elapsed)
|
||||
{
|
||||
assert(! Clock::is_steady ||
|
||||
(now_ + elapsed) >= now_);
|
||||
now_ += elapsed;
|
||||
}
|
||||
|
||||
/** Convenience for advancing the clock by one second. */
|
||||
manual_clock&
|
||||
operator++ ()
|
||||
{
|
||||
advance(std::chrono::seconds(1));
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -20,11 +20,8 @@
|
||||
// MODULES: ../impl/chrono_io.cpp
|
||||
|
||||
#include <beast/chrono/abstract_clock.h>
|
||||
#include <beast/chrono/abstract_clock_io.h>
|
||||
#include <beast/chrono/manual_clock.h>
|
||||
|
||||
#include <beast/unit_test/suite.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
@@ -34,7 +31,8 @@ namespace beast {
|
||||
class abstract_clock_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
void test (abstract_clock <std::chrono::seconds>& c)
|
||||
template <class Clock>
|
||||
void test (abstract_clock<Clock>& c)
|
||||
{
|
||||
{
|
||||
auto const t1 (c.now ());
|
||||
@@ -53,18 +51,18 @@ public:
|
||||
|
||||
void test_manual ()
|
||||
{
|
||||
typedef manual_clock <std::chrono::seconds> clock_type;
|
||||
using clock_type = manual_clock<std::chrono::steady_clock>;
|
||||
clock_type c;
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "now() = " << c.now () << std::endl;
|
||||
ss << "now() = " << c.now().time_since_epoch() << std::endl;
|
||||
|
||||
c.set (clock_type::time_point (std::chrono::seconds (1)));
|
||||
ss << "now() = " << c.now () << std::endl;
|
||||
c.set (clock_type::time_point (std::chrono::seconds(1)));
|
||||
ss << "now() = " << c.now().time_since_epoch() << std::endl;
|
||||
|
||||
c.set (clock_type::time_point (std::chrono::seconds (2)));
|
||||
ss << "now() = " << c.now () << std::endl;
|
||||
c.set (clock_type::time_point (std::chrono::seconds(2)));
|
||||
ss << "now() = " << c.now().time_since_epoch() << std::endl;
|
||||
|
||||
log << ss.str();
|
||||
}
|
||||
@@ -72,16 +70,16 @@ public:
|
||||
void run ()
|
||||
{
|
||||
log << "steady_clock";
|
||||
test (get_abstract_clock <std::chrono::steady_clock,
|
||||
std::chrono::seconds> ());
|
||||
test (get_abstract_clock<
|
||||
std::chrono::steady_clock>());
|
||||
|
||||
log << "system_clock";
|
||||
test (get_abstract_clock <std::chrono::system_clock,
|
||||
std::chrono::seconds> ());
|
||||
test (get_abstract_clock<
|
||||
std::chrono::system_clock>());
|
||||
|
||||
log << "high_resolution_clock";
|
||||
test (get_abstract_clock <std::chrono::high_resolution_clock,
|
||||
std::chrono::seconds> ());
|
||||
test (get_abstract_clock<
|
||||
std::chrono::high_resolution_clock>());
|
||||
|
||||
log << "manual_clock";
|
||||
test_manual ();
|
||||
@@ -90,6 +88,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(abstract_clock,chrono,beast);
|
||||
BEAST_DEFINE_TESTSUITE_MANUAL(abstract_clock,chrono,beast);
|
||||
|
||||
}
|
||||
|
||||
@@ -44,10 +44,6 @@
|
||||
#define BEAST_DISABLE_CONTRACT_CHECKS 0
|
||||
#endif
|
||||
|
||||
#ifndef BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES
|
||||
#define BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES 0
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
// Ideas from boost
|
||||
|
||||
// Intel
|
||||
#ifndef BEAST_CONFIG_SELECTCOMPILERCONFIG_H_INCLUDED
|
||||
#define BEAST_CONFIG_SELECTCOMPILERCONFIG_H_INCLUDED
|
||||
|
||||
#if defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)
|
||||
#define BEAST_COMPILER_CONFIG "config/compiler/Intel.h"
|
||||
|
||||
@@ -42,3 +45,4 @@
|
||||
#error "Unsupported compiler."
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
// Ideas from boost
|
||||
|
||||
// Android, which must be manually set by defining BEAST_ANDROID
|
||||
#ifndef BEAST_CONFIG_SELECTPLATFORMCONFIG_H_INCLUDED
|
||||
#define BEAST_CONFIG_SELECTPLATFORMCONFIG_H_INCLUDED
|
||||
|
||||
#if defined(BEAST_ANDROID)
|
||||
#define BEAST_PLATFORM_CONFIG "config/platform/Android.h"
|
||||
|
||||
@@ -42,3 +45,4 @@
|
||||
#else
|
||||
#error "Unsupported platform."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -19,4 +19,8 @@
|
||||
|
||||
// Microsoft Visual C++ compiler configuration
|
||||
|
||||
#ifndef BEAST_CONFIG_COMPILER_VISUALC_H_INCLUDED
|
||||
#define BEAST_CONFIG_COMPILER_VISUALC_H_INCLUDED
|
||||
|
||||
#include <beast/utility/noexcept.h>
|
||||
#endif
|
||||
|
||||
@@ -19,8 +19,12 @@
|
||||
|
||||
// Android platform configuration
|
||||
|
||||
#ifndef BEAST_CONFIG_PLATFORM_ANDROID_H_INCLUDED
|
||||
#define BEAST_CONFIG_PLATFORM_ANDROID_H_INCLUDED
|
||||
|
||||
#ifdef BEAST_ANDROID
|
||||
#undef BEAST_ANDROID
|
||||
#endif
|
||||
#define BEAST_ANDROID 1
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,10 +21,4 @@
|
||||
#include <BeastConfig.h>
|
||||
#endif
|
||||
|
||||
#include <beast/container/impl/spookyv2.cpp>
|
||||
#include <beast/container/impl/siphash.cpp>
|
||||
|
||||
#include <beast/container/tests/aged_associative_container.test.cpp>
|
||||
#include <beast/container/tests/buffer_view.test.cpp>
|
||||
#include <beast/container/tests/hardened_hash.test.cpp>
|
||||
#include <beast/container/tests/hash_append.test.cpp>
|
||||
|
||||
@@ -31,12 +31,12 @@ namespace beast {
|
||||
template <
|
||||
class Key,
|
||||
class T,
|
||||
class Duration = std::chrono::seconds,
|
||||
class Clock = std::chrono::steady_clock,
|
||||
class Compare = std::less <Key>,
|
||||
class Allocator = std::allocator <std::pair <Key const, T>>
|
||||
>
|
||||
using aged_map = detail::aged_ordered_container <
|
||||
false, true, Key, T, Duration, Compare, Allocator>;
|
||||
false, true, Key, T, Clock, Compare, Allocator>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -31,12 +31,12 @@ namespace beast {
|
||||
template <
|
||||
class Key,
|
||||
class T,
|
||||
class Duration = std::chrono::seconds,
|
||||
class Clock = std::chrono::steady_clock,
|
||||
class Compare = std::less <Key>,
|
||||
class Allocator = std::allocator <std::pair <Key const, T>>
|
||||
>
|
||||
using aged_multimap = detail::aged_ordered_container <
|
||||
true, true, Key, T, Duration, Compare, Allocator>;
|
||||
true, true, Key, T, Clock, Compare, Allocator>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -30,12 +30,12 @@ namespace beast {
|
||||
|
||||
template <
|
||||
class Key,
|
||||
class Duration = std::chrono::seconds,
|
||||
class Clock = std::chrono::steady_clock,
|
||||
class Compare = std::less <Key>,
|
||||
class Allocator = std::allocator <Key>
|
||||
>
|
||||
using aged_multiset = detail::aged_ordered_container <
|
||||
true, false, Key, void, Duration, Compare, Allocator>;
|
||||
true, false, Key, void, Clock, Compare, Allocator>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -30,12 +30,12 @@ namespace beast {
|
||||
|
||||
template <
|
||||
class Key,
|
||||
class Duration = std::chrono::seconds,
|
||||
class Clock = std::chrono::steady_clock,
|
||||
class Compare = std::less <Key>,
|
||||
class Allocator = std::allocator <Key>
|
||||
>
|
||||
using aged_set = detail::aged_ordered_container <
|
||||
false, false, Key, void, Duration, Compare, Allocator>;
|
||||
false, false, Key, void, Clock, Compare, Allocator>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -31,13 +31,13 @@ namespace beast {
|
||||
template <
|
||||
class Key,
|
||||
class T,
|
||||
class Duration = std::chrono::seconds,
|
||||
class Clock = std::chrono::steady_clock,
|
||||
class Hash = std::hash <Key>,
|
||||
class KeyEqual = std::equal_to <Key>,
|
||||
class Allocator = std::allocator <std::pair <Key const, T>>
|
||||
>
|
||||
using aged_unordered_map = detail::aged_unordered_container <
|
||||
false, true, Key, T, Duration, Hash, KeyEqual, Allocator>;
|
||||
false, true, Key, T, Clock, Hash, KeyEqual, Allocator>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -31,13 +31,13 @@ namespace beast {
|
||||
template <
|
||||
class Key,
|
||||
class T,
|
||||
class Duration = std::chrono::seconds,
|
||||
class Clock = std::chrono::steady_clock,
|
||||
class Hash = std::hash <Key>,
|
||||
class KeyEqual = std::equal_to <Key>,
|
||||
class Allocator = std::allocator <std::pair <Key const, T>>
|
||||
>
|
||||
using aged_unordered_multimap = detail::aged_unordered_container <
|
||||
true, true, Key, T, Duration, Hash, KeyEqual, Allocator>;
|
||||
true, true, Key, T, Clock, Hash, KeyEqual, Allocator>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -30,13 +30,13 @@ namespace beast {
|
||||
|
||||
template <
|
||||
class Key,
|
||||
class Duration = std::chrono::seconds,
|
||||
class Clock = std::chrono::steady_clock,
|
||||
class Hash = std::hash <Key>,
|
||||
class KeyEqual = std::equal_to <Key>,
|
||||
class Allocator = std::allocator <Key>
|
||||
>
|
||||
using aged_unordered_multiset = detail::aged_unordered_container <
|
||||
true, false, Key, void, Duration, Hash, KeyEqual, Allocator>;
|
||||
true, false, Key, void, Clock, Hash, KeyEqual, Allocator>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -30,13 +30,13 @@ namespace beast {
|
||||
|
||||
template <
|
||||
class Key,
|
||||
class Duration = std::chrono::seconds,
|
||||
class Clock = std::chrono::steady_clock,
|
||||
class Hash = std::hash <Key>,
|
||||
class KeyEqual = std::equal_to <Key>,
|
||||
class Allocator = std::allocator <Key>
|
||||
>
|
||||
using aged_unordered_set = detail::aged_unordered_container <
|
||||
false, false, Key, void, Duration, Hash, KeyEqual, Allocator>;
|
||||
false, false, Key, void, Clock, Hash, KeyEqual, Allocator>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_CYCLIC_ITERATOR_H_INCLUDED
|
||||
#define BEAST_CYCLIC_ITERATOR_H_INCLUDED
|
||||
#ifndef BEAST_CONTAINER_CYCLIC_ITERATOR_H_INCLUDED
|
||||
#define BEAST_CONTAINER_CYCLIC_ITERATOR_H_INCLUDED
|
||||
|
||||
#include <iterator>
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_CONTAINER_AGED_ASSOCIATIVE_CONTAINER_H_INCLUDED
|
||||
#define BEAST_CONTAINER_AGED_ASSOCIATIVE_CONTAINER_H_INCLUDED
|
||||
#ifndef BEAST_CONTAINER_DETAIL_AGED_ASSOCIATIVE_CONTAINER_H_INCLUDED
|
||||
#define BEAST_CONTAINER_DETAIL_AGED_ASSOCIATIVE_CONTAINER_H_INCLUDED
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_CONTAINER_AGED_CONTAINER_ITERATOR_H_INCLUDED
|
||||
#define BEAST_CONTAINER_AGED_CONTAINER_ITERATOR_H_INCLUDED
|
||||
#ifndef BEAST_CONTAINER_DETAIL_AGED_CONTAINER_ITERATOR_H_INCLUDED
|
||||
#define BEAST_CONTAINER_DETAIL_AGED_CONTAINER_ITERATOR_H_INCLUDED
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
@@ -49,7 +49,7 @@ class aged_container_iterator
|
||||
: public Base
|
||||
{
|
||||
public:
|
||||
typedef typename Iterator::value_type::stashed::time_point time_point;
|
||||
using time_point = typename Iterator::value_type::stashed::time_point;
|
||||
|
||||
// Could be '= default', but Visual Studio 2013 chokes on it [Aug 2014]
|
||||
aged_container_iterator ()
|
||||
|
||||
@@ -17,20 +17,17 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_CONTAINER_AGED_ORDERED_CONTAINER_H_INCLUDED
|
||||
#define BEAST_CONTAINER_AGED_ORDERED_CONTAINER_H_INCLUDED
|
||||
#ifndef BEAST_CONTAINER_DETAIL_AGED_ORDERED_CONTAINER_H_INCLUDED
|
||||
#define BEAST_CONTAINER_DETAIL_AGED_ORDERED_CONTAINER_H_INCLUDED
|
||||
|
||||
#include <beast/container/detail/aged_container_iterator.h>
|
||||
#include <beast/container/detail/aged_associative_container.h>
|
||||
|
||||
#include <beast/container/aged_container.h>
|
||||
|
||||
#include <beast/chrono/abstract_clock.h>
|
||||
#include <beast/utility/empty_base_optimization.h>
|
||||
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <boost/intrusive/set.hpp>
|
||||
|
||||
#include <boost/version.hpp>
|
||||
#include <beast/cxx14/algorithm.h> // <algorithm>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
@@ -49,10 +46,17 @@ struct is_boost_reverse_iterator
|
||||
: std::false_type
|
||||
{};
|
||||
|
||||
#if BOOST_VERSION >= 105800
|
||||
template <class It>
|
||||
struct is_boost_reverse_iterator<boost::intrusive::reverse_iterator<It>>
|
||||
: std::true_type
|
||||
{};
|
||||
#else
|
||||
template <class It>
|
||||
struct is_boost_reverse_iterator<boost::intrusive::detail::reverse_iterator<It>>
|
||||
: std::true_type
|
||||
{};
|
||||
#endif
|
||||
|
||||
/** Associative container where each element is also indexed by time.
|
||||
|
||||
@@ -75,7 +79,7 @@ template <
|
||||
bool IsMap,
|
||||
class Key,
|
||||
class T,
|
||||
class Duration = std::chrono::seconds,
|
||||
class Clock = std::chrono::steady_clock,
|
||||
class Compare = std::less <Key>,
|
||||
class Allocator = std::allocator <
|
||||
typename std::conditional <IsMap,
|
||||
@@ -85,25 +89,20 @@ template <
|
||||
class aged_ordered_container
|
||||
{
|
||||
public:
|
||||
typedef abstract_clock <Duration> clock_type;
|
||||
typedef typename clock_type::time_point time_point;
|
||||
typedef typename clock_type::duration duration;
|
||||
typedef Key key_type;
|
||||
typedef T mapped_type;
|
||||
typedef typename std::conditional <
|
||||
IsMap,
|
||||
std::pair <Key const, T>,
|
||||
Key>::type value_type;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
using clock_type = abstract_clock<Clock>;
|
||||
using time_point = typename clock_type::time_point;
|
||||
using duration = typename clock_type::duration;
|
||||
using key_type = Key;
|
||||
using mapped_type = T;
|
||||
using value_type = typename std::conditional <
|
||||
IsMap, std::pair <Key const, T>, Key>::type;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
// Introspection (for unit tests)
|
||||
typedef std::false_type is_unordered;
|
||||
typedef std::integral_constant <bool, IsMulti> is_multi;
|
||||
typedef std::integral_constant <bool, IsMap> is_map;
|
||||
|
||||
// VFALCO TODO How can we reorder the declarations to keep
|
||||
// all the public things together contiguously?
|
||||
using is_unordered = std::false_type;
|
||||
using is_multi = std::integral_constant <bool, IsMulti>;
|
||||
using is_map = std::integral_constant <bool, IsMap>;
|
||||
|
||||
private:
|
||||
static Key const& extract (value_type const& value)
|
||||
@@ -126,8 +125,8 @@ private:
|
||||
// need to see the container declaration.
|
||||
struct stashed
|
||||
{
|
||||
typedef typename aged_ordered_container::value_type value_type;
|
||||
typedef typename aged_ordered_container::time_point time_point;
|
||||
using value_type = typename aged_ordered_container::value_type;
|
||||
using time_point = typename aged_ordered_container::time_point;
|
||||
};
|
||||
|
||||
element (
|
||||
@@ -244,11 +243,10 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
typedef typename boost::intrusive::make_list <element,
|
||||
boost::intrusive::constant_time_size <false>
|
||||
>::type list_type;
|
||||
using list_type = typename boost::intrusive::make_list <element,
|
||||
boost::intrusive::constant_time_size <false>>::type;
|
||||
|
||||
typedef typename std::conditional <
|
||||
using cont_type = typename std::conditional <
|
||||
IsMulti,
|
||||
typename boost::intrusive::make_multiset <element,
|
||||
boost::intrusive::constant_time_size <true>
|
||||
@@ -256,10 +254,10 @@ private:
|
||||
typename boost::intrusive::make_set <element,
|
||||
boost::intrusive::constant_time_size <true>
|
||||
>::type
|
||||
>::type cont_type;
|
||||
>::type;
|
||||
|
||||
typedef typename std::allocator_traits <
|
||||
Allocator>::template rebind_alloc <element> ElementAllocator;
|
||||
using ElementAllocator = typename std::allocator_traits <
|
||||
Allocator>::template rebind_alloc <element>;
|
||||
|
||||
using ElementAllocatorTraits = std::allocator_traits <ElementAllocator>;
|
||||
|
||||
@@ -427,29 +425,29 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
typedef Compare key_compare;
|
||||
typedef typename std::conditional <
|
||||
using key_compare = Compare;
|
||||
using value_compare = typename std::conditional <
|
||||
IsMap,
|
||||
pair_value_compare,
|
||||
Compare>::type value_compare;
|
||||
typedef Allocator allocator_type;
|
||||
typedef value_type& reference;
|
||||
typedef value_type const& const_reference;
|
||||
typedef typename std::allocator_traits <
|
||||
Allocator>::pointer pointer;
|
||||
typedef typename std::allocator_traits <
|
||||
Allocator>::const_pointer const_pointer;
|
||||
Compare>::type;
|
||||
using allocator_type = Allocator;
|
||||
using reference = value_type&;
|
||||
using const_reference = value_type const&;
|
||||
using pointer = typename std::allocator_traits <
|
||||
Allocator>::pointer;
|
||||
using const_pointer = typename std::allocator_traits <
|
||||
Allocator>::const_pointer;
|
||||
|
||||
// A set (that is, !IsMap) iterator is aways const because the elements
|
||||
// of a set are immutable.
|
||||
typedef detail::aged_container_iterator <!IsMap,
|
||||
typename cont_type::iterator> iterator;
|
||||
typedef detail::aged_container_iterator <true,
|
||||
typename cont_type::iterator> const_iterator;
|
||||
typedef detail::aged_container_iterator <!IsMap,
|
||||
typename cont_type::reverse_iterator> reverse_iterator;
|
||||
typedef detail::aged_container_iterator <true,
|
||||
typename cont_type::reverse_iterator> const_reverse_iterator;
|
||||
// A set iterator (IsMap==false) is always const
|
||||
// because the elements of a set are immutable.
|
||||
using iterator = detail::aged_container_iterator<
|
||||
! IsMap, typename cont_type::iterator>;
|
||||
using const_iterator = detail::aged_container_iterator<
|
||||
true, typename cont_type::iterator>;
|
||||
using reverse_iterator = detail::aged_container_iterator<
|
||||
! IsMap, typename cont_type::reverse_iterator>;
|
||||
using const_reverse_iterator = detail::aged_container_iterator<
|
||||
true, typename cont_type::reverse_iterator>;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
@@ -463,16 +461,16 @@ public:
|
||||
class chronological_t
|
||||
{
|
||||
public:
|
||||
// A set (that is, !IsMap) iterator is aways const because the elements
|
||||
// of a set are immutable.
|
||||
typedef detail::aged_container_iterator <!IsMap,
|
||||
typename list_type::iterator> iterator;
|
||||
typedef detail::aged_container_iterator <true,
|
||||
typename list_type::iterator> const_iterator;
|
||||
typedef detail::aged_container_iterator <!IsMap,
|
||||
typename list_type::reverse_iterator> reverse_iterator;
|
||||
typedef detail::aged_container_iterator <true,
|
||||
typename list_type::reverse_iterator> const_reverse_iterator;
|
||||
// A set iterator (IsMap==false) is always const
|
||||
// because the elements of a set are immutable.
|
||||
using iterator = detail::aged_container_iterator<
|
||||
! IsMap, typename list_type::iterator>;
|
||||
using const_iterator = detail::aged_container_iterator<
|
||||
true, typename list_type::iterator>;
|
||||
using reverse_iterator = detail::aged_container_iterator<
|
||||
! IsMap, typename list_type::reverse_iterator>;
|
||||
using const_reverse_iterator = detail::aged_container_iterator<
|
||||
true, typename list_type::reverse_iterator>;
|
||||
|
||||
iterator begin ()
|
||||
{
|
||||
@@ -570,6 +568,8 @@ public:
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
aged_ordered_container() = delete;
|
||||
|
||||
explicit aged_ordered_container (clock_type& clock);
|
||||
|
||||
aged_ordered_container (clock_type& clock,
|
||||
@@ -1237,8 +1237,8 @@ private:
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
class Clock, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
aged_ordered_container (
|
||||
clock_type& clock)
|
||||
: m_config (clock)
|
||||
@@ -1246,8 +1246,8 @@ aged_ordered_container (
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
class Clock, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
aged_ordered_container (
|
||||
clock_type& clock,
|
||||
Compare const& comp)
|
||||
@@ -1256,8 +1256,8 @@ aged_ordered_container (
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
class Clock, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
aged_ordered_container (
|
||||
clock_type& clock,
|
||||
Allocator const& alloc)
|
||||
@@ -1266,8 +1266,8 @@ aged_ordered_container (
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
class Clock, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
aged_ordered_container (
|
||||
clock_type& clock,
|
||||
Compare const& comp,
|
||||
@@ -1277,9 +1277,9 @@ aged_ordered_container (
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <class InputIt>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
aged_ordered_container (InputIt first, InputIt last,
|
||||
clock_type& clock)
|
||||
: m_config (clock)
|
||||
@@ -1288,9 +1288,9 @@ aged_ordered_container (InputIt first, InputIt last,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <class InputIt>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
aged_ordered_container (InputIt first, InputIt last,
|
||||
clock_type& clock,
|
||||
Compare const& comp)
|
||||
@@ -1300,9 +1300,9 @@ aged_ordered_container (InputIt first, InputIt last,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <class InputIt>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
aged_ordered_container (InputIt first, InputIt last,
|
||||
clock_type& clock,
|
||||
Allocator const& alloc)
|
||||
@@ -1312,9 +1312,9 @@ aged_ordered_container (InputIt first, InputIt last,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <class InputIt>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
aged_ordered_container (InputIt first, InputIt last,
|
||||
clock_type& clock,
|
||||
Compare const& comp,
|
||||
@@ -1325,8 +1325,8 @@ aged_ordered_container (InputIt first, InputIt last,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
class Clock, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
aged_ordered_container (aged_ordered_container const& other)
|
||||
: m_config (other.m_config)
|
||||
{
|
||||
@@ -1334,8 +1334,8 @@ aged_ordered_container (aged_ordered_container const& other)
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
class Clock, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
aged_ordered_container (aged_ordered_container const& other,
|
||||
Allocator const& alloc)
|
||||
: m_config (other.m_config, alloc)
|
||||
@@ -1344,8 +1344,8 @@ aged_ordered_container (aged_ordered_container const& other,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
class Clock, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
aged_ordered_container (aged_ordered_container&& other)
|
||||
: m_config (std::move (other.m_config))
|
||||
, m_cont (std::move (other.m_cont))
|
||||
@@ -1354,8 +1354,8 @@ aged_ordered_container (aged_ordered_container&& other)
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
class Clock, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
aged_ordered_container (aged_ordered_container&& other,
|
||||
Allocator const& alloc)
|
||||
: m_config (std::move (other.m_config), alloc)
|
||||
@@ -1365,8 +1365,8 @@ aged_ordered_container (aged_ordered_container&& other,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
class Clock, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
aged_ordered_container (std::initializer_list <value_type> init,
|
||||
clock_type& clock)
|
||||
: m_config (clock)
|
||||
@@ -1375,8 +1375,8 @@ aged_ordered_container (std::initializer_list <value_type> init,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
class Clock, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
aged_ordered_container (std::initializer_list <value_type> init,
|
||||
clock_type& clock,
|
||||
Compare const& comp)
|
||||
@@ -1386,8 +1386,8 @@ aged_ordered_container (std::initializer_list <value_type> init,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
class Clock, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
aged_ordered_container (std::initializer_list <value_type> init,
|
||||
clock_type& clock,
|
||||
Allocator const& alloc)
|
||||
@@ -1397,8 +1397,8 @@ aged_ordered_container (std::initializer_list <value_type> init,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
class Clock, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
aged_ordered_container (std::initializer_list <value_type> init,
|
||||
clock_type& clock,
|
||||
Compare const& comp,
|
||||
@@ -1409,17 +1409,17 @@ aged_ordered_container (std::initializer_list <value_type> init,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
class Clock, class Compare, class Allocator>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
~aged_ordered_container()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
auto
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
operator= (aged_ordered_container const& other) ->
|
||||
aged_ordered_container&
|
||||
{
|
||||
@@ -1433,9 +1433,9 @@ operator= (aged_ordered_container const& other) ->
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
auto
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
operator= (aged_ordered_container&& other) ->
|
||||
aged_ordered_container&
|
||||
{
|
||||
@@ -1447,9 +1447,9 @@ operator= (aged_ordered_container&& other) ->
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
auto
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
operator= (std::initializer_list <value_type> init) ->
|
||||
aged_ordered_container&
|
||||
{
|
||||
@@ -1461,10 +1461,10 @@ operator= (std::initializer_list <value_type> init) ->
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <class K, bool maybe_multi, bool maybe_map, class>
|
||||
typename std::conditional <IsMap, T, void*>::type&
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
at (K const& k)
|
||||
{
|
||||
auto const iter (m_cont.find (k,
|
||||
@@ -1475,10 +1475,10 @@ at (K const& k)
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <class K, bool maybe_multi, bool maybe_map, class>
|
||||
typename std::conditional <IsMap, T, void*>::type const&
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
at (K const& k) const
|
||||
{
|
||||
auto const iter (m_cont.find (k,
|
||||
@@ -1489,10 +1489,10 @@ at (K const& k) const
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <bool maybe_multi, bool maybe_map, class>
|
||||
typename std::conditional <IsMap, T, void*>::type&
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
operator[] (Key const& key)
|
||||
{
|
||||
typename cont_type::insert_commit_data d;
|
||||
@@ -1511,10 +1511,10 @@ operator[] (Key const& key)
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <bool maybe_multi, bool maybe_map, class>
|
||||
typename std::conditional <IsMap, T, void*>::type&
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
operator[] (Key&& key)
|
||||
{
|
||||
typename cont_type::insert_commit_data d;
|
||||
@@ -1536,9 +1536,9 @@ operator[] (Key&& key)
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
void
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
clear()
|
||||
{
|
||||
for (auto iter (chronological.list.begin());
|
||||
@@ -1550,10 +1550,10 @@ clear()
|
||||
|
||||
// map, set
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <bool maybe_multi>
|
||||
auto
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
insert (value_type const& value) ->
|
||||
typename std::enable_if <! maybe_multi,
|
||||
std::pair <iterator, bool>>::type
|
||||
@@ -1573,10 +1573,10 @@ insert (value_type const& value) ->
|
||||
|
||||
// multimap, multiset
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <bool maybe_multi>
|
||||
auto
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
insert (value_type const& value) ->
|
||||
typename std::enable_if <maybe_multi,
|
||||
iterator>::type
|
||||
@@ -1591,10 +1591,10 @@ insert (value_type const& value) ->
|
||||
|
||||
// set
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <bool maybe_multi, bool maybe_map>
|
||||
auto
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
insert (value_type&& value) ->
|
||||
typename std::enable_if <! maybe_multi && ! maybe_map,
|
||||
std::pair <iterator, bool>>::type
|
||||
@@ -1614,10 +1614,10 @@ insert (value_type&& value) ->
|
||||
|
||||
// multiset
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <bool maybe_multi, bool maybe_map>
|
||||
auto
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
insert (value_type&& value) ->
|
||||
typename std::enable_if <maybe_multi && ! maybe_map,
|
||||
iterator>::type
|
||||
@@ -1634,10 +1634,10 @@ insert (value_type&& value) ->
|
||||
|
||||
// map, set
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <bool maybe_multi>
|
||||
auto
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
insert (const_iterator hint, value_type const& value) ->
|
||||
typename std::enable_if <! maybe_multi,
|
||||
iterator>::type
|
||||
@@ -1657,10 +1657,10 @@ insert (const_iterator hint, value_type const& value) ->
|
||||
|
||||
// map, set
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <bool maybe_multi>
|
||||
auto
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
insert (const_iterator hint, value_type&& value) ->
|
||||
typename std::enable_if <! maybe_multi,
|
||||
iterator>::type
|
||||
@@ -1680,10 +1680,10 @@ insert (const_iterator hint, value_type&& value) ->
|
||||
|
||||
// map, set
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <bool maybe_multi, class... Args>
|
||||
auto
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
emplace (Args&&... args) ->
|
||||
typename std::enable_if <! maybe_multi,
|
||||
std::pair <iterator, bool>>::type
|
||||
@@ -1707,10 +1707,10 @@ emplace (Args&&... args) ->
|
||||
|
||||
// multiset, multimap
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <bool maybe_multi, class... Args>
|
||||
auto
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
emplace (Args&&... args) ->
|
||||
typename std::enable_if <maybe_multi,
|
||||
iterator>::type
|
||||
@@ -1726,10 +1726,10 @@ emplace (Args&&... args) ->
|
||||
|
||||
// map, set
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <bool maybe_multi, class... Args>
|
||||
auto
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
emplace_hint (const_iterator hint, Args&&... args) ->
|
||||
typename std::enable_if <! maybe_multi,
|
||||
std::pair <iterator, bool>>::type
|
||||
@@ -1752,10 +1752,10 @@ emplace_hint (const_iterator hint, Args&&... args) ->
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <bool is_const, class Iterator, class Base, class>
|
||||
detail::aged_container_iterator <false, Iterator, Base>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
erase (detail::aged_container_iterator <is_const, Iterator, Base> pos)
|
||||
{
|
||||
unlink_and_delete_element(&*((pos++).iterator()));
|
||||
@@ -1764,10 +1764,10 @@ erase (detail::aged_container_iterator <is_const, Iterator, Base> pos)
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <bool is_const, class Iterator, class Base, class>
|
||||
detail::aged_container_iterator <false, Iterator, Base>
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
erase (detail::aged_container_iterator <is_const, Iterator, Base> first,
|
||||
detail::aged_container_iterator <is_const, Iterator, Base> last)
|
||||
{
|
||||
@@ -1779,10 +1779,10 @@ erase (detail::aged_container_iterator <is_const, Iterator, Base> first,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <class K>
|
||||
auto
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
erase (K const& k) ->
|
||||
size_type
|
||||
{
|
||||
@@ -1805,9 +1805,9 @@ erase (K const& k) ->
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
void
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
swap (aged_ordered_container& other) noexcept
|
||||
{
|
||||
swap_data (other);
|
||||
@@ -1818,10 +1818,10 @@ swap (aged_ordered_container& other) noexcept
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <class K>
|
||||
auto
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
touch (K const& k) ->
|
||||
size_type
|
||||
{
|
||||
@@ -1839,19 +1839,19 @@ touch (K const& k) ->
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <bool OtherIsMulti, bool OtherIsMap,
|
||||
class OtherT, class OtherDuration, class OtherAllocator>
|
||||
bool
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
operator== (
|
||||
aged_ordered_container <OtherIsMulti, OtherIsMap,
|
||||
Key, OtherT, OtherDuration, Compare,
|
||||
OtherAllocator> const& other) const
|
||||
{
|
||||
typedef aged_ordered_container <OtherIsMulti, OtherIsMap,
|
||||
using Other = aged_ordered_container <OtherIsMulti, OtherIsMap,
|
||||
Key, OtherT, OtherDuration, Compare,
|
||||
OtherAllocator> Other;
|
||||
OtherAllocator>;
|
||||
if (size() != other.size())
|
||||
return false;
|
||||
std::equal_to <void> eq;
|
||||
@@ -1866,10 +1866,10 @@ operator== (
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <bool is_const, class Iterator, class Base, class>
|
||||
void
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
touch (detail::aged_container_iterator <
|
||||
is_const, Iterator, Base> pos,
|
||||
typename clock_type::time_point const& now)
|
||||
@@ -1881,10 +1881,10 @@ touch (detail::aged_container_iterator <
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <bool maybe_propagate>
|
||||
typename std::enable_if <maybe_propagate>::type
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
swap_data (aged_ordered_container& other) noexcept
|
||||
{
|
||||
std::swap (m_config.key_compare(), other.m_config.key_compare());
|
||||
@@ -1893,10 +1893,10 @@ swap_data (aged_ordered_container& other) noexcept
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
template <bool maybe_propagate>
|
||||
typename std::enable_if <! maybe_propagate>::type
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Duration, Compare, Allocator>::
|
||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||
swap_data (aged_ordered_container& other) noexcept
|
||||
{
|
||||
std::swap (m_config.key_compare(), other.m_config.key_compare());
|
||||
@@ -1908,9 +1908,9 @@ swap_data (aged_ordered_container& other) noexcept
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
struct is_aged_container <detail::aged_ordered_container <
|
||||
IsMulti, IsMap, Key, T, Duration, Compare, Allocator>>
|
||||
IsMulti, IsMap, Key, T, Clock, Compare, Allocator>>
|
||||
: std::true_type
|
||||
{
|
||||
};
|
||||
@@ -1918,22 +1918,22 @@ struct is_aged_container <detail::aged_ordered_container <
|
||||
// Free functions
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator>
|
||||
class Clock, class Compare, class Allocator>
|
||||
void swap (
|
||||
detail::aged_ordered_container <IsMulti, IsMap,
|
||||
Key, T, Duration, Compare, Allocator>& lhs,
|
||||
Key, T, Clock, Compare, Allocator>& lhs,
|
||||
detail::aged_ordered_container <IsMulti, IsMap,
|
||||
Key, T, Duration, Compare, Allocator>& rhs) noexcept
|
||||
Key, T, Clock, Compare, Allocator>& rhs) noexcept
|
||||
{
|
||||
lhs.swap (rhs);
|
||||
}
|
||||
|
||||
/** Expire aged container items past the specified age. */
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Compare, class Allocator,
|
||||
class Clock, class Compare, class Allocator,
|
||||
class Rep, class Period>
|
||||
std::size_t expire (detail::aged_ordered_container <
|
||||
IsMulti, IsMap, Key, T, Duration, Compare, Allocator>& c,
|
||||
IsMulti, IsMap, Key, T, Clock, Compare, Allocator>& c,
|
||||
std::chrono::duration <Rep, Period> const& age)
|
||||
{
|
||||
std::size_t n (0);
|
||||
|
||||
@@ -17,20 +17,16 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_CONTAINER_AGED_UNORDERED_CONTAINER_H_INCLUDED
|
||||
#define BEAST_CONTAINER_AGED_UNORDERED_CONTAINER_H_INCLUDED
|
||||
#ifndef BEAST_CONTAINER_DETAIL_AGED_UNORDERED_CONTAINER_H_INCLUDED
|
||||
#define BEAST_CONTAINER_DETAIL_AGED_UNORDERED_CONTAINER_H_INCLUDED
|
||||
|
||||
#include <beast/container/detail/aged_container_iterator.h>
|
||||
#include <beast/container/detail/aged_associative_container.h>
|
||||
|
||||
#include <beast/container/aged_container.h>
|
||||
|
||||
#include <beast/chrono/abstract_clock.h>
|
||||
#include <beast/utility/empty_base_optimization.h>
|
||||
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <boost/intrusive/unordered_set.hpp>
|
||||
|
||||
#include <beast/cxx14/algorithm.h> // <algorithm>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
@@ -80,7 +76,7 @@ template <
|
||||
bool IsMap,
|
||||
class Key,
|
||||
class T,
|
||||
class Duration = std::chrono::seconds,
|
||||
class Clock = std::chrono::steady_clock,
|
||||
class Hash = std::hash <Key>,
|
||||
class KeyEqual = std::equal_to <Key>,
|
||||
class Allocator = std::allocator <
|
||||
@@ -91,24 +87,20 @@ template <
|
||||
class aged_unordered_container
|
||||
{
|
||||
public:
|
||||
typedef abstract_clock <Duration> clock_type;
|
||||
typedef typename clock_type::time_point time_point;
|
||||
typedef typename clock_type::duration duration;
|
||||
typedef Key key_type;
|
||||
typedef T mapped_type;
|
||||
typedef typename std::conditional <IsMap,
|
||||
std::pair <Key const, T>,
|
||||
Key>::type value_type;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
using clock_type = abstract_clock<Clock>;
|
||||
using time_point = typename clock_type::time_point;
|
||||
using duration = typename clock_type::duration;
|
||||
using key_type = Key;
|
||||
using mapped_type = T;
|
||||
using value_type = typename std::conditional <IsMap,
|
||||
std::pair <Key const, T>, Key>::type;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
// Introspection (for unit tests)
|
||||
typedef std::true_type is_unordered;
|
||||
typedef std::integral_constant <bool, IsMulti> is_multi;
|
||||
typedef std::integral_constant <bool, IsMap> is_map;
|
||||
|
||||
// VFALCO TODO How can we reorder the declarations to keep
|
||||
// all the public things together contiguously?
|
||||
using is_unordered = std::true_type;
|
||||
using is_multi = std::integral_constant <bool, IsMulti>;
|
||||
using is_map = std::integral_constant <bool, IsMap>;
|
||||
|
||||
private:
|
||||
static Key const& extract (value_type const& value)
|
||||
@@ -131,8 +123,8 @@ private:
|
||||
// need to see the container declaration.
|
||||
struct stashed
|
||||
{
|
||||
typedef typename aged_unordered_container::value_type value_type;
|
||||
typedef typename aged_unordered_container::time_point time_point;
|
||||
using value_type = typename aged_unordered_container::value_type;
|
||||
using time_point = typename aged_unordered_container::time_point;
|
||||
};
|
||||
|
||||
element (
|
||||
@@ -256,11 +248,10 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
typedef typename boost::intrusive::make_list <element,
|
||||
boost::intrusive::constant_time_size <false>
|
||||
>::type list_type;
|
||||
using list_type = typename boost::intrusive::make_list <element,
|
||||
boost::intrusive::constant_time_size <false>>::type ;
|
||||
|
||||
typedef typename std::conditional <
|
||||
using cont_type = typename std::conditional <
|
||||
IsMulti,
|
||||
typename boost::intrusive::make_unordered_multiset <element,
|
||||
boost::intrusive::constant_time_size <true>,
|
||||
@@ -274,18 +265,18 @@ private:
|
||||
boost::intrusive::equal <KeyValueEqual>,
|
||||
boost::intrusive::cache_begin <true>
|
||||
>::type
|
||||
>::type cont_type;
|
||||
>::type;
|
||||
|
||||
typedef typename cont_type::bucket_type bucket_type;
|
||||
typedef typename cont_type::bucket_traits bucket_traits;
|
||||
using bucket_type = typename cont_type::bucket_type;
|
||||
using bucket_traits = typename cont_type::bucket_traits;
|
||||
|
||||
typedef typename std::allocator_traits <
|
||||
Allocator>::template rebind_alloc <element> ElementAllocator;
|
||||
using ElementAllocator = typename std::allocator_traits <
|
||||
Allocator>::template rebind_alloc <element>;
|
||||
|
||||
using ElementAllocatorTraits = std::allocator_traits <ElementAllocator>;
|
||||
|
||||
typedef typename std::allocator_traits <
|
||||
Allocator>::template rebind_alloc <element> BucketAllocator;
|
||||
using BucketAllocator = typename std::allocator_traits <
|
||||
Allocator>::template rebind_alloc <element>;
|
||||
|
||||
using BucketAllocatorTraits = std::allocator_traits <BucketAllocator>;
|
||||
|
||||
@@ -479,10 +470,10 @@ private:
|
||||
class Buckets
|
||||
{
|
||||
public:
|
||||
typedef std::vector <
|
||||
using vec_type = std::vector<
|
||||
bucket_type,
|
||||
typename std::allocator_traits <Allocator>::
|
||||
template rebind_alloc <bucket_type>> vec_type;
|
||||
template rebind_alloc <bucket_type>>;
|
||||
|
||||
Buckets ()
|
||||
: m_max_load_factor (1.f)
|
||||
@@ -615,27 +606,27 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
typedef Hash hasher;
|
||||
typedef KeyEqual key_equal;
|
||||
typedef Allocator allocator_type;
|
||||
typedef value_type& reference;
|
||||
typedef value_type const& const_reference;
|
||||
typedef typename std::allocator_traits <
|
||||
Allocator>::pointer pointer;
|
||||
typedef typename std::allocator_traits <
|
||||
Allocator>::const_pointer const_pointer;
|
||||
using hasher = Hash;
|
||||
using key_equal = KeyEqual;
|
||||
using allocator_type = Allocator;
|
||||
using reference = value_type&;
|
||||
using const_reference = value_type const&;
|
||||
using pointer = typename std::allocator_traits <
|
||||
Allocator>::pointer;
|
||||
using const_pointer = typename std::allocator_traits <
|
||||
Allocator>::const_pointer;
|
||||
|
||||
// A set (that is, !IsMap) iterator is aways const because the elements
|
||||
// of a set are immutable.
|
||||
typedef detail::aged_container_iterator <!IsMap,
|
||||
typename cont_type::iterator> iterator;
|
||||
typedef detail::aged_container_iterator <true,
|
||||
typename cont_type::iterator> const_iterator;
|
||||
// A set iterator (IsMap==false) is always const
|
||||
// because the elements of a set are immutable.
|
||||
using iterator= detail::aged_container_iterator <!IsMap,
|
||||
typename cont_type::iterator>;
|
||||
using const_iterator = detail::aged_container_iterator <true,
|
||||
typename cont_type::iterator>;
|
||||
|
||||
typedef detail::aged_container_iterator <!IsMap,
|
||||
typename cont_type::local_iterator> local_iterator;
|
||||
typedef detail::aged_container_iterator <true,
|
||||
typename cont_type::local_iterator> const_local_iterator;
|
||||
using local_iterator = detail::aged_container_iterator <!IsMap,
|
||||
typename cont_type::local_iterator>;
|
||||
using const_local_iterator = detail::aged_container_iterator <true,
|
||||
typename cont_type::local_iterator>;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
@@ -649,16 +640,16 @@ public:
|
||||
class chronological_t
|
||||
{
|
||||
public:
|
||||
// A set (that is, !IsMap) iterator is aways const because the elements
|
||||
// of a set are immutable.
|
||||
typedef detail::aged_container_iterator <!IsMap,
|
||||
typename list_type::iterator> iterator;
|
||||
typedef detail::aged_container_iterator <true,
|
||||
typename list_type::iterator> const_iterator;
|
||||
typedef detail::aged_container_iterator <!IsMap,
|
||||
typename list_type::reverse_iterator> reverse_iterator;
|
||||
typedef detail::aged_container_iterator <true,
|
||||
typename list_type::reverse_iterator> const_reverse_iterator;
|
||||
// A set iterator (IsMap==false) is always const
|
||||
// because the elements of a set are immutable.
|
||||
using iterator = detail::aged_container_iterator <
|
||||
! IsMap, typename list_type::iterator>;
|
||||
using const_iterator = detail::aged_container_iterator <
|
||||
true, typename list_type::iterator>;
|
||||
using reverse_iterator = detail::aged_container_iterator <
|
||||
! IsMap, typename list_type::reverse_iterator>;
|
||||
using const_reverse_iterator = detail::aged_container_iterator <
|
||||
true, typename list_type::reverse_iterator>;
|
||||
|
||||
iterator begin ()
|
||||
{
|
||||
@@ -756,6 +747,8 @@ public:
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
aged_unordered_container() = delete;
|
||||
|
||||
explicit aged_unordered_container (clock_type& clock);
|
||||
|
||||
aged_unordered_container (clock_type& clock, Hash const& hash);
|
||||
@@ -1504,8 +1497,8 @@ private:
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (
|
||||
clock_type& clock)
|
||||
@@ -1517,8 +1510,8 @@ aged_unordered_container (
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (
|
||||
clock_type& clock,
|
||||
@@ -1531,8 +1524,8 @@ aged_unordered_container (
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (
|
||||
clock_type& clock,
|
||||
@@ -1545,8 +1538,8 @@ aged_unordered_container (
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (
|
||||
clock_type& clock,
|
||||
@@ -1560,8 +1553,8 @@ aged_unordered_container (
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (
|
||||
clock_type& clock,
|
||||
@@ -1575,8 +1568,8 @@ aged_unordered_container (
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (
|
||||
clock_type& clock,
|
||||
@@ -1591,8 +1584,8 @@ aged_unordered_container (
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (
|
||||
clock_type& clock,
|
||||
@@ -1607,8 +1600,8 @@ aged_unordered_container (
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (
|
||||
clock_type& clock,
|
||||
@@ -1624,9 +1617,9 @@ aged_unordered_container (
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <class InputIt>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (InputIt first, InputIt last,
|
||||
clock_type& clock)
|
||||
@@ -1639,9 +1632,9 @@ aged_unordered_container (InputIt first, InputIt last,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <class InputIt>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (InputIt first, InputIt last,
|
||||
clock_type& clock,
|
||||
@@ -1655,9 +1648,9 @@ aged_unordered_container (InputIt first, InputIt last,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <class InputIt>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (InputIt first, InputIt last,
|
||||
clock_type& clock,
|
||||
@@ -1671,9 +1664,9 @@ aged_unordered_container (InputIt first, InputIt last,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <class InputIt>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (InputIt first, InputIt last,
|
||||
clock_type& clock,
|
||||
@@ -1688,9 +1681,9 @@ aged_unordered_container (InputIt first, InputIt last,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <class InputIt>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (InputIt first, InputIt last,
|
||||
clock_type& clock,
|
||||
@@ -1705,9 +1698,9 @@ aged_unordered_container (InputIt first, InputIt last,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <class InputIt>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (InputIt first, InputIt last,
|
||||
clock_type& clock,
|
||||
@@ -1723,9 +1716,9 @@ aged_unordered_container (InputIt first, InputIt last,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <class InputIt>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (InputIt first, InputIt last,
|
||||
clock_type& clock,
|
||||
@@ -1741,9 +1734,9 @@ aged_unordered_container (InputIt first, InputIt last,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <class InputIt>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (InputIt first, InputIt last,
|
||||
clock_type& clock,
|
||||
@@ -1760,8 +1753,8 @@ aged_unordered_container (InputIt first, InputIt last,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (aged_unordered_container const& other)
|
||||
: m_config (other.m_config)
|
||||
@@ -1774,8 +1767,8 @@ aged_unordered_container (aged_unordered_container const& other)
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (aged_unordered_container const& other,
|
||||
Allocator const& alloc)
|
||||
@@ -1789,8 +1782,8 @@ aged_unordered_container (aged_unordered_container const& other,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (aged_unordered_container&& other)
|
||||
: m_config (std::move (other.m_config))
|
||||
@@ -1801,8 +1794,8 @@ aged_unordered_container (aged_unordered_container&& other)
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (aged_unordered_container&& other,
|
||||
Allocator const& alloc)
|
||||
@@ -1817,8 +1810,8 @@ aged_unordered_container (aged_unordered_container&& other,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (std::initializer_list <value_type> init,
|
||||
clock_type& clock)
|
||||
@@ -1831,8 +1824,8 @@ aged_unordered_container (std::initializer_list <value_type> init,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (std::initializer_list <value_type> init,
|
||||
clock_type& clock,
|
||||
@@ -1846,8 +1839,8 @@ aged_unordered_container (std::initializer_list <value_type> init,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (std::initializer_list <value_type> init,
|
||||
clock_type& clock,
|
||||
@@ -1861,8 +1854,8 @@ aged_unordered_container (std::initializer_list <value_type> init,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (std::initializer_list <value_type> init,
|
||||
clock_type& clock,
|
||||
@@ -1877,8 +1870,8 @@ aged_unordered_container (std::initializer_list <value_type> init,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (std::initializer_list <value_type> init,
|
||||
clock_type& clock,
|
||||
@@ -1893,8 +1886,8 @@ aged_unordered_container (std::initializer_list <value_type> init,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (std::initializer_list <value_type> init,
|
||||
clock_type& clock,
|
||||
@@ -1910,8 +1903,8 @@ aged_unordered_container (std::initializer_list <value_type> init,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (std::initializer_list <value_type> init,
|
||||
clock_type& clock,
|
||||
@@ -1927,8 +1920,8 @@ aged_unordered_container (std::initializer_list <value_type> init,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
aged_unordered_container (std::initializer_list <value_type> init,
|
||||
clock_type& clock,
|
||||
@@ -1945,8 +1938,8 @@ aged_unordered_container (std::initializer_list <value_type> init,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
~aged_unordered_container()
|
||||
{
|
||||
@@ -1954,9 +1947,9 @@ aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
auto
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
operator= (aged_unordered_container const& other)
|
||||
-> aged_unordered_container&
|
||||
@@ -1974,9 +1967,9 @@ operator= (aged_unordered_container const& other)
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
auto
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
operator= (aged_unordered_container&& other) ->
|
||||
aged_unordered_container&
|
||||
@@ -1992,9 +1985,9 @@ operator= (aged_unordered_container&& other) ->
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
auto
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
operator= (std::initializer_list <value_type> init) ->
|
||||
aged_unordered_container&
|
||||
@@ -2007,10 +2000,10 @@ operator= (std::initializer_list <value_type> init) ->
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <class K, bool maybe_multi, bool maybe_map, class>
|
||||
typename std::conditional <IsMap, T, void*>::type&
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
at (K const& k)
|
||||
{
|
||||
@@ -2023,10 +2016,10 @@ at (K const& k)
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <class K, bool maybe_multi, bool maybe_map, class>
|
||||
typename std::conditional <IsMap, T, void*>::type const&
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
at (K const& k) const
|
||||
{
|
||||
@@ -2039,10 +2032,10 @@ at (K const& k) const
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <bool maybe_multi, bool maybe_map, class>
|
||||
typename std::conditional <IsMap, T, void*>::type&
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
operator[] (Key const& key)
|
||||
{
|
||||
@@ -2065,10 +2058,10 @@ operator[] (Key const& key)
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <bool maybe_multi, bool maybe_map, class>
|
||||
typename std::conditional <IsMap, T, void*>::type&
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
operator[] (Key&& key)
|
||||
{
|
||||
@@ -2093,9 +2086,9 @@ operator[] (Key&& key)
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
void
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
clear()
|
||||
{
|
||||
@@ -2109,10 +2102,10 @@ clear()
|
||||
|
||||
// map, set
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <bool maybe_multi>
|
||||
auto
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
insert (value_type const& value) ->
|
||||
typename std::enable_if <! maybe_multi,
|
||||
@@ -2135,10 +2128,10 @@ insert (value_type const& value) ->
|
||||
|
||||
// multimap, multiset
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <bool maybe_multi>
|
||||
auto
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
insert (value_type const& value) ->
|
||||
typename std::enable_if <maybe_multi,
|
||||
@@ -2153,10 +2146,10 @@ insert (value_type const& value) ->
|
||||
|
||||
// map, set
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <bool maybe_multi, bool maybe_map>
|
||||
auto
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
insert (value_type&& value) ->
|
||||
typename std::enable_if <! maybe_multi && ! maybe_map,
|
||||
@@ -2179,10 +2172,10 @@ insert (value_type&& value) ->
|
||||
|
||||
// multimap, multiset
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <bool maybe_multi, bool maybe_map>
|
||||
auto
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
insert (value_type&& value) ->
|
||||
typename std::enable_if <maybe_multi && ! maybe_map,
|
||||
@@ -2198,10 +2191,10 @@ insert (value_type&& value) ->
|
||||
#if 1 // Use insert() instead of insert_check() insert_commit()
|
||||
// set, map
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <bool maybe_multi, class... Args>
|
||||
auto
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
emplace (Args&&... args) ->
|
||||
typename std::enable_if <! maybe_multi,
|
||||
@@ -2223,10 +2216,10 @@ emplace (Args&&... args) ->
|
||||
#else // As original, use insert_check() / insert_commit () pair.
|
||||
// set, map
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <bool maybe_multi, class... Args>
|
||||
auto
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
emplace (Args&&... args) ->
|
||||
typename std::enable_if <! maybe_multi,
|
||||
@@ -2254,10 +2247,10 @@ emplace (Args&&... args) ->
|
||||
|
||||
// multiset, multimap
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <bool maybe_multi, class... Args>
|
||||
auto
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
emplace (Args&&... args) ->
|
||||
typename std::enable_if <maybe_multi,
|
||||
@@ -2273,10 +2266,10 @@ emplace (Args&&... args) ->
|
||||
|
||||
// set, map
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <bool maybe_multi, class... Args>
|
||||
auto
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
emplace_hint (const_iterator /*hint*/, Args&&... args) ->
|
||||
typename std::enable_if <! maybe_multi,
|
||||
@@ -2302,10 +2295,10 @@ emplace_hint (const_iterator /*hint*/, Args&&... args) ->
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <bool is_const, class Iterator, class Base>
|
||||
detail::aged_container_iterator <false, Iterator, Base>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
erase (detail::aged_container_iterator <
|
||||
is_const, Iterator, Base> pos)
|
||||
@@ -2316,10 +2309,10 @@ erase (detail::aged_container_iterator <
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <bool is_const, class Iterator, class Base>
|
||||
detail::aged_container_iterator <false, Iterator, Base>
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
erase (detail::aged_container_iterator <
|
||||
is_const, Iterator, Base> first,
|
||||
@@ -2334,10 +2327,10 @@ erase (detail::aged_container_iterator <
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <class K>
|
||||
auto
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
erase (K const& k) ->
|
||||
size_type
|
||||
@@ -2361,9 +2354,9 @@ erase (K const& k) ->
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
void
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
swap (aged_unordered_container& other) noexcept
|
||||
{
|
||||
@@ -2373,10 +2366,10 @@ swap (aged_unordered_container& other) noexcept
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <class K>
|
||||
auto
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
touch (K const& k) ->
|
||||
size_type
|
||||
@@ -2393,7 +2386,7 @@ touch (K const& k) ->
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <
|
||||
bool OtherIsMap,
|
||||
class OtherKey,
|
||||
@@ -2405,7 +2398,7 @@ template <
|
||||
>
|
||||
typename std::enable_if <! maybe_multi, bool>::type
|
||||
aged_unordered_container <
|
||||
IsMulti, IsMap, Key, T, Duration, Hash, KeyEqual, Allocator>::
|
||||
IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
|
||||
operator== (
|
||||
aged_unordered_container <false, OtherIsMap,
|
||||
OtherKey, OtherT, OtherDuration, OtherHash, KeyEqual,
|
||||
@@ -2424,7 +2417,7 @@ operator== (
|
||||
}
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <
|
||||
bool OtherIsMap,
|
||||
class OtherKey,
|
||||
@@ -2436,7 +2429,7 @@ template <
|
||||
>
|
||||
typename std::enable_if <maybe_multi, bool>::type
|
||||
aged_unordered_container <
|
||||
IsMulti, IsMap, Key, T, Duration, Hash, KeyEqual, Allocator>::
|
||||
IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>::
|
||||
operator== (
|
||||
aged_unordered_container <true, OtherIsMap,
|
||||
OtherKey, OtherT, OtherDuration, OtherHash, KeyEqual,
|
||||
@@ -2444,7 +2437,7 @@ operator== (
|
||||
{
|
||||
if (size() != other.size())
|
||||
return false;
|
||||
typedef std::pair <const_iterator, const_iterator> EqRng;
|
||||
using EqRng = std::pair <const_iterator, const_iterator>;
|
||||
for (auto iter (cbegin()), last (cend()); iter != last;)
|
||||
{
|
||||
auto const& k (extract (*iter));
|
||||
@@ -2469,10 +2462,10 @@ operator== (
|
||||
|
||||
// map, set
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <bool maybe_multi>
|
||||
auto
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
insert_unchecked (value_type const& value) ->
|
||||
typename std::enable_if <! maybe_multi,
|
||||
@@ -2494,10 +2487,10 @@ insert_unchecked (value_type const& value) ->
|
||||
|
||||
// multimap, multiset
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
template <bool maybe_multi>
|
||||
auto
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Duration,
|
||||
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
|
||||
Hash, KeyEqual, Allocator>::
|
||||
insert_unchecked (value_type const& value) ->
|
||||
typename std::enable_if <maybe_multi,
|
||||
@@ -2516,32 +2509,32 @@ insert_unchecked (value_type const& value) ->
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator>
|
||||
class Clock, class Hash, class KeyEqual, class Allocator>
|
||||
struct is_aged_container <detail::aged_unordered_container <
|
||||
IsMulti, IsMap, Key, T, Duration, Hash, KeyEqual, Allocator>>
|
||||
IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>>
|
||||
: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
// Free functions
|
||||
|
||||
template <bool IsMulti, bool IsMap, class Key, class T, class Duration,
|
||||
template <bool IsMulti, bool IsMap, class Key, class T, class Clock,
|
||||
class Hash, class KeyEqual, class Allocator>
|
||||
void swap (
|
||||
detail::aged_unordered_container <IsMulti, IsMap,
|
||||
Key, T, Duration, Hash, KeyEqual, Allocator>& lhs,
|
||||
Key, T, Clock, Hash, KeyEqual, Allocator>& lhs,
|
||||
detail::aged_unordered_container <IsMulti, IsMap,
|
||||
Key, T, Duration, Hash, KeyEqual, Allocator>& rhs) noexcept
|
||||
Key, T, Clock, Hash, KeyEqual, Allocator>& rhs) noexcept
|
||||
{
|
||||
lhs.swap (rhs);
|
||||
}
|
||||
|
||||
/** Expire aged container items past the specified age. */
|
||||
template <bool IsMulti, bool IsMap, class Key, class T,
|
||||
class Duration, class Hash, class KeyEqual, class Allocator,
|
||||
class Clock, class Hash, class KeyEqual, class Allocator,
|
||||
class Rep, class Period>
|
||||
std::size_t expire (detail::aged_unordered_container <
|
||||
IsMulti, IsMap, Key, T, Duration, Hash, KeyEqual, Allocator>& c,
|
||||
IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>& c,
|
||||
std::chrono::duration <Rep, Period> const& age) noexcept
|
||||
{
|
||||
std::size_t n (0);
|
||||
|
||||
@@ -302,7 +302,7 @@ public:
|
||||
>
|
||||
using Cont = detail::aged_ordered_container <
|
||||
Base::is_multi::value, Base::is_map::value, typename Base::Key,
|
||||
typename Base::T, typename Base::Dur, Compare, Allocator>;
|
||||
typename Base::T, typename Base::Clock, Compare, Allocator>;
|
||||
};
|
||||
|
||||
// unordered
|
||||
@@ -318,7 +318,7 @@ public:
|
||||
>
|
||||
using Cont = detail::aged_unordered_container <
|
||||
Base::is_multi::value, Base::is_map::value,
|
||||
typename Base::Key, typename Base::T, typename Base::Dur,
|
||||
typename Base::Key, typename Base::T, typename Base::Clock,
|
||||
Hash, KeyEqual, Allocator>;
|
||||
};
|
||||
|
||||
@@ -327,8 +327,8 @@ public:
|
||||
struct TestTraitsBase
|
||||
{
|
||||
typedef std::string Key;
|
||||
typedef std::chrono::seconds Dur;
|
||||
typedef manual_clock <Dur> Clock;
|
||||
typedef std::chrono::steady_clock Clock;
|
||||
typedef manual_clock<Clock> ManualClock;
|
||||
};
|
||||
|
||||
template <bool IsUnordered, bool IsMulti, bool IsMap>
|
||||
@@ -387,10 +387,10 @@ public:
|
||||
|
||||
template <class Cont>
|
||||
static
|
||||
std::list <typename Cont::value_type>
|
||||
std::vector <typename Cont::value_type>
|
||||
make_list (Cont const& c)
|
||||
{
|
||||
return std::list <typename Cont::value_type> (
|
||||
return std::vector <typename Cont::value_type> (
|
||||
c.begin(), c.end());
|
||||
}
|
||||
|
||||
@@ -744,12 +744,12 @@ testConstructEmpty ()
|
||||
typedef typename Traits::Value Value;
|
||||
typedef typename Traits::Key Key;
|
||||
typedef typename Traits::T T;
|
||||
typedef typename Traits::Dur Dur;
|
||||
typedef typename Traits::Clock Clock;
|
||||
typedef typename Traits::Comp Comp;
|
||||
typedef typename Traits::Alloc Alloc;
|
||||
typedef typename Traits::MyComp MyComp;
|
||||
typedef typename Traits::MyAlloc MyAlloc;
|
||||
typename Traits::Clock clock;
|
||||
typename Traits::ManualClock clock;
|
||||
|
||||
//testcase (Traits::name() + " empty");
|
||||
testcase ("empty");
|
||||
@@ -789,14 +789,14 @@ testConstructEmpty ()
|
||||
typedef typename Traits::Value Value;
|
||||
typedef typename Traits::Key Key;
|
||||
typedef typename Traits::T T;
|
||||
typedef typename Traits::Dur Dur;
|
||||
typedef typename Traits::Clock Clock;
|
||||
typedef typename Traits::Hash Hash;
|
||||
typedef typename Traits::Equal Equal;
|
||||
typedef typename Traits::Alloc Alloc;
|
||||
typedef typename Traits::MyHash MyHash;
|
||||
typedef typename Traits::MyEqual MyEqual;
|
||||
typedef typename Traits::MyAlloc MyAlloc;
|
||||
typename Traits::Clock clock;
|
||||
typename Traits::ManualClock clock;
|
||||
|
||||
//testcase (Traits::name() + " empty");
|
||||
testcase ("empty");
|
||||
@@ -859,12 +859,12 @@ testConstructRange ()
|
||||
typedef typename Traits::Value Value;
|
||||
typedef typename Traits::Key Key;
|
||||
typedef typename Traits::T T;
|
||||
typedef typename Traits::Dur Dur;
|
||||
typedef typename Traits::Clock Clock;
|
||||
typedef typename Traits::Comp Comp;
|
||||
typedef typename Traits::Alloc Alloc;
|
||||
typedef typename Traits::MyComp MyComp;
|
||||
typedef typename Traits::MyAlloc MyAlloc;
|
||||
typename Traits::Clock clock;
|
||||
typename Traits::ManualClock clock;
|
||||
auto const v (Traits::values());
|
||||
|
||||
//testcase (Traits::name() + " range");
|
||||
@@ -922,14 +922,14 @@ testConstructRange ()
|
||||
typedef typename Traits::Value Value;
|
||||
typedef typename Traits::Key Key;
|
||||
typedef typename Traits::T T;
|
||||
typedef typename Traits::Dur Dur;
|
||||
typedef typename Traits::Clock Clock;
|
||||
typedef typename Traits::Hash Hash;
|
||||
typedef typename Traits::Equal Equal;
|
||||
typedef typename Traits::Alloc Alloc;
|
||||
typedef typename Traits::MyHash MyHash;
|
||||
typedef typename Traits::MyEqual MyEqual;
|
||||
typedef typename Traits::MyAlloc MyAlloc;
|
||||
typename Traits::Clock clock;
|
||||
typename Traits::ManualClock clock;
|
||||
auto const v (Traits::values());
|
||||
|
||||
//testcase (Traits::name() + " range");
|
||||
@@ -1002,12 +1002,12 @@ testConstructInitList ()
|
||||
typedef typename Traits::Value Value;
|
||||
typedef typename Traits::Key Key;
|
||||
typedef typename Traits::T T;
|
||||
typedef typename Traits::Dur Dur;
|
||||
typedef typename Traits::Clock Clock;
|
||||
typedef typename Traits::Comp Comp;
|
||||
typedef typename Traits::Alloc Alloc;
|
||||
typedef typename Traits::MyComp MyComp;
|
||||
typedef typename Traits::MyAlloc MyAlloc;
|
||||
typename Traits::Clock clock;
|
||||
typename Traits::ManualClock clock;
|
||||
|
||||
//testcase (Traits::name() + " init-list");
|
||||
testcase ("init-list");
|
||||
@@ -1027,14 +1027,14 @@ testConstructInitList ()
|
||||
typedef typename Traits::Value Value;
|
||||
typedef typename Traits::Key Key;
|
||||
typedef typename Traits::T T;
|
||||
typedef typename Traits::Dur Dur;
|
||||
typedef typename Traits::Clock Clock;
|
||||
typedef typename Traits::Hash Hash;
|
||||
typedef typename Traits::Equal Equal;
|
||||
typedef typename Traits::Alloc Alloc;
|
||||
typedef typename Traits::MyHash MyHash;
|
||||
typedef typename Traits::MyEqual MyEqual;
|
||||
typedef typename Traits::MyAlloc MyAlloc;
|
||||
typename Traits::Clock clock;
|
||||
typename Traits::ManualClock clock;
|
||||
|
||||
//testcase (Traits::name() + " init-list");
|
||||
testcase ("init-list");
|
||||
@@ -1057,7 +1057,7 @@ testCopyMove ()
|
||||
typedef TestTraits <IsUnordered, IsMulti, IsMap> Traits;
|
||||
typedef typename Traits::Value Value;
|
||||
typedef typename Traits::Alloc Alloc;
|
||||
typename Traits::Clock clock;
|
||||
typename Traits::ManualClock clock;
|
||||
auto const v (Traits::values());
|
||||
|
||||
//testcase (Traits::name() + " copy/move");
|
||||
@@ -1139,7 +1139,7 @@ testIterator()
|
||||
typedef TestTraits <IsUnordered, IsMulti, IsMap> Traits;
|
||||
typedef typename Traits::Value Value;
|
||||
typedef typename Traits::Alloc Alloc;
|
||||
typename Traits::Clock clock;
|
||||
typename Traits::ManualClock clock;
|
||||
auto const v (Traits::values());
|
||||
|
||||
//testcase (Traits::name() + " iterators");
|
||||
@@ -1202,7 +1202,7 @@ testReverseIterator()
|
||||
typedef TestTraits <IsUnordered, IsMulti, IsMap> Traits;
|
||||
typedef typename Traits::Value Value;
|
||||
typedef typename Traits::Alloc Alloc;
|
||||
typename Traits::Clock clock;
|
||||
typename Traits::ManualClock clock;
|
||||
auto const v (Traits::values());
|
||||
|
||||
//testcase (Traits::name() + " reverse_iterators");
|
||||
@@ -1357,7 +1357,7 @@ aged_associative_container_test_base::
|
||||
testModifiers()
|
||||
{
|
||||
typedef TestTraits <IsUnordered, IsMulti, IsMap> Traits;
|
||||
typename Traits::Clock clock;
|
||||
typename Traits::ManualClock clock;
|
||||
auto const v (Traits::values());
|
||||
auto const l (make_list (v));
|
||||
|
||||
@@ -1418,7 +1418,7 @@ testChronological ()
|
||||
{
|
||||
typedef TestTraits <IsUnordered, IsMulti, IsMap> Traits;
|
||||
typedef typename Traits::Value Value;
|
||||
typename Traits::Clock clock;
|
||||
typename Traits::ManualClock clock;
|
||||
auto const v (Traits::values());
|
||||
|
||||
//testcase (Traits::name() + " chronological");
|
||||
@@ -1484,7 +1484,7 @@ aged_associative_container_test_base::
|
||||
testArrayCreate()
|
||||
{
|
||||
typedef TestTraits <IsUnordered, IsMulti, IsMap> Traits;
|
||||
typename Traits::Clock clock;
|
||||
typename Traits::ManualClock clock;
|
||||
auto v (Traits::values());
|
||||
|
||||
//testcase (Traits::name() + " array create");
|
||||
@@ -1522,8 +1522,9 @@ reverseFillAgedContainer (Container& c, Values const& values)
|
||||
c.clear();
|
||||
|
||||
// c.clock() returns an abstract_clock, so dynamic_cast to manual_clock.
|
||||
typedef TestTraitsBase::Clock Clock;
|
||||
Clock& clk (dynamic_cast <Clock&> (c.clock ()));
|
||||
// VFALCO NOTE This is sketchy
|
||||
typedef TestTraitsBase::ManualClock ManualClock;
|
||||
ManualClock& clk (dynamic_cast <ManualClock&> (c.clock()));
|
||||
clk.set (0);
|
||||
|
||||
Values rev (values);
|
||||
@@ -1626,8 +1627,8 @@ testElementErase ()
|
||||
testcase ("element erase");
|
||||
|
||||
// Make and fill the container
|
||||
typename Traits::Clock ck;
|
||||
typename Traits::template Cont <> c {ck};
|
||||
typename Traits::ManualClock clock;
|
||||
typename Traits::template Cont <> c {clock};
|
||||
reverseFillAgedContainer (c, Traits::values());
|
||||
|
||||
{
|
||||
@@ -1756,8 +1757,8 @@ testRangeErase ()
|
||||
testcase ("range erase");
|
||||
|
||||
// Make and fill the container
|
||||
typename Traits::Clock ck;
|
||||
typename Traits::template Cont <> c {ck};
|
||||
typename Traits::ManualClock clock;
|
||||
typename Traits::template Cont <> c {clock};
|
||||
reverseFillAgedContainer (c, Traits::values());
|
||||
|
||||
// Not bothering to test range erase with reverse iterators.
|
||||
@@ -1785,7 +1786,7 @@ testCompare ()
|
||||
{
|
||||
typedef TestTraits <IsUnordered, IsMulti, IsMap> Traits;
|
||||
typedef typename Traits::Value Value;
|
||||
typename Traits::Clock clock;
|
||||
typename Traits::ManualClock clock;
|
||||
auto const v (Traits::values());
|
||||
|
||||
//testcase (Traits::name() + " array create");
|
||||
@@ -1819,7 +1820,7 @@ aged_associative_container_test_base::
|
||||
testObservers()
|
||||
{
|
||||
typedef TestTraits <IsUnordered, IsMulti, IsMap> Traits;
|
||||
typename Traits::Clock clock;
|
||||
typename Traits::ManualClock clock;
|
||||
|
||||
//testcase (Traits::name() + " observers");
|
||||
testcase ("observers");
|
||||
@@ -1838,7 +1839,7 @@ aged_associative_container_test_base::
|
||||
testObservers()
|
||||
{
|
||||
typedef TestTraits <IsUnordered, IsMulti, IsMap> Traits;
|
||||
typename Traits::Clock clock;
|
||||
typename Traits::ManualClock clock;
|
||||
|
||||
//testcase (Traits::name() + " observers");
|
||||
testcase ("observers");
|
||||
|
||||
@@ -1,320 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <beast/unit_test/suite.h>
|
||||
|
||||
#include <beast/container/buffer_view.h>
|
||||
|
||||
#include <beast/cxx14/algorithm.h> // <algorithm>
|
||||
|
||||
namespace beast {
|
||||
|
||||
class buffer_view_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
// Returns `true` if the iterator distance matches the size
|
||||
template <class FwdIt, class Size>
|
||||
static bool eq_dist (FwdIt first, FwdIt last, Size size)
|
||||
{
|
||||
auto const dist (std::distance (first, last));
|
||||
|
||||
static_assert (std::is_signed <decltype (dist)>::value,
|
||||
"dist must be signed");
|
||||
|
||||
if (dist < 0)
|
||||
return false;
|
||||
|
||||
return static_cast <Size> (dist) == size;
|
||||
}
|
||||
|
||||
// Check the contents of a buffer_view against the container
|
||||
template <class C, class T>
|
||||
void check (C const& c, buffer_view <T> v)
|
||||
{
|
||||
expect (! v.empty() || c.empty());
|
||||
expect (v.size() == c.size());
|
||||
expect (v.max_size() == v.size());
|
||||
expect (v.capacity() == v.size());
|
||||
|
||||
expect (eq_dist (v.begin(), v.end(), v.size()));
|
||||
expect (eq_dist (v.cbegin(), v.cend(), v.size()));
|
||||
expect (eq_dist (v.rbegin(), v.rend(), v.size()));
|
||||
expect (eq_dist (v.crbegin(), v.crend(), v.size()));
|
||||
|
||||
expect (std::equal (
|
||||
c.cbegin(), c.cend(), v.cbegin(), v.cend()));
|
||||
|
||||
expect (std::equal (
|
||||
c.crbegin(), c.crend(), v.crbegin(), v.crend()));
|
||||
|
||||
if (v.size() == c.size())
|
||||
{
|
||||
if (! v.empty())
|
||||
{
|
||||
expect (v.front() == c.front());
|
||||
expect (v.back() == c.back());
|
||||
}
|
||||
|
||||
for (std::size_t i (0); i < v.size(); ++i)
|
||||
expect (v[i] == c[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Call at() with an invalid index
|
||||
template <class V>
|
||||
void checkBadIndex (V& v,
|
||||
std::enable_if_t <
|
||||
std::is_const <typename V::value_type>::value>* = 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
v.at(0);
|
||||
fail();
|
||||
}
|
||||
catch (std::out_of_range e)
|
||||
{
|
||||
pass();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
// Call at() with an invalid index
|
||||
template <class V>
|
||||
void checkBadIndex (V& v,
|
||||
std::enable_if_t <
|
||||
! std::is_const <typename V::value_type>::value>* = 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
v.at(0);
|
||||
fail();
|
||||
}
|
||||
catch (std::out_of_range e)
|
||||
{
|
||||
pass();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
fail();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
v.at(0) = 1;
|
||||
fail();
|
||||
}
|
||||
catch (std::out_of_range e)
|
||||
{
|
||||
pass();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
// Checks invariants for an empty buffer_view
|
||||
template <class V>
|
||||
void checkEmpty (V& v)
|
||||
{
|
||||
expect (v.empty());
|
||||
expect (v.size() == 0);
|
||||
expect (v.max_size() == v.size());
|
||||
expect (v.capacity() == v.size());
|
||||
expect (v.begin() == v.end());
|
||||
expect (v.cbegin() == v.cend());
|
||||
expect (v.begin() == v.cend());
|
||||
expect (v.rbegin() == v.rend());
|
||||
expect (v.crbegin() == v.rend());
|
||||
|
||||
checkBadIndex (v);
|
||||
}
|
||||
|
||||
// Test empty containers
|
||||
void testEmpty()
|
||||
{
|
||||
testcase ("empty");
|
||||
|
||||
buffer_view <char> v1;
|
||||
checkEmpty (v1);
|
||||
|
||||
buffer_view <char> v2;
|
||||
swap (v1, v2);
|
||||
checkEmpty (v1);
|
||||
checkEmpty (v2);
|
||||
|
||||
buffer_view <char const> v3 (v2);
|
||||
checkEmpty (v3);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Construct const views from a container
|
||||
template <class C>
|
||||
void testConstructConst (C const& c)
|
||||
{
|
||||
typedef buffer_view <std::add_const_t <
|
||||
typename C::value_type>> V;
|
||||
|
||||
{
|
||||
// construct from container
|
||||
V v (c);
|
||||
check (c, v);
|
||||
|
||||
// construct from buffer_view
|
||||
V v2 (v);
|
||||
check (c, v2);
|
||||
}
|
||||
|
||||
if (! c.empty())
|
||||
{
|
||||
{
|
||||
// construct from const pointer range
|
||||
V v (&c.front(), &c.back()+1);
|
||||
check (c, v);
|
||||
|
||||
// construct from pointer and size
|
||||
V v2 (&c.front(), c.size());
|
||||
check (v, v2);
|
||||
}
|
||||
|
||||
{
|
||||
// construct from non const pointer range
|
||||
C cp (c);
|
||||
V v (&cp.front(), &cp.back()+1);
|
||||
check (cp, v);
|
||||
|
||||
// construct from pointer and size
|
||||
V v2 (&cp.front(), cp.size());
|
||||
check (v, v2);
|
||||
|
||||
// construct from data and size
|
||||
V v3 (v2.data(), v2.size());
|
||||
check (c, v3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Construct view from a container
|
||||
template <class C>
|
||||
void testConstruct (C const& c)
|
||||
{
|
||||
static_assert (! std::is_const <typename C::value_type>::value,
|
||||
"Container value_type cannot be const");
|
||||
|
||||
testConstructConst (c);
|
||||
|
||||
typedef buffer_view <typename C::value_type> V;
|
||||
|
||||
C cp (c);
|
||||
V v (cp);
|
||||
check (cp, v);
|
||||
|
||||
std::reverse (v.begin(), v.end());
|
||||
check (cp, v);
|
||||
|
||||
expect (std::equal (v.rbegin(), v.rend(),
|
||||
c.begin(), c.end()));
|
||||
}
|
||||
|
||||
void testConstruct()
|
||||
{
|
||||
testcase ("std::vector <char>");
|
||||
testConstruct (
|
||||
std::vector <char> ({'h', 'e', 'l', 'l', 'o'}));
|
||||
|
||||
testcase ("std::string <char>");
|
||||
testConstruct (
|
||||
std::basic_string <char> ("hello"));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void testCoerce()
|
||||
{
|
||||
testcase ("coerce");
|
||||
|
||||
std::string const s ("hello");
|
||||
const_buffer_view <unsigned char> v (s);
|
||||
|
||||
pass();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void testAssign()
|
||||
{
|
||||
testcase ("testAssign");
|
||||
std::vector <int> v1({1, 2, 3});
|
||||
buffer_view<int> r1(v1);
|
||||
std::vector <int> v2({4, 5, 6, 7});
|
||||
buffer_view<int> r2(v2);
|
||||
r1 = r2;
|
||||
expect (std::equal (r1.begin(), r1.end(), v2.begin(), v2.end()));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
static_assert (std::is_constructible <buffer_view <int>,
|
||||
std::vector <int>&>::value, "");
|
||||
|
||||
static_assert (!std::is_constructible <buffer_view <int>,
|
||||
std::vector <int> const&>::value, "");
|
||||
|
||||
static_assert (std::is_constructible <buffer_view <int const>,
|
||||
std::vector <int>&>::value, "");
|
||||
|
||||
static_assert (std::is_constructible <buffer_view <int const>,
|
||||
std::vector <int> const&>::value, "");
|
||||
|
||||
static_assert (std::is_nothrow_default_constructible <
|
||||
buffer_view <int>>::value, "");
|
||||
|
||||
static_assert (std::is_nothrow_destructible <
|
||||
buffer_view <int>>::value, "");
|
||||
|
||||
static_assert (std::is_nothrow_copy_constructible <
|
||||
buffer_view <int>>::value, "");
|
||||
|
||||
static_assert (std::is_nothrow_copy_assignable <
|
||||
buffer_view<int>>::value, "");
|
||||
|
||||
static_assert (std::is_nothrow_move_constructible <
|
||||
buffer_view <int>>::value, "");
|
||||
|
||||
static_assert (std::is_nothrow_move_assignable <
|
||||
buffer_view <int>>::value, "");
|
||||
|
||||
void run()
|
||||
{
|
||||
testEmpty();
|
||||
testConstruct();
|
||||
testCoerce();
|
||||
testAssign();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(buffer_view,container,beast);
|
||||
|
||||
}
|
||||
@@ -21,7 +21,6 @@
|
||||
#include <BeastConfig.h>
|
||||
#endif
|
||||
|
||||
#include <beast/crypto/impl/MurmurHash.cpp>
|
||||
#include <beast/crypto/impl/Sha256.cpp>
|
||||
|
||||
#include <beast/crypto/tests/base64.test.cpp>
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_CRYPTO_MURMURHASH_H_INCLUDED
|
||||
#define BEAST_CRYPTO_MURMURHASH_H_INCLUDED
|
||||
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
|
||||
// Original source code links in .cpp file
|
||||
|
||||
namespace beast {
|
||||
namespace Murmur {
|
||||
|
||||
extern void MurmurHash3_x86_32 (const void* key, int len, std::uint32_t seed, void* out);
|
||||
extern void MurmurHash3_x86_128 (const void* key, int len, std::uint32_t seed, void* out);
|
||||
extern void MurmurHash3_x64_128 (const void* key, int len, std::uint32_t seed, void* out);
|
||||
|
||||
// Uses Beast to choose an appropriate routine
|
||||
|
||||
// This handy template deduces which size hash is desired
|
||||
template <typename HashType>
|
||||
inline void Hash (const void* key, int len, std::uint32_t seed, HashType* out)
|
||||
{
|
||||
switch (8 * sizeof (HashType))
|
||||
{
|
||||
case 32:
|
||||
MurmurHash3_x86_32 (key, len, seed, out);
|
||||
break;
|
||||
|
||||
#if BEAST_64BIT
|
||||
case 64:
|
||||
{
|
||||
HashType tmp[2];
|
||||
MurmurHash3_x64_128 (key, len, seed, &tmp[0]);
|
||||
*out = tmp[0];
|
||||
}
|
||||
break;
|
||||
|
||||
case 128:
|
||||
MurmurHash3_x64_128 (key, len, seed, out);
|
||||
break;
|
||||
|
||||
#else
|
||||
case 64:
|
||||
{
|
||||
HashType tmp[2];
|
||||
MurmurHash3_x86_128 (key, len, seed, &tmp[0]);
|
||||
*out = tmp[0];
|
||||
}
|
||||
break;
|
||||
|
||||
case 128:
|
||||
MurmurHash3_x86_128 (key, len, seed, out);
|
||||
break;
|
||||
|
||||
#endif
|
||||
|
||||
default:
|
||||
throw std::runtime_error ("invalid key size in MurmurHash");
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,492 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
// http://code.google.com/p/smhasher/
|
||||
|
||||
#include <beast/crypto/MurmurHash.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace beast {
|
||||
namespace Murmur {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Platform-specific functions and macros
|
||||
|
||||
// Microsoft Visual Studio
|
||||
|
||||
#if BEAST_MSVC
|
||||
|
||||
#define ROTL32(x,y) _rotl(x,y)
|
||||
#define ROTL64(x,y) _rotl64(x,y)
|
||||
|
||||
#define BIG_CONSTANT(x) (x)
|
||||
|
||||
// Other compilers
|
||||
|
||||
#else
|
||||
|
||||
static inline std::uint32_t rotl32 ( std::uint32_t x, int8_t r )
|
||||
{
|
||||
return (x << r) | (x >> (32 - r));
|
||||
}
|
||||
|
||||
static inline std::uint64_t rotl64 ( std::uint64_t x, int8_t r )
|
||||
{
|
||||
return (x << r) | (x >> (64 - r));
|
||||
}
|
||||
|
||||
#define ROTL32(x,y) rotl32(x,y)
|
||||
#define ROTL64(x,y) rotl64(x,y)
|
||||
|
||||
#define BIG_CONSTANT(x) (x##LLU)
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Block read - if your platform needs to do endian-swapping or can only
|
||||
// handle aligned reads, do the conversion here
|
||||
|
||||
static inline std::uint32_t getblock ( const std::uint32_t* p, int i )
|
||||
{
|
||||
return p[i];
|
||||
}
|
||||
|
||||
static inline std::uint64_t getblock ( const std::uint64_t* p, int i )
|
||||
{
|
||||
return p[i];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Finalization mix - force all bits of a hash block to avalanche
|
||||
|
||||
static inline std::uint32_t fmix ( std::uint32_t h )
|
||||
{
|
||||
h ^= h >> 16;
|
||||
h *= 0x85ebca6b;
|
||||
h ^= h >> 13;
|
||||
h *= 0xc2b2ae35;
|
||||
h ^= h >> 16;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
//----------
|
||||
|
||||
static inline std::uint64_t fmix ( std::uint64_t k )
|
||||
{
|
||||
k ^= k >> 33;
|
||||
k *= BIG_CONSTANT (0xff51afd7ed558ccd);
|
||||
k ^= k >> 33;
|
||||
k *= BIG_CONSTANT (0xc4ceb9fe1a85ec53);
|
||||
k ^= k >> 33;
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void MurmurHash3_x86_32 ( const void* key, int len,
|
||||
std::uint32_t seed, void* out )
|
||||
{
|
||||
const uint8_t* data = (const uint8_t*)key;
|
||||
const int nblocks = len / 4;
|
||||
|
||||
std::uint32_t h1 = seed;
|
||||
|
||||
std::uint32_t c1 = 0xcc9e2d51;
|
||||
std::uint32_t c2 = 0x1b873593;
|
||||
|
||||
//----------
|
||||
// body
|
||||
|
||||
const std::uint32_t* blocks = (const std::uint32_t*) (data + nblocks * 4);
|
||||
|
||||
for (int i = -nblocks; i; i++)
|
||||
{
|
||||
std::uint32_t k1 = getblock (blocks, i);
|
||||
|
||||
k1 *= c1;
|
||||
k1 = ROTL32 (k1, 15);
|
||||
k1 *= c2;
|
||||
|
||||
h1 ^= k1;
|
||||
h1 = ROTL32 (h1, 13);
|
||||
h1 = h1 * 5 + 0xe6546b64;
|
||||
}
|
||||
|
||||
//----------
|
||||
// tail
|
||||
|
||||
const uint8_t* tail = (const uint8_t*) (data + nblocks * 4);
|
||||
|
||||
std::uint32_t k1 = 0;
|
||||
|
||||
switch (len & 3)
|
||||
{
|
||||
case 3:
|
||||
k1 ^= tail[2] << 16;
|
||||
|
||||
case 2:
|
||||
k1 ^= tail[1] << 8;
|
||||
|
||||
case 1:
|
||||
k1 ^= tail[0];
|
||||
k1 *= c1;
|
||||
k1 = ROTL32 (k1, 15);
|
||||
k1 *= c2;
|
||||
h1 ^= k1;
|
||||
};
|
||||
|
||||
//----------
|
||||
// finalization
|
||||
|
||||
h1 ^= len;
|
||||
|
||||
h1 = fmix (h1);
|
||||
|
||||
* (std::uint32_t*)out = h1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void MurmurHash3_x86_128 ( const void* key, const int len,
|
||||
std::uint32_t seed, void* out )
|
||||
{
|
||||
const uint8_t* data = (const uint8_t*)key;
|
||||
const int nblocks = len / 16;
|
||||
|
||||
std::uint32_t h1 = seed;
|
||||
std::uint32_t h2 = seed;
|
||||
std::uint32_t h3 = seed;
|
||||
std::uint32_t h4 = seed;
|
||||
|
||||
std::uint32_t c1 = 0x239b961b;
|
||||
std::uint32_t c2 = 0xab0e9789;
|
||||
std::uint32_t c3 = 0x38b34ae5;
|
||||
std::uint32_t c4 = 0xa1e38b93;
|
||||
|
||||
//----------
|
||||
// body
|
||||
|
||||
const std::uint32_t* blocks = (const std::uint32_t*) (data + nblocks * 16);
|
||||
|
||||
for (int i = -nblocks; i; i++)
|
||||
{
|
||||
std::uint32_t k1 = getblock (blocks, i * 4 + 0);
|
||||
std::uint32_t k2 = getblock (blocks, i * 4 + 1);
|
||||
std::uint32_t k3 = getblock (blocks, i * 4 + 2);
|
||||
std::uint32_t k4 = getblock (blocks, i * 4 + 3);
|
||||
|
||||
k1 *= c1;
|
||||
k1 = ROTL32 (k1, 15);
|
||||
k1 *= c2;
|
||||
h1 ^= k1;
|
||||
|
||||
h1 = ROTL32 (h1, 19);
|
||||
h1 += h2;
|
||||
h1 = h1 * 5 + 0x561ccd1b;
|
||||
|
||||
k2 *= c2;
|
||||
k2 = ROTL32 (k2, 16);
|
||||
k2 *= c3;
|
||||
h2 ^= k2;
|
||||
|
||||
h2 = ROTL32 (h2, 17);
|
||||
h2 += h3;
|
||||
h2 = h2 * 5 + 0x0bcaa747;
|
||||
|
||||
k3 *= c3;
|
||||
k3 = ROTL32 (k3, 17);
|
||||
k3 *= c4;
|
||||
h3 ^= k3;
|
||||
|
||||
h3 = ROTL32 (h3, 15);
|
||||
h3 += h4;
|
||||
h3 = h3 * 5 + 0x96cd1c35;
|
||||
|
||||
k4 *= c4;
|
||||
k4 = ROTL32 (k4, 18);
|
||||
k4 *= c1;
|
||||
h4 ^= k4;
|
||||
|
||||
h4 = ROTL32 (h4, 13);
|
||||
h4 += h1;
|
||||
h4 = h4 * 5 + 0x32ac3b17;
|
||||
}
|
||||
|
||||
//----------
|
||||
// tail
|
||||
|
||||
const uint8_t* tail = (const uint8_t*) (data + nblocks * 16);
|
||||
|
||||
std::uint32_t k1 = 0;
|
||||
std::uint32_t k2 = 0;
|
||||
std::uint32_t k3 = 0;
|
||||
std::uint32_t k4 = 0;
|
||||
|
||||
switch (len & 15)
|
||||
{
|
||||
case 15:
|
||||
k4 ^= tail[14] << 16;
|
||||
|
||||
case 14:
|
||||
k4 ^= tail[13] << 8;
|
||||
|
||||
case 13:
|
||||
k4 ^= tail[12] << 0;
|
||||
k4 *= c4;
|
||||
k4 = ROTL32 (k4, 18);
|
||||
k4 *= c1;
|
||||
h4 ^= k4;
|
||||
|
||||
case 12:
|
||||
k3 ^= tail[11] << 24;
|
||||
|
||||
case 11:
|
||||
k3 ^= tail[10] << 16;
|
||||
|
||||
case 10:
|
||||
k3 ^= tail[ 9] << 8;
|
||||
|
||||
case 9:
|
||||
k3 ^= tail[ 8] << 0;
|
||||
k3 *= c3;
|
||||
k3 = ROTL32 (k3, 17);
|
||||
k3 *= c4;
|
||||
h3 ^= k3;
|
||||
|
||||
case 8:
|
||||
k2 ^= tail[ 7] << 24;
|
||||
|
||||
case 7:
|
||||
k2 ^= tail[ 6] << 16;
|
||||
|
||||
case 6:
|
||||
k2 ^= tail[ 5] << 8;
|
||||
|
||||
case 5:
|
||||
k2 ^= tail[ 4] << 0;
|
||||
k2 *= c2;
|
||||
k2 = ROTL32 (k2, 16);
|
||||
k2 *= c3;
|
||||
h2 ^= k2;
|
||||
|
||||
case 4:
|
||||
k1 ^= tail[ 3] << 24;
|
||||
|
||||
case 3:
|
||||
k1 ^= tail[ 2] << 16;
|
||||
|
||||
case 2:
|
||||
k1 ^= tail[ 1] << 8;
|
||||
|
||||
case 1:
|
||||
k1 ^= tail[ 0] << 0;
|
||||
k1 *= c1;
|
||||
k1 = ROTL32 (k1, 15);
|
||||
k1 *= c2;
|
||||
h1 ^= k1;
|
||||
};
|
||||
|
||||
//----------
|
||||
// finalization
|
||||
|
||||
h1 ^= len;
|
||||
|
||||
h2 ^= len;
|
||||
|
||||
h3 ^= len;
|
||||
|
||||
h4 ^= len;
|
||||
|
||||
h1 += h2;
|
||||
|
||||
h1 += h3;
|
||||
|
||||
h1 += h4;
|
||||
|
||||
h2 += h1;
|
||||
|
||||
h3 += h1;
|
||||
|
||||
h4 += h1;
|
||||
|
||||
h1 = fmix (h1);
|
||||
|
||||
h2 = fmix (h2);
|
||||
|
||||
h3 = fmix (h3);
|
||||
|
||||
h4 = fmix (h4);
|
||||
|
||||
h1 += h2;
|
||||
|
||||
h1 += h3;
|
||||
|
||||
h1 += h4;
|
||||
|
||||
h2 += h1;
|
||||
|
||||
h3 += h1;
|
||||
|
||||
h4 += h1;
|
||||
|
||||
((std::uint32_t*)out)[0] = h1;
|
||||
|
||||
((std::uint32_t*)out)[1] = h2;
|
||||
|
||||
((std::uint32_t*)out)[2] = h3;
|
||||
|
||||
((std::uint32_t*)out)[3] = h4;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void MurmurHash3_x64_128 ( const void* key, const int len,
|
||||
const std::uint32_t seed, void* out )
|
||||
{
|
||||
const uint8_t* data = (const uint8_t*)key;
|
||||
const int nblocks = len / 16;
|
||||
|
||||
std::uint64_t h1 = seed;
|
||||
std::uint64_t h2 = seed;
|
||||
|
||||
std::uint64_t c1 = BIG_CONSTANT (0x87c37b91114253d5);
|
||||
std::uint64_t c2 = BIG_CONSTANT (0x4cf5ad432745937f);
|
||||
|
||||
//----------
|
||||
// body
|
||||
|
||||
const std::uint64_t* blocks = (const std::uint64_t*) (data);
|
||||
|
||||
for (int i = 0; i < nblocks; i++)
|
||||
{
|
||||
std::uint64_t k1 = getblock (blocks, i * 2 + 0);
|
||||
std::uint64_t k2 = getblock (blocks, i * 2 + 1);
|
||||
|
||||
k1 *= c1;
|
||||
k1 = ROTL64 (k1, 31);
|
||||
k1 *= c2;
|
||||
h1 ^= k1;
|
||||
|
||||
h1 = ROTL64 (h1, 27);
|
||||
h1 += h2;
|
||||
h1 = h1 * 5 + 0x52dce729;
|
||||
|
||||
k2 *= c2;
|
||||
k2 = ROTL64 (k2, 33);
|
||||
k2 *= c1;
|
||||
h2 ^= k2;
|
||||
|
||||
h2 = ROTL64 (h2, 31);
|
||||
h2 += h1;
|
||||
h2 = h2 * 5 + 0x38495ab5;
|
||||
}
|
||||
|
||||
//----------
|
||||
// tail
|
||||
|
||||
const uint8_t* tail = (const uint8_t*) (data + nblocks * 16);
|
||||
|
||||
std::uint64_t k1 = 0;
|
||||
std::uint64_t k2 = 0;
|
||||
|
||||
switch (len & 15)
|
||||
{
|
||||
case 15:
|
||||
k2 ^= std::uint64_t (tail[14]) << 48;
|
||||
|
||||
case 14:
|
||||
k2 ^= std::uint64_t (tail[13]) << 40;
|
||||
|
||||
case 13:
|
||||
k2 ^= std::uint64_t (tail[12]) << 32;
|
||||
|
||||
case 12:
|
||||
k2 ^= std::uint64_t (tail[11]) << 24;
|
||||
|
||||
case 11:
|
||||
k2 ^= std::uint64_t (tail[10]) << 16;
|
||||
|
||||
case 10:
|
||||
k2 ^= std::uint64_t (tail[ 9]) << 8;
|
||||
|
||||
case 9:
|
||||
k2 ^= std::uint64_t (tail[ 8]) << 0;
|
||||
k2 *= c2;
|
||||
k2 = ROTL64 (k2, 33);
|
||||
k2 *= c1;
|
||||
h2 ^= k2;
|
||||
|
||||
case 8:
|
||||
k1 ^= std::uint64_t (tail[ 7]) << 56;
|
||||
|
||||
case 7:
|
||||
k1 ^= std::uint64_t (tail[ 6]) << 48;
|
||||
|
||||
case 6:
|
||||
k1 ^= std::uint64_t (tail[ 5]) << 40;
|
||||
|
||||
case 5:
|
||||
k1 ^= std::uint64_t (tail[ 4]) << 32;
|
||||
|
||||
case 4:
|
||||
k1 ^= std::uint64_t (tail[ 3]) << 24;
|
||||
|
||||
case 3:
|
||||
k1 ^= std::uint64_t (tail[ 2]) << 16;
|
||||
|
||||
case 2:
|
||||
k1 ^= std::uint64_t (tail[ 1]) << 8;
|
||||
|
||||
case 1:
|
||||
k1 ^= std::uint64_t (tail[ 0]) << 0;
|
||||
k1 *= c1;
|
||||
k1 = ROTL64 (k1, 31);
|
||||
k1 *= c2;
|
||||
h1 ^= k1;
|
||||
};
|
||||
|
||||
//----------
|
||||
// finalization
|
||||
|
||||
h1 ^= len;
|
||||
|
||||
h2 ^= len;
|
||||
|
||||
h1 += h2;
|
||||
|
||||
h2 += h1;
|
||||
|
||||
h1 = fmix (h1);
|
||||
|
||||
h2 = fmix (h2);
|
||||
|
||||
h1 += h2;
|
||||
|
||||
h2 += h1;
|
||||
|
||||
((std::uint64_t*)out)[0] = h1;
|
||||
|
||||
((std::uint64_t*)out)[1] = h2;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -32,8 +32,8 @@
|
||||
* $Id: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $
|
||||
*/
|
||||
|
||||
#ifndef __SHA2_H__
|
||||
#define __SHA2_H__
|
||||
#ifndef BEAST_CRYPTO_SHA2_SHA2_H_INCLUDED
|
||||
#define BEAST_CRYPTO_SHA2_SHA2_H_INCLUDED
|
||||
|
||||
//#ifdef __cplusplus
|
||||
//extern "C" {
|
||||
|
||||
71
src/beast/beast/hash/fnv1a.h
Normal file
@@ -0,0 +1,71 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2014, Howard Hinnant <howard.hinnant@gmail.com>,
|
||||
Vinnie Falco <vinnie.falco@gmail.com
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_HASH_FNV1A_H_INCLUDED
|
||||
#define BEAST_HASH_FNV1A_H_INCLUDED
|
||||
|
||||
#include <beast/utility/noexcept.h>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <beast/cxx14/type_traits.h> // <type_traits>
|
||||
|
||||
namespace beast {
|
||||
|
||||
// See http://www.isthe.com/chongo/tech/comp/fnv/
|
||||
//
|
||||
class fnv1a
|
||||
{
|
||||
private:
|
||||
std::uint64_t state_ = 14695981039346656037ULL;
|
||||
|
||||
public:
|
||||
using result_type = std::size_t;
|
||||
|
||||
fnv1a() = default;
|
||||
|
||||
template <class Seed,
|
||||
std::enable_if_t<
|
||||
std::is_unsigned<Seed>::value>* = nullptr>
|
||||
explicit
|
||||
fnv1a (Seed seed)
|
||||
{
|
||||
append (&seed, sizeof(seed));
|
||||
}
|
||||
|
||||
void
|
||||
append (void const* key, std::size_t len) noexcept
|
||||
{
|
||||
unsigned char const* p =
|
||||
static_cast<unsigned char const*>(key);
|
||||
unsigned char const* const e = p + len;
|
||||
for (; p < e; ++p)
|
||||
state_ = (state_ ^ *p) * 1099511628211ULL;
|
||||
}
|
||||
|
||||
explicit
|
||||
operator std::size_t() noexcept
|
||||
{
|
||||
return static_cast<std::size_t>(state_);
|
||||
}
|
||||
};
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -18,18 +18,14 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_CONTAINER_HASH_APPEND_H_INCLUDED
|
||||
#define BEAST_CONTAINER_HASH_APPEND_H_INCLUDED
|
||||
#ifndef BEAST_HASH_HASH_APPEND_H_INCLUDED
|
||||
#define BEAST_HASH_HASH_APPEND_H_INCLUDED
|
||||
|
||||
#include <beast/utility/meta.h>
|
||||
|
||||
#include <beast/container/impl/spookyv2.h>
|
||||
|
||||
#include <beast/utility/noexcept.h>
|
||||
#if BEAST_USE_BOOST_FEATURES
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#endif
|
||||
|
||||
#include <beast/utility/noexcept.h>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
@@ -656,96 +652,6 @@ hash_append (Hasher& h, T0 const& t0, T1 const& t1, T const& ...t) noexcept
|
||||
hash_append (h, t1, t...);
|
||||
}
|
||||
|
||||
// See http://www.isthe.com/chongo/tech/comp/fnv/
|
||||
class fnv1a
|
||||
{
|
||||
std::uint64_t state_ = 14695981039346656037ULL;
|
||||
public:
|
||||
|
||||
using result_type = std::size_t;
|
||||
|
||||
void
|
||||
append (void const* key, std::size_t len) noexcept
|
||||
{
|
||||
unsigned char const* p = static_cast<unsigned char const*>(key);
|
||||
unsigned char const* const e = p + len;
|
||||
for (; p < e; ++p)
|
||||
state_ = (state_ ^ *p) * 1099511628211ULL;
|
||||
}
|
||||
|
||||
explicit
|
||||
operator std::size_t() noexcept
|
||||
{
|
||||
return static_cast<std::size_t>(state_);
|
||||
}
|
||||
};
|
||||
|
||||
// See http://burtleburtle.net/bob/hash/spooky.html
|
||||
class spooky
|
||||
{
|
||||
SpookyHash state_;
|
||||
public:
|
||||
using result_type = std::size_t;
|
||||
|
||||
spooky (std::size_t seed1 = 1, std::size_t seed2 = 2) noexcept
|
||||
{
|
||||
state_.Init (seed1, seed2);
|
||||
}
|
||||
|
||||
void
|
||||
append (void const* key, std::size_t len) noexcept
|
||||
{
|
||||
state_.Update (key, len);
|
||||
}
|
||||
|
||||
explicit
|
||||
operator std::size_t() noexcept
|
||||
{
|
||||
std::uint64_t h1, h2;
|
||||
state_.Final (&h1, &h2);
|
||||
return static_cast <std::size_t> (h1);
|
||||
}
|
||||
};
|
||||
|
||||
// See https://131002.net/siphash/
|
||||
class siphash
|
||||
{
|
||||
std::uint64_t v0_ = 0x736f6d6570736575ULL;
|
||||
std::uint64_t v1_ = 0x646f72616e646f6dULL;
|
||||
std::uint64_t v2_ = 0x6c7967656e657261ULL;
|
||||
std::uint64_t v3_ = 0x7465646279746573ULL;
|
||||
unsigned char buf_[8];
|
||||
unsigned bufsize_ = 0;
|
||||
unsigned total_length_ = 0;
|
||||
public:
|
||||
using result_type = std::size_t;
|
||||
|
||||
siphash() = default;
|
||||
explicit siphash(std::uint64_t k0, std::uint64_t k1 = 0) noexcept;
|
||||
|
||||
void
|
||||
append (void const* key, std::size_t len) noexcept;
|
||||
|
||||
explicit
|
||||
operator std::size_t() noexcept;
|
||||
};
|
||||
|
||||
template <class Hasher = spooky>
|
||||
struct uhash
|
||||
{
|
||||
using result_type = typename Hasher::result_type;
|
||||
|
||||
template <class T>
|
||||
result_type
|
||||
operator()(T const& t) const noexcept
|
||||
{
|
||||
Hasher h;
|
||||
hash_append (h, t);
|
||||
return static_cast<result_type>(h);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
85
src/beast/beast/hash/impl/hash_speed_test.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#if BEAST_INCLUDE_BEASTCONFIG
|
||||
#include <BeastConfig.h>
|
||||
#endif
|
||||
#include <beast/container/fnv1a.h>
|
||||
#include <beast/container/siphash.h>
|
||||
#include <beast/container/xxhasher.h>
|
||||
#include <beast/random/rngfill.h>
|
||||
#include <beast/random/xor_shift_engine.h>
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <random>
|
||||
|
||||
namespace beast {
|
||||
|
||||
class hash_speed_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
using clock_type =
|
||||
std::chrono::high_resolution_clock;
|
||||
template <class Hasher, std::size_t KeySize>
|
||||
void
|
||||
test (std::string const& what, std::size_t n)
|
||||
{
|
||||
using namespace std;
|
||||
using namespace std::chrono;
|
||||
xor_shift_engine g(1);
|
||||
array<std::uint8_t, KeySize> key;
|
||||
auto const start = clock_type::now();
|
||||
while(n--)
|
||||
{
|
||||
rngfill (key, g);
|
||||
Hasher h;
|
||||
h.append(key.data(), KeySize);
|
||||
volatile size_t temp =
|
||||
static_cast<std::size_t>(h);
|
||||
(void)temp;
|
||||
}
|
||||
auto const elapsed = clock_type::now() - start;
|
||||
log << setw(12) << what << " " <<
|
||||
duration<double>(elapsed) << "s";
|
||||
}
|
||||
|
||||
void
|
||||
run()
|
||||
{
|
||||
enum
|
||||
{
|
||||
N = 100000000
|
||||
};
|
||||
|
||||
#if ! BEAST_NO_XXHASH
|
||||
test<xxhasher,32> ("xxhash", N);
|
||||
#endif
|
||||
test<fnv1a,32> ("fnv1a", N);
|
||||
test<siphash,32> ("siphash", N);
|
||||
pass();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE_MANUAL(hash_speed,container,beast);
|
||||
|
||||
} // beast
|
||||
@@ -24,18 +24,15 @@
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include <beast/container/hash_append.h>
|
||||
#include <beast/hash/siphash.h>
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
// namespace acme is used to demonstrate example code. It is not proposed.
|
||||
|
||||
namespace beast
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace beast {
|
||||
namespace detail {
|
||||
|
||||
typedef std::uint64_t u64;
|
||||
typedef std::uint32_t u32;
|
||||
@@ -82,7 +79,7 @@ sipround(u64& v0, u64& v1, u64& v2, u64& v3)
|
||||
v2 = rotl(v2, 32);
|
||||
}
|
||||
|
||||
} // unnamed
|
||||
} // detail
|
||||
|
||||
siphash::siphash(std::uint64_t k0, std::uint64_t k1) noexcept
|
||||
{
|
||||
@@ -95,6 +92,7 @@ siphash::siphash(std::uint64_t k0, std::uint64_t k1) noexcept
|
||||
void
|
||||
siphash::append (void const* key, std::size_t inlen) noexcept
|
||||
{
|
||||
using namespace detail;
|
||||
u8 const* in = static_cast<const u8*>(key);
|
||||
total_length_ += inlen;
|
||||
if (bufsize_ + inlen < 8)
|
||||
@@ -130,6 +128,7 @@ siphash::append (void const* key, std::size_t inlen) noexcept
|
||||
|
||||
siphash::operator std::size_t() noexcept
|
||||
{
|
||||
using namespace detail;
|
||||
std::size_t b = static_cast<u64>(total_length_) << 56;
|
||||
switch(bufsize_)
|
||||
{
|
||||
@@ -163,4 +162,4 @@ siphash::operator std::size_t() noexcept
|
||||
return b;
|
||||
}
|
||||
|
||||
} // beast
|
||||
} // beast
|
||||
@@ -10,7 +10,7 @@
|
||||
// August 5 2012: SpookyV2: d = should be d += in short hash, and remove extra mix from long hash
|
||||
|
||||
#include <memory.h>
|
||||
#include <beast/container/impl/spookyv2.h>
|
||||
#include <beast/hash/impl/spookyv2.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
@@ -26,8 +26,8 @@
|
||||
// slower than MD5.
|
||||
//
|
||||
|
||||
#ifndef BEAST_SPOOKYV2_H_INCLUDED
|
||||
#define BEAST_SPOOKYV2_H_INCLUDED
|
||||
#ifndef BEAST_HASH_SPOOKYV2_H_INCLUDED
|
||||
#define BEAST_HASH_SPOOKYV2_H_INCLUDED
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
934
src/beast/beast/hash/impl/xxhash.c
Normal file
@@ -0,0 +1,934 @@
|
||||
/*
|
||||
xxHash - Fast Hash algorithm
|
||||
Copyright (C) 2012-2014, Yann Collet.
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- xxHash source repository : http://code.google.com/p/xxhash/
|
||||
- public discussion board : https://groups.google.com/forum/#!forum/lz4c
|
||||
*/
|
||||
|
||||
#include <beast/hash/impl/xxhash.h>
|
||||
|
||||
//**************************************
|
||||
// Tuning parameters
|
||||
//**************************************
|
||||
// Unaligned memory access is automatically enabled for "common" CPU, such as x86.
|
||||
// For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected.
|
||||
// If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance.
|
||||
// You can also enable this parameter if you know your input data will always be aligned (boundaries of 4, for U32).
|
||||
#if defined(__ARM_FEATURE_UNALIGNED) || defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
|
||||
# define XXH_USE_UNALIGNED_ACCESS 1
|
||||
#endif
|
||||
|
||||
// XXH_ACCEPT_NULL_INPUT_POINTER :
|
||||
// If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer.
|
||||
// When this option is enabled, xxHash output for null input pointers will be the same as a null-length input.
|
||||
// This option has a very small performance cost (only measurable on small inputs).
|
||||
// By default, this option is disabled. To enable it, uncomment below define :
|
||||
// #define XXH_ACCEPT_NULL_INPUT_POINTER 1
|
||||
|
||||
// XXH_FORCE_NATIVE_FORMAT :
|
||||
// By default, xxHash library provides endian-independant Hash values, based on little-endian convention.
|
||||
// Results are therefore identical for little-endian and big-endian CPU.
|
||||
// This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
|
||||
// Should endian-independance be of no importance for your application, you may set the #define below to 1.
|
||||
// It will improve speed for Big-endian CPU.
|
||||
// This option has no impact on Little_Endian CPU.
|
||||
#define XXH_FORCE_NATIVE_FORMAT 0
|
||||
|
||||
//**************************************
|
||||
// Compiler Specific Options
|
||||
//**************************************
|
||||
// Disable some Visual warning messages
|
||||
#ifdef _MSC_VER // Visual Studio
|
||||
# pragma warning(disable : 4127) // disable: C4127: conditional expression is constant
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER // Visual Studio
|
||||
# define FORCE_INLINE static __forceinline
|
||||
#else
|
||||
# ifdef __GNUC__
|
||||
# define FORCE_INLINE static inline __attribute__((always_inline))
|
||||
# else
|
||||
# define FORCE_INLINE static inline
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//**************************************
|
||||
// Includes & Memory related functions
|
||||
//**************************************
|
||||
//#include "xxhash.h"
|
||||
// Modify the local functions below should you wish to use some other memory routines
|
||||
// for malloc(), free()
|
||||
#include <stdlib.h>
|
||||
static void* XXH_malloc(size_t s) { return malloc(s); }
|
||||
static void XXH_free (void* p) { free(p); }
|
||||
// for memcpy()
|
||||
#include <string.h>
|
||||
static void* XXH_memcpy(void* dest, const void* src, size_t size)
|
||||
{
|
||||
return memcpy(dest,src,size);
|
||||
}
|
||||
|
||||
|
||||
//**************************************
|
||||
// Basic Types
|
||||
//**************************************
|
||||
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L // C99
|
||||
# include <stdint.h>
|
||||
typedef uint8_t BYTE;
|
||||
typedef uint16_t U16;
|
||||
typedef uint32_t U32;
|
||||
typedef int32_t S32;
|
||||
typedef uint64_t U64;
|
||||
#else
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned short U16;
|
||||
typedef unsigned int U32;
|
||||
typedef signed int S32;
|
||||
typedef unsigned long long U64;
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && !defined(XXH_USE_UNALIGNED_ACCESS)
|
||||
# define _PACKED __attribute__ ((packed))
|
||||
#else
|
||||
# define _PACKED
|
||||
#endif
|
||||
|
||||
#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__)
|
||||
# ifdef __IBMC__
|
||||
# pragma pack(1)
|
||||
# else
|
||||
# pragma pack(push, 1)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace beast {
|
||||
namespace detail {
|
||||
|
||||
typedef struct _U32_S
|
||||
{
|
||||
U32 v;
|
||||
} _PACKED U32_S;
|
||||
typedef struct _U64_S
|
||||
{
|
||||
U64 v;
|
||||
} _PACKED U64_S;
|
||||
|
||||
#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__)
|
||||
# pragma pack(pop)
|
||||
#endif
|
||||
|
||||
#define A32(x) (((U32_S *)(x))->v)
|
||||
#define A64(x) (((U64_S *)(x))->v)
|
||||
|
||||
|
||||
//***************************************
|
||||
// Compiler-specific Functions and Macros
|
||||
//***************************************
|
||||
#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
|
||||
// Note : although _rotl exists for minGW (GCC under windows), performance seems poor
|
||||
#if defined(_MSC_VER)
|
||||
# define XXH_rotl32(x,r) _rotl(x,r)
|
||||
# define XXH_rotl64(x,r) _rotl64(x,r)
|
||||
#else
|
||||
# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
|
||||
# define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r)))
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) // Visual Studio
|
||||
# define XXH_swap32 _byteswap_ulong
|
||||
# define XXH_swap64 _byteswap_uint64
|
||||
#elif GCC_VERSION >= 403
|
||||
# define XXH_swap32 __builtin_bswap32
|
||||
# define XXH_swap64 __builtin_bswap64
|
||||
#else
|
||||
static inline U32 XXH_swap32 (U32 x)
|
||||
{
|
||||
return ((x << 24) & 0xff000000 ) |
|
||||
((x << 8) & 0x00ff0000 ) |
|
||||
((x >> 8) & 0x0000ff00 ) |
|
||||
((x >> 24) & 0x000000ff );
|
||||
}
|
||||
static inline U64 XXH_swap64 (U64 x)
|
||||
{
|
||||
return ((x << 56) & 0xff00000000000000ULL) |
|
||||
((x << 40) & 0x00ff000000000000ULL) |
|
||||
((x << 24) & 0x0000ff0000000000ULL) |
|
||||
((x << 8) & 0x000000ff00000000ULL) |
|
||||
((x >> 8) & 0x00000000ff000000ULL) |
|
||||
((x >> 24) & 0x0000000000ff0000ULL) |
|
||||
((x >> 40) & 0x000000000000ff00ULL) |
|
||||
((x >> 56) & 0x00000000000000ffULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//**************************************
|
||||
// Constants
|
||||
//**************************************
|
||||
#define PRIME32_1 2654435761U
|
||||
#define PRIME32_2 2246822519U
|
||||
#define PRIME32_3 3266489917U
|
||||
#define PRIME32_4 668265263U
|
||||
#define PRIME32_5 374761393U
|
||||
|
||||
#define PRIME64_1 11400714785074694791ULL
|
||||
#define PRIME64_2 14029467366897019727ULL
|
||||
#define PRIME64_3 1609587929392839161ULL
|
||||
#define PRIME64_4 9650029242287828579ULL
|
||||
#define PRIME64_5 2870177450012600261ULL
|
||||
|
||||
//**************************************
|
||||
// Architecture Macros
|
||||
//**************************************
|
||||
typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
|
||||
#ifndef XXH_CPU_LITTLE_ENDIAN // It is possible to define XXH_CPU_LITTLE_ENDIAN externally, for example using a compiler switch
|
||||
static const int one = 1;
|
||||
# define XXH_CPU_LITTLE_ENDIAN (*(char*)(&one))
|
||||
#endif
|
||||
|
||||
|
||||
//**************************************
|
||||
// Macros
|
||||
//**************************************
|
||||
#define XXH_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(!!(c)) }; } // use only *after* variable declarations
|
||||
|
||||
|
||||
//****************************
|
||||
// Memory reads
|
||||
//****************************
|
||||
typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
|
||||
|
||||
FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
if (align==XXH_unaligned)
|
||||
return endian==XXH_littleEndian ? A32(ptr) : XXH_swap32(A32(ptr));
|
||||
else
|
||||
return endian==XXH_littleEndian ? *(U32*)ptr : XXH_swap32(*(U32*)ptr);
|
||||
}
|
||||
|
||||
FORCE_INLINE U32 XXH_readLE32(const void* ptr, XXH_endianess endian)
|
||||
{
|
||||
return XXH_readLE32_align(ptr, endian, XXH_unaligned);
|
||||
}
|
||||
|
||||
FORCE_INLINE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
if (align==XXH_unaligned)
|
||||
return endian==XXH_littleEndian ? A64(ptr) : XXH_swap64(A64(ptr));
|
||||
else
|
||||
return endian==XXH_littleEndian ? *(U64*)ptr : XXH_swap64(*(U64*)ptr);
|
||||
}
|
||||
|
||||
FORCE_INLINE U64 XXH_readLE64(const void* ptr, XXH_endianess endian)
|
||||
{
|
||||
return XXH_readLE64_align(ptr, endian, XXH_unaligned);
|
||||
}
|
||||
|
||||
|
||||
//****************************
|
||||
// Simple Hash Functions
|
||||
//****************************
|
||||
FORCE_INLINE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* bEnd = p + len;
|
||||
U32 h32;
|
||||
#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align)
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (p==NULL)
|
||||
{
|
||||
len=0;
|
||||
bEnd=p=(const BYTE*)(size_t)16;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (len>=16)
|
||||
{
|
||||
const BYTE* const limit = bEnd - 16;
|
||||
U32 v1 = seed + PRIME32_1 + PRIME32_2;
|
||||
U32 v2 = seed + PRIME32_2;
|
||||
U32 v3 = seed + 0;
|
||||
U32 v4 = seed - PRIME32_1;
|
||||
|
||||
do
|
||||
{
|
||||
v1 += XXH_get32bits(p) * PRIME32_2;
|
||||
v1 = XXH_rotl32(v1, 13);
|
||||
v1 *= PRIME32_1;
|
||||
p+=4;
|
||||
v2 += XXH_get32bits(p) * PRIME32_2;
|
||||
v2 = XXH_rotl32(v2, 13);
|
||||
v2 *= PRIME32_1;
|
||||
p+=4;
|
||||
v3 += XXH_get32bits(p) * PRIME32_2;
|
||||
v3 = XXH_rotl32(v3, 13);
|
||||
v3 *= PRIME32_1;
|
||||
p+=4;
|
||||
v4 += XXH_get32bits(p) * PRIME32_2;
|
||||
v4 = XXH_rotl32(v4, 13);
|
||||
v4 *= PRIME32_1;
|
||||
p+=4;
|
||||
}
|
||||
while (p<=limit);
|
||||
|
||||
h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
|
||||
}
|
||||
else
|
||||
{
|
||||
h32 = seed + PRIME32_5;
|
||||
}
|
||||
|
||||
h32 += (U32) len;
|
||||
|
||||
while (p+4<=bEnd)
|
||||
{
|
||||
h32 += XXH_get32bits(p) * PRIME32_3;
|
||||
h32 = XXH_rotl32(h32, 17) * PRIME32_4 ;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd)
|
||||
{
|
||||
h32 += (*p) * PRIME32_5;
|
||||
h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
|
||||
p++;
|
||||
}
|
||||
|
||||
h32 ^= h32 >> 15;
|
||||
h32 *= PRIME32_2;
|
||||
h32 ^= h32 >> 13;
|
||||
h32 *= PRIME32_3;
|
||||
h32 ^= h32 >> 16;
|
||||
|
||||
return h32;
|
||||
}
|
||||
|
||||
|
||||
unsigned int XXH32 (const void* input, size_t len, unsigned seed)
|
||||
{
|
||||
#if 0
|
||||
// Simple version, good for code maintenance, but unfortunately slow for small inputs
|
||||
XXH32_state_t state;
|
||||
XXH32_reset(&state, seed);
|
||||
XXH32_update(&state, input, len);
|
||||
return XXH32_digest(&state);
|
||||
#else
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
# if !defined(XXH_USE_UNALIGNED_ACCESS)
|
||||
if ((((size_t)input) & 3) == 0) // Input is aligned, let's leverage the speed advantage
|
||||
{
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
|
||||
else
|
||||
return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
|
||||
}
|
||||
# endif
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
|
||||
else
|
||||
return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCE_INLINE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* bEnd = p + len;
|
||||
U64 h64;
|
||||
#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align)
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (p==NULL)
|
||||
{
|
||||
len=0;
|
||||
bEnd=p=(const BYTE*)(size_t)32;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (len>=32)
|
||||
{
|
||||
const BYTE* const limit = bEnd - 32;
|
||||
U64 v1 = seed + PRIME64_1 + PRIME64_2;
|
||||
U64 v2 = seed + PRIME64_2;
|
||||
U64 v3 = seed + 0;
|
||||
U64 v4 = seed - PRIME64_1;
|
||||
|
||||
do
|
||||
{
|
||||
v1 += XXH_get64bits(p) * PRIME64_2;
|
||||
p+=8;
|
||||
v1 = XXH_rotl64(v1, 31);
|
||||
v1 *= PRIME64_1;
|
||||
v2 += XXH_get64bits(p) * PRIME64_2;
|
||||
p+=8;
|
||||
v2 = XXH_rotl64(v2, 31);
|
||||
v2 *= PRIME64_1;
|
||||
v3 += XXH_get64bits(p) * PRIME64_2;
|
||||
p+=8;
|
||||
v3 = XXH_rotl64(v3, 31);
|
||||
v3 *= PRIME64_1;
|
||||
v4 += XXH_get64bits(p) * PRIME64_2;
|
||||
p+=8;
|
||||
v4 = XXH_rotl64(v4, 31);
|
||||
v4 *= PRIME64_1;
|
||||
}
|
||||
while (p<=limit);
|
||||
|
||||
h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
|
||||
|
||||
v1 *= PRIME64_2;
|
||||
v1 = XXH_rotl64(v1, 31);
|
||||
v1 *= PRIME64_1;
|
||||
h64 ^= v1;
|
||||
h64 = h64 * PRIME64_1 + PRIME64_4;
|
||||
|
||||
v2 *= PRIME64_2;
|
||||
v2 = XXH_rotl64(v2, 31);
|
||||
v2 *= PRIME64_1;
|
||||
h64 ^= v2;
|
||||
h64 = h64 * PRIME64_1 + PRIME64_4;
|
||||
|
||||
v3 *= PRIME64_2;
|
||||
v3 = XXH_rotl64(v3, 31);
|
||||
v3 *= PRIME64_1;
|
||||
h64 ^= v3;
|
||||
h64 = h64 * PRIME64_1 + PRIME64_4;
|
||||
|
||||
v4 *= PRIME64_2;
|
||||
v4 = XXH_rotl64(v4, 31);
|
||||
v4 *= PRIME64_1;
|
||||
h64 ^= v4;
|
||||
h64 = h64 * PRIME64_1 + PRIME64_4;
|
||||
}
|
||||
else
|
||||
{
|
||||
h64 = seed + PRIME64_5;
|
||||
}
|
||||
|
||||
h64 += (U64) len;
|
||||
|
||||
while (p+8<=bEnd)
|
||||
{
|
||||
U64 k1 = XXH_get64bits(p);
|
||||
k1 *= PRIME64_2;
|
||||
k1 = XXH_rotl64(k1,31);
|
||||
k1 *= PRIME64_1;
|
||||
h64 ^= k1;
|
||||
h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
|
||||
p+=8;
|
||||
}
|
||||
|
||||
if (p+4<=bEnd)
|
||||
{
|
||||
h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1;
|
||||
h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd)
|
||||
{
|
||||
h64 ^= (*p) * PRIME64_5;
|
||||
h64 = XXH_rotl64(h64, 11) * PRIME64_1;
|
||||
p++;
|
||||
}
|
||||
|
||||
h64 ^= h64 >> 33;
|
||||
h64 *= PRIME64_2;
|
||||
h64 ^= h64 >> 29;
|
||||
h64 *= PRIME64_3;
|
||||
h64 ^= h64 >> 32;
|
||||
|
||||
return h64;
|
||||
}
|
||||
|
||||
|
||||
unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed)
|
||||
{
|
||||
#if 0
|
||||
// Simple version, good for code maintenance, but unfortunately slow for small inputs
|
||||
XXH64_state_t state;
|
||||
XXH64_reset(&state, seed);
|
||||
XXH64_update(&state, input, len);
|
||||
return XXH64_digest(&state);
|
||||
#else
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
# if !defined(XXH_USE_UNALIGNED_ACCESS)
|
||||
if ((((size_t)input) & 7)==0) // Input is aligned, let's leverage the speed advantage
|
||||
{
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
|
||||
else
|
||||
return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
|
||||
}
|
||||
# endif
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
|
||||
else
|
||||
return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************
|
||||
* Advanced Hash Functions
|
||||
****************************************************/
|
||||
|
||||
/*** Allocation ***/
|
||||
typedef struct
|
||||
{
|
||||
U64 total_len;
|
||||
U32 seed;
|
||||
U32 v1;
|
||||
U32 v2;
|
||||
U32 v3;
|
||||
U32 v4;
|
||||
U32 mem32[4]; /* defined as U32 for alignment */
|
||||
U32 memsize;
|
||||
} XXH_istate32_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
U64 total_len;
|
||||
U64 seed;
|
||||
U64 v1;
|
||||
U64 v2;
|
||||
U64 v3;
|
||||
U64 v4;
|
||||
U64 mem64[4]; /* defined as U64 for alignment */
|
||||
U32 memsize;
|
||||
} XXH_istate64_t;
|
||||
|
||||
|
||||
XXH32_state_t* XXH32_createState(void)
|
||||
{
|
||||
static_assert(sizeof(XXH32_state_t) >= sizeof(XXH_istate32_t), ""); // A compilation error here means XXH32_state_t is not large enough
|
||||
return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t));
|
||||
}
|
||||
XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr)
|
||||
{
|
||||
XXH_free(statePtr);
|
||||
return XXH_OK;
|
||||
};
|
||||
|
||||
XXH64_state_t* XXH64_createState(void)
|
||||
{
|
||||
static_assert(sizeof(XXH64_state_t) >= sizeof(XXH_istate64_t), ""); // A compilation error here means XXH64_state_t is not large enough
|
||||
return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t));
|
||||
}
|
||||
XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr)
|
||||
{
|
||||
XXH_free(statePtr);
|
||||
return XXH_OK;
|
||||
};
|
||||
|
||||
|
||||
/*** Hash feed ***/
|
||||
|
||||
XXH_errorcode XXH32_reset(XXH32_state_t* state_in, U32 seed)
|
||||
{
|
||||
XXH_istate32_t* state = (XXH_istate32_t*) state_in;
|
||||
state->seed = seed;
|
||||
state->v1 = seed + PRIME32_1 + PRIME32_2;
|
||||
state->v2 = seed + PRIME32_2;
|
||||
state->v3 = seed + 0;
|
||||
state->v4 = seed - PRIME32_1;
|
||||
state->total_len = 0;
|
||||
state->memsize = 0;
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
XXH_errorcode XXH64_reset(XXH64_state_t* state_in, unsigned long long seed)
|
||||
{
|
||||
XXH_istate64_t* state = (XXH_istate64_t*) state_in;
|
||||
state->seed = seed;
|
||||
state->v1 = seed + PRIME64_1 + PRIME64_2;
|
||||
state->v2 = seed + PRIME64_2;
|
||||
state->v3 = seed + 0;
|
||||
state->v4 = seed - PRIME64_1;
|
||||
state->total_len = 0;
|
||||
state->memsize = 0;
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE XXH_errorcode XXH32_update_endian (XXH32_state_t* state_in, const void* input, size_t len, XXH_endianess endian)
|
||||
{
|
||||
XXH_istate32_t* state = (XXH_istate32_t *) state_in;
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* const bEnd = p + len;
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (input==NULL) return XXH_ERROR;
|
||||
#endif
|
||||
|
||||
state->total_len += len;
|
||||
|
||||
if (state->memsize + len < 16) // fill in tmp buffer
|
||||
{
|
||||
XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len);
|
||||
state->memsize += (U32)len;
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
if (state->memsize) // some data left from previous update
|
||||
{
|
||||
XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize);
|
||||
{
|
||||
const U32* p32 = state->mem32;
|
||||
state->v1 += XXH_readLE32(p32, endian) * PRIME32_2;
|
||||
state->v1 = XXH_rotl32(state->v1, 13);
|
||||
state->v1 *= PRIME32_1;
|
||||
p32++;
|
||||
state->v2 += XXH_readLE32(p32, endian) * PRIME32_2;
|
||||
state->v2 = XXH_rotl32(state->v2, 13);
|
||||
state->v2 *= PRIME32_1;
|
||||
p32++;
|
||||
state->v3 += XXH_readLE32(p32, endian) * PRIME32_2;
|
||||
state->v3 = XXH_rotl32(state->v3, 13);
|
||||
state->v3 *= PRIME32_1;
|
||||
p32++;
|
||||
state->v4 += XXH_readLE32(p32, endian) * PRIME32_2;
|
||||
state->v4 = XXH_rotl32(state->v4, 13);
|
||||
state->v4 *= PRIME32_1;
|
||||
p32++;
|
||||
}
|
||||
p += 16-state->memsize;
|
||||
state->memsize = 0;
|
||||
}
|
||||
|
||||
if (p <= bEnd-16)
|
||||
{
|
||||
const BYTE* const limit = bEnd - 16;
|
||||
U32 v1 = state->v1;
|
||||
U32 v2 = state->v2;
|
||||
U32 v3 = state->v3;
|
||||
U32 v4 = state->v4;
|
||||
|
||||
do
|
||||
{
|
||||
v1 += XXH_readLE32(p, endian) * PRIME32_2;
|
||||
v1 = XXH_rotl32(v1, 13);
|
||||
v1 *= PRIME32_1;
|
||||
p+=4;
|
||||
v2 += XXH_readLE32(p, endian) * PRIME32_2;
|
||||
v2 = XXH_rotl32(v2, 13);
|
||||
v2 *= PRIME32_1;
|
||||
p+=4;
|
||||
v3 += XXH_readLE32(p, endian) * PRIME32_2;
|
||||
v3 = XXH_rotl32(v3, 13);
|
||||
v3 *= PRIME32_1;
|
||||
p+=4;
|
||||
v4 += XXH_readLE32(p, endian) * PRIME32_2;
|
||||
v4 = XXH_rotl32(v4, 13);
|
||||
v4 *= PRIME32_1;
|
||||
p+=4;
|
||||
}
|
||||
while (p<=limit);
|
||||
|
||||
state->v1 = v1;
|
||||
state->v2 = v2;
|
||||
state->v3 = v3;
|
||||
state->v4 = v4;
|
||||
}
|
||||
|
||||
if (p < bEnd)
|
||||
{
|
||||
XXH_memcpy(state->mem32, p, bEnd-p);
|
||||
state->memsize = (int)(bEnd-p);
|
||||
}
|
||||
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_update_endian(state_in, input, len, XXH_littleEndian);
|
||||
else
|
||||
return XXH32_update_endian(state_in, input, len, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
|
||||
FORCE_INLINE U32 XXH32_digest_endian (const XXH32_state_t* state_in, XXH_endianess endian)
|
||||
{
|
||||
XXH_istate32_t* state = (XXH_istate32_t*) state_in;
|
||||
const BYTE * p = (const BYTE*)state->mem32;
|
||||
BYTE* bEnd = (BYTE*)(state->mem32) + state->memsize;
|
||||
U32 h32;
|
||||
|
||||
if (state->total_len >= 16)
|
||||
{
|
||||
h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18);
|
||||
}
|
||||
else
|
||||
{
|
||||
h32 = state->seed + PRIME32_5;
|
||||
}
|
||||
|
||||
h32 += (U32) state->total_len;
|
||||
|
||||
while (p+4<=bEnd)
|
||||
{
|
||||
h32 += XXH_readLE32(p, endian) * PRIME32_3;
|
||||
h32 = XXH_rotl32(h32, 17) * PRIME32_4;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd)
|
||||
{
|
||||
h32 += (*p) * PRIME32_5;
|
||||
h32 = XXH_rotl32(h32, 11) * PRIME32_1;
|
||||
p++;
|
||||
}
|
||||
|
||||
h32 ^= h32 >> 15;
|
||||
h32 *= PRIME32_2;
|
||||
h32 ^= h32 >> 13;
|
||||
h32 *= PRIME32_3;
|
||||
h32 ^= h32 >> 16;
|
||||
|
||||
return h32;
|
||||
}
|
||||
|
||||
|
||||
U32 XXH32_digest (const XXH32_state_t* state_in)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH32_digest_endian(state_in, XXH_littleEndian);
|
||||
else
|
||||
return XXH32_digest_endian(state_in, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE XXH_errorcode XXH64_update_endian (XXH64_state_t* state_in, const void* input, size_t len, XXH_endianess endian)
|
||||
{
|
||||
XXH_istate64_t * state = (XXH_istate64_t *) state_in;
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* const bEnd = p + len;
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (input==NULL) return XXH_ERROR;
|
||||
#endif
|
||||
|
||||
state->total_len += len;
|
||||
|
||||
if (state->memsize + len < 32) // fill in tmp buffer
|
||||
{
|
||||
XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len);
|
||||
state->memsize += (U32)len;
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
if (state->memsize) // some data left from previous update
|
||||
{
|
||||
XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize);
|
||||
{
|
||||
const U64* p64 = state->mem64;
|
||||
state->v1 += XXH_readLE64(p64, endian) * PRIME64_2;
|
||||
state->v1 = XXH_rotl64(state->v1, 31);
|
||||
state->v1 *= PRIME64_1;
|
||||
p64++;
|
||||
state->v2 += XXH_readLE64(p64, endian) * PRIME64_2;
|
||||
state->v2 = XXH_rotl64(state->v2, 31);
|
||||
state->v2 *= PRIME64_1;
|
||||
p64++;
|
||||
state->v3 += XXH_readLE64(p64, endian) * PRIME64_2;
|
||||
state->v3 = XXH_rotl64(state->v3, 31);
|
||||
state->v3 *= PRIME64_1;
|
||||
p64++;
|
||||
state->v4 += XXH_readLE64(p64, endian) * PRIME64_2;
|
||||
state->v4 = XXH_rotl64(state->v4, 31);
|
||||
state->v4 *= PRIME64_1;
|
||||
p64++;
|
||||
}
|
||||
p += 32-state->memsize;
|
||||
state->memsize = 0;
|
||||
}
|
||||
|
||||
if (p+32 <= bEnd)
|
||||
{
|
||||
const BYTE* const limit = bEnd - 32;
|
||||
U64 v1 = state->v1;
|
||||
U64 v2 = state->v2;
|
||||
U64 v3 = state->v3;
|
||||
U64 v4 = state->v4;
|
||||
|
||||
do
|
||||
{
|
||||
v1 += XXH_readLE64(p, endian) * PRIME64_2;
|
||||
v1 = XXH_rotl64(v1, 31);
|
||||
v1 *= PRIME64_1;
|
||||
p+=8;
|
||||
v2 += XXH_readLE64(p, endian) * PRIME64_2;
|
||||
v2 = XXH_rotl64(v2, 31);
|
||||
v2 *= PRIME64_1;
|
||||
p+=8;
|
||||
v3 += XXH_readLE64(p, endian) * PRIME64_2;
|
||||
v3 = XXH_rotl64(v3, 31);
|
||||
v3 *= PRIME64_1;
|
||||
p+=8;
|
||||
v4 += XXH_readLE64(p, endian) * PRIME64_2;
|
||||
v4 = XXH_rotl64(v4, 31);
|
||||
v4 *= PRIME64_1;
|
||||
p+=8;
|
||||
}
|
||||
while (p<=limit);
|
||||
|
||||
state->v1 = v1;
|
||||
state->v2 = v2;
|
||||
state->v3 = v3;
|
||||
state->v4 = v4;
|
||||
}
|
||||
|
||||
if (p < bEnd)
|
||||
{
|
||||
XXH_memcpy(state->mem64, p, bEnd-p);
|
||||
state->memsize = (int)(bEnd-p);
|
||||
}
|
||||
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH64_update_endian(state_in, input, len, XXH_littleEndian);
|
||||
else
|
||||
return XXH64_update_endian(state_in, input, len, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
|
||||
FORCE_INLINE U64 XXH64_digest_endian (const XXH64_state_t* state_in, XXH_endianess endian)
|
||||
{
|
||||
XXH_istate64_t * state = (XXH_istate64_t *) state_in;
|
||||
const BYTE * p = (const BYTE*)state->mem64;
|
||||
BYTE* bEnd = (BYTE*)state->mem64 + state->memsize;
|
||||
U64 h64;
|
||||
|
||||
if (state->total_len >= 32)
|
||||
{
|
||||
U64 v1 = state->v1;
|
||||
U64 v2 = state->v2;
|
||||
U64 v3 = state->v3;
|
||||
U64 v4 = state->v4;
|
||||
|
||||
h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
|
||||
|
||||
v1 *= PRIME64_2;
|
||||
v1 = XXH_rotl64(v1, 31);
|
||||
v1 *= PRIME64_1;
|
||||
h64 ^= v1;
|
||||
h64 = h64*PRIME64_1 + PRIME64_4;
|
||||
|
||||
v2 *= PRIME64_2;
|
||||
v2 = XXH_rotl64(v2, 31);
|
||||
v2 *= PRIME64_1;
|
||||
h64 ^= v2;
|
||||
h64 = h64*PRIME64_1 + PRIME64_4;
|
||||
|
||||
v3 *= PRIME64_2;
|
||||
v3 = XXH_rotl64(v3, 31);
|
||||
v3 *= PRIME64_1;
|
||||
h64 ^= v3;
|
||||
h64 = h64*PRIME64_1 + PRIME64_4;
|
||||
|
||||
v4 *= PRIME64_2;
|
||||
v4 = XXH_rotl64(v4, 31);
|
||||
v4 *= PRIME64_1;
|
||||
h64 ^= v4;
|
||||
h64 = h64*PRIME64_1 + PRIME64_4;
|
||||
}
|
||||
else
|
||||
{
|
||||
h64 = state->seed + PRIME64_5;
|
||||
}
|
||||
|
||||
h64 += (U64) state->total_len;
|
||||
|
||||
while (p+8<=bEnd)
|
||||
{
|
||||
U64 k1 = XXH_readLE64(p, endian);
|
||||
k1 *= PRIME64_2;
|
||||
k1 = XXH_rotl64(k1,31);
|
||||
k1 *= PRIME64_1;
|
||||
h64 ^= k1;
|
||||
h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
|
||||
p+=8;
|
||||
}
|
||||
|
||||
if (p+4<=bEnd)
|
||||
{
|
||||
h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1;
|
||||
h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd)
|
||||
{
|
||||
h64 ^= (*p) * PRIME64_5;
|
||||
h64 = XXH_rotl64(h64, 11) * PRIME64_1;
|
||||
p++;
|
||||
}
|
||||
|
||||
h64 ^= h64 >> 33;
|
||||
h64 *= PRIME64_2;
|
||||
h64 ^= h64 >> 29;
|
||||
h64 *= PRIME64_3;
|
||||
h64 ^= h64 >> 32;
|
||||
|
||||
return h64;
|
||||
}
|
||||
|
||||
|
||||
unsigned long long XXH64_digest (const XXH64_state_t* state_in)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XXH64_digest_endian(state_in, XXH_littleEndian);
|
||||
else
|
||||
return XXH64_digest_endian(state_in, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
} // detail
|
||||
} // beast
|
||||
154
src/beast/beast/hash/impl/xxhash.h
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
xxHash - Extremely Fast Hash algorithm
|
||||
Header File
|
||||
Copyright (C) 2012-2014, Yann Collet.
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- xxHash source repository : http://code.google.com/p/xxhash/
|
||||
*/
|
||||
|
||||
/* Notice extracted from xxHash homepage :
|
||||
|
||||
xxHash is an extremely fast Hash algorithm, running at RAM speed limits.
|
||||
It also successfully passes all tests from the SMHasher suite.
|
||||
|
||||
Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz)
|
||||
|
||||
Name Speed Q.Score Author
|
||||
xxHash 5.4 GB/s 10
|
||||
CrapWow 3.2 GB/s 2 Andrew
|
||||
MumurHash 3a 2.7 GB/s 10 Austin Appleby
|
||||
SpookyHash 2.0 GB/s 10 Bob Jenkins
|
||||
SBox 1.4 GB/s 9 Bret Mulvey
|
||||
Lookup3 1.2 GB/s 9 Bob Jenkins
|
||||
SuperFastHash 1.2 GB/s 1 Paul Hsieh
|
||||
CityHash64 1.05 GB/s 10 Pike & Alakuijala
|
||||
FNV 0.55 GB/s 5 Fowler, Noll, Vo
|
||||
CRC32 0.43 GB/s 9
|
||||
MD5-32 0.33 GB/s 10 Ronald L. Rivest
|
||||
SHA1-32 0.28 GB/s 10
|
||||
|
||||
Q.Score is a measure of quality of the hash function.
|
||||
It depends on successfully passing SMHasher test set.
|
||||
10 is a perfect score.
|
||||
*/
|
||||
|
||||
#ifndef BEAST_HASH_XXHASH_H_INCLUDED
|
||||
#define BEAST_HASH_XXHASH_H_INCLUDED
|
||||
|
||||
/*****************************
|
||||
Includes
|
||||
*****************************/
|
||||
#include <stddef.h> /* size_t */
|
||||
|
||||
namespace beast {
|
||||
namespace detail {
|
||||
|
||||
/*****************************
|
||||
Type
|
||||
*****************************/
|
||||
typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
|
||||
|
||||
|
||||
|
||||
/*****************************
|
||||
Simple Hash Functions
|
||||
*****************************/
|
||||
|
||||
unsigned int XXH32 (const void* input, size_t length, unsigned seed);
|
||||
unsigned long long XXH64 (const void* input, size_t length, unsigned long long seed);
|
||||
|
||||
/*
|
||||
XXH32() :
|
||||
Calculate the 32-bits hash of sequence "length" bytes stored at memory address "input".
|
||||
The memory between input & input+length must be valid (allocated and read-accessible).
|
||||
"seed" can be used to alter the result predictably.
|
||||
This function successfully passes all SMHasher tests.
|
||||
Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s
|
||||
XXH64() :
|
||||
Calculate the 64-bits hash of sequence of length "len" stored at memory address "input".
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*****************************
|
||||
Advanced Hash Functions
|
||||
*****************************/
|
||||
typedef struct { long long ll[ 6]; } XXH32_state_t;
|
||||
typedef struct { long long ll[11]; } XXH64_state_t;
|
||||
|
||||
/*
|
||||
These structures allow static allocation of XXH states.
|
||||
States must then be initialized using XXHnn_reset() before first use.
|
||||
|
||||
If you prefer dynamic allocation, please refer to functions below.
|
||||
*/
|
||||
|
||||
XXH32_state_t* XXH32_createState(void);
|
||||
XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr);
|
||||
|
||||
XXH64_state_t* XXH64_createState(void);
|
||||
XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr);
|
||||
|
||||
/*
|
||||
These functions create and release memory for XXH state.
|
||||
States must then be initialized using XXHnn_reset() before first use.
|
||||
*/
|
||||
|
||||
|
||||
XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned seed);
|
||||
XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length);
|
||||
unsigned int XXH32_digest (const XXH32_state_t* statePtr);
|
||||
|
||||
XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed);
|
||||
XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length);
|
||||
unsigned long long XXH64_digest (const XXH64_state_t* statePtr);
|
||||
|
||||
/*
|
||||
These functions calculate the xxHash of an input provided in multiple smaller packets,
|
||||
as opposed to an input provided as a single block.
|
||||
|
||||
XXH state space must first be allocated, using either static or dynamic method provided above.
|
||||
|
||||
Start a new hash by initializing state with a seed, using XXHnn_reset().
|
||||
|
||||
Then, feed the hash state by calling XXHnn_update() as many times as necessary.
|
||||
Obviously, input must be valid, meaning allocated and read accessible.
|
||||
The function returns an error code, with 0 meaning OK, and any other value meaning there is an error.
|
||||
|
||||
Finally, you can produce a hash anytime, by using XXHnn_digest().
|
||||
This function returns the final nn-bits hash.
|
||||
You can nonetheless continue feeding the hash state with more input,
|
||||
and therefore get some new hashes, by calling again XXHnn_digest().
|
||||
|
||||
When you are done, don't forget to free XXH state space, using typically XXHnn_freeState().
|
||||
*/
|
||||
|
||||
} // detail
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
59
src/beast/beast/hash/siphash.h
Normal file
@@ -0,0 +1,59 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2014, Howard Hinnant <howard.hinnant@gmail.com>,
|
||||
Vinnie Falco <vinnie.falco@gmail.com
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_HASH_SIPHASH_H_INCLUDED
|
||||
#define BEAST_HASH_SIPHASH_H_INCLUDED
|
||||
|
||||
#include <beast/utility/noexcept.h>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace beast {
|
||||
|
||||
// See https://131002.net/siphash/
|
||||
class siphash
|
||||
{
|
||||
private:
|
||||
std::uint64_t v0_ = 0x736f6d6570736575ULL;
|
||||
std::uint64_t v1_ = 0x646f72616e646f6dULL;
|
||||
std::uint64_t v2_ = 0x6c7967656e657261ULL;
|
||||
std::uint64_t v3_ = 0x7465646279746573ULL;
|
||||
unsigned char buf_[8];
|
||||
unsigned bufsize_ = 0;
|
||||
unsigned total_length_ = 0;
|
||||
|
||||
public:
|
||||
using result_type = std::size_t;
|
||||
|
||||
siphash() = default;
|
||||
|
||||
explicit
|
||||
siphash (std::uint64_t k0, std::uint64_t k1 = 0) noexcept;
|
||||
|
||||
void
|
||||
append (void const* key, std::size_t len) noexcept;
|
||||
|
||||
explicit
|
||||
operator std::size_t() noexcept;
|
||||
};
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,8 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
Copyright 2014, Howard Hinnant <howard.hinnant@gmail.com>,
|
||||
Vinnie Falco <vinnie.falco@gmail.com
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -17,30 +18,42 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_SQLITE_H_INCLUDED
|
||||
#define BEAST_SQLITE_H_INCLUDED
|
||||
#ifndef BEAST_HASH_SPOOKY_H_INCLUDED
|
||||
#define BEAST_HASH_SPOOKY_H_INCLUDED
|
||||
|
||||
/** A self-contained, serverless, zero configuration, transactional SQL engine.
|
||||
#include <beast/hash/impl/spookyv2.h>
|
||||
|
||||
This external module provides the SQLite embedded database library.
|
||||
namespace beast {
|
||||
|
||||
SQLite is public domain software, visit http://sqlite.org
|
||||
*/
|
||||
// See http://burtleburtle.net/bob/hash/spooky.html
|
||||
class spooky
|
||||
{
|
||||
private:
|
||||
SpookyHash state_;
|
||||
|
||||
#include <beast/config/PlatformConfig.h>
|
||||
public:
|
||||
using result_type = std::size_t;
|
||||
|
||||
#if BEAST_IOS || BEAST_MAC
|
||||
# define BEAST_HAVE_NATIVE_SQLITE 1
|
||||
#else
|
||||
# define BEAST_HAVE_NATIVE_SQLITE 0
|
||||
#endif
|
||||
spooky (std::size_t seed1 = 1, std::size_t seed2 = 2) noexcept
|
||||
{
|
||||
state_.Init (seed1, seed2);
|
||||
}
|
||||
|
||||
#ifndef BEAST_SQLITE_CPP_INCLUDED
|
||||
# if BEAST_USE_NATIVE_SQLITE && BEAST_HAVE_NATIVE_SQLITE
|
||||
#include <sqlite3.h>
|
||||
# else
|
||||
#include <beast/module/sqlite/sqlite/sqlite3.h> // Amalgamated
|
||||
# endif
|
||||
#endif
|
||||
void
|
||||
append (void const* key, std::size_t len) noexcept
|
||||
{
|
||||
state_.Update (key, len);
|
||||
}
|
||||
|
||||
explicit
|
||||
operator std::size_t() noexcept
|
||||
{
|
||||
std::uint64_t h1, h2;
|
||||
state_.Final (&h1, &h2);
|
||||
return static_cast <std::size_t> (h1);
|
||||
}
|
||||
};
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -17,21 +17,15 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
// MODULES: ../impl/spookyv2.cpp
|
||||
|
||||
#if BEAST_INCLUDE_BEASTCONFIG
|
||||
#include <BeastConfig.h>
|
||||
#endif
|
||||
|
||||
#include <beast/container/tests/hash_metrics.h>
|
||||
|
||||
#include <beast/container/hash_append.h>
|
||||
#include <beast/container/impl/spookyv2.h>
|
||||
|
||||
#include <beast/hash/tests/hash_metrics.h>
|
||||
#include <beast/hash/hash_append.h>
|
||||
#include <beast/chrono/chrono_io.h>
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <beast/utility/type_name.h>
|
||||
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
@@ -40,8 +34,6 @@
|
||||
|
||||
namespace beast {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class Block, class Derived>
|
||||
class block_stream
|
||||
{
|
||||
@@ -18,8 +18,8 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_CONTAINER_TESTS_HASH_METRICS_H_INCLUDED
|
||||
#define BEAST_CONTAINER_TESTS_HASH_METRICS_H_INCLUDED
|
||||
#ifndef BEAST_HASH_HASH_METRICS_H_INCLUDED
|
||||
#define BEAST_HASH_HASH_METRICS_H_INCLUDED
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
86
src/beast/beast/hash/tests/hash_speed_test.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#if BEAST_INCLUDE_BEASTCONFIG
|
||||
#include <BeastConfig.h>
|
||||
#endif
|
||||
#include <beast/hash/fnv1a.h>
|
||||
#include <beast/hash/siphash.h>
|
||||
#include <beast/hash/xxhasher.h>
|
||||
#include <beast/chrono/chrono_io.h>
|
||||
#include <beast/random/rngfill.h>
|
||||
#include <beast/random/xor_shift_engine.h>
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <random>
|
||||
|
||||
namespace beast {
|
||||
|
||||
class hash_speed_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
using clock_type =
|
||||
std::chrono::high_resolution_clock;
|
||||
template <class Hasher, std::size_t KeySize>
|
||||
void
|
||||
test (std::string const& what, std::size_t n)
|
||||
{
|
||||
using namespace std;
|
||||
using namespace std::chrono;
|
||||
xor_shift_engine g(1);
|
||||
array<std::uint8_t, KeySize> key;
|
||||
auto const start = clock_type::now();
|
||||
while(n--)
|
||||
{
|
||||
rngfill (key, g);
|
||||
Hasher h;
|
||||
h.append(key.data(), KeySize);
|
||||
volatile size_t temp =
|
||||
static_cast<std::size_t>(h);
|
||||
(void)temp;
|
||||
}
|
||||
auto const elapsed = clock_type::now() - start;
|
||||
log << setw(12) << what << " " <<
|
||||
duration<double>(elapsed) << "s";
|
||||
}
|
||||
|
||||
void
|
||||
run()
|
||||
{
|
||||
enum
|
||||
{
|
||||
N = 100000000
|
||||
};
|
||||
|
||||
#if ! BEAST_NO_XXHASH
|
||||
test<xxhasher,32> ("xxhash", N);
|
||||
#endif
|
||||
test<fnv1a,32> ("fnv1a", N);
|
||||
test<siphash,32> ("siphash", N);
|
||||
pass();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE_MANUAL(hash_speed,container,beast);
|
||||
|
||||
} // beast
|
||||
46
src/beast/beast/hash/uhash.h
Normal file
@@ -0,0 +1,46 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2014, Howard Hinnant <howard.hinnant@gmail.com>,
|
||||
Vinnie Falco <vinnie.falco@gmail.com
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_HASH_UHASH_H_INCLUDED
|
||||
#define BEAST_HASH_UHASH_H_INCLUDED
|
||||
|
||||
#include <beast/hash/spooky.h>
|
||||
|
||||
namespace beast {
|
||||
|
||||
// Universal hash function
|
||||
template <class Hasher = spooky>
|
||||
struct uhash
|
||||
{
|
||||
using result_type = typename Hasher::result_type;
|
||||
|
||||
template <class T>
|
||||
result_type
|
||||
operator()(T const& t) const noexcept
|
||||
{
|
||||
Hasher h;
|
||||
hash_append (h, t);
|
||||
return static_cast<result_type>(h);
|
||||
}
|
||||
};
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
86
src/beast/beast/hash/xxhasher.h
Normal file
@@ -0,0 +1,86 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2014, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_HASH_XXHASHER_H_INCLUDED
|
||||
#define BEAST_HASH_XXHASHER_H_INCLUDED
|
||||
|
||||
#ifndef BEAST_NO_XXHASH
|
||||
#define BEAST_NO_XXHASH 0
|
||||
#endif
|
||||
|
||||
#if ! BEAST_NO_XXHASH
|
||||
|
||||
#include <beast/hash/impl/xxhash.h>
|
||||
#include <beast/utility/noexcept.h>
|
||||
#include <beast/cxx14/type_traits.h> // <type_traits>
|
||||
#include <cstddef>
|
||||
|
||||
namespace beast {
|
||||
|
||||
class xxhasher
|
||||
{
|
||||
private:
|
||||
// requires 64-bit std::size_t
|
||||
static_assert(sizeof(std::size_t)==8, "");
|
||||
|
||||
detail::XXH64_state_t state_;
|
||||
|
||||
public:
|
||||
using result_type = std::size_t;
|
||||
|
||||
xxhasher() noexcept
|
||||
{
|
||||
detail::XXH64_reset (&state_, 1);
|
||||
}
|
||||
|
||||
template <class Seed,
|
||||
std::enable_if_t<
|
||||
std::is_unsigned<Seed>::value>* = nullptr>
|
||||
explicit
|
||||
xxhasher (Seed seed)
|
||||
{
|
||||
detail::XXH64_reset (&state_, seed);
|
||||
}
|
||||
|
||||
template <class Seed,
|
||||
std::enable_if_t<
|
||||
std::is_unsigned<Seed>::value>* = nullptr>
|
||||
xxhasher (Seed seed, Seed)
|
||||
{
|
||||
detail::XXH64_reset (&state_, seed);
|
||||
}
|
||||
|
||||
void
|
||||
append (void const* key, std::size_t len) noexcept
|
||||
{
|
||||
detail::XXH64_update (&state_, key, len);
|
||||
}
|
||||
|
||||
explicit
|
||||
operator std::size_t() noexcept
|
||||
{
|
||||
return detail::XXH64_digest(&state_);
|
||||
}
|
||||
};
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <beast/http/impl/raw_parser.cpp>
|
||||
#include <beast/http/impl/URL.cpp>
|
||||
|
||||
#include <beast/http/tests/chunked_encoder.test.cpp>
|
||||
#include <beast/http/tests/parser.test.cpp>
|
||||
#include <beast/http/tests/rfc2616.test.cpp>
|
||||
#include <beast/http/tests/URL.test.cpp>
|
||||
|
||||
@@ -50,17 +50,16 @@ public:
|
||||
body (body const&) = delete;
|
||||
body& operator= (body const&) = delete;
|
||||
|
||||
template <class = void>
|
||||
void
|
||||
clear();
|
||||
|
||||
void
|
||||
write (void const* data, std::size_t bytes);
|
||||
|
||||
template <class ConstBufferSequence>
|
||||
void
|
||||
write (ConstBufferSequence const& buffers)
|
||||
{
|
||||
for (auto const& buffer : buffers)
|
||||
write (boost::asio::buffer_cast <void const*> (buffer),
|
||||
boost::asio::buffer_size (buffer));
|
||||
}
|
||||
write (ConstBufferSequence const& buffers);
|
||||
|
||||
std::size_t
|
||||
size() const;
|
||||
@@ -92,8 +91,9 @@ body::body()
|
||||
|
||||
inline
|
||||
body::body (body&& other)
|
||||
: buf_ (std::move(other.buf_))
|
||||
{
|
||||
buf_ = std::move(other.buf_);
|
||||
other.clear();
|
||||
}
|
||||
|
||||
inline
|
||||
@@ -101,9 +101,17 @@ body&
|
||||
body::operator= (body&& other)
|
||||
{
|
||||
buf_ = std::move(other.buf_);
|
||||
other.clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class>
|
||||
void
|
||||
body::clear()
|
||||
{
|
||||
buf_ = std::make_unique <buffer_type>();
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
body::write (void const* data, std::size_t bytes)
|
||||
@@ -112,6 +120,15 @@ body::write (void const* data, std::size_t bytes)
|
||||
boost::asio::const_buffers_1 (data, bytes)));
|
||||
}
|
||||
|
||||
template <class ConstBufferSequence>
|
||||
void
|
||||
body::write (ConstBufferSequence const& buffers)
|
||||
{
|
||||
for (auto const& buffer : buffers)
|
||||
write (boost::asio::buffer_cast <void const*> (buffer),
|
||||
boost::asio::buffer_size (buffer));
|
||||
}
|
||||
|
||||
inline
|
||||
std::size_t
|
||||
body::size() const
|
||||
|
||||
285
src/beast/beast/http/chunk_encode.h
Normal file
@@ -0,0 +1,285 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_HTTP_CHUNK_ENCODE_H_INCLUDED
|
||||
#define BEAST_HTTP_CHUNK_ENCODE_H_INCLUDED
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <beast/cxx14/type_traits.h> // <type_traits>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class Buffers>
|
||||
class chunk_encoded_buffers
|
||||
{
|
||||
private:
|
||||
using const_buffer = boost::asio::const_buffer;
|
||||
|
||||
Buffers buffers_;
|
||||
const_buffer head_;
|
||||
const_buffer tail_;
|
||||
|
||||
// Storage for the longest hex string we might need, plus delimiters.
|
||||
std::array<char, 2 * sizeof(std::size_t) + 2> data_;
|
||||
|
||||
public:
|
||||
using value_type = boost::asio::const_buffer;
|
||||
|
||||
class const_iterator;
|
||||
|
||||
chunk_encoded_buffers() = delete;
|
||||
chunk_encoded_buffers (chunk_encoded_buffers const&) = default;
|
||||
chunk_encoded_buffers& operator= (chunk_encoded_buffers const&) = default;
|
||||
|
||||
chunk_encoded_buffers (Buffers const& buffers, bool final_chunk);
|
||||
|
||||
const_iterator
|
||||
begin() const
|
||||
{
|
||||
return const_iterator(*this, false);
|
||||
}
|
||||
|
||||
const_iterator
|
||||
end() const
|
||||
{
|
||||
return const_iterator(*this, true);
|
||||
}
|
||||
|
||||
private:
|
||||
// Unchecked conversion of unsigned to hex string
|
||||
template<class OutIter, class Unsigned>
|
||||
static
|
||||
std::enable_if_t<std::is_unsigned<Unsigned>::value, OutIter>
|
||||
to_hex(OutIter const first, OutIter const last, Unsigned n);
|
||||
};
|
||||
|
||||
template <class Buffers>
|
||||
class chunk_encoded_buffers<Buffers>::const_iterator
|
||||
: public std::iterator<std::bidirectional_iterator_tag, const_buffer>
|
||||
{
|
||||
private:
|
||||
using iterator = typename Buffers::const_iterator;
|
||||
enum class Where { head, input, end };
|
||||
chunk_encoded_buffers const* buffers_;
|
||||
Where where_;
|
||||
iterator iter_;
|
||||
|
||||
public:
|
||||
const_iterator();
|
||||
const_iterator (const_iterator const&) = default;
|
||||
const_iterator& operator= (const_iterator const&) = default;
|
||||
bool operator== (const_iterator const& other) const;
|
||||
bool operator!= (const_iterator const& other) const;
|
||||
const_iterator& operator++();
|
||||
const_iterator& operator--();
|
||||
const_iterator operator++(int) const;
|
||||
const_iterator operator--(int) const;
|
||||
const_buffer operator*() const;
|
||||
|
||||
private:
|
||||
friend class chunk_encoded_buffers;
|
||||
const_iterator(chunk_encoded_buffers const& buffers, bool past_the_end);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class Buffers>
|
||||
chunk_encoded_buffers<Buffers>::chunk_encoded_buffers (
|
||||
Buffers const& buffers, bool final_chunk)
|
||||
: buffers_(buffers)
|
||||
{
|
||||
auto const size = boost::asio::buffer_size(buffers);
|
||||
data_[data_.size() - 2] = '\r';
|
||||
data_[data_.size() - 1] = '\n';
|
||||
auto pos = to_hex(data_.begin(), data_.end() - 2, size);
|
||||
head_ = const_buffer(&*pos,
|
||||
std::distance(pos, data_.end()));
|
||||
if (size > 0 && final_chunk)
|
||||
tail_ = const_buffer("\r\n0\r\n\r\n", 7);
|
||||
else
|
||||
tail_ = const_buffer("\r\n", 2);
|
||||
}
|
||||
|
||||
template <class Buffers>
|
||||
template <class OutIter, class Unsigned>
|
||||
std::enable_if_t<std::is_unsigned<Unsigned>::value, OutIter>
|
||||
chunk_encoded_buffers<Buffers>::to_hex(
|
||||
OutIter const first, OutIter const last, Unsigned n)
|
||||
{
|
||||
assert(first != last);
|
||||
OutIter iter = last;
|
||||
if(n == 0)
|
||||
{
|
||||
*--iter = '0';
|
||||
return iter;
|
||||
}
|
||||
while(n)
|
||||
{
|
||||
assert(iter != first);
|
||||
*--iter = "0123456789abcdef"[n&0xf];
|
||||
n>>=4;
|
||||
}
|
||||
return iter;
|
||||
}
|
||||
|
||||
template <class Buffers>
|
||||
chunk_encoded_buffers<Buffers>::const_iterator::const_iterator()
|
||||
: where_(Where::end)
|
||||
, buffers_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Buffers>
|
||||
bool
|
||||
chunk_encoded_buffers<Buffers>::const_iterator::operator==(
|
||||
const_iterator const& other) const
|
||||
{
|
||||
return buffers_ == other.buffers_ &&
|
||||
where_ == other.where_ && iter_ == other.iter_;
|
||||
}
|
||||
|
||||
template <class Buffers>
|
||||
bool
|
||||
chunk_encoded_buffers<Buffers>::const_iterator::operator!=(
|
||||
const_iterator const& other) const
|
||||
{
|
||||
return buffers_ != other.buffers_ ||
|
||||
where_ != other.where_ || iter_ != other.iter_;
|
||||
}
|
||||
|
||||
template <class Buffers>
|
||||
auto
|
||||
chunk_encoded_buffers<Buffers>::const_iterator::operator++() ->
|
||||
const_iterator&
|
||||
{
|
||||
assert(buffers_);
|
||||
assert(where_ != Where::end);
|
||||
if (where_ == Where::head)
|
||||
where_ = Where::input;
|
||||
else if (iter_ != buffers_->buffers_.end())
|
||||
++iter_;
|
||||
else
|
||||
where_ = Where::end;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Buffers>
|
||||
auto
|
||||
chunk_encoded_buffers<Buffers>::const_iterator::operator--() ->
|
||||
const_iterator&
|
||||
{
|
||||
assert(buffers_);
|
||||
assert(where_ != Where::begin);
|
||||
if (where_ == Where::end)
|
||||
where_ = Where::input;
|
||||
else if (iter_ != buffers_->buffers_.begin())
|
||||
--iter_;
|
||||
else
|
||||
where_ = Where::head;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Buffers>
|
||||
auto
|
||||
chunk_encoded_buffers<Buffers>::const_iterator::operator++(int) const ->
|
||||
const_iterator
|
||||
{
|
||||
auto iter = *this;
|
||||
++iter;
|
||||
return iter;
|
||||
}
|
||||
|
||||
template <class Buffers>
|
||||
auto
|
||||
chunk_encoded_buffers<Buffers>::const_iterator::operator--(int) const ->
|
||||
const_iterator
|
||||
{
|
||||
auto iter = *this;
|
||||
--iter;
|
||||
return iter;
|
||||
}
|
||||
|
||||
template <class Buffers>
|
||||
auto
|
||||
chunk_encoded_buffers<Buffers>::const_iterator::operator*() const ->
|
||||
const_buffer
|
||||
{
|
||||
assert(buffers_);
|
||||
assert(where_ != Where::end);
|
||||
if (where_ == Where::head)
|
||||
return buffers_->head_;
|
||||
if (iter_ != buffers_->buffers_.end())
|
||||
return *iter_;
|
||||
return buffers_->tail_;
|
||||
}
|
||||
|
||||
template <class Buffers>
|
||||
chunk_encoded_buffers<Buffers>::const_iterator::const_iterator(
|
||||
chunk_encoded_buffers const& buffers, bool past_the_end)
|
||||
: buffers_(&buffers)
|
||||
, where_(past_the_end ? Where::end : Where::head)
|
||||
, iter_(past_the_end ? buffers_->buffers_.end() :
|
||||
buffers_->buffers_.begin())
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Returns a chunk-encoded BufferSequence.
|
||||
|
||||
See:
|
||||
http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1
|
||||
|
||||
@tparam Buffers A type meeting the requirements of BufferSequence.
|
||||
@param buffers The input buffer sequence.
|
||||
@param final_chunk `true` If this should include a final-chunk.
|
||||
@return A chunk-encoded ConstBufferSeqeunce representing the input.
|
||||
*/
|
||||
/** @{ */
|
||||
template <class Buffers>
|
||||
detail::chunk_encoded_buffers<Buffers>
|
||||
chunk_encode (Buffers const& buffers,
|
||||
bool final_chunk = false)
|
||||
{
|
||||
return detail::chunk_encoded_buffers<
|
||||
Buffers>(buffers, final_chunk);
|
||||
}
|
||||
|
||||
// Returns a chunked encoding final chunk.
|
||||
inline
|
||||
boost::asio::const_buffers_1
|
||||
chunk_encode_final()
|
||||
{
|
||||
return boost::asio::const_buffers_1(
|
||||
"0\r\n\r\n", 5);
|
||||
}
|
||||
/** @} */
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_HTTP_HEADER_TRAITS_H_INCLUDED
|
||||
#define BEAST_HTTP_HEADER_TRAITS_H_INCLUDED
|
||||
#ifndef BEAST_HTTP_DETAIL_HEADER_TRAITS_H_INCLUDED
|
||||
#define BEAST_HTTP_DETAIL_HEADER_TRAITS_H_INCLUDED
|
||||
|
||||
#include <beast/utility/ci_char_traits.h>
|
||||
|
||||
|
||||
@@ -38,11 +38,7 @@ namespace http {
|
||||
class headers
|
||||
{
|
||||
public:
|
||||
struct value_type
|
||||
{
|
||||
std::string field;
|
||||
std::string value;
|
||||
};
|
||||
using value_type = std::pair<std::string, std::string>;
|
||||
|
||||
private:
|
||||
struct element
|
||||
@@ -139,6 +135,13 @@ public:
|
||||
void
|
||||
clear() noexcept;
|
||||
|
||||
/** Remove a field.
|
||||
@return The number of fields removed.
|
||||
*/
|
||||
template <class = void>
|
||||
std::size_t
|
||||
erase (std::string const& field);
|
||||
|
||||
/** Append a field value.
|
||||
If a field value already exists the new value will be
|
||||
extended as per RFC2616 Section 4.2.
|
||||
@@ -164,8 +167,8 @@ template <class>
|
||||
headers::element::element (
|
||||
std::string const& f, std::string const& v)
|
||||
{
|
||||
data.field = f;
|
||||
data.value = v;
|
||||
data.first = f;
|
||||
data.second = v;
|
||||
}
|
||||
|
||||
template <class String>
|
||||
@@ -173,7 +176,7 @@ bool
|
||||
headers::less::operator() (
|
||||
String const& lhs, element const& rhs) const
|
||||
{
|
||||
return beast::ci_less::operator() (lhs, rhs.data.field);
|
||||
return beast::ci_less::operator() (lhs, rhs.data.first);
|
||||
}
|
||||
|
||||
template <class String>
|
||||
@@ -181,7 +184,7 @@ bool
|
||||
headers::less::operator() (
|
||||
element const& lhs, String const& rhs) const
|
||||
{
|
||||
return beast::ci_less::operator() (lhs.data.field, rhs);
|
||||
return beast::ci_less::operator() (lhs.data.first, rhs);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -210,7 +213,7 @@ inline
|
||||
headers::headers (headers const& other)
|
||||
{
|
||||
for (auto const& e : other.list_)
|
||||
append (e.data.field, e.data.value);
|
||||
append (e.data.first, e.data.second);
|
||||
}
|
||||
|
||||
inline
|
||||
@@ -219,7 +222,7 @@ headers::operator= (headers const& other)
|
||||
{
|
||||
clear();
|
||||
for (auto const& e : other.list_)
|
||||
append (e.data.field, e.data.value);
|
||||
append (e.data.first, e.data.second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -269,7 +272,7 @@ headers::operator[] (std::string const& field) const
|
||||
auto const found (find (field));
|
||||
if (found == end())
|
||||
return none;
|
||||
return found->value;
|
||||
return found->second;
|
||||
}
|
||||
|
||||
template <class>
|
||||
@@ -280,6 +283,20 @@ headers::clear() noexcept
|
||||
delete &(*iter++);
|
||||
}
|
||||
|
||||
template <class>
|
||||
std::size_t
|
||||
headers::erase (std::string const& field)
|
||||
{
|
||||
auto const iter = set_.find(field, less{});
|
||||
if (iter == set_.end())
|
||||
return 0;
|
||||
element& e = *iter;
|
||||
set_.erase(set_.iterator_to(e));
|
||||
list_.erase(list_.iterator_to(e));
|
||||
delete &e;
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <class>
|
||||
void
|
||||
headers::append (std::string const& field,
|
||||
@@ -296,7 +313,7 @@ headers::append (std::string const& field,
|
||||
}
|
||||
// If field already exists, append comma
|
||||
// separated value as per RFC2616 section 4.2
|
||||
auto& cur (result.first->data.value);
|
||||
auto& cur (result.first->data.second);
|
||||
cur.reserve (cur.size() + 1 + value.size());
|
||||
cur.append (1, ',');
|
||||
cur.append (value);
|
||||
@@ -304,6 +321,36 @@ headers::append (std::string const& field,
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class Streambuf>
|
||||
void
|
||||
write (Streambuf& stream, std::string const& s)
|
||||
{
|
||||
stream.commit (boost::asio::buffer_copy (
|
||||
stream.prepare (s.size()), boost::asio::buffer(s)));
|
||||
}
|
||||
|
||||
template <class Streambuf>
|
||||
void
|
||||
write (Streambuf& stream, char const* s)
|
||||
{
|
||||
auto const len (::strlen(s));
|
||||
stream.commit (boost::asio::buffer_copy (
|
||||
stream.prepare (len), boost::asio::buffer (s, len)));
|
||||
}
|
||||
|
||||
template <class Streambuf>
|
||||
void
|
||||
write (Streambuf& stream, headers const& h)
|
||||
{
|
||||
for (auto const& _ : h)
|
||||
{
|
||||
write (stream, _.first);
|
||||
write (stream, ": ");
|
||||
write (stream, _.second);
|
||||
write (stream, "\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
template <class>
|
||||
std::string
|
||||
to_string (headers const& h)
|
||||
@@ -311,13 +358,13 @@ to_string (headers const& h)
|
||||
std::string s;
|
||||
std::size_t n (0);
|
||||
for (auto const& e : h)
|
||||
n += e.field.size() + 2 + e.value.size() + 2;
|
||||
n += e.first.size() + 2 + e.second.size() + 2;
|
||||
s.reserve (n);
|
||||
for (auto const& e : h)
|
||||
{
|
||||
s.append (e.field);
|
||||
s.append (e.first);
|
||||
s.append (": ");
|
||||
s.append (e.value);
|
||||
s.append (e.second);
|
||||
s.append ("\r\n");
|
||||
}
|
||||
return s;
|
||||
@@ -338,10 +385,10 @@ build_map (headers const& h)
|
||||
std::map <std::string, std::string> c;
|
||||
for (auto const& e : h)
|
||||
{
|
||||
auto key (e.field);
|
||||
auto key (e.first);
|
||||
// TODO Replace with safe C++14 version
|
||||
std::transform (key.begin(), key.end(), key.begin(), ::tolower);
|
||||
c [key] = e.value;
|
||||
c [key] = e.second;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -18,8 +18,9 @@
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef http_parser_h
|
||||
#define http_parser_h
|
||||
#ifndef BEAST_HTTP_HTTP_PARSER_HTTP_PARSER_H_INCLUDED
|
||||
#define BEAST_HTTP_HTTP_PARSER_HTTP_PARSER_H_INCLUDED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -134,7 +135,7 @@ enum flags
|
||||
|
||||
|
||||
/* Map for errno-related constants
|
||||
*
|
||||
*
|
||||
* The provided argument should be a macro that takes 2 arguments.
|
||||
*/
|
||||
#define HTTP_ERRNO_MAP(XX) \
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#define BEAST_HTTP_MESSAGE_H_INCLUDED
|
||||
|
||||
#include <beast/http/basic_parser.h>
|
||||
#include <beast/http/body.h>
|
||||
#include <beast/http/method.h>
|
||||
#include <beast/http/headers.h>
|
||||
#include <beast/utility/ci_char_traits.h>
|
||||
@@ -31,11 +30,26 @@
|
||||
#include <cctype>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
inline
|
||||
std::pair<int, int>
|
||||
http_1_0()
|
||||
{
|
||||
return std::pair<int, int>(1, 0);
|
||||
}
|
||||
|
||||
inline
|
||||
std::pair<int, int>
|
||||
http_1_1()
|
||||
{
|
||||
return std::pair<int, int>(1, 1);
|
||||
}
|
||||
|
||||
class message
|
||||
{
|
||||
private:
|
||||
@@ -72,9 +86,8 @@ public:
|
||||
|
||||
#endif
|
||||
|
||||
// Memberspaces
|
||||
// Memberspace
|
||||
beast::http::headers headers;
|
||||
beast::http::body body;
|
||||
|
||||
bool
|
||||
request() const
|
||||
@@ -180,6 +193,12 @@ public:
|
||||
version_ = std::make_pair (major, minor);
|
||||
}
|
||||
|
||||
void
|
||||
version (std::pair<int, int> p)
|
||||
{
|
||||
version_ = p;
|
||||
}
|
||||
|
||||
std::pair<int, int>
|
||||
version() const
|
||||
{
|
||||
@@ -213,7 +232,6 @@ message::message (message&& other)
|
||||
, keep_alive_ (other.keep_alive_)
|
||||
, upgrade_ (other.upgrade_)
|
||||
, headers (std::move(other.headers))
|
||||
, body (std::move(other.body))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -230,33 +248,15 @@ message::operator= (message&& other)
|
||||
keep_alive_ = other.keep_alive_;
|
||||
upgrade_ = other.upgrade_;
|
||||
headers = std::move(other.headers);
|
||||
body = std::move(other.body);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class AsioStreamBuf>
|
||||
template <class Streambuf>
|
||||
void
|
||||
write (AsioStreamBuf& stream, std::string const& s)
|
||||
{
|
||||
stream.commit (boost::asio::buffer_copy (
|
||||
stream.prepare (s.size()), boost::asio::buffer(s)));
|
||||
}
|
||||
|
||||
template <class AsioStreamBuf>
|
||||
void
|
||||
write (AsioStreamBuf& stream, char const* s)
|
||||
{
|
||||
auto const len (::strlen(s));
|
||||
stream.commit (boost::asio::buffer_copy (
|
||||
stream.prepare (len), boost::asio::buffer (s, len)));
|
||||
}
|
||||
|
||||
template <class AsioStreamBuf>
|
||||
void
|
||||
write (AsioStreamBuf& stream, message const& m)
|
||||
write (Streambuf& stream, message const& m)
|
||||
{
|
||||
if (m.request())
|
||||
{
|
||||
@@ -280,13 +280,7 @@ write (AsioStreamBuf& stream, message const& m)
|
||||
write (stream, m.reason());
|
||||
}
|
||||
write (stream, "\r\n");
|
||||
for (auto const& header : m.headers)
|
||||
{
|
||||
write (stream, header.field);
|
||||
write (stream, ": ");
|
||||
write (stream, header.value);
|
||||
write (stream, "\r\n");
|
||||
}
|
||||
write(stream, m.headers);
|
||||
write (stream, "\r\n");
|
||||
}
|
||||
|
||||
@@ -311,4 +305,4 @@ to_string (message const& m)
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#define BEAST_HTTP_PARSER_H_INCLUDED
|
||||
|
||||
#include <beast/http/message.h>
|
||||
#include <beast/http/body.h>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
@@ -34,15 +36,33 @@ class parser : public beast::http::basic_parser
|
||||
{
|
||||
private:
|
||||
std::reference_wrapper <message> message_;
|
||||
std::function<void(void const*, std::size_t)> write_body_;
|
||||
|
||||
public:
|
||||
/** Construct a parser for HTTP request or response.
|
||||
The result is stored in the passed message.
|
||||
The headers plus request or status line are stored in message.
|
||||
The content-body, if any, is passed as a series of calls to
|
||||
the write_body function. Transfer encodings are applied before
|
||||
any data is passed to the write_body function.
|
||||
*/
|
||||
parser (message& m, bool request)
|
||||
parser (std::function<void(void const*, std::size_t)> write_body,
|
||||
message& m, bool request)
|
||||
: beast::http::basic_parser (request)
|
||||
, message_(m)
|
||||
, write_body_(std::move(write_body))
|
||||
{
|
||||
message_.get().request(request);
|
||||
}
|
||||
|
||||
parser (message& m, body& b, bool request)
|
||||
: beast::http::basic_parser (request)
|
||||
, message_(m)
|
||||
{
|
||||
write_body_ = [&b](void const* data, std::size_t size)
|
||||
{
|
||||
b.write(data, size);
|
||||
};
|
||||
|
||||
message_.get().request(request);
|
||||
}
|
||||
|
||||
@@ -135,7 +155,7 @@ parser::operator= (parser&& other)
|
||||
|
||||
template <class>
|
||||
void
|
||||
parser::do_start ()
|
||||
parser::do_start()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -176,7 +196,7 @@ template <class>
|
||||
void
|
||||
parser::do_body (void const* data, std::size_t bytes)
|
||||
{
|
||||
message_.get().body.write (data, bytes);
|
||||
write_body_(data, bytes);
|
||||
}
|
||||
|
||||
template <class>
|
||||
|
||||
@@ -20,12 +20,14 @@
|
||||
#ifndef BEAST_HTTP_RFC2616_H_INCLUDED
|
||||
#define BEAST_HTTP_RFC2616_H_INCLUDED
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
/** Routines for performing RFC2616 compliance.
|
||||
RFC2616:
|
||||
@@ -129,8 +131,8 @@ trim (String const& s)
|
||||
{
|
||||
using std::begin;
|
||||
using std::end;
|
||||
auto first (begin(s));
|
||||
auto last (end(s));
|
||||
auto first = begin(s);
|
||||
auto last = end(s);
|
||||
std::tie (first, last) = trim (first, last);
|
||||
return { first, last };
|
||||
}
|
||||
@@ -154,21 +156,25 @@ trim (std::string const& s)
|
||||
return trim <std::string> (s);
|
||||
}
|
||||
|
||||
/** Call a functor for each comma delimited element.
|
||||
Quotes and escape sequences will be parsed and converted appropriately.
|
||||
Excess white space, commas, double quotes, and empty elements are not
|
||||
passed to func.
|
||||
/** Parse a character sequence of values separated by commas.
|
||||
Double quotes and escape sequences will be converted. Excess white
|
||||
space, commas, double quotes, and empty elements are not copied.
|
||||
Format:
|
||||
#(token|quoted-string)
|
||||
Reference:
|
||||
http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2
|
||||
*/
|
||||
template <class FwdIter, class Function>
|
||||
void
|
||||
for_each_element (FwdIter first, FwdIter last, Function func)
|
||||
template <class FwdIt,
|
||||
class Result = std::vector<
|
||||
std::basic_string<typename FwdIt::value_type>>,
|
||||
class Char>
|
||||
Result
|
||||
split(FwdIt first, FwdIt last, Char delim)
|
||||
{
|
||||
FwdIter iter (first);
|
||||
std::string e;
|
||||
Result result;
|
||||
using string = typename Result::value_type;
|
||||
FwdIt iter = first;
|
||||
string e;
|
||||
while (iter != last)
|
||||
{
|
||||
if (*iter == '"')
|
||||
@@ -198,16 +204,16 @@ for_each_element (FwdIter first, FwdIter last, Function func)
|
||||
}
|
||||
if (! e.empty())
|
||||
{
|
||||
func (e);
|
||||
result.emplace_back(std::move(e));
|
||||
e.clear();
|
||||
}
|
||||
}
|
||||
else if (*iter == ',')
|
||||
else if (*iter == delim)
|
||||
{
|
||||
e = trim_right (e);
|
||||
if (! e.empty())
|
||||
{
|
||||
func (e);
|
||||
result.emplace_back(std::move(e));
|
||||
e.clear();
|
||||
}
|
||||
++iter;
|
||||
@@ -226,13 +232,29 @@ for_each_element (FwdIter first, FwdIter last, Function func)
|
||||
{
|
||||
e = trim_right (e);
|
||||
if (! e.empty())
|
||||
func (e);
|
||||
result.emplace_back(std::move(e));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class FwdIt,
|
||||
class Result = std::vector<
|
||||
std::basic_string<typename FwdIt::value_type>>>
|
||||
Result
|
||||
split_commas(FwdIt first, FwdIt last)
|
||||
{
|
||||
return split(first, last, ',');
|
||||
}
|
||||
|
||||
template <class Result = std::vector<std::string>>
|
||||
Result
|
||||
split_commas(std::string const& s)
|
||||
{
|
||||
return split_commas(s.begin(), s.end());
|
||||
}
|
||||
|
||||
} // rfc2616
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
|
||||
151
src/beast/beast/http/tests/chunked_encoder.test.cpp
Normal file
@@ -0,0 +1,151 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <beast/asio/streambuf.h>
|
||||
#include <beast/http/chunk_encode.h>
|
||||
#include <beast/unit_test/suite.h>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
class chunk_encode_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
// Convert CR LF to printables for display
|
||||
static
|
||||
std::string
|
||||
encode (std::string const& s)
|
||||
{
|
||||
std::string result;
|
||||
for(auto const c : s)
|
||||
{
|
||||
if (c == '\r')
|
||||
result += "\\r";
|
||||
else if (c== '\n')
|
||||
result += "\\n";
|
||||
else
|
||||
result += c;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Print the contents of a ConstBufferSequence to the log
|
||||
template <class ConstBufferSequence, class Log>
|
||||
static
|
||||
void
|
||||
print (ConstBufferSequence const& buffers, Log log)
|
||||
{
|
||||
for(auto const& buf : buffers)
|
||||
log << encode (std::string(
|
||||
boost::asio::buffer_cast<char const*>(buf),
|
||||
boost::asio::buffer_size(buf)));
|
||||
}
|
||||
|
||||
// Convert a ConstBufferSequence to a string
|
||||
template <class ConstBufferSequence>
|
||||
static
|
||||
std::string
|
||||
buffer_to_string (ConstBufferSequence const& b)
|
||||
{
|
||||
std::string s;
|
||||
auto const n = boost::asio::buffer_size(b);
|
||||
s.resize(n);
|
||||
boost::asio::buffer_copy(
|
||||
boost::asio::buffer(&s[0], n), b);
|
||||
return s;
|
||||
}
|
||||
|
||||
// Append a ConstBufferSequence to an existing string
|
||||
template <class ConstBufferSequence>
|
||||
static
|
||||
void
|
||||
buffer_append (std::string& s, ConstBufferSequence const& b)
|
||||
{
|
||||
s += buffer_to_string(b);
|
||||
}
|
||||
|
||||
// Convert the input sequence of the stream to a
|
||||
// chunked-encoded string. The input sequence is consumed.
|
||||
template <class Streambuf>
|
||||
static
|
||||
std::string
|
||||
streambuf_to_string (Streambuf& sb,
|
||||
bool final_chunk = false)
|
||||
{
|
||||
std::string s;
|
||||
buffer_append(s, chunk_encode(sb.data(), final_chunk));
|
||||
return s;
|
||||
}
|
||||
|
||||
// Check an input against the correct chunk encoded version
|
||||
void
|
||||
check (std::string const& in, std::string const& answer,
|
||||
bool final_chunk = true)
|
||||
{
|
||||
asio::streambuf sb(3);
|
||||
sb << in;
|
||||
auto const out = streambuf_to_string (sb, final_chunk);
|
||||
if (! expect (out == answer))
|
||||
log << "expected\n" << encode(answer) <<
|
||||
"\ngot\n" << encode(out);
|
||||
}
|
||||
|
||||
void testStreambuf()
|
||||
{
|
||||
asio::streambuf sb(3);
|
||||
std::string const s =
|
||||
"0123456789012345678901234567890123456789012345678901234567890123456789"
|
||||
"0123456789012345678901234567890123456789012345678901234567890123456789"
|
||||
"0123456789012345678901234567890123456789012345678901234567890123456789";
|
||||
sb << s;
|
||||
expect(buffer_to_string(sb.data()) == s);
|
||||
}
|
||||
|
||||
void
|
||||
testEncoder()
|
||||
{
|
||||
check("", "0\r\n\r\n");
|
||||
check("x", "1\r\nx\r\n0\r\n\r\n");
|
||||
check("abcd", "4\r\nabcd\r\n0\r\n\r\n");
|
||||
check("x", "1\r\nx\r\n", false);
|
||||
check(
|
||||
"0123456789012345678901234567890123456789012345678901234567890123456789"
|
||||
"0123456789012345678901234567890123456789012345678901234567890123456789"
|
||||
"0123456789012345678901234567890123456789012345678901234567890123456789"
|
||||
,
|
||||
"d2\r\n"
|
||||
"0123456789012345678901234567890123456789012345678901234567890123456789"
|
||||
"0123456789012345678901234567890123456789012345678901234567890123456789"
|
||||
"0123456789012345678901234567890123456789012345678901234567890123456789"
|
||||
"\r\n"
|
||||
"0\r\n\r\n");
|
||||
}
|
||||
|
||||
void
|
||||
run()
|
||||
{
|
||||
testStreambuf();
|
||||
testEncoder();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(chunk_encode,http,beast);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <beast/http/message.h>
|
||||
#include <beast/http/parser.h>
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
@@ -31,7 +32,8 @@ public:
|
||||
request (std::string const& text)
|
||||
{
|
||||
message m;
|
||||
parser p (m, true);
|
||||
body b;
|
||||
parser p (m, b, true);
|
||||
auto result (p.write (boost::asio::buffer(text)));
|
||||
p.write_eof();
|
||||
return std::make_pair (std::move(m), result.first);
|
||||
@@ -56,16 +58,27 @@ public:
|
||||
log << "|" << result.first.headers["Field"] << "|";
|
||||
}
|
||||
|
||||
void
|
||||
test_headers()
|
||||
{
|
||||
headers h;
|
||||
h.append("Field", "Value");
|
||||
expect (h.erase("Field") == 1);
|
||||
}
|
||||
|
||||
void
|
||||
run()
|
||||
{
|
||||
test_headers();
|
||||
|
||||
{
|
||||
std::string const text =
|
||||
"GET / HTTP/1.1\r\n"
|
||||
"\r\n"
|
||||
;
|
||||
message m;
|
||||
parser p (m, true);
|
||||
body b;
|
||||
parser p (m, b, true);
|
||||
auto result (p.write (boost::asio::buffer(text)));
|
||||
expect (! result.first);
|
||||
auto result2 (p.write_eof());
|
||||
@@ -80,7 +93,8 @@ public:
|
||||
"\r\n"
|
||||
;
|
||||
message m;
|
||||
parser p (m, true);
|
||||
body b;
|
||||
parser p (m, b, true);
|
||||
auto result = p.write (boost::asio::buffer(text));
|
||||
if (expect (result.first))
|
||||
expect (result.first.message() == "invalid HTTP method");
|
||||
|
||||
@@ -27,62 +27,56 @@
|
||||
#include <vector>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
namespace rfc2616 {
|
||||
|
||||
class rfc2616_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
void
|
||||
check (std::string const& value,
|
||||
check (std::string const& s,
|
||||
std::vector <std::string> const& expected)
|
||||
{
|
||||
std::vector <std::string> parsed;
|
||||
for_each_element (value.begin(), value.end(),
|
||||
[&](std::string const& element)
|
||||
{
|
||||
parsed.push_back (element);
|
||||
});
|
||||
auto const parsed = split_commas(s.begin(), s.end());
|
||||
expect (parsed == expected);
|
||||
}
|
||||
|
||||
void test_split_commas()
|
||||
{
|
||||
testcase("split_commas");
|
||||
check ("", {});
|
||||
check (" ", {});
|
||||
check (" ", {});
|
||||
check ("\t", {});
|
||||
check (" \t ", {});
|
||||
check (",", {});
|
||||
check (",,", {});
|
||||
check (" ,", {});
|
||||
check (" , ,", {});
|
||||
check ("x", {"x"});
|
||||
check (" x", {"x"});
|
||||
check (" \t x", {"x"});
|
||||
check ("x ", {"x"});
|
||||
check ("x \t", {"x"});
|
||||
check (" \t x \t ", {"x"});
|
||||
check ("\"\"", {});
|
||||
check (" \"\"", {});
|
||||
check ("\"\" ", {});
|
||||
check ("\"x\"", {"x"});
|
||||
check ("\" \"", {" "});
|
||||
check ("\" x\"", {" x"});
|
||||
check ("\"x \"", {"x "});
|
||||
check ("\" x \"", {" x "});
|
||||
check ("\"\tx \"", {"\tx "});
|
||||
check ("x,y", { "x", "y" });
|
||||
check ("x ,\ty ", { "x", "y" });
|
||||
check ("x, y, z", {"x","y","z"});
|
||||
check ("x, \"y\", z", {"x","y","z"});
|
||||
}
|
||||
|
||||
void
|
||||
run()
|
||||
{
|
||||
check ("", {});
|
||||
check (" ", {});
|
||||
check (" ", {});
|
||||
check ("\t", {});
|
||||
check (" \t ", {});
|
||||
|
||||
check (",", {});
|
||||
check (",,", {});
|
||||
check (" ,", {});
|
||||
check (" , ,", {});
|
||||
|
||||
check ("x", {"x"});
|
||||
check (" x", {"x"});
|
||||
check (" \t x", {"x"});
|
||||
check ("x ", {"x"});
|
||||
check ("x \t", {"x"});
|
||||
check (" \t x \t ", {"x"});
|
||||
|
||||
check ("\"\"", {});
|
||||
check (" \"\"", {});
|
||||
check ("\"\" ", {});
|
||||
|
||||
check ("\"x\"", {"x"});
|
||||
check ("\" \"", {" "});
|
||||
check ("\" x\"", {" x"});
|
||||
check ("\"x \"", {"x "});
|
||||
check ("\" x \"", {" x "});
|
||||
check ("\"\tx \"", {"\tx "});
|
||||
|
||||
check ("x,y", { "x", "y" });
|
||||
check ("x ,\ty ", { "x", "y" });
|
||||
|
||||
check ("x, y, z", {"x","y","z"});
|
||||
check ("x, \"y\", z", {"x","y","z"});
|
||||
test_split_commas();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -90,4 +84,3 @@ BEAST_DEFINE_TESTSUITE(rfc2616,http,beast);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include <beast/cxx14/memory.h>
|
||||
#include <beast/hash/uhash.h>
|
||||
#include <beast/cxx14/memory.h> // <memory>
|
||||
|
||||
namespace beast {
|
||||
namespace insight {
|
||||
|
||||
@@ -322,7 +322,10 @@ public:
|
||||
std::move (buffer))));
|
||||
}
|
||||
|
||||
void on_send (boost::system::error_code ec, std::size_t)
|
||||
// The keepAlive parameter makes sure the buffers sent to
|
||||
// boost::asio::async_send do not go away until the call is finished
|
||||
void on_send (std::shared_ptr<std::deque<std::string>> /*keepAlive*/,
|
||||
boost::system::error_code ec, std::size_t)
|
||||
{
|
||||
if (ec == boost::asio::error::operation_aborted)
|
||||
return;
|
||||
@@ -354,6 +357,9 @@ public:
|
||||
// Send what we have
|
||||
void send_buffers ()
|
||||
{
|
||||
if (m_data.empty ())
|
||||
return;
|
||||
|
||||
// Break up the array of strings into blocks
|
||||
// that each fit into one UDP packet.
|
||||
//
|
||||
@@ -361,7 +367,12 @@ public:
|
||||
std::vector <boost::asio::const_buffer> buffers;
|
||||
buffers.reserve (m_data.size ());
|
||||
std::size_t size (0);
|
||||
for (auto const& s : m_data)
|
||||
|
||||
auto keepAlive =
|
||||
std::make_shared<std::deque<std::string>>(std::move (m_data));
|
||||
m_data.clear ();
|
||||
|
||||
for (auto const& s : *keepAlive)
|
||||
{
|
||||
std::size_t const length (s.size ());
|
||||
assert (! s.empty ());
|
||||
@@ -371,7 +382,7 @@ public:
|
||||
log (buffers);
|
||||
#endif
|
||||
m_socket.async_send (buffers, std::bind (
|
||||
&StatsDCollectorImp::on_send, this,
|
||||
&StatsDCollectorImp::on_send, this, keepAlive,
|
||||
beast::asio::placeholders::error,
|
||||
beast::asio::placeholders::bytes_transferred));
|
||||
buffers.clear ();
|
||||
@@ -388,11 +399,10 @@ public:
|
||||
log (buffers);
|
||||
#endif
|
||||
m_socket.async_send (buffers, std::bind (
|
||||
&StatsDCollectorImp::on_send, this,
|
||||
&StatsDCollectorImp::on_send, this, keepAlive,
|
||||
beast::asio::placeholders::error,
|
||||
beast::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
m_data.clear ();
|
||||
}
|
||||
|
||||
void set_timer ()
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_ASYNCOBJECT_H_INCLUDED
|
||||
#define BEAST_ASIO_ASYNCOBJECT_H_INCLUDED
|
||||
#ifndef BEAST_MODULE_ASIO_ASYNCOBJECT_H_INCLUDED
|
||||
#define BEAST_MODULE_ASIO_ASYNCOBJECT_H_INCLUDED
|
||||
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
@@ -83,8 +83,8 @@ public:
|
||||
|
||||
void removeReference ()
|
||||
{
|
||||
if (--m_pending)
|
||||
(static_cast <Derived *> (this))->asyncHandlersComplete ();
|
||||
if (--m_pending == 0)
|
||||
(static_cast<Derived*>(this))->asyncHandlersComplete();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_SYSTEM_BOOSTINCLUDES_H_INCLUDED
|
||||
#define BEAST_ASIO_SYSTEM_BOOSTINCLUDES_H_INCLUDED
|
||||
#ifndef BEAST_MODULE_ASIO_BOOSTINCLUDES_H_INCLUDED
|
||||
#define BEAST_MODULE_ASIO_BOOSTINCLUDES_H_INCLUDED
|
||||
|
||||
// Make sure we take care of fixing boost::bind oddities first.
|
||||
#if !defined(BEAST_CORE_H_INCLUDED)
|
||||
|
||||