├── .gitignore
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── kaleidoscoped
├── kindastd.h
├── nostd.h
└── ssl
│ ├── README.md
│ └── crypto
│ └── chacha
│ └── chacha.h
├── src
├── README.md
├── impl
│ ├── kscope_common.h
│ ├── kscope_context.h
│ ├── kscope_injection.h
│ ├── kscope_literal.h
│ └── kscope_prng.h
├── kscope.h
└── kscope_sample_extension.h
└── test
├── chachatest.cpp
├── internaltest.cpp
├── kscope.txt
├── lest.hpp
├── nix
├── README.md
├── benchtest.sh
├── build-official.sh
└── randomtest.sh
├── officialtest.cpp
├── randomtestgen.cpp
├── randomtestgen.h
├── test.h
└── win
├── README.md
├── officialtest
├── officialtest.sln
├── officialtest.vcxproj
└── officialtest.vcxproj.filters
├── randomtest.bat
└── randomtest32.bat
/.gitignore:
--------------------------------------------------------------------------------
1 | /test/kscope2.txt
2 |
3 | /test/nix/local_kscope.txt
4 | /test/nix/testapp
5 | /test/nix/officialtest
6 | /test/nix/randomtestgen
7 | /test/nix/failedrandomtest.sh
8 | /test/nix/generatedrandomtest.sh
9 | /test/nix/nohup.out
10 | /test/nix/testapp.dSYM/
11 | /test/nix/randomtest
12 | /test/nix/bench.txt
13 |
14 | /.vs
15 | /test/win/officialtest/.vs
16 | /test/win/officialtest/Debug
17 | /test/win/officialtest/x64/Debug
18 | /test/win/runtest32
19 | /test/win/vc140.idb
20 | /test/win/vc140.pdb
21 | /test/win/randomtestgen.exe
22 | /test/win/randomtestgen.obj
23 | /test/win/reported-bugs
24 | /test/win/failedrandomtest.bat
25 | /test/win/generatedrandomtest.bat
26 | /test/win/local_kscope.txt
27 | /test/win/officialtest.pdb
28 | /test/win/officialtest.obj
29 | /test/win/officialtest.ilk
30 | /test/win/officialtest.exe
31 | /test/win/chachatest.obj
32 | /test/win/officialtest/x64/Release
33 | /test/win/randomtest.pdb
34 | /test/win/randomtest.exe
35 | /test/win/randomtest.ilk
36 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Towards our noble goal of making C++17 compilers less buggy using kscope-provided testing, contributions in
2 | the following fields look the most interesting (feel free to make your own suggestions too, below is just a list of
3 | the-most-obvious-ideas):
4 |
5 | * **running existing randomtest.sh/randomtest.bat tests in /test/ folder – and be ready to report bugs to respective compiler writers too**.
6 | To do it – find a box which is not-too-shabby in terms of RAM (at least 4G RAM+4G swap is recommended),
7 | then clone the latest master branch of kscope there, and you should be good to go.
8 | Running existing tests might help to reveal bugs under:
9 | * supposedly-C++17-compliant compilers-other-than-Clang/GCC/MSVC (when they start to support all-we-need-from-C++17,
10 | with constexpr support, including constexpr-if, being the most-likely-missing features)
11 | * when the support from other compilers comes, most likely kscope will require some code changed patches to
12 | support such other-compilers; such patches are ESPECIALLY welcome
13 | * *versions* of compilers other-than-{Clang5,GCC7.2,MSVC from VS 15.5.5) (while newer versions are supposed to work, in practice you never know)
14 | * of special interest are regressions in top-of-the-trunk compilers
15 | * compiler options different from those currently used
16 | * will require hacking test/randomtestgen.cpp - and such patches are ESPECIALLY welcome.
17 | * platforms other x86/x64 (in theory, should be ok – but the less common the platform is, the more
18 | chance that subtle codegen bugs in it are sitting there for ages :-( ).
19 | * operating systems other than Linux/Mac OS X/Windows
20 | * supporting such systems may require some patching of .sh or test/randomtestgen.cpp - such patches is
21 | ESPECIALLY welcome.
22 | * Oh, and if/when you find some bug (which may or may not happen):
23 | * try to check whether it can be a bug in the ithare::kscope (it can happen; TBH, currently about 50% of the bugs found
24 | are still within kscope :-( )
25 | * after reporting the bug to the respective compiler team – please drop me a line, I will add your bug report to the /README.md (if you want - with your name too :-) ).
26 | * **adding new injections** (along the lines of src/kscope_sample_extension.h); they’re really important to have
27 | as-much-stuff-tested as possible. Ideally – there would be whole libraries of different injections, so even more
28 | scenarios can be tested.
29 | * for the most adventurous :-) – **adding new kaleidoscoped functions**, also to increase the number of the
30 | scenarios-being-tested, though in a completely different space. Currently, of the most interest are
31 | (a) not-system-related (~="pure") std:: functions (such as algorithms and containers), and (b) crypto-functions and parsers
32 | (in particular, from TLS); (a) will allow to kaleidoscop things further, and (b) will allow to have more of compile-time
33 | crypto (and things such as compile-time ASN.1 parser, etc.). If you’re interested – take a look at kaleidoscoped/ folder,
34 | and see whether you like it (this is NOT documented yet, but I can be reached at nobugs@ithare.com to answer any questions
35 | you may have).
36 |
37 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | IMPORTANT: portions of ithare::kscope project (in particular, those in
2 | /kaleidoscoped folder and in /test folder) may include source code licensed
3 | under other licenses. To the best of our knowledge, and without providing
4 | any warranties, the list of the licenses for the code adapted from other
5 | projects, currently includes:
6 | * public domain
7 | * 2-Clause BSD License
8 | * Boost Software License, Version 1.0
9 | * OpenSSL License
10 | * SSLeay License
11 |
12 | All the contributions by ithare::kscope project itself, are licensed under
13 | BSD 3-Clause License
14 |
15 | Copyright (c) 2018, ITHare.com
16 | All rights reserved.
17 |
18 | Redistribution and use in source and binary forms, with or without
19 | modification, are permitted provided that the following conditions are met:
20 |
21 | * Redistributions of source code must retain the above copyright notice, this
22 | list of conditions and the following disclaimer.
23 |
24 | * Redistributions in binary form must reproduce the above copyright notice,
25 | this list of conditions and the following disclaimer in the documentation
26 | and/or other materials provided with the distribution.
27 |
28 | * Neither the name of the copyright holder nor the names of its
29 | contributors may be used to endorse or promote products derived from
30 | this software without specific prior written permission.
31 |
32 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
36 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
38 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
39 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
40 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
41 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # kscope
2 | kscope is a short for kaleidoscope. Essentially - a library which recursively generates randomized code while keeping it 100% equivalent to the original one. Can be used for compiler torture-testing and optimisation testing, and for a few other things too :-).
3 |
4 | **The Big Idea(tm) behind kscope project is to make C++17 compilers less buggy (via providing reproducible bug reports, and pushing respective compiler teams to fix them).** An unusual part of specifically kscope, is that we're using C++17 itself to generate very different (but supposedly-equivalent) code depending on compile-time define -DITHARE_KSCOPE_SEED . A bit of further motivation and some explanations can be found at http://ithare.com/c17-compiler-bug-hunt-very-first-results-12-bugs-reported-3-already-fixed/ .
5 |
6 | # List of already-reported bugs
7 |
8 | Compiler: | Clang | GCC | MSVC
9 | --------- | ----- | --- | ----
10 | Reported-and-Fixed Bugs | ~~[#36055](https://bugs.llvm.org/show_bug.cgi?id=36055)~~ (fixed in trunk in 2 weeks after kscope report, fix reportedly scheduled to apply to Clang 6.0) | ~~[#84401](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84401)~~ (an enhancement; reportedly fixed as of r251104 - 6 days after kscope report) | ~~[#195484](https://developercommunity.visualstudio.com/content/problem/195484/p-option-doesnt-replace-every-second-occurrence-of.html)~~ (reportedly fixed in a week after kscope report, fix scheduled to apply to VS2017 15.7 Preview 2)
~~[#195579](https://developercommunity.visualstudio.com/content/problem/195579/misreported-location-for-warning-in-constexpr-func.html)~~ (reportedly, was fixed before kscope report in a recent preview)
~~[#196885](https://developercommunity.visualstudio.com/content/problem/196885/c1001-in-fddvctoolscompilercxxfeslp1cwalkcpp-line.html)~~ (reportedly fixed in 3 days(!) after kscope report, fix scheduled to apply to VS2017 15.7 Preview 2)
11 | Reported-and-Pending Bugs | [#36333](https://bugs.llvm.org/show_bug.cgi?id=36333) (only Clang 5.0.x, upcoming Clang 6.0 seems to be unaffected) | [#47488](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47488) (it seems that we run into a new manifestation of the old bug, we tried to bump it)
[#84463](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84463) | [#195483](https://developercommunity.visualstudio.com/content/problem/195483/continue-in-constexpr-function-causes-constexpr-fu.html) (reportedly already-known to MSFT internally but not fixed yet)
[#195665](https://developercommunity.visualstudio.com/content/problem/195665/-line-cannot-be-used-as-an-argument-for-constexpr.html) (reportedly already-known to MSFT internally but not fixed yet; OTOH, some MSFT ppl say this incompliance is actually a feature (really?))
[#196900](https://developercommunity.visualstudio.com/content/problem/196900/c1001-in-file-msc1cpp-line-1507.html) (reportedly already-known to MSFT internally but not fixed yet)
[#199554](https://developercommunity.visualstudio.com/content/problem/199554/suspected-bad-code-generation-for-release-build.html)
[#202584](https://developercommunity.visualstudio.com/content/problem/202584/suspected-invalid-codegen-for-release-build.html)
[#202598](https://developercommunity.visualstudio.com/content/problem/202598/suspected-invalid-codegen-for-x86-release-build.html)
12 | # License
13 |
14 | License of the kscope project (including kscope contributions to adaptations of 3rd-party open-source projects) is 3-clause BSD License. On the other hand, whenever 3rd-party code is adapted by kscope - BOTH original license of the 3rd-party code, AND kscope's 3-clause BSD license apply (on the plus side, as of now and to the best of our knowledge, all the 3rd-party licenses used by kscope, are permissive). For more detail, see [LICENSE.md](https://github.com/ITHare/kscope/blob/master/LICENSE.md) .
15 |
16 | # Contributing
17 |
18 | Contributions are **VERY welcome**. For list of the ideas on "how to make our test coverage better" (ranging from simple running existing tests under different platforms, to writing your own injective functions and kaleidoscoping crypto) - see [CONTRIBUTING.md](https://github.com/ITHare/kscope/blob/master/CONTRIBUTING.md) .
19 |
--------------------------------------------------------------------------------
/kaleidoscoped/kindastd.h:
--------------------------------------------------------------------------------
1 | //ithare::kscope kindastd.h
2 | // constexpr-and-kaleidoscoped versions of SOME of std:: functions
3 |
4 | /*
5 |
6 | Copyright (c) 2018, ITHare.com
7 | All rights reserved.
8 |
9 | Redistribution and use in source and binary forms, with or without
10 | modification, are permitted provided that the following conditions are met:
11 |
12 | * Redistributions of source code must retain the above copyright notice, this
13 | list of conditions and the following disclaimer.
14 |
15 | * Redistributions in binary form must reproduce the above copyright notice,
16 | this list of conditions and the following disclaimer in the documentation
17 | and/or other materials provided with the distribution.
18 |
19 | * Neither the name of the copyright holder nor the names of its
20 | contributors may be used to endorse or promote products derived from
21 | this software without specific prior written permission.
22 |
23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
27 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 |
34 | */
35 |
36 | #ifndef ithare_kscope_kaleidoscoped_kindastd_h_included
37 | #define ithare_kscope_kaleidoscoped_kindastd_h_included
38 |
39 | namespace ithare { namespace kscope {
40 |
41 | ITHARE_KSCOPE_DECLAREFUNC_WITHEXTRA(class InputIt, class OutputIt)
42 | OutputIt kscope_copy(InputIt first, InputIt last, OutputIt d_first) {
43 | while(first != last) {
44 | *d_first++ = *first++;
45 | }
46 | return d_first;
47 | }
48 |
49 | }} //namespace ithare::kscope
50 |
51 | #endif //ithare_kscope_kaleidoscoped_kindastd_h_included
52 |
--------------------------------------------------------------------------------
/kaleidoscoped/nostd.h:
--------------------------------------------------------------------------------
1 | //ithare::kscope nostd.h
2 | // helpers for writing and using kaleidoscoped functions
3 |
4 | /*
5 |
6 | Copyright (c) 2018, ITHare.com
7 | All rights reserved.
8 |
9 | Redistribution and use in source and binary forms, with or without
10 | modification, are permitted provided that the following conditions are met:
11 |
12 | * Redistributions of source code must retain the above copyright notice, this
13 | list of conditions and the following disclaimer.
14 |
15 | * Redistributions in binary form must reproduce the above copyright notice,
16 | this list of conditions and the following disclaimer in the documentation
17 | and/or other materials provided with the distribution.
18 |
19 | * Neither the name of the copyright holder nor the names of its
20 | contributors may be used to endorse or promote products derived from
21 | this software without specific prior written permission.
22 |
23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
27 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 |
34 | */
35 |
36 | #ifndef ithare_kscope_kaleidoscoped_nostd_h_included
37 | #define ithare_kscope_kaleidoscoped_nostd_h_included
38 |
39 | #include "../src/kscope.h"
40 |
41 | namespace ithare { namespace kscope {
42 |
43 | /* //ITHARE_KSCOPE_DECLAREFUNC_WITHEXTRA(class TT,class T,size_t N)
44 | template constexpr ITHARE_KSCOPE_FORCEINLINE
45 | KscopeArrayWrapper kscope_copyarr(T(&src)[N]) {
46 | KscopeArrayWrapper ret = {};
47 | for( size_t i=0; i < N ; ++i) {
48 | ret.arr[i] = src[i];
49 | }
50 | return ret;
51 | }*/
52 |
53 | /* //NOT kaleidoscoped (at least ATM, there seems to be no need for it)
54 | template
55 | constexpr ITHARE_KSCOPE_FORCEINLINE KscopeArrayWrapper kscope_toplainarr(T(&src)[N]) {//converts KscopeInt[N] into KscopeArrayWrapper
56 | KscopeArrayWrapper ret = {};
57 | for( size_t i=0; i < N ; ++i ) {
58 | ret[i] = src[i];
59 | }
60 | }*/
61 |
62 | //kscope_to_ct_kscope_int(), kscope_int_arr_to_kscope_int(), functions are NOT kaleidoscoped (at least ATM, it is used only in KSCOPE_CT wrappers, so there seems to be no need for kaleidoscoping this function)
63 |
64 | #ifndef ITHARE_KSCOPE_DISABLE
65 | #ifdef ITHARE_KSCOPE_SEED
66 | /*template constexpr ITHARE_KSCOPE_FORCEINLINE
67 | KscopeArrayWrapper,N>
68 | kscope_int_arr_to_ct_kscope_int(T(&src)[N]) {//converts T[N] into KscopeArrayWrapper,N>
69 | KscopeArrayWrapper,N> ret = {};
70 | for( size_t i=0; i < N ; ++i ) {
71 | ret.arr[i] = src[i];
72 | }
73 | return ret;
74 | }
75 | template constexpr ITHARE_KSCOPE_FORCEINLINE
76 | KscopeArrayWrapper,N>
77 | kscope_int_arr_to_ct_kscope_int(T* src,size_t m=N) {//converts TT[N] into KscopeArrayWrapper,N>
78 | assert(m<=N);
79 | KscopeArrayWrapper,N> ret = {};
80 | for( size_t i=0; i < m ; ++i ) {
81 | ret.arr[i] = src[i];
82 | }
83 | return ret;
84 | }*/
85 |
86 | template constexpr ITHARE_KSCOPE_FORCEINLINE
87 | KscopeArrayWrapper,N>
88 | kscope_int_arr_to_kscope_int(T(&src)[N]) {//converts T[N] into KscopeArrayWrapper,N>
89 | KscopeArrayWrapper,N> ret = {};
90 | for( size_t i=0; i < N ; ++i ) {
91 | ret.arr[i] = src[i];
92 | }
93 | return ret;
94 | }
95 | #define ITHARE_KSCOPE_INT_ARR_TO_KSCOPE_INT3(src) ithare::kscope::kscope_int_arr_to_kscope_int(src)
96 | template constexpr ITHARE_KSCOPE_FORCEINLINE
97 | KscopeArrayWrapper,N>
98 | kscope_int_arr_to_kscope_int(T* src, size_t m=N) {//converts T[N] into KscopeArrayWrapper,N>
99 | KscopeArrayWrapper,N> ret = {};
100 | assert(m<=N);
101 | for( size_t i=0; i < m ; ++i ) {
102 | ret.arr[i] = src[i];
103 | }
104 | return ret;
105 | }
106 | #define ITHARE_KSCOPE_INT_ARR_TO_KSCOPE_INT3X(maxsz,src,cursz) ithare::kscope::kscope_int_arr_to_kscope_int(src,cursz)
107 | #else //ITHARE_KSCOPE_SEED
108 |
109 | /*template constexpr ITHARE_KSCOPE_FORCEINLINE
110 | KscopeArrayWrapper,N>
111 | kscope_int_arr_to_ct_kscope_int(T(&src)[N]) {//converts T[N] into KscopeArrayWrapper,N>
112 | KscopeArrayWrapper,N> ret = {};
113 | for( size_t i=0; i < N ; ++i ) {
114 | ret.arr[i] = src[i];
115 | }
116 | return ret;
117 | }
118 | template constexpr ITHARE_KSCOPE_FORCEINLINE
119 | KscopeArrayWrapper,N>
120 | kscope_int_arr_to_ct_kscope_int(T* src,size_t m=N) {//converts TT[N] into KscopeArrayWrapper,N>
121 | assert(m<=N);
122 | KscopeArrayWrapper,N> ret = {};
123 | for( size_t i=0; i < m ; ++i ) {
124 | ret.arr[i] = src[i];
125 | }
126 | return ret;
127 | }*/
128 |
129 | template constexpr ITHARE_KSCOPE_FORCEINLINE
130 | KscopeArrayWrapper,N>
131 | kscope_int_arr_to_kscope_int(T(&src)[N]) {//converts T[N] into KscopeArrayWrapper,N>
132 | KscopeArrayWrapper,N> ret = {};
133 | for( size_t i=0; i < N ; ++i ) {
134 | ret.arr[i] = src[i];
135 | }
136 | return ret;
137 | }
138 | #define ITHARE_KSCOPE_INT_ARR_TO_KSCOPE_INT3(src) ithare::kscope::kscope_int_arr_to_kscope_int(src)
139 | template constexpr ITHARE_KSCOPE_FORCEINLINE
140 | KscopeArrayWrapper,N>
141 | kscope_int_arr_to_kscope_int(T* src, size_t m=N) {//converts T[N] into KscopeArrayWrapper,N>
142 | KscopeArrayWrapper,N> ret = {};
143 | assert(m<=N);
144 | for( size_t i=0; i < m ; ++i ) {
145 | ret.arr[i] = src[i];
146 | }
147 | return ret;
148 | }
149 | #define ITHARE_KSCOPE_INT_ARR_TO_KSCOPE_INT3X(maxsz,src,cursz) ithare::kscope::kscope_int_arr_to_kscope_int(src,cursz)
150 | #endif //ITHARE_KSCOPE_SEED
151 |
152 | #define ITHARE_KSCOPE_INT_ARR(x) x.arr
153 |
154 | #else //ITHARE_KSCOPE_DISABLE
155 |
156 | /*template constexpr ITHARE_KSCOPE_FORCEINLINE
157 | KscopeArrayWrapper::type>::type,N>
158 | kscope_int_arr_to_kscope_int(T(&src)[N]) {//converts T[N] into KscopeArrayWrapper
159 | KscopeArrayWrapper::type>::type,N> ret = {};
160 | for( size_t i=0; i < N ; ++i ) {
161 | ret.arr[i] = src[i];
162 | }
163 | return ret;
164 | }
165 | #define ITHARE_KSCOPE_INT_ARR_TO_KSCOPE_INT3(src) ithare::kscope::kscope_int_arr_to_kscope_int(src)
166 | template constexpr ITHARE_KSCOPE_FORCEINLINE
167 | KscopeArrayWrapper::type>::type,N>
168 | kscope_int_arr_to_kscope_int(T* src, size_t m=N) {//converts T[N] into KscopeArrayWrapper
169 | KscopeArrayWrapper::type>::type,N> ret = {};
170 | assert(m<=N);
171 | for( size_t i=0; i < m ; ++i ) {
172 | ret.arr[i] = src[i];
173 | }
174 | return ret;
175 | }
176 | #define ITHARE_KSCOPE_INT_ARR_TO_KSCOPE_INT3X(maxsz,src,cursz) ithare::kscope::kscope_int_arr_to_kscope_int(src,cursz)
177 | */
178 |
179 | #define ITHARE_KSCOPE_INT_ARR_TO_KSCOPE_INT3(src) src
180 | #define ITHARE_KSCOPE_INT_ARR_TO_KSCOPE_INT3X(maxsz,src,cursz) src
181 | #define ITHARE_KSCOPE_INT_ARR(x) x
182 |
183 | #endif //ITHARE_KSCOPE_DISABLE
184 |
185 | //TODO: kaleidoscope (?)
186 | template constexpr ITHARE_KSCOPE_FORCEINLINE
187 | void kscope_copyarr(T* dst,const TT* src, size_t N) {
188 | for(size_t i=0; i < N ; ++i) {
189 | dst[i] = src[i];
190 | }
191 | }
192 | //TODO: kaleidoscope (?)
193 | template constexpr ITHARE_KSCOPE_FORCEINLINE
194 | int kscope_cmparr(const T* a,const TT* b, size_t N) {
195 | for(size_t i=0; i < N ; ++i) {
196 | if( a[i] != b[i] )
197 | return a[i] < b[i] ? -1 : 1;
198 | }
199 | return 0;
200 | }
201 | }} //namespace ithare::kscope
202 |
203 | #endif //ithare_kscope_kaleidoscoped_nostd_h_included
204 |
--------------------------------------------------------------------------------
/kaleidoscoped/ssl/README.md:
--------------------------------------------------------------------------------
1 | kaleidoscoped/ssl is intended to contain a very limited set of tls-related stuff adapted from LibreSSL.
2 | The idea is to eventually support very-minimal (but still working) fully-kaleidoscoped TLS implementation (currently,
3 | we have just started and ~1% of that goal). As a nice side effect, it will provide constexpr versions of all the supported
4 | crypto, enabling use of supported crypto in compile-time.
5 |
6 | All the code inherited from LibreSSL, keeps their respective licenses (to the best of our knowledge,
7 | it is a combination of public domain, BSD, OpenSSL, and SSLeay licenses.
8 |
9 | All the additions/changes made by kscope project, are under 3-claus BSD license.
10 |
--------------------------------------------------------------------------------
/kaleidoscoped/ssl/crypto/chacha/chacha.h:
--------------------------------------------------------------------------------
1 | //ithare::kscope::ssl crypto/chacha.h
2 | // kaleidoscoped version of crypto/chacha/chacha-merged.c, include/openssl/chacha.h, and crypto/chacha/chacha.c from LibreSSL 2.6.4
3 |
4 | /*
5 |
6 | Copyright (c) 2018, ITHare.com
7 | All rights reserved.
8 |
9 | Redistribution and use in source and binary forms, with or without
10 | modification, are permitted provided that the following conditions are met:
11 |
12 | * Redistributions of source code must retain the above copyright notice, this
13 | list of conditions and the following disclaimer.
14 |
15 | * Redistributions in binary form must reproduce the above copyright notice,
16 | this list of conditions and the following disclaimer in the documentation
17 | and/or other materials provided with the distribution.
18 |
19 | * Neither the name of the copyright holder nor the names of its
20 | contributors may be used to endorse or promote products derived from
21 | this software without specific prior written permission.
22 |
23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
27 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 |
34 | */
35 | //SEE ALSO COPYRIGHT NOTICES BELOW
36 |
37 | #ifndef ithare_kscope_kaleidoscoped_ssl_crypto_chacha_h_included
38 | #define ithare_kscope_kaleidoscoped_ssl_crypto_chacha_h_included
39 |
40 | #include "../../../../src/kscope.h"
41 | #include "../../../kindastd.h"
42 | #include "../../../nostd.h"
43 |
44 | namespace ithare { namespace kscope { namespace ssl {
45 |
46 | /* $OpenBSD: chacha-merged.c,v 1.8 2017/08/13 16:55:31 jsing Exp $ */
47 | /*
48 | chacha-merged.c version 20080118
49 | D. J. Bernstein
50 | Public domain.
51 | */
52 |
53 | constexpr int CHACHA_MINKEYLEN = 16;
54 | constexpr int CHACHA_NONCELEN = 8;
55 | constexpr int CHACHA_CTRLEN = 8;
56 | constexpr int CHACHA_STATELEN = CHACHA_NONCELEN+CHACHA_CTRLEN;
57 | constexpr int CHACHA_BLOCKLEN = 64;
58 |
59 | ITHARE_KSCOPE_DECLARECLASS
60 | struct ChaCha_ctx {
61 | ITHARE_KSCOPE_CINTARR(uint32_t,16) input;
62 | ITHARE_KSCOPE_CINTARR(uint8_t,CHACHA_BLOCKLEN) ks;
63 | ITHARE_KSCOPE_CINT(uint8_t) unused;
64 |
65 | //{ constructors are more-or-less equivalent to default ones (adding initialization where applicable)
66 | // but declared so that we can enforce force-inline
67 | constexpr ITHARE_KSCOPE_FORCEINLINE ChaCha_ctx()
68 | : input{}, ks{}, unused{} {
69 | }
70 | constexpr ITHARE_KSCOPE_FORCEINLINE ChaCha_ctx(const ChaCha_ctx& other)
71 | : input{other.input}, ks(other.ks), unused(other.unused) {
72 | }
73 | constexpr ITHARE_KSCOPE_FORCEINLINE ChaCha_ctx& operator =(const ChaCha_ctx&) = delete;
74 | constexpr ITHARE_KSCOPE_FORCEINLINE ChaCha_ctx(const ChaCha_ctx&& other)
75 | : input{other.input}, ks{other.ks}, unused(other.unused) {
76 | }
77 | constexpr ITHARE_KSCOPE_FORCEINLINE ChaCha_ctx& operator =(const ChaCha_ctx&&) = delete;
78 | //} constructors are more-or-less equivalent to default ones (adding initialization where applicable)
79 | };
80 |
81 | #define ITHARE_KSCOPE_U8V(v) ((uint8_t)(v) & UINT8_C(0xFF))
82 | #define ITHARE_KSCOPE_U32V(v) ((uint32_t)(v) & UINT32_C(0xFFFFFFFF))
83 |
84 | #define ITHARE_KSCOPE_ROTL32(v, n) \
85 | (ITHARE_KSCOPE_U32V((v) << (n)) | ((v) >> (32 - (n))))
86 |
87 | #define ITHARE_KSCOPE_U8TO32_LITTLE(p) \
88 | (((uint32_t)((p)[0])) | \
89 | ((uint32_t)((p)[1]) << 8) | \
90 | ((uint32_t)((p)[2]) << 16) | \
91 | ((uint32_t)((p)[3]) << 24))
92 |
93 | #define ITHARE_KSCOPE_U32TO8_LITTLE(p, v) \
94 | do { \
95 | (p)[0] = ITHARE_KSCOPE_U8V((v)); \
96 | (p)[1] = ITHARE_KSCOPE_U8V((v) >> 8); \
97 | (p)[2] = ITHARE_KSCOPE_U8V((v) >> 16); \
98 | (p)[3] = ITHARE_KSCOPE_U8V((v) >> 24); \
99 | } while (0)
100 |
101 | #define ITHARE_KSCOPE_ROTATE(v,c) (ITHARE_KSCOPE_ROTL32(v,c))
102 | #define ITHARE_KSCOPE_XOR(v,w) ((v) ^ (w))
103 | #define ITHARE_KSCOPE_PLUS(v,w) (ITHARE_KSCOPE_U32V((v) + (w)))
104 | #define ITHARE_KSCOPE_PLUSONE(v) (ITHARE_KSCOPE_PLUS((v),1))
105 |
106 | #define ITHARE_KSCOPE_QUARTERROUND(a,b,c,d) \
107 | a = ITHARE_KSCOPE_PLUS(a,b); d = ITHARE_KSCOPE_ROTATE(ITHARE_KSCOPE_XOR(d,a),16); \
108 | c = ITHARE_KSCOPE_PLUS(c,d); b = ITHARE_KSCOPE_ROTATE(ITHARE_KSCOPE_XOR(b,c),12); \
109 | a = ITHARE_KSCOPE_PLUS(a,b); d = ITHARE_KSCOPE_ROTATE(ITHARE_KSCOPE_XOR(d,a), 8); \
110 | c = ITHARE_KSCOPE_PLUS(c,d); b = ITHARE_KSCOPE_ROTATE(ITHARE_KSCOPE_XOR(b,c), 7);
111 |
112 | ITHARE_KSCOPE_DECLAREFUNC_WITHPARAMS_CLASS_2xINT
113 | void chacha_keysetup(ITHARE_KSCOPE_DECLAREPARAM_CLASS(ChaCha_ctx) *x, const ITHARE_KSCOPE_DECLAREPARAM_INT(uint8_t) *k, ITHARE_KSCOPE_DECLAREPARAM_INT2(unsigned) kbits_/*128 or 256*/)
114 | ITHARE_KSCOPE_BOUNDED_MINBYTES(2, CHACHA_MINKEYLEN)
115 | {
116 | ITHARE_KSCOPE_ASSERT_INT_PTR_PARAM(uint8_t,k);
117 | ITHARE_KSCOPE_CONVERT_INT_PARAM(unsigned,kbits,kbits_);
118 |
119 | uint32_t constants32[4] = {
120 | ITHARE_KSCOPE_FINTLIT(UINT32_C(0x6170'7865)),
121 | ITHARE_KSCOPE_FINTLIT(UINT32_C(0x3320'646e)),
122 | ITHARE_KSCOPE_FINTLIT(UINT32_C(0x7962'2d32)),
123 | ITHARE_KSCOPE_FINTLIT(UINT32_C(0x6b20'6574)) };
124 | /* sigma:
125 | 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x20, 0x33,
126 | 0x32, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x20, 0x6b,
127 | */
128 |
129 | x->input[4] = ITHARE_KSCOPE_U8TO32_LITTLE(k + 0);
130 | x->input[5] = ITHARE_KSCOPE_U8TO32_LITTLE(k + 4);
131 | x->input[6] = ITHARE_KSCOPE_U8TO32_LITTLE(k + 8);
132 | x->input[7] = ITHARE_KSCOPE_U8TO32_LITTLE(k + 12);
133 | if (kbits == ITHARE_KSCOPE_FINTLIT(256)) { /* recommended */
134 | #ifdef ITHARE_KSCOPE_WORKAROUND_FOR_MSVC_BUG_199554
135 | k += 16;
136 | #else
137 | k += ITHARE_KSCOPE_FINTLIT(16);
138 | #endif
139 | } else { /* kbits == 128; NOT TESTED(!) */
140 | assert(kbits==ITHARE_KSCOPE_FINTLIT(128));
141 | constants32[1] -= ITHARE_KSCOPE_FINTLIT(UINT32_C(0x0200'0000));
142 | constants32[2] += ITHARE_KSCOPE_FINTLIT(UINT32_C(0x0000'0004));
143 | /* tau
144 | 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x20, 0x31,
145 | 0x36, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x20, 0x6b,
146 | };*/
147 | }
148 | x->input[8] = ITHARE_KSCOPE_U8TO32_LITTLE(k + 0);
149 | x->input[9] = ITHARE_KSCOPE_U8TO32_LITTLE(k + 4);
150 | x->input[10] = ITHARE_KSCOPE_U8TO32_LITTLE(k + 8);
151 | x->input[11] = ITHARE_KSCOPE_U8TO32_LITTLE(k + 12);
152 | //x->input[0] = ITHARE_KSCOPE_U8TO32_LITTLE(constants + 0);
153 | //x->input[1] = ITHARE_KSCOPE_U8TO32_LITTLE(constants + 4);
154 | //x->input[2] = ITHARE_KSCOPE_U8TO32_LITTLE(constants + 8);
155 | //x->input[3] = ITHARE_KSCOPE_U8TO32_LITTLE(constants + 12);
156 | x->input[0] = constants32[0];
157 | x->input[1] = constants32[1];
158 | x->input[2] = constants32[2];
159 | x->input[3] = constants32[3];
160 | }
161 |
162 | ITHARE_KSCOPE_DECLAREFUNC_WITHPARAMS_CLASS_2xINT
163 | void chacha_ivsetup(ITHARE_KSCOPE_DECLAREPARAM_CLASS(ChaCha_ctx)* x, const ITHARE_KSCOPE_DECLAREPARAM_INT(uint8_t)* iv, const ITHARE_KSCOPE_DECLAREPARAM_INT2(uint8_t)* counter)
164 | ITHARE_KSCOPE_BOUNDED_MINBYTES(2, CHACHA_NONCELEN)
165 | ITHARE_KSCOPE_BOUNDED_MINBYTES(3, CHACHA_CTRLEN)
166 | {
167 | ITHARE_KSCOPE_ASSERT_INT_PTR_PARAM(uint8_t,iv);
168 | ITHARE_KSCOPE_ASSERT_INT_PTR_PARAM(uint8_t,counter);
169 |
170 | x->input[12] = counter == nullptr ? 0 : ITHARE_KSCOPE_U8TO32_LITTLE(counter + 0);
171 | x->input[13] = counter == nullptr ? 0 : ITHARE_KSCOPE_U8TO32_LITTLE(counter + 4);
172 | x->input[14] = ITHARE_KSCOPE_U8TO32_LITTLE(iv + 0);
173 | x->input[15] = ITHARE_KSCOPE_U8TO32_LITTLE(iv + 4);
174 | }
175 |
176 |
177 | ITHARE_KSCOPE_DECLAREFUNC_WITHPARAMS_CLASS_3xINT
178 | void chacha_encrypt_bytes(ITHARE_KSCOPE_DECLAREPARAM_CLASS(ChaCha_ctx)* x, const ITHARE_KSCOPE_DECLAREPARAM_INT(uint8_t)* m, ITHARE_KSCOPE_DECLAREPARAM_INT2(uint8_t)* c, ITHARE_KSCOPE_DECLAREPARAM_INT3(size_t) bytes_)
179 | ITHARE_KSCOPE_BOUNDED_BUFFER(2, 4)
180 | ITHARE_KSCOPE_BOUNDED_BUFFER(3, 4)
181 | {
182 | ITHARE_KSCOPE_CONVERT_INT_PARAM(size_t,bytes,bytes_);
183 | ITHARE_KSCOPE_ASSERT_INT_PTR_PARAM(uint8_t,m);
184 | ITHARE_KSCOPE_ASSERT_INT_PTR_PARAM(uint8_t,c);
185 |
186 | if (!bytes)
187 | return;
188 |
189 | ITHARE_KSCOPE_FINT(uint32_t) j0 = x->input[0];
190 | ITHARE_KSCOPE_FINT(uint32_t) j1 = x->input[1];
191 | ITHARE_KSCOPE_FINT(uint32_t) j2 = x->input[2];
192 | ITHARE_KSCOPE_FINT(uint32_t) j3 = x->input[3];
193 | ITHARE_KSCOPE_FINT(uint32_t) j4 = x->input[4];
194 | ITHARE_KSCOPE_FINT(uint32_t) j5 = x->input[5];
195 | ITHARE_KSCOPE_FINT(uint32_t) j6 = x->input[6];
196 | ITHARE_KSCOPE_FINT(uint32_t) j7 = x->input[7];
197 | ITHARE_KSCOPE_FINT(uint32_t) j8 = x->input[8];
198 | ITHARE_KSCOPE_FINT(uint32_t) j9 = x->input[9];
199 | ITHARE_KSCOPE_FINT(uint32_t) j10 = x->input[10];
200 | ITHARE_KSCOPE_FINT(uint32_t) j11 = x->input[11];
201 | ITHARE_KSCOPE_FINT(uint32_t) j12 = x->input[12];
202 | ITHARE_KSCOPE_FINT(uint32_t) j13 = x->input[13];
203 | ITHARE_KSCOPE_FINT(uint32_t) j14 = x->input[14];
204 | ITHARE_KSCOPE_FINT(uint32_t) j15 = x->input[15];
205 |
206 | for (;;) {
207 | ITHARE_KSCOPE_PTR_OF_SAME_TYPE_AS(c) ctarget = nullptr;
208 | ITHARE_KSCOPE_ARRAY_OF_SAME_TYPE_AS(m) tmpm[64] = {};
209 | ITHARE_KSCOPE_ARRAY_OF_SAME_TYPE_AS(c) tmpc[64] = {};
210 | if (bytes < ITHARE_KSCOPE_FINTLIT(64)) {
211 | for (ITHARE_KSCOPE_FINT(size_t) i = 0; i < bytes; ++i)
212 | tmpm[i] = m[i];
213 | m = tmpm;
214 | ctarget = c;
215 | c = tmpc;
216 | }
217 | ITHARE_KSCOPE_FINT(uint32_t) x0 = j0;
218 | ITHARE_KSCOPE_FINT(uint32_t) x1 = j1;
219 | ITHARE_KSCOPE_FINT(uint32_t) x2 = j2;
220 | ITHARE_KSCOPE_FINT(uint32_t) x3 = j3;
221 | ITHARE_KSCOPE_FINT(uint32_t) x4 = j4;
222 | ITHARE_KSCOPE_FINT(uint32_t) x5 = j5;
223 | ITHARE_KSCOPE_FINT(uint32_t) x6 = j6;
224 | ITHARE_KSCOPE_FINT(uint32_t) x7 = j7;
225 | ITHARE_KSCOPE_FINT(uint32_t) x8 = j8;
226 | ITHARE_KSCOPE_FINT(uint32_t) x9 = j9;
227 | ITHARE_KSCOPE_FINT(uint32_t) x10 = j10;
228 | ITHARE_KSCOPE_FINT(uint32_t) x11 = j11;
229 | ITHARE_KSCOPE_FINT(uint32_t) x12 = j12;
230 | ITHARE_KSCOPE_FINT(uint32_t) x13 = j13;
231 | ITHARE_KSCOPE_FINT(uint32_t) x14 = j14;
232 | ITHARE_KSCOPE_FINT(uint32_t) x15 = j15;
233 | for (ITHARE_KSCOPE_FINT(unsigned) i = 20; i > ITHARE_KSCOPE_FINTLIT(0); i -= 2) {
234 | ITHARE_KSCOPE_QUARTERROUND(x0, x4, x8, x12)
235 | ITHARE_KSCOPE_QUARTERROUND(x1, x5, x9, x13)
236 | ITHARE_KSCOPE_QUARTERROUND(x2, x6, x10, x14)
237 | ITHARE_KSCOPE_QUARTERROUND(x3, x7, x11, x15)
238 | ITHARE_KSCOPE_QUARTERROUND(x0, x5, x10, x15)
239 | ITHARE_KSCOPE_QUARTERROUND(x1, x6, x11, x12)
240 | ITHARE_KSCOPE_QUARTERROUND(x2, x7, x8, x13)
241 | ITHARE_KSCOPE_QUARTERROUND(x3, x4, x9, x14)
242 | }
243 | x0 = ITHARE_KSCOPE_PLUS(x0, j0);
244 | x1 = ITHARE_KSCOPE_PLUS(x1, j1);
245 | x2 = ITHARE_KSCOPE_PLUS(x2, j2);
246 | x3 = ITHARE_KSCOPE_PLUS(x3, j3);
247 | x4 = ITHARE_KSCOPE_PLUS(x4, j4);
248 | x5 = ITHARE_KSCOPE_PLUS(x5, j5);
249 | x6 = ITHARE_KSCOPE_PLUS(x6, j6);
250 | x7 = ITHARE_KSCOPE_PLUS(x7, j7);
251 | x8 = ITHARE_KSCOPE_PLUS(x8, j8);
252 | x9 = ITHARE_KSCOPE_PLUS(x9, j9);
253 | x10 = ITHARE_KSCOPE_PLUS(x10, j10);
254 | x11 = ITHARE_KSCOPE_PLUS(x11, j11);
255 | x12 = ITHARE_KSCOPE_PLUS(x12, j12);
256 | x13 = ITHARE_KSCOPE_PLUS(x13, j13);
257 | x14 = ITHARE_KSCOPE_PLUS(x14, j14);
258 | x15 = ITHARE_KSCOPE_PLUS(x15, j15);
259 |
260 | if (bytes < ITHARE_KSCOPE_FINTLIT(64)) {
261 | ITHARE_KSCOPE_U32TO8_LITTLE(x->ks + 0, x0);
262 | ITHARE_KSCOPE_U32TO8_LITTLE(x->ks + 4, x1);
263 | ITHARE_KSCOPE_U32TO8_LITTLE(x->ks + 8, x2);
264 | ITHARE_KSCOPE_U32TO8_LITTLE(x->ks + 12, x3);
265 | ITHARE_KSCOPE_U32TO8_LITTLE(x->ks + 16, x4);
266 | ITHARE_KSCOPE_U32TO8_LITTLE(x->ks + 20, x5);
267 | ITHARE_KSCOPE_U32TO8_LITTLE(x->ks + 24, x6);
268 | ITHARE_KSCOPE_U32TO8_LITTLE(x->ks + 28, x7);
269 | ITHARE_KSCOPE_U32TO8_LITTLE(x->ks + 32, x8);
270 | ITHARE_KSCOPE_U32TO8_LITTLE(x->ks + 36, x9);
271 | ITHARE_KSCOPE_U32TO8_LITTLE(x->ks + 40, x10);
272 | ITHARE_KSCOPE_U32TO8_LITTLE(x->ks + 44, x11);
273 | ITHARE_KSCOPE_U32TO8_LITTLE(x->ks + 48, x12);
274 | ITHARE_KSCOPE_U32TO8_LITTLE(x->ks + 52, x13);
275 | ITHARE_KSCOPE_U32TO8_LITTLE(x->ks + 56, x14);
276 | ITHARE_KSCOPE_U32TO8_LITTLE(x->ks + 60, x15);
277 | }
278 |
279 | x0 = ITHARE_KSCOPE_XOR(x0, ITHARE_KSCOPE_U8TO32_LITTLE(m + 0));
280 | x1 = ITHARE_KSCOPE_XOR(x1, ITHARE_KSCOPE_U8TO32_LITTLE(m + 4));
281 | x2 = ITHARE_KSCOPE_XOR(x2, ITHARE_KSCOPE_U8TO32_LITTLE(m + 8));
282 | x3 = ITHARE_KSCOPE_XOR(x3, ITHARE_KSCOPE_U8TO32_LITTLE(m + 12));
283 | x4 = ITHARE_KSCOPE_XOR(x4, ITHARE_KSCOPE_U8TO32_LITTLE(m + 16));
284 | x5 = ITHARE_KSCOPE_XOR(x5, ITHARE_KSCOPE_U8TO32_LITTLE(m + 20));
285 | x6 = ITHARE_KSCOPE_XOR(x6, ITHARE_KSCOPE_U8TO32_LITTLE(m + 24));
286 | x7 = ITHARE_KSCOPE_XOR(x7, ITHARE_KSCOPE_U8TO32_LITTLE(m + 28));
287 | x8 = ITHARE_KSCOPE_XOR(x8, ITHARE_KSCOPE_U8TO32_LITTLE(m + 32));
288 | x9 = ITHARE_KSCOPE_XOR(x9, ITHARE_KSCOPE_U8TO32_LITTLE(m + 36));
289 | x10 = ITHARE_KSCOPE_XOR(x10, ITHARE_KSCOPE_U8TO32_LITTLE(m + 40));
290 | x11 = ITHARE_KSCOPE_XOR(x11, ITHARE_KSCOPE_U8TO32_LITTLE(m + 44));
291 | x12 = ITHARE_KSCOPE_XOR(x12, ITHARE_KSCOPE_U8TO32_LITTLE(m + 48));
292 | x13 = ITHARE_KSCOPE_XOR(x13, ITHARE_KSCOPE_U8TO32_LITTLE(m + 52));
293 | x14 = ITHARE_KSCOPE_XOR(x14, ITHARE_KSCOPE_U8TO32_LITTLE(m + 56));
294 | x15 = ITHARE_KSCOPE_XOR(x15, ITHARE_KSCOPE_U8TO32_LITTLE(m + 60));
295 |
296 | j12 = ITHARE_KSCOPE_PLUSONE(j12);
297 | if (!j12) {
298 | j13 = ITHARE_KSCOPE_PLUSONE(j13);
299 | /*
300 | * Stopping at 2^70 bytes per nonce is the user's
301 | * responsibility.
302 | */
303 | }
304 |
305 | ITHARE_KSCOPE_U32TO8_LITTLE(c + 0, x0);
306 | ITHARE_KSCOPE_U32TO8_LITTLE(c + 4, x1);
307 | ITHARE_KSCOPE_U32TO8_LITTLE(c + 8, x2);
308 | ITHARE_KSCOPE_U32TO8_LITTLE(c + 12, x3);
309 | ITHARE_KSCOPE_U32TO8_LITTLE(c + 16, x4);
310 | ITHARE_KSCOPE_U32TO8_LITTLE(c + 20, x5);
311 | ITHARE_KSCOPE_U32TO8_LITTLE(c + 24, x6);
312 | ITHARE_KSCOPE_U32TO8_LITTLE(c + 28, x7);
313 | ITHARE_KSCOPE_U32TO8_LITTLE(c + 32, x8);
314 | ITHARE_KSCOPE_U32TO8_LITTLE(c + 36, x9);
315 | ITHARE_KSCOPE_U32TO8_LITTLE(c + 40, x10);
316 | ITHARE_KSCOPE_U32TO8_LITTLE(c + 44, x11);
317 | ITHARE_KSCOPE_U32TO8_LITTLE(c + 48, x12);
318 | ITHARE_KSCOPE_U32TO8_LITTLE(c + 52, x13);
319 | ITHARE_KSCOPE_U32TO8_LITTLE(c + 56, x14);
320 | ITHARE_KSCOPE_U32TO8_LITTLE(c + 60, x15);
321 |
322 | if (bytes <= ITHARE_KSCOPE_FINTLIT(64)) {
323 | if (bytes < ITHARE_KSCOPE_FINTLIT(64)) {
324 | for (ITHARE_KSCOPE_FINT(size_t) i = 0; i < bytes; ++i)
325 | ctarget[i] = c[i];
326 | }
327 | x->input[12] = j12;
328 | x->input[13] = j13;
329 | x->unused = uint8_t(64 - bytes);
330 | return;
331 | }
332 | bytes -= 64;
333 | c += 64;
334 | m += 64;
335 | }
336 | }
337 |
338 | //undefining temporaries to avoid polluting macro namespace
339 | #undef ITHARE_KSCOPE_QUARTERROUND
340 |
341 | #undef ITHARE_KSCOPE_PLUSONE
342 | #undef ITHARE_KSCOPE_PLUS
343 | #undef ITHARE_KSCOPE_XOR
344 | #undef ITHARE_KSCOPE_ROTATE
345 |
346 | #undef ITHARE_KSCOPE_U32TO8_LITTLE
347 | #undef ITHARE_KSCOPE_U8TO32_LITTLE
348 |
349 | #undef ITHARE_KSCOPE_ROTL32
350 |
351 | #undef ITHARE_KSCOPE_U32V
352 | #undef ITHARE_KSCOPE_U8V
353 |
354 | /* $OpenBSD: chacha.h,v 1.7 2015/12/09 14:07:55 bcook Exp $ */
355 | /*
356 | * Copyright (c) 2014 Joel Sing
357 | *
358 | * Permission to use, copy, modify, and distribute this software for any
359 | * purpose with or without fee is hereby granted, provided that the above
360 | * copyright notice and this permission notice appear in all copies.
361 | *
362 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
363 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
364 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
365 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
366 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
367 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
368 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
369 | */
370 |
371 | /* $OpenBSD: chacha.c,v 1.7 2015/12/09 14:07:55 bcook Exp $ */
372 | /*
373 | * Copyright (c) 2014 Joel Sing
374 | *
375 | * Permission to use, copy, modify, and distribute this software for any
376 | * purpose with or without fee is hereby granted, provided that the above
377 | * copyright notice and this permission notice appear in all copies.
378 | *
379 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
380 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
381 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
382 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
383 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
384 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
385 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
386 | */
387 |
388 | ITHARE_KSCOPE_DECLAREFUNC_WITHPARAMS_CLASS_2xINT
389 | void ChaCha_set_key(ITHARE_KSCOPE_DECLAREPARAM_CLASS(ChaCha_ctx)* ctx, const ITHARE_KSCOPE_DECLAREPARAM_INT(uint8_t)* key, ITHARE_KSCOPE_DECLAREPARAM_INT2(uint32_t) keybits_ /*128 or 256*/)
390 | {
391 | ITHARE_KSCOPE_ASSERT_INT_PTR_PARAM(uint8_t,key);
392 | ITHARE_KSCOPE_CONVERT_INT_PARAM(unsigned,keybits,keybits_);
393 |
394 | assert(keybits == 128U || keybits == 256U);
395 | ITHARE_KSCOPE_FCALL(chacha_keysetup)(ctx, key, keybits);
396 | ctx->unused = 0;
397 | }
398 |
399 | ITHARE_KSCOPE_DECLAREFUNC_WITHPARAMS_CLASS_2xINT
400 | void ChaCha_set_iv(ITHARE_KSCOPE_DECLAREPARAM_CLASS(ChaCha_ctx)* ctx, const ITHARE_KSCOPE_DECLAREPARAM_INT(uint8_t)* iv, const ITHARE_KSCOPE_DECLAREPARAM_INT2(uint8_t)* counter)
401 | {
402 | ITHARE_KSCOPE_ASSERT_INT_PTR_PARAM(uint8_t,iv);
403 | ITHARE_KSCOPE_ASSERT_INT_PTR_PARAM(uint8_t,counter);
404 |
405 | ITHARE_KSCOPE_FCALL(chacha_ivsetup)(ctx, iv, counter);
406 | ctx->unused = 0;
407 | }
408 |
409 | ITHARE_KSCOPE_DECLAREFUNC_WITHPARAMS_CLASS_3xINT
410 | void ChaCha(ITHARE_KSCOPE_DECLAREPARAM_CLASS(ChaCha_ctx)* ctx, ITHARE_KSCOPE_DECLAREPARAM_INT(uint8_t)* out, const ITHARE_KSCOPE_DECLAREPARAM_INT2(uint8_t)* in, ITHARE_KSCOPE_DECLAREPARAM_INT3(size_t) len_)
411 | {
412 | ITHARE_KSCOPE_ASSERT_INT_PTR_PARAM(uint8_t,out);
413 | ITHARE_KSCOPE_ASSERT_INT_PTR_PARAM(uint8_t,in);
414 | ITHARE_KSCOPE_CONVERT_INT_PARAM(size_t,len,len_);
415 |
416 | /* Consume remaining keystream, if any exists. */
417 | if (ctx->unused > 0) {
418 | auto k = ctx->ks + 64 - ctx->unused;
419 | size_t l = (len > ctx->unused) ? ITHARE_KSCOPE_VALUE(ctx->unused) : ITHARE_KSCOPE_VALUE(len);
420 | for (size_t i = 0; i < l; i++)
421 | *(out++) = *(in++) ^ *(k++);
422 | assert(l <= 255);
423 | ctx->unused -= uint8_t(l);
424 | len -= l;
425 | }
426 |
427 | ITHARE_KSCOPE_FCALL(chacha_encrypt_bytes)(ctx, in, out, len);
428 | }
429 |
430 | ITHARE_KSCOPE_DECLAREFUNC_WITHPARAMS_5xINT
431 | void CRYPTO_chacha_20(ITHARE_KSCOPE_DECLAREPARAM_INT(uint8_t)* out, const ITHARE_KSCOPE_DECLAREPARAM_INT2(uint8_t)* in, ITHARE_KSCOPE_DECLAREPARAM_INT3(size_t) len_,
432 | const ITHARE_KSCOPE_DECLAREPARAM_INT4(uint8_t) key[32], const ITHARE_KSCOPE_DECLAREPARAM_INT5(uint8_t) iv[8], uint64_t counter)
433 | {
434 | ITHARE_KSCOPE_ASSERT_INT_PTR_PARAM(uint8_t,out);
435 | ITHARE_KSCOPE_ASSERT_INT_PTR_PARAM(uint8_t,in);
436 | ITHARE_KSCOPE_CONVERT_INT_PARAM(size_t,len,len_);
437 | ITHARE_KSCOPE_ASSERT_INT_PTR_PARAM(uint8_t,key);
438 | ITHARE_KSCOPE_ASSERT_INT_PTR_PARAM(uint8_t,iv);
439 |
440 | ITHARE_KSCOPE_KSCOPECLASS(ChaCha_ctx) ctx = {};
441 |
442 | /*
443 | * chacha_ivsetup expects the counter to be in u8. Rather than
444 | * converting size_t to u8 and then back again, pass a counter of
445 | * NULL and manually assign it afterwards.
446 | */
447 | ITHARE_KSCOPE_FCALL(chacha_keysetup)(&ctx, key, ITHARE_KSCOPE_FINTLIT(256));
448 | ITHARE_KSCOPE_FCALL(chacha_ivsetup)(&ctx, iv, ITHARE_KSCOPE_INTNULLPTR);
449 | if (counter != 0) {
450 | ctx.input[12] = (uint32_t)counter;
451 | ctx.input[13] = (uint32_t)(counter >> 32);
452 | }
453 |
454 | ITHARE_KSCOPE_FCALL(chacha_encrypt_bytes)(&ctx, in, out, len);
455 | }
456 |
457 | //wrappers for compile-time crypto; feel free to add more along the same lines as necessary
458 | constexpr ChaCha_ctx<>
459 | KSCOPE_CT_Chacha_set_key_iv(const uint8_t* key0, int keybits /*128 or 256*/, const uint8_t iv0[8], const uint8_t counter0[8]) {//combining Chacha_set_key() and Chacha_set_iv() to reduce number of constexpr vars for the user. If necessary - can be split back.
460 | ChaCha_ctx<> ctx = {};
461 | assert(keybits==128||keybits==256);
462 | //auto key = kscope_int_arr_to_ct_kscope_int<64 /*maximum value*/>(key0,keybits/8 /*actual value*/);
463 | //auto iv = kscope_int_arr_to_ct_kscope_int<8>(iv0);
464 | ITHARE_KSCOPE_CALL_AS_CONSTEXPR(ChaCha_set_key)(&ctx,key0, keybits);
465 | if(counter0==nullptr)
466 | ITHARE_KSCOPE_CALL_AS_CONSTEXPR(ChaCha_set_iv)(&ctx,iv0,ITHARE_KSCOPE_INTNULLPTR);
467 | else {
468 | //auto counter = kscope_int_arr_to_ct_kscope_int<8>(counter0);
469 | ITHARE_KSCOPE_CALL_AS_CONSTEXPR(ChaCha_set_iv)(&ctx,iv0,counter0);
470 | }
471 | return ctx;
472 | }
473 |
474 | template
475 | constexpr std::pair,KscopeArrayWrapper>
476 | KSCOPE_CT_Chacha(ChaCha_ctx<> ctx, const uint8_t (&in0)[N]) {
477 | //auto in = kscope_int_arr_to_ct_kscope_int(in0);
478 | //ITHARE_KSCOPE_INT_CONSTEXPR(uint8_t) out[N];
479 | KscopeArrayWrapper ret = {};
480 | ITHARE_KSCOPE_CALL_AS_CONSTEXPR(ChaCha)(&ctx, ret.arr, in0, N);
481 | //KscopeArrayWrapper ret = {};
482 | //ithare::kscope::kscope_copyarr(ret.arr,out,N);
483 | return std::pair,KscopeArrayWrapper>(ctx,ret);
484 | }
485 |
486 | }}} // namespace ithare::kscope::ssl
487 |
488 | #endif //ithare_kscope_kaleidoscoped_ssl_crypto_chacha_h_included
489 |
--------------------------------------------------------------------------------
/src/README.md:
--------------------------------------------------------------------------------
1 | By design, kscope is a header-only library (="don't expect to find any .cpp files here").
2 |
3 | See /test folder for .cpps-which-use-kscope (and more generally - for an automated testing environment).
4 |
--------------------------------------------------------------------------------
/src/impl/kscope_common.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (c) 2018, ITHare.com
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
31 | */
32 |
33 | #ifndef ithare_kscope_common_h_included
34 | #define ithare_kscope_common_h_included
35 |
36 | //NOT intended to be #included directly
37 | // #include ../kscope.h instead
38 |
39 | //kscope_common.h
40 | // Basic setup for ithare::kscope
41 |
42 | #include
43 | #include
44 | #include
45 | #include //CHAR_BIT
46 | #include //memset/memcpy
47 | //#include - prefer KScopeArrayWrapper instead
48 | //#include
49 | #include
50 | //#include
51 | #include
52 | #include //for dbg_print() only
53 | #include //for dbg_print() only
54 |
55 | #ifdef ITHARE_KSCOPE_DISABLE
56 | #if defined(ITHARE_KSCOPE_SEED) || defined(ITHARE_KSCOPE_SEED2)
57 | #error Make up your mind - ITHARE_KSCOPE_DISABLE is incompatible with ITHARE_KSCOPE_SEED/ITHARE_KSCOPE_SEED2
58 | #endif
59 | #if defined(ITHARE_KSCOPE_ENABLE_DBGPRINT) || defined(ITHARE_KSCOPE_ENABLE_AUTO_DBGPRINT)
60 | #error Make up your mind - ITHARE_KSCOPE_DISABLE is incompatible with ITHARE_KSCOPE_ENABLE_DBGPRINT/ITHARE_KSCOPE_ENABLE_AUTO_DBGPRINT
61 | #endif
62 |
63 | #endif
64 |
65 | #ifdef ITHARE_KSCOPE_DBG_RUNTIME_CHECKS
66 | #define ITHARE_KSCOPE_DBG_ENABLE_DBGPRINT//necessary for checks to work
67 | #endif
68 |
69 | #ifdef ITHARE_KSCOPE_ENABLE_AUTO_DBGPRINT
70 | #define ITHARE_KSCOPE_DBG_ENABLE_DBGPRINT //prerequisite
71 | #endif
72 |
73 | #ifdef ITHARE_KSCOPE_SEED
74 | #ifndef ITHARE_KSCOPE_SEED2
75 | #define ITHARE_KSCOPE_SEED2 0
76 | #endif
77 | #endif
78 |
79 | #ifndef ITHARE_KSCOPE_COMPILE_TIME_TESTS
80 | #define ITHARE_KSCOPE_COMPILE_TIME_TESTS 100
81 | #endif
82 |
83 | #ifdef _MSC_VER
84 | #if _MSC_VER < 1910
85 | #pragma message("MSVC prior to VS2017 is not likely to work :-(")
86 | #endif
87 | #if _MSC_VER == 1913 || _MSC_VER == 1914
88 | #pragma message("Between Visual Studio 15.5.5 and 15.7.5, MSVC got a nasty regression preventing kscope from compiling :-(. If you're experiencing ''seed': invalid template argument for...' errors when running kscope's randomtest.bat, please downgrade Visual Studio to 15.5.5, or upgrade to 15.8 Preview 4 or later, both are known to work :-)")
89 | #endif
90 | #pragma warning (disable:4307 4146 4310 4702)
91 |
92 | #ifdef ITHARE_KSCOPE_NOFORCEINLINE
93 | #define ITHARE_KSCOPE_FORCEINLINE inline
94 | #else
95 | #define ITHARE_KSCOPE_FORCEINLINE __forceinline
96 | #endif
97 | #define ITHARE_KSCOPE_NOINLINE __declspec(noinline)
98 | #define ITHARE_KSCOPE_CONSTEXPR_ASSERT_UNREACHABLE assert(false)
99 |
100 | #define ITHARE_KSCOPE_BOUNDED_MINBYTES(param_num,minlen) //As there are no apples growing on oak trees (="bound checks for MSVC"), we can't do much about it...
101 | #define ITHARE_KSCOPE_BOUNDED_BUFFER(param_num,len) //No apples growing on oak trees...
102 |
103 | #define ITHARE_KSCOPE_WORKAROUND_FOR_MSVC_BUG_195483 //workaround for https://developercommunity.visualstudio.com/content/problem/195483/continue-in-constexpr-function-causes-constexpr-fu.html
104 | #define ITHARE_KSCOPE_WORKAROUND_FOR_MSVC_BUG_196885 //workaround for https://developercommunity.visualstudio.com/content/problem/196885/c1001-in-fddvctoolscompilercxxfeslp1cwalkcpp-line.html
105 | #define ITHARE_KSCOPE_WORKAROUND_FOR_MSVC_BUG_196900 //workaround for https://developercommunity.visualstudio.com/content/problem/196900/c1001-in-file-msc1cpp-line-1507.html
106 | #define ITHARE_KSCOPE_WORKAROUND_FOR_MSVC_BUG_199554 //workaround for https://developercommunity.visualstudio.com/content/problem/199554/suspected-bad-code-generation-for-release-build.html
107 |
108 | #elif defined(__clang__)//As Clang also #defines __GNUC__, we MUST always check __clang__ first
109 |
110 | #ifdef __apple_build_version__
111 | #if __clang_major__ < 8
112 | #pragma message "Apple Clang prior to version 8 is not likely to work :-("
113 | #endif
114 | #else
115 | #if __clang_major__ < 4
116 | #pragma message "Clang prior to version 4 is not likely to work :-("
117 | #endif
118 | #endif
119 |
120 | #define ITHARE_KSCOPE_FORCEINLINE __attribute__((always_inline)) inline
121 | #define ITHARE_KSCOPE_NOINLINE __attribute__((noinline))
122 | #define ITHARE_KSCOPE_CONSTEXPR_ASSERT_UNREACHABLE assert(false)
123 |
124 | #define ITHARE_KSCOPE_BOUNDED_MINBYTES(param_num,minlen) __attribute__((__bounded__(__minbytes__,param_num,minlen)))
125 | #define ITHARE_KSCOPE_BOUNDED_BUFFER(param_num,len) __attribute__((__bounded__(__buffer__,param_num,len)))
126 |
127 | #elif defined(__GNUC__)
128 |
129 | #if __GNUC__ < 7
130 | #pragma message "GCC prior to version 7 is not likely to work :-("
131 | #endif
132 |
133 | #define ITHARE_KSCOPE_WORKAROUND_FOR_GCC_BUG_47488 //workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47488
134 | #define ITHARE_KSCOPE_WORKAROUND_FOR_GCC_BUG_84463 //workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84463
135 |
136 | #ifdef ITHARE_KSCOPE_NOFORCEINLINE
137 | #define ITHARE_KSCOPE_FORCEINLINE inline
138 | #else
139 | #define ITHARE_KSCOPE_FORCEINLINE __attribute__((always_inline)) inline
140 | #endif
141 | #define ITHARE_KSCOPE_NOINLINE __attribute__((noinline))
142 | #define ITHARE_KSCOPE_CONSTEXPR_ASSERT_UNREACHABLE //as of GCC 7.2.0, assert(false) doesn't work in constexpr functions in GCC ; other ideas on "how to assert in supposedly-unreachable constexpr code" are very welcome
143 |
144 | //for GCC, attributes are not allowed on function definitions
145 | // - and 99.9% of our kaleidoscoped functions are definition-only (for a good reason too)
146 | #define ITHARE_KSCOPE_BOUNDED_MINBYTES(param_num,minlen)
147 | #define ITHARE_KSCOPE_BOUNDED_BUFFER(param_num,len)
148 |
149 | #else
150 | #error Other compilers than MSVC, Clang, and GCC are not supported
151 | #endif//_MSC_VER || __clang__ || __GNUC__
152 |
153 | #if defined(__clang__)|| defined(__GNUC__)
154 | #if __cplusplus <= 201402 //C++ 14 or before; for reference - working Apple Clang 9.0.0 gives 201406
155 | #pragma message "Are you sure you didn't forget to specify -std=c++17 or -std=c++1z when compiling?"
156 | #endif
157 | #endif
158 | //for VS2017, __cplusplus is still stuck at 199711 regardless of compiler switches :-( => no possibility to warn about missing /std:c++17
159 |
160 | #ifndef _MSC_VER //as of VS2017, MSVC doesn't seem to support C++ feature test macros :-(
161 | #if __cpp_constexpr < 201304
162 | #error "ithare::kscope DOES use constexprs extensively"
163 | #endif
164 | #if __cpp_if_constexpr < 201606
165 | #error "ithare::kscope heavily relies on constexpr if"
166 | #endif
167 | #if __cpp_decltype < 200707
168 | #error "ithare::kscope DOES need decltype."
169 | #endif
170 | #if __cpp_variadic_templates < 200704
171 | #error "ithare::kscope DOES need variadic templates."
172 | #endif
173 | #if __cpp_static_assert < 201411
174 | #error "ithare::kscope DOES use short form of static assert. Can be rewritten, but will unlikely help due to other requirements"
175 | #endif
176 | #endif//_MSC_VER
177 |
178 | //NAMESPACE POLICIES (we have to be very strict as it is a header-only library):
179 | // EVERYTHING goes into ithare::kscope namespace - except for #defines
180 | // ALL #defines MUST be prefixed with ITHARE_KSCOPE_
181 |
182 | //VERY generic requirements:
183 | // 8-bit systems only at the moment
184 | static_assert(CHAR_BIT==8);//adapting for non-8-bit systems is theoretically possible, but will take quite a bit of tweaking
185 | // requiring uint*_t, detection along the lines of https://stackoverflow.com/a/14078003/4947867
186 | #if !defined(UINT8_MAX) || !defined(UINT16_MAX) || !defined(UINT32_MAX) || !defined(UINT64_MAX)//TODO: allow to skip uint64_t
187 | #error kscope requires that your compiler supports all of the uint8_t, uint16_t, uint32_t, and uint64_t types - and they ARE supported for vast majority of platforms. Maybe there is something wrong with supposedly-standard headers on your box (they are supposed to be defined in stdint.h which is included above, but you never know)?
188 | #endif
189 |
190 | //regardless of ITHARE_KSCOPE_SEED
191 | namespace ithare {
192 | namespace kscope {
193 | template
194 | ITHARE_KSCOPE_FORCEINLINE constexpr size_t kscope_arraysz(T(&)[N]) { return N; }
195 |
196 | template
197 | struct KscopeArrayWrapper {//returns from constexpr functions
198 | T arr[N];
199 |
200 | constexpr T operator[](int idx) const {
201 | return arr[idx];
202 | }
203 | constexpr T& operator[](int idx) {
204 | return arr[idx];
205 | }
206 | constexpr const T* operator+(int idx) const {
207 | return arr + idx;
208 | }
209 | constexpr T* operator+(int idx) {
210 | return arr + idx;
211 | }
212 | };
213 |
214 | constexpr size_t kscope_strlen(const char* s) {
215 | for (size_t ret = 0; ; ++ret, ++s)
216 | if (*s == 0)
217 | return ret;
218 | }
219 |
220 | constexpr uint64_t kscope_string_hash(const char* s) {
221 | uint64_t u = 5381;
222 | for (const char* p = s; *p; ++p)//djb2 by Dan Bernstein
223 | u = ((u << 5) + u) + *p;
224 | return u;
225 | }
226 |
227 | using kscope_aliased_byte = unsigned char;//GUARANTEES pointer aliasing even if uint8_t is not the same as unsigned char
228 | // THE ONLY type which should be used for cast-based fooling around
229 | static_assert(sizeof(kscope_aliased_byte)==1);
230 |
231 | /* not used now, if needed for kaleidoscoped - will re-instate
232 | enum class kscope_endian//along the lines of p0463r1, to be replaced with std::endian
233 | {
234 | #ifdef _MSC_VER
235 | #if defined(_M_IX86) || defined(_M_X64)
236 | little = 0x22d7,//from random.org :-), to discourage relying on specific values
237 | big = 0xe72d,//from random.org
238 | native = little
239 | //x86/x64
240 | #else
241 | #error "Endianness not defined yet"
242 | #endif
243 |
244 | //_MSC_VER
245 | #else
246 | little = __ORDER_LITTLE_ENDIAN__,
247 | big = __ORDER_BIG_ENDIAN__,
248 | native = __BYTE_ORDER__,
249 | #endif
250 | };
251 | */
252 |
253 | using KSCOPEFLAGS = uint64_t;
254 | constexpr KSCOPEFLAGS kscope_flag_is_constexpr = 0x01;
255 |
256 | struct kscope_private_constructor_tag {
257 | };
258 |
259 | template struct kscope_larger_type {
260 | static_assert(std::is_integral::value);
261 | static_assert(std::is_integral::value);
262 | constexpr static bool ts = std::is_signed::value;
263 | constexpr static bool t2s = std::is_signed::value;
264 | static_assert(ts == t2s);//'larger_type' is undefined for different sign-ness
265 | constexpr static bool which = sizeof(T) > sizeof(T2);
266 | using type = typename std::conditional::type;
267 |
268 | static_assert(sizeof(type) >= sizeof(T));
269 | static_assert(sizeof(type) >= sizeof(T2));
270 | };
271 |
272 | template
273 | struct kscope_uint_by_size;
274 | template<>
275 | struct kscope_uint_by_size<8> { using type = uint8_t; };
276 | template<>
277 | struct kscope_uint_by_size<16> { using type = uint16_t; };
278 | template<>
279 | struct kscope_uint_by_size<32> { using type = uint32_t; };
280 | template<>
281 | struct kscope_uint_by_size<64> { using type = uint64_t; };
282 | template
283 | struct kscope_normalized_unsigned_integral_type {
284 | static_assert(std::is_integral::value);
285 | using type = typename kscope_uint_by_size<8*sizeof(T)>::type;
286 | static_assert(sizeof(type)==sizeof(T));
287 | static_assert(std::is_unsigned::value);
288 | };
289 |
290 | template
291 | struct kscope_sint_by_size;
292 | template<>
293 | struct kscope_sint_by_size<8> { using type = int8_t; };
294 | template<>
295 | struct kscope_sint_by_size<16> { using type = int16_t; };
296 | template<>
297 | struct kscope_sint_by_size<32> { using type = int32_t; };
298 | template<>
299 | struct kscope_sint_by_size<64> { using type = int64_t; };
300 | template
301 | struct kscope_normalized_signed_integral_type {
302 | static_assert(std::is_integral::value);
303 | using type = typename kscope_sint_by_size<8*sizeof(T)>::type;
304 | static_assert(sizeof(type)==sizeof(T));
305 | static_assert(std::is_signed::value);
306 | };
307 |
308 | template
309 | struct kscope_normalized_integral_type {//to normalize things such as 'unsigned long' which MIGHT happen to be different from our standard set
310 | static_assert(std::is_integral::value);
311 | using type = typename std::conditional< std::is_signed::value,
312 | typename kscope_normalized_signed_integral_type::type,
313 | typename kscope_normalized_unsigned_integral_type::type
314 | >::type;
315 |
316 | static_assert(std::is_integral::value);
317 | static_assert(sizeof(T)==sizeof(type));
318 | static_assert(std::is_signed::value == std::is_signed::value);
319 | };
320 |
321 | //well-known shortcuts just to save a bit of compile time...
322 | template<>
323 | struct kscope_normalized_integral_type {
324 | using type = uint64_t;
325 | };
326 | template<>
327 | struct kscope_normalized_integral_type {
328 | using type = uint32_t;
329 | };
330 | template<>
331 | struct kscope_normalized_integral_type {
332 | using type = uint16_t;
333 | };
334 | template<>
335 | struct kscope_normalized_integral_type {
336 | using type = uint8_t;
337 | };
338 | template<>
339 | struct kscope_normalized_integral_type {
340 | using type = int64_t;
341 | };
342 | template<>
343 | struct kscope_normalized_integral_type {
344 | using type = int32_t;
345 | };
346 | template<>
347 | struct kscope_normalized_integral_type {
348 | using type = int16_t;
349 | };
350 | template<>
351 | struct kscope_normalized_integral_type {
352 | using type = int8_t;
353 | };
354 |
355 | template<>
356 | struct kscope_normalized_unsigned_integral_type {
357 | using type = uint64_t;
358 | };
359 | template<>
360 | struct kscope_normalized_unsigned_integral_type {
361 | using type = uint32_t;
362 | };
363 | template<>
364 | struct kscope_normalized_unsigned_integral_type {
365 | using type = uint16_t;
366 | };
367 | template<>
368 | struct kscope_normalized_unsigned_integral_type {
369 | using type = uint8_t;
370 | };
371 | template<>
372 | struct kscope_normalized_unsigned_integral_type {
373 | using type = uint64_t;
374 | };
375 | template<>
376 | struct kscope_normalized_unsigned_integral_type {
377 | using type = uint32_t;
378 | };
379 | template<>
380 | struct kscope_normalized_unsigned_integral_type {
381 | using type = uint16_t;
382 | };
383 | template<>
384 | struct kscope_normalized_unsigned_integral_type {
385 | using type = uint8_t;
386 | };
387 |
388 | constexpr size_t kscope_smallest_uint_size(size_t n) {
389 | assert(n <= 64);
390 | if (n <= 8)
391 | return 8;
392 | else if (n <= 16)
393 | return 16;
394 | else if (n <= 32)
395 | return 32;
396 | else {
397 | assert(n <= 64);
398 | return 64;
399 | }
400 | }
401 |
402 | // My translation of "integral promotion" section from http://en.cppreference.com/w/cpp/language/implicit_conversion, PLUS http://en.cppreference.com/w/cpp/language/operator_arithmetic#Conversions (under more-or-less reasonable assumptions of real-world 32/64-bit platforms):
403 | // If we have type T on the left, and type T2 on the right, all arithmetic is done in the type TT (which is also returned); TT can be calculated as follows:
404 | // assert( sizeof(int)==sizeof(unsigned))
405 | // TPROMOTED = sizeof(T) < sizeof(int) ? int : T; //sic - int regardless of the T being signed or not!
406 | // same logic for TPROMOTED2
407 | // if both TPROMOTED and TPROMOTED2 are signed, or both are unsigned:
408 | // -- TT = larger_type
409 | // if TPROMOTED is signed and TPROMOTED2 is unsigned:
410 | // -- TT = sizeof(TPROMOTED)>sizeof(TPROMOTED2) ? TPROMOTED : /* including equal size */ TPROMOTED2;
411 | // same logic for TPROMOTED2 signed and TPROMOTED unsigned
412 | // Hope it makes sense
413 |
414 | static_assert(sizeof(int)==sizeof(unsigned));
415 | template
416 | struct kscope_integral_promotion {
417 | static_assert(std::is_integral::value);
418 | using type = typename std::conditional< (sizeof(T) < sizeof(int)), int, T >::type;
419 |
420 | static_assert(sizeof(type) >= sizeof(T));
421 | static_assert(sizeof(type) >= sizeof(int));
422 | };
423 |
424 | template
425 | struct kscope_integral_operator_promoconv {
426 | using TPROMOTED = typename kscope_integral_promotion::type;
427 | using T2PROMOTED = typename kscope_integral_promotion::type;
428 | static_assert(sizeof(TPROMOTED) >= sizeof(T));
429 | static_assert(sizeof(T2PROMOTED) >= sizeof(T2));
430 | static constexpr bool ts = std::is_signed::value;
431 | static constexpr bool t2s = std::is_signed::value;
432 |
433 | using type = typename std::conditional< ts == t2s,
434 | typename std::conditional< (sizeof(TPROMOTED) >= sizeof(T2PROMOTED)), TPROMOTED,T2PROMOTED>::type,
435 | typename std::conditional< ts ,
436 | typename std::conditional< (sizeof(TPROMOTED) > sizeof(T2PROMOTED)), TPROMOTED, T2PROMOTED >::type,
437 | typename std::conditional< (sizeof(T2PROMOTED) > sizeof(TPROMOTED)), T2PROMOTED, TPROMOTED >::type
438 | >::type
439 | >::type;
440 |
441 | static_assert(sizeof(type) >= sizeof(TPROMOTED));
442 | static_assert(sizeof(type) >= sizeof(T2PROMOTED));
443 | };
444 |
445 | class KscopeSint128 {//larger than the largest integral type, so we can use it to store maximums/minimums for ALL the types, signed or unsigned
446 | int64_t hi;
447 | uint64_t lo;
448 |
449 | public:
450 | constexpr KscopeSint128(uint64_t x) : hi(0), lo(x) {
451 | }
452 | constexpr KscopeSint128(int64_t x) : hi(x<0?int64_t(-1):0), lo(x) {
453 | }
454 | constexpr KscopeSint128(uint32_t x) : KscopeSint128(uint64_t(x)) {
455 | }
456 | constexpr KscopeSint128(int32_t x) : KscopeSint128(int64_t(x)) {
457 | }
458 | constexpr KscopeSint128(uint16_t x) : KscopeSint128(uint64_t(x)) {
459 | }
460 | constexpr KscopeSint128(int16_t x) : KscopeSint128(int64_t(x)) {
461 | }
462 | constexpr KscopeSint128(uint8_t x) : KscopeSint128(uint64_t(x)) {
463 | }
464 | constexpr KscopeSint128(int8_t x) : KscopeSint128(int64_t(x)) {
465 | }
466 |
467 | constexpr bool operator <=(const KscopeSint128& other) const {
468 | return cmp(other) <= 0;
469 | }
470 | constexpr bool operator >=(const KscopeSint128& other) const {
471 | return cmp(other) >= 0;
472 | }
473 |
474 | private:
475 | constexpr int cmp(const KscopeSint128& other) const {
476 | if( hi < other.hi )
477 | return -1;
478 | if( hi > other.hi )
479 | return 1;
480 |
481 | int ret = 0;
482 | if( lo < other.lo )
483 | ret = -1;
484 | if( lo > other.lo )
485 | ret = 1;
486 | return hi >= 0 ? ret : -ret;
487 | }
488 | };
489 |
490 | template
491 | constexpr bool kscope_integral_operator_literal_cast_is_safe() {
492 | using TCNORMAL = typename kscope_normalized_integral_type::type;
493 | static_assert(std::numeric_limits::min()==std::numeric_limits::min());
494 | static_assert(std::numeric_limits::max()==std::numeric_limits::max());
495 |
496 | using TNORMAL = typename kscope_normalized_integral_type::type;
497 | static_assert(std::numeric_limits::min()==std::numeric_limits::min());
498 | static_assert(std::numeric_limits::max()==std::numeric_limits::max());
499 |
500 | return KscopeSint128(TCNORMAL(C)) <= KscopeSint128(std::numeric_limits::max()) &&
501 | KscopeSint128(TCNORMAL(C)) >= KscopeSint128(std::numeric_limits::min());
502 | }
503 |
504 | }//namespace kscope
505 | }//namespace ithare
506 |
507 | //Generic string manipulation macros with lots of indirections to solve problems ;-)
508 | #define ITHARE_KSCOPE_STRINGIFY(X) ITHARE_KSCOPE_STRINGIFY2(X)
509 | #define ITHARE_KSCOPE_STRINGIFY2(X) #X
510 |
511 | #define ITHARE_KSCOPE_CAT(X,Y) ITHARE_KSCOPE_CAT2(X,Y)
512 | #define ITHARE_KSCOPE_CAT2(X,Y) X##Y
513 |
514 | #ifdef _MSC_VER
515 | //direct use of __LINE__ doesn't count as constexpr in MSVC - see https://developercommunity.visualstudio.com/content/problem/195665/-line-cannot-be-used-as-an-argument-for-constexpr.html
516 | #define ITHARE_KSCOPE_LINE int(ITHARE_KSCOPE_CAT(__LINE__,U)) //appending 'U' shouldn't change much as __LINE__ is supposedly non-negative anyway
517 | #else
518 | #define ITHARE_KSCOPE_LINE __LINE__
519 | #endif
520 |
521 | //KSCOPE_SEED-dependent stuff
522 | #ifdef ITHARE_KSCOPE_SEED
523 |
524 | namespace ithare {
525 | namespace kscope {
526 | using KSCOPECYCLES = int32_t;//signed!
527 | using KSCOPELEVEL = int16_t;//signed!
528 |
529 | constexpr KSCOPELEVEL kscope_addlevel(KSCOPELEVEL base, KSCOPELEVEL diff) {
530 | KSCOPELEVEL ret = base + diff;
531 | if( base < 0 )
532 | return std::min(KSCOPELEVEL(-1),ret);
533 | else {
534 | assert( base >= 0 );
535 | return std::max(KSCOPELEVEL(0),ret);
536 | }
537 | }
538 |
539 | //KSCOPEFLAGS 0x01 is already defined regardless of KSCOPE_SEED, see above
540 | constexpr KSCOPEFLAGS kscope_flag_cross_platform_only = 0x02;
541 |
542 | using KSCOPEINJECTIONCAPS = uint64_t;//injection capability flags
543 | constexpr KSCOPEINJECTIONCAPS kscope_injection_has_add_mod_max_value_ex = 0x01;
544 |
545 | using KSCOPECONSTFLAGS = uint64_t;//constant description flags
546 | constexpr KSCOPECONSTFLAGS kscope_const_zero_ok = 0x01;
547 | constexpr KSCOPECONSTFLAGS kscope_const_one_ok = 0x02;
548 | constexpr KSCOPECONSTFLAGS kscope_const_odd_only = 0x04;
549 |
550 | constexpr bool kscope_avoid_memxxx = true;
551 |
552 | //KscopeTraits<>
553 | template
554 | struct KscopeTraits;
555 |
556 | template<>
557 | struct KscopeTraits {
558 | static constexpr bool is_built_in = true;
559 | static std::string type_name() { return "uint64_t"; }
560 | //using signed_type = int64_t;
561 | using literal_type = uint64_t;
562 | using construct_from_type = uint64_t;
563 |
564 | static constexpr bool has_half_type = true;
565 | using HalfT = uint32_t;
566 | using UintT = typename kscope_larger_type::type;//UintT is a type to cast to, to avoid idiocies like uint16_t*uint16_t being promoted to signed(!) int, and then overflowing to cause UB
567 | static constexpr bool is_bit_based = true;
568 | static constexpr size_t nbits = 64;
569 | };
570 |
571 | template<>
572 | struct KscopeTraits {
573 | static constexpr bool is_built_in = true;
574 | static std::string type_name() { return "uint32_t"; }
575 | //using signed_type = int32_t;
576 | using literal_type = uint32_t;
577 | using construct_from_type = uint32_t;
578 |
579 | static constexpr bool has_half_type = true;
580 | using HalfT = uint16_t;
581 | using UintT = typename kscope_larger_type::type;
582 | static constexpr bool is_bit_based = true;
583 | static constexpr size_t nbits = 32;
584 | };
585 |
586 | template<>
587 | struct KscopeTraits {
588 | static constexpr bool is_built_in = true;
589 | static std::string type_name() { return "uint16_t"; }
590 | //using signed_type = int16_t;
591 | using literal_type = uint16_t;
592 | using construct_from_type = uint16_t;
593 |
594 | static constexpr bool has_half_type = true;
595 | using HalfT = uint8_t;
596 | using UintT = typename kscope_larger_type::type;
597 | static constexpr bool is_bit_based = true;
598 | static constexpr size_t nbits = 16;
599 | };
600 |
601 | template<>
602 | struct KscopeTraits {
603 | static constexpr bool is_built_in = true;
604 | static std::string type_name() { return "uint8_t"; }
605 | //using signed_type = int8_t;
606 | using literal_type = uint8_t;
607 | using construct_from_type = uint8_t;
608 |
609 | static constexpr bool has_half_type = false;
610 | using UintT = typename kscope_larger_type::type;
611 | static constexpr bool is_bit_based = true;
612 | static constexpr size_t nbits = 8;
613 | };
614 |
615 | #ifdef ITHARE_KSCOPE_DBG_ENABLE_DBGPRINT
616 | //dbg_print helpers
617 | template
618 | std::string kscope_dbg_print_t() {
619 | return KscopeTraits::type_name();
620 | }
621 |
622 | //fwd decl
623 | template
624 | class KscopeBitUint;
625 |
626 | template
627 | struct KscopePrintC {
628 | using type = T;
629 | };
630 | template<>
631 | struct KscopePrintC {
632 | using type = int;
633 | };
634 | template
635 | struct KscopePrintC> {
636 | using type = typename KscopePrintC::T>::type;
637 | };
638 |
639 | template
640 | typename KscopePrintC::type kscope_dbg_print_c(T c) {
641 | return typename KscopePrintC::type(c);
642 | }
643 | #endif
644 |
645 | template
646 | constexpr T kscope_mask(size_t n) {
647 | assert(n <= sizeof(T) * 8);
648 | if (n == sizeof(T) * 8)
649 | return T(-1);
650 | else
651 | return (T(1) << n) - T(1);
652 | }
653 |
654 | #ifdef _MSC_VER
655 | #pragma warning(push)
656 | #pragma warning(disable:4521) //multiple constructors
657 | #endif
658 | template
659 | class KscopeBitUint {
660 | public:
661 | static constexpr size_t N = N_;
662 | using T = typename kscope_uint_by_size::type;
663 | static_assert(N <= sizeof(T) * 8);
664 |
665 | private:
666 | static constexpr T mask = kscope_mask(N);
667 |
668 | public:
669 | constexpr ITHARE_KSCOPE_FORCEINLINE KscopeBitUint() : val(0) {}
670 | constexpr ITHARE_KSCOPE_FORCEINLINE KscopeBitUint(T x) : val(x & mask) {}
671 | constexpr KscopeBitUint(const KscopeBitUint& other) : val(other.val) {}
672 | constexpr KscopeBitUint(const volatile KscopeBitUint& other) : val(other.val) {}
673 |
674 | constexpr ITHARE_KSCOPE_FORCEINLINE operator T() const { assert((val&mask) == val); return val & mask; }
675 |
676 | constexpr ITHARE_KSCOPE_FORCEINLINE KscopeBitUint operator -() const { return KscopeBitUint(-val); }
677 | constexpr ITHARE_KSCOPE_FORCEINLINE KscopeBitUint operator *(KscopeBitUint x) const { return KscopeBitUint(val * x.val); }
678 | constexpr ITHARE_KSCOPE_FORCEINLINE KscopeBitUint operator +(KscopeBitUint x) const { return KscopeBitUint(val + x.val); }
679 | constexpr ITHARE_KSCOPE_FORCEINLINE KscopeBitUint operator -(KscopeBitUint x) const { return KscopeBitUint(val - x.val); }
680 | constexpr ITHARE_KSCOPE_FORCEINLINE KscopeBitUint operator %(KscopeBitUint x) const { return KscopeBitUint(val%x.val); }
681 | constexpr ITHARE_KSCOPE_FORCEINLINE KscopeBitUint operator /(KscopeBitUint x) const { return KscopeBitUint(val / x.val); }
682 |
683 | constexpr ITHARE_KSCOPE_FORCEINLINE KscopeBitUint operator ~() const { return KscopeBitUint(~val); }
684 | constexpr ITHARE_KSCOPE_FORCEINLINE KscopeBitUint operator &(KscopeBitUint x) const { return KscopeBitUint(val & x.val); }
685 | constexpr ITHARE_KSCOPE_FORCEINLINE KscopeBitUint operator |(KscopeBitUint x) const { return KscopeBitUint(val | x.val); }
686 | constexpr ITHARE_KSCOPE_FORCEINLINE KscopeBitUint operator ^(KscopeBitUint x) const { return KscopeBitUint(val ^ x.val); }
687 | constexpr ITHARE_KSCOPE_FORCEINLINE KscopeBitUint operator <<(size_t shift) const { return KscopeBitUint(val << shift); }
688 | constexpr ITHARE_KSCOPE_FORCEINLINE KscopeBitUint operator >>(size_t shift) const { return KscopeBitUint(val >> shift); }
689 |
690 | #ifdef ITHARE_KSCOPE_DBG_ENABLE_DBGPRINT
691 | static void dbg_print(size_t offset = 0,const char* prefix="") {
692 | std::cout << std::string(offset, ' ') << prefix << "KscopeBitUint<" << N << ">: mask =" << kscope_dbg_print_c(mask) << std::endl;
693 | }
694 | #endif
695 |
696 | private:
697 | T val;
698 | };
699 | #ifdef _MSC_VER
700 | #pragma warning(pop)
701 | #endif
702 |
703 | /*template
704 | class KscopeBitSint {
705 | public:
706 | static constexpr size_t N = N_;
707 | using UT = typename kscope_uint_by_size::type;
708 | using T = typename std::make_signed::type;
709 | static_assert(N <= sizeof(T) * 8);
710 | static_assert(sizeof(T) == sizeof(typename KscopeBitUint::T));
711 |
712 | private:
713 | static constexpr UT mask = kscope_mask(N);
714 |
715 | public:
716 | constexpr KscopeBitSint() : val(0) {}
717 | constexpr KscopeBitSint(T x) : val(UT(x)&mask) {}
718 | constexpr operator T() const { return T(val & mask); }
719 |
720 | constexpr KscopeBitSint operator -() const { return KscopeBitSint((~val)+1); }
721 |
722 | private:
723 | UT val;
724 | };*/
725 |
726 | template
727 | struct KscopeTraits> {
728 | private:
729 | using TT = KscopeBitUint;
730 | public:
731 | static constexpr bool is_built_in = false;
732 | static std::string type_name() {
733 | return std::string("KscopeBitUint<") + std::to_string(N) + ">";
734 | }
735 | //using signed_type = KscopeBitSint;
736 | using literal_type = typename TT::T;
737 | using construct_from_type = typename TT::T;
738 |
739 | static constexpr bool has_half_type = false;
740 | using UintT = typename kscope_larger_type::type;
741 | static constexpr bool is_bit_based = true;
742 | static constexpr size_t nbits = N;
743 | };
744 |
745 | }//namespace kscope
746 | }//namespace ithare
747 |
748 | #else
749 | namespace ithare {
750 | namespace kscope {
751 |
752 | constexpr bool kscope_avoid_memxxx = false;
753 |
754 | }//namespace kscope
755 | }//namespace ithare
756 | #endif //ITHARE_KSCOPE_SEED
757 |
758 | #endif //ithare_kscope_common_h_included
759 |
--------------------------------------------------------------------------------
/src/impl/kscope_context.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (c) 2018, ITHare.com
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
31 | */
32 |
33 | #ifndef ithare_kscope_context_h_included
34 | #define ithare_kscope_context_h_included
35 |
36 |
37 | #ifdef ITHARE_KSCOPE_SEED
38 |
39 | namespace ithare { namespace kscope {
40 |
41 | //forward declarations
42 | template
43 | class KscopeInjection;
44 |
45 | template
46 | class KscopeExtendedLiteralContext;
47 |
48 | template
49 | struct KscopeLiteralContextVersion;
50 |
51 |
52 | template
53 | class KscopeLiteralFromContext {
54 | static_assert(std::is_integral::value);
55 | static_assert(std::is_unsigned::value);
56 |
57 | struct InjectionRequirements {
58 | static constexpr size_t exclude_version = size_t(-1);
59 | static constexpr bool is_constexpr = true;
60 | static constexpr bool only_bijections = false;
61 | static constexpr bool no_substrate_size_increase = false;
62 | };
63 | using Injection = KscopeInjection;
64 | public:
65 | ITHARE_KSCOPE_FORCEINLINE constexpr KscopeLiteralFromContext() : val(Injection::template injection(C)) {
66 | }
67 | ITHARE_KSCOPE_FORCEINLINE constexpr T value() const {
68 | return Injection::template surjection(val);
69 | }
70 |
71 | #ifdef ITHARE_KSCOPE_DBG_ENABLE_DBGPRINT
72 | static void dbg_print(size_t offset = 0, const char* prefix = "") {
73 | std::cout << std::string(offset, ' ') << prefix << "KscopeLiteralFromContext<" << kscope_dbg_print_t() << "," << kscope_dbg_print_c(C) << "," << kscope_dbg_print_seed() << "," << cycles << ">" << std::endl;
74 | Injection::dbg_print(offset + 1);
75 | }
76 | static void dbg_check() {
77 | #ifndef NDEBUG //to be used in assert() below
78 | typename Injection::return_type c = Injection::template injection(C);
79 | T cc = Injection::template surjection(c);
80 | #endif
81 | assert(cc == C);
82 | }
83 | #endif
84 | private:
85 | typename Injection::return_type val;
86 | };
87 |
88 | template
89 | struct KscopeZeroLiteralContext {
90 | //to be used as a context for literals-created-from-literals
91 | using Type = T;
92 | constexpr static KSCOPECYCLES context_cycles = 0;
93 | constexpr static KSCOPECYCLES calc_cycles([[maybe_unused]] KSCOPECYCLES inj, KSCOPECYCLES surj) {
94 | return surj;//for literals, ONLY surjection costs apply in runtime (as injection applies in compile-time)
95 | }
96 | constexpr static KSCOPECYCLES literal_cycles = 0;
97 | template
98 | struct literal {
99 | using type = KscopeLiteralFromContext, seed, literal_cycles>;
100 | };
101 | template
102 | constexpr static T2 random_const(T2 upper_bound=0) {
103 | return kscope_random_const(upper_bound);
104 | }
105 | template
106 | using recursive_context_type = KscopeZeroLiteralContext;
107 | template
108 | using intermediate_context_type = KscopeZeroLiteralContext;
109 |
110 | template
111 | ITHARE_KSCOPE_FORCEINLINE static constexpr T final_injection(T x) {
112 | return x;
113 | }
114 | template
115 | ITHARE_KSCOPE_FORCEINLINE static constexpr T final_surjection(T y) {
116 | return y;
117 | }
118 |
119 | #ifdef ITHARE_KSCOPE_DBG_ENABLE_DBGPRINT
120 | static void dbg_print(size_t offset = 0, const char* prefix = "") {
121 | std::cout << std::string(offset, ' ') << prefix << "KscopeZeroContext<" << kscope_dbg_print_t() << ">" << std::endl;
122 | }
123 | #endif
124 | };
125 |
126 | //KscopeIntVarContext
127 | template
128 | struct KscopeIntVarContext {
129 | using Type = T;
130 | constexpr static KSCOPECYCLES context_cycles = 0;
131 | constexpr static KSCOPECYCLES calc_cycles(KSCOPECYCLES inj, KSCOPECYCLES surj) {
132 | return inj + surj;//for variables, BOTH injection and surjection are executed in runtime
133 | }
134 |
135 | constexpr static KSCOPECYCLES literal_cycles = std::min(cycles/2,50);//TODO: justify (or define?)
136 | template
137 | struct literal {
138 | using LiteralContext = KscopeExtendedLiteralContext;
139 | using type = KscopeLiteralFromContext;
140 | };
141 | template
142 | using recursive_context_type = KscopeIntVarContext;//TODO:COMBINED
143 | template
144 | using intermediate_context_type = KscopeIntVarContext;//TODO:COMBINED
145 |
146 | template
147 | constexpr static T2 random_const(T2 upper_bound=0) {
148 | return kscope_random_const(upper_bound);
149 | }
150 |
151 | template
152 | ITHARE_KSCOPE_FORCEINLINE static constexpr T final_injection(T x) {
153 | return x;
154 | }
155 | template
156 | ITHARE_KSCOPE_FORCEINLINE static constexpr T final_surjection( T y) {
157 | return y;
158 | }
159 |
160 | #ifdef ITHARE_KSCOPE_DBG_ENABLE_DBGPRINT
161 | static void dbg_print(size_t offset = 0, const char* prefix = "") {
162 | std::cout << std::string(offset, ' ') << prefix << "KscopeIntVarContext<" << kscope_dbg_print_t() << ">" << std::endl;
163 | }
164 | #endif
165 | };
166 |
167 | template
168 | class KscopeExtensibleLiteralContext {
169 | using Traits = KscopeTraits;
170 | constexpr static size_t which = kscope_random_choice_from_list(cycles, Descr::descr);
171 | using WhichType = KscopeLiteralContextVersion;
172 |
173 | public:
174 | using Type = T;
175 | constexpr static KSCOPECYCLES context_cycles = WhichType::context_cycles;
176 | constexpr static KSCOPECYCLES calc_cycles([[maybe_unused]] KSCOPECYCLES inj, KSCOPECYCLES surj) {
177 | return surj;//for literals, ONLY surjection costs apply in runtime (as injection applies in compile-time)
178 | }
179 |
180 | template
181 | using recursive_context_type = KscopeExtendedLiteralContext;
182 | template
183 | using intermediate_context_type = typename ithare::kscope::KscopeExtendedLiteralContext;//whenever cycles is low (which is very often), will fallback to version0
184 |
185 | template
186 | constexpr static T2 random_const(T2 upper_bound=0) {
187 | return kscope_random_const(upper_bound);
188 | }
189 |
190 | constexpr static KSCOPECYCLES literal_cycles = 0;
191 | template
192 | struct literal {
193 | using type = KscopeLiteralFromContext, ITHARE_KSCOPE_COMBINED_PRNG(seed,seed2), literal_cycles>;
194 | };
195 |
196 | template
197 | ITHARE_KSCOPE_FORCEINLINE static constexpr /* only if flags & kscope_flag_is_constexpr */ T final_injection(T x) {
198 | ITHARE_KSCOPE_DECLAREPRNG_INFUNC seedc = ITHARE_KSCOPE_COMBINED_PRNG(seed,seed2);
199 | return WhichType::template final_injection(x);
200 | }
201 | template
202 | ITHARE_KSCOPE_FORCEINLINE static constexpr /* only if flags & kscope_flag_is_constexpr */ T final_surjection(T y) {
203 | ITHARE_KSCOPE_DECLAREPRNG_INFUNC seedc = ITHARE_KSCOPE_COMBINED_PRNG(seed,seed2);
204 | return WhichType::template final_surjection(y);
205 | }
206 |
207 | public:
208 | #ifdef ITHARE_KSCOPE_DBG_ENABLE_DBGPRINT
209 | static void dbg_print(size_t offset = 0, const char* prefix = "") {
210 | size_t dbgWhich = kscope_random_choice_from_list(cycles, Descr::descr);
211 | std::cout << std::string(offset, ' ') << prefix << "KscopeExtensibleLiteralContext() << "," << kscope_dbg_print_seed() << "," << cycles << ">: which=" << which << " dbgWhich=" << dbgWhich << std::endl;
212 | WhichType::dbg_print(offset + 1);
213 | }
214 | #endif
215 | };
216 |
217 | }} //namespace ithare::kscope
218 |
219 | #endif //ITHARE_KSCOPE_SEED
220 |
221 | #endif //ithare_kscope_context_h_included
222 |
--------------------------------------------------------------------------------
/src/impl/kscope_literal.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (c) 2018, ITHare.com
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
31 | */
32 |
33 | #ifndef ithare_kscope_literal_h_included
34 | #define ithare_kscope_literal_h_included
35 |
36 | //NOT intended to be #included directly
37 | // #include ../kscope.h instead
38 |
39 | #include "kscope_common.h"
40 | #include "kscope_prng.h"
41 |
42 | //NB: principles for cross-platform kaleidoscopes, laid out in kscope_injection.h, _seem_ to be UNNECESSARY for literals
43 | // Current implementation still complies with them, but it _seems_ that if necessary, we can ignore them for literals
44 |
45 | #ifdef ITHARE_KSCOPE_SEED
46 |
47 | namespace ithare {
48 | namespace kscope {
49 |
50 | //KscopeLiteralContext
51 | template
52 | struct KscopeLiteralContextVersion;
53 | //forward declaration:
54 | template
55 | class KscopeLiteralContext;
56 |
57 | //version 0: identity
58 | struct KscopeLiteralContextVersion0Descr {
59 | static constexpr KscopeDescriptor descr = KscopeDescriptor(0, 1,KscopeDescriptor::flag_is_last_resort);
60 | };
61 |
62 | template
63 | struct KscopeLiteralContextVersion<0,T,seed> {
64 | using Traits = KscopeTraits;
65 | constexpr static KSCOPECYCLES context_cycles = KscopeLiteralContextVersion0Descr::descr.min_cycles;
66 |
67 | template
68 | ITHARE_KSCOPE_FORCEINLINE static constexpr T final_injection(T x) {
69 | return x;
70 | }
71 | template
72 | ITHARE_KSCOPE_FORCEINLINE static constexpr T final_surjection(T y) {
73 | return y;
74 | }
75 |
76 | #ifdef ITHARE_KSCOPE_DBG_ENABLE_DBGPRINT
77 | static void dbg_print(size_t offset = 0, const char* prefix = "") {
78 | std::cout << std::string(offset, ' ') << prefix << "KscopeLiteralContextVersion<0/*identity*/," << kscope_dbg_print_t() << ">" << std::endl;
79 | }
80 | #endif
81 | };
82 |
83 | //version 1: global volatile constant
84 | struct KscopeLiteralContextVersion1Descr {
85 | static constexpr KscopeDescriptor descr = KscopeDescriptor(6, 100);
86 | };
87 |
88 | template
89 | struct KscopeLiteralContextVersion<1,T,seed> {
90 | using Traits = KscopeTraits;
91 | constexpr static KSCOPECYCLES context_cycles = KscopeLiteralContextVersion1Descr::descr.min_cycles;
92 |
93 | constexpr static T CC = kscope_random_const();
94 | template
95 | ITHARE_KSCOPE_FORCEINLINE static constexpr T final_injection(T x) {
96 | return x + CC;
97 | }
98 | template
99 | ITHARE_KSCOPE_FORCEINLINE static constexpr /* only if flags & kscope_flag_is_constexpr */ T final_surjection(T y) {
100 | if constexpr(flags&kscope_flag_is_constexpr)
101 | return y - CC;
102 | else
103 | return y - T(c);
104 | }
105 |
106 | #ifdef ITHARE_KSCOPE_DBG_ENABLE_DBGPRINT
107 | static void dbg_print(size_t offset = 0, const char* prefix = "") {
108 | std::cout << std::string(offset, ' ') << prefix << "KscopeLiteralContextVersion<1/*global volatile*/," << kscope_dbg_print_t() << "," << kscope_dbg_print_seed() << ">: CC=" << kscope_dbg_print_c(CC) << std::endl;
109 | }
110 | #endif
111 | private:
112 | static volatile T c;
113 | };
114 |
115 | template
116 | volatile T KscopeLiteralContextVersion<1, T, seed>::c = CC;
117 |
118 | } //namespace kscope
119 | } //namespace ithare
120 |
121 | #define ITHARE_KSCOPE_STOCK_LITERAL_DESCRIPTOR_LIST \
122 | KscopeLiteralContextVersion0Descr::descr,\
123 | KscopeLiteralContextVersion1Descr::descr,
124 |
125 | #define ITHARE_KSCOPE_LAST_STOCK_LITERAL 1
126 |
127 | #endif //ITHARE_KSCOPE_SEED
128 |
129 | #endif //ithare_kscope_literal_h_included
130 |
--------------------------------------------------------------------------------
/src/impl/kscope_prng.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Copyright (c) 2018, ITHare.com
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
31 | */
32 |
33 | #ifndef ithare_kscope_prng_h_included
34 | #define ithare_kscope_prng_h_included
35 |
36 | //NOT intended to be #included directly
37 | // #include ../kscope.h instead
38 |
39 | //kscope_prng.h
40 | // Compile-time pseudo-random generation from seeds
41 |
42 | #include
43 | #include "kscope_common.h"
44 |
45 | #ifdef ITHARE_KSCOPE_SEED
46 |
47 | #define ITHARE_KSCOPE_UINT64C(c) UINT64_C(c)//to avoid issues with Clang when trying to UINT64_C(MACRO)
48 |
49 | namespace ithare {
50 | namespace kscope {
51 | constexpr uint64_t kscope_global_seed = ITHARE_KSCOPE_UINT64C(ITHARE_KSCOPE_SEED);
52 | constexpr uint64_t kscope_global_seed2 = ITHARE_KSCOPE_UINT64C(ITHARE_KSCOPE_SEED2);
53 |
54 | constexpr uint64_t kscope_const_random0[] = {
55 | UINT64_C(0x4d97'89b5'e76f'c505), UINT64_C(0xac1e'21fb'6594'ce31), UINT64_C(0xbc9e'7c29'054a'beb5), UINT64_C(0x418c'3b82'd2d8'a0db),
56 | UINT64_C(0x9220'9ecf'b9b7'cb70), UINT64_C(0xfaca'eca7'6bf3'c919), UINT64_C(0x7379'36be'7574'654a), UINT64_C(0x4205'd596'48bc'd330),
57 | UINT64_C(0xf2aa'35c8'c670'b1a2), UINT64_C(0xeef5'9ef8'28d8'fed2), UINT64_C(0x8d86'2109'a268'8a6b), UINT64_C(0x535d'2930'052b'7ab5),
58 | UINT64_C(0x7f79'42d6'cffd'21a7), UINT64_C(0x8f18'3618'68b2'c1ac), UINT64_C(0x69da'cd1c'a7fd'549a), UINT64_C(0x9345'341d'e34a'81e0),
59 | UINT64_C(0x5344'84d5'2a07'c80c), UINT64_C(0xee2d'ef87'6dde'1d20), UINT64_C(0x43d0'3cc3'39ae'deea), UINT64_C(0xf2f3'dbac'698d'b760)
60 |
61 | };/*from random.org*/
62 | constexpr uint64_t kscope_const_random1[] = {
63 | UINT64_C(0x30c9'c242'c935'61e2), UINT64_C(0xd529'3193'1e57'0a40), UINT64_C(0xd01d'41d1'142c'e938), UINT64_C(0x327b'2d31'2760'1f6b),
64 | UINT64_C(0x463b'ef56'47cb'121a), UINT64_C(0xb657'76c9'8087'3d61), UINT64_C(0x63e8'7a37'88c7'03b4), UINT64_C(0xd648'095c'c6f6'5473),
65 | UINT64_C(0xba02'be98'd2e6'4836), UINT64_C(0x6b2b'e8ab'f44c'2af3), UINT64_C(0x971c'4f88'0d7d'd7a5), UINT64_C(0xe728'ed94'3c0e'9724),
66 | UINT64_C(0xed42'd3d0'44cf'a1cc), UINT64_C(0xb333'dc8d'6f58'1f30), UINT64_C(0x2700'b0b7'ad09'32eb), UINT64_C(0xa431'c3be'c084'4f3c),
67 | UINT64_C(0xf11b'114c'eaab'76ed), UINT64_C(0xf387'892d'f0d6'9be2), UINT64_C(0x8078'e911'2775'9316), UINT64_C(0xce72'fb19'76fc'6ffe)
68 | };/*from random.org*/
69 |
70 | constexpr const char* kscope_normalize_fname(const char* file) {
71 | //normalizing __FILE__ to the bare file name (without path, which does change between debug/release)
72 | const char* ret = file;
73 | for (const char *p = file; *p; ++p)
74 | if (*p == '/' || *p == '\\')
75 | ret = p + 1;
76 | return ret;
77 | }
78 |
79 | #ifndef ITHARE_KSCOPE_CRYPTO_PRNG//CRYPTO PRNG slows down compile but uses 128-bit crypto-grade PRNGs
80 |
81 |
82 | constexpr uint64_t kscope_murmurhash2(uint64_t u, uint64_t seed) {
83 | //adapted to 64-bit-only input from https://sites.google.com/site/murmurhash/MurmurHash2_64.cpp
84 | const int len = 8;
85 | const uint64_t m = 0xc6a4'a793'5bd1'e995;
86 | const int r = 47;
87 |
88 | uint64_t h = seed ^ (len * m);
89 |
90 | //was loop in original, but we don't need loop here
91 | uint64_t k = u;
92 |
93 | k *= m;
94 | k ^= k >> r;
95 | k *= m;
96 |
97 | h ^= k;
98 | h *= m;
99 | //end of loop-in-original
100 |
101 | h ^= h >> r;
102 | h *= m;
103 | h ^= h >> r;
104 |
105 | return h;
106 | }
107 | constexpr uint64_t kscope_ranhash(uint64_t u) {
108 | //ranhash from Numerical Recipes
109 | uint64_t v = u * UINT64_C(3935559000370003845) + UINT64_C(2691343689449507681);
110 | v ^= v >> 21; v ^= v << 37; v ^= v >> 4;
111 | v *= UINT64_C(4768777513237032717);
112 | v ^= v << 20; v ^= v >> 41; v ^= v << 5;
113 | return v;
114 | }
115 | constexpr size_t kscope_random(uint64_t seed, uint32_t modifier, size_t maxn) {
116 | //for maxn < 1M, bias is limited to <0.1% - more than enough for our purposes
117 | assert(maxn > 0);
118 | assert(maxn < 1'048'576);//limiting bits to 20 and bias to <0.1%
119 | // if REALLY necessary - can raise the limit at the cost of increased bias
120 |
121 | assert(modifier < sizeof(kscope_const_random0) / sizeof(uint64_t));//if necessary - add more random data to kscope_const_random0
122 | uint64_t u = kscope_const_random0[modifier] ^ seed;
123 | uint64_t v = kscope_ranhash(u);
124 | return v % maxn;
125 | }
126 | static constexpr size_t kscope_const_nrandom0 = sizeof(kscope_const_random0) / sizeof(uint64_t);
127 | constexpr uint32_t kscope_random_uint32(uint64_t seed, uint32_t modifier) {
128 | uint64_t init = 0;
129 | if(modifier >= kscope_const_nrandom0) {
130 | init ^= kscope_const_random0[kscope_const_nrandom0-1];
131 | modifier -= kscope_const_nrandom0;
132 | assert(modifier
187 | std::string kscope_dbg_print_seed() {
188 | return std::to_string(seed);
189 | }
190 | #endif
191 | #else
192 | //XXTEA as a PLACEHOLDER for real crypto; TODO - replace with a serious cryptography
193 |
194 | #define ITHARE_KSCOPE_XXTEA_MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))
195 | constexpr KscopeArrayWrapper kscope_xxtea_encipher(std::pair v0, const uint32_t key[4]) {
196 | //TODO: validate implementation
197 | constexpr uint32_t DELTA = 0x9e3779b9;
198 | unsigned n = 4;
199 | unsigned rounds = 6 + 52 / n;
200 | KscopeArrayWrapper v{ { uint32_t(v0.first), uint32_t(v0.first >> 32), uint32_t(v0.second), uint32_t(v0.second >> 32) } };
201 | uint32_t y = 0, z = 0, sum = 0;
202 | unsigned p = 0, e = 0;
203 | sum = 0;
204 | z = v.arr[n - 1];
205 | do {
206 | sum += DELTA;
207 | e = (sum >> 2) & 3;
208 | for (p = 0; p < n - 1; p++) {
209 | y = v.arr[p + 1];
210 | z = v.arr[p] = v.arr[p] + ITHARE_KSCOPE_XXTEA_MX;
211 | }
212 | y = v.arr[0];
213 | z = v.arr[n - 1] = v.arr[n - 1] + ITHARE_KSCOPE_XXTEA_MX;
214 | } while (--rounds);
215 |
216 | return v;
217 | }
218 | #undef ITHARE_KSCOPE_XXTEA_MX
219 |
220 | template
221 | struct KscopeSeed {
222 | static constexpr uint64_t lo = lo_;
223 | static constexpr uint64_t hi = hi_;
224 | static constexpr int depth = depth_;
225 | };
226 | //TODO: generate ALL the keys (for_random, for_init, and a hundred of keys for different depths) from an externally-provided-seed...
227 | constexpr uint32_t kscope_prng_xxtea_key_for_init[4] = {
228 | UINT32_C(0xf4f8'a649), UINT32_C(0xa77a'ee49), UINT32_C(0xfbdb'8ec9), UINT32_C(0x380b'2725)
229 | };//from random.org
230 | constexpr uint32_t kscope_prng_xxtea_key_for_random[4] = {
231 | UINT32_C(0x1fa3'669f), UINT32_C(0x7cf5'7cf9), UINT32_C(0x7df5'4887), UINT32_C(0x9c92'd8d5)
232 | };//from random.org
233 | constexpr uint32_t kscope_prng_xxtea_key0[4] = {
234 | UINT32_C(0xa0d7'9b06), UINT32_C(0x29da'2659), UINT32_C(0x3b70'20ec), UINT32_C(0xa3ff'52fb)
235 | };//from random.org
236 | constexpr std::pair kscope_new_prng(uint64_t lo, uint64_t hi, uint32_t modifier) {
237 | assert(modifier < sizeof(kscope_const_random0) / sizeof(uint64_t));//if necessary - add more random data to kscope_const_random0
238 | //using block cipher (currently XXTEA) in CTR mode
239 | assert(modifier < sizeof(kscope_const_random1) / sizeof(uint64_t));//if necessary - add more random data to kscope_const_random0
240 | //using block cipher (currently XXTEA) in CTR mode
241 |
242 | uint64_t l = lo ^ kscope_const_random0[modifier];
243 | uint64_t h = hi ^ kscope_const_random1[modifier];
244 | std::pair ctr_block = { l ^ kscope_global_seed,h ^kscope_global_seed2 };
245 | //TODO: use different keys for different 'depth'
246 | KscopeArrayWrapper v = kscope_xxtea_encipher(ctr_block, kscope_prng_xxtea_key0);
247 |
248 | uint64_t rlo = (uint64_t(v.arr[1]) << 32) | uint64_t(v.arr[0]);
249 | uint64_t rhi = (uint64_t(v.arr[3]) << 32) | uint64_t(v.arr[2]);
250 | return std::pair