├── .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(rlo, rhi); 251 | } 252 | constexpr size_t kscope_random(uint64_t lo, uint64_t hi, uint32_t modifier, size_t maxn) { 253 | //for maxn < 1M, bias is limited to <0.1% - more than enough for our purposes 254 | assert(maxn > 0); 255 | assert(maxn < 1'048'576);//limiting bits to 20 and bias to <0.1% 256 | // if REALLY necessary - can raise the limit at the cost of increased bias 257 | 258 | assert(modifier < sizeof(kscope_const_random0) / sizeof(uint64_t));//if necessary - add more random data to kscope_const_random0 259 | //using block cipher (currently XXTEA) in CTR mode 260 | assert(modifier < sizeof(kscope_const_random1) / sizeof(uint64_t));//if necessary - add more random data to kscope_const_random0 261 | //using block cipher (currently XXTEA) in CTR mode 262 | 263 | uint64_t l = lo ^ kscope_const_random1[modifier];//TODO: add random 2/3 264 | uint64_t h = hi ^ kscope_const_random0[modifier]; 265 | 266 | std::pair ctr_block = { l ^ kscope_global_seed,h ^kscope_global_seed2 }; 267 | KscopeArrayWrapper v = kscope_xxtea_encipher(ctr_block, kscope_prng_xxtea_key_for_random); 268 | uint64_t rlo = (uint64_t(v.arr[1]) << 32) | uint64_t(v.arr[0]); 269 | return rlo % maxn; 270 | } 271 | constexpr uint32_t kscope_random_uint32(uint64_t lo, uint64_t hi, uint32_t modifier) { 272 | assert(modifier < sizeof(kscope_const_random0) / sizeof(uint64_t));//if necessary - add more random data to kscope_const_random0 273 | //using block cipher (currently XXTEA) in CTR mode 274 | assert(modifier < sizeof(kscope_const_random1) / sizeof(uint64_t));//if necessary - add more random data to kscope_const_random0 275 | //using block cipher (currently XXTEA) in CTR mode 276 | 277 | uint64_t l = lo ^ kscope_const_random1[modifier];//TODO: add random 2/3 278 | uint64_t h = hi ^ kscope_const_random0[modifier]; 279 | 280 | std::pair ctr_block = { l ^ kscope_global_seed,h ^kscope_global_seed2 }; 281 | KscopeArrayWrapper v = kscope_xxtea_encipher(ctr_block, kscope_prng_xxtea_key_for_random); 282 | uint64_t rlo = (uint64_t(v.arr[1]) << 32) | uint64_t(v.arr[0]); 283 | return uint32_t(rlo); 284 | } 285 | constexpr std::pair kscope_init_prng(const char* file, int line, int counter) { 286 | uint64_t v0 = line; 287 | #ifdef ITHARE_KSCOPE_CONSISTENT_XPLATFORM_IMPLICIT_SEEDS 288 | const char* filename = kscope_normalize_fname(file); 289 | #else//!CONSISTENT 290 | v0 ^= counter; 291 | const char* filename = file; 292 | #endif 293 | uint64_t u = kscope_string_hash(filename); 294 | std::pair ctr_block = { u ^ kscope_global_seed,v0 ^kscope_global_seed2 }; 295 | KscopeArrayWrapper v = kscope_xxtea_encipher(ctr_block, kscope_prng_xxtea_key_for_init); 296 | uint64_t rlo = (uint64_t(v.arr[1]) << 32) | uint64_t(v.arr[0]); 297 | uint64_t rhi = (uint64_t(v.arr[3]) << 32) | uint64_t(v.arr[2]); 298 | return std::pair(rlo, rhi); 299 | } 300 | constexpr std::pair kscope_init_prng_gcc_workaround(int line, int counter) { 301 | uint64_t v0 = line; 302 | #ifdef ITHARE_KSCOPE_CONSISTENT_XPLATFORM_IMPLICIT_SEEDS 303 | #else//!CONSISTENT 304 | v0 ^= counter; 305 | #endif 306 | uint64_t u = 0; 307 | std::pair ctr_block = { u ^ kscope_global_seed,v0 ^kscope_global_seed2 }; 308 | KscopeArrayWrapper v = kscope_xxtea_encipher(ctr_block, kscope_prng_xxtea_key_for_init); 309 | uint64_t rlo = (uint64_t(v.arr[1]) << 32) | uint64_t(v.arr[0]); 310 | uint64_t rhi = (uint64_t(v.arr[3]) << 32) | uint64_t(v.arr[2]); 311 | return std::pair(rlo, rhi); 312 | } 313 | constexpr std::pair kscope_combined_prng(uint64_t lo, uint64_t hi, uint64_t lo2, uint64_t hi2) { 314 | uint64_t l = lo ^ hi2;//why not? 315 | uint64_t h = hi ^ lo2; 316 | std::pair ctr_block = { l ^ kscope_global_seed,h ^kscope_global_seed2 }; 317 | //TODO: use different keys for different 'depth' 318 | KscopeArrayWrapper v = kscope_xxtea_encipher(ctr_block, kscope_prng_xxtea_key0); 319 | 320 | uint64_t rlo = (uint64_t(v.arr[1]) << 32) | uint64_t(v.arr[0]); 321 | uint64_t rhi = (uint64_t(v.arr[3]) << 32) | uint64_t(v.arr[2]); 322 | return std::pair(rlo, rhi); 323 | } 324 | #define ITHARE_KSCOPE_SEEDTPARAM class /* sic! */ 325 | #define ITHARE_KSCOPE_DUMMYSEED ithare::kscope::KscopeSeed<0,0,-1> 326 | #define ITHARE_KSCOPE_DECLAREPRNG using /* don't ask ;-) */ 327 | #define ITHARE_KSCOPE_DECLAREPRNG_INFUNC using 328 | #define ITHARE_KSCOPE_INIT_PRNG(file,line,counter) ithare::kscope::KscopeSeed 329 | #define ITHARE_KSCOPE_NEW_PRNG(prng,modifier) ithare::kscope::KscopeSeed 330 | #define ITHARE_KSCOPE_COMBINED_PRNG(prng,prng2) ithare::kscope::KscopeSeed 331 | #if defined(ITHARE_KSCOPE_WORKAROUND_FOR_MSVC_BUG_196900) || defined(ITHARE_KSCOPE_CONSISTENT_XPLATFORM_IMPLICIT_SEEDS) 332 | //https://developercommunity.visualstudio.com/content/problem/196885/c1001-in-fddvctoolscompilercxxfeslp1cwalkcpp-line.html //MSVC doesn't like 'too complicated' stuff (what it does accept, was found experimentally) 333 | //as soon as the bug is fixed, the whole #if branch can be removed 334 | 335 | #define ITHARE_KSCOPE_INIT_COMBINED_PRNG(prng2,file,line,counter) ithare::kscope::KscopeSeed //HAVE to use gcc_workaround to cover CONSISTENT_XPLATFORM case 336 | 337 | #ifdef _MSC_VER 338 | #pragma message("SERIOUS DEGRADATION: NO DEPENDENCY ON prng2 in ITHARE_KSCOPE_INIT_COMBINED_PRNG(). Fix depends on https://developercommunity.visualstudio.com/content/problem/196900/c1001-in-file-msc1cpp-line-1507.html. Meanwhile, you may want to avoid using ITHARE_KSCOPE_CRYPTO_PRNG under MSVC.") 339 | #else 340 | #pragma message "SERIOUS DEGRADATION: NO DEPENDENCY ON prng2 in ITHARE_KSCOPE_INIT_COMBINED_PRNG(). Problem is due to a bug in MSVC, and will go away if NOT using ITHARE_KSCOPE_CONSISTENT_XPLATFORM_IMPLICIT_SEEDS, or ITHARE_KSCOPE_CRYPTO_PRNG" 341 | #endif 342 | 343 | #elif defined(ITHARE_KSCOPE_WORKAROUND_FOR_GCC_BUG_47488) 344 | //https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47488 ; GCC doesn't like using __FILE__ literal in this context... 345 | // as soon as the bug is fixed, the whole #elif branch is to be removed 346 | 347 | #define ITHARE_KSCOPE_INIT_PRNG_WORKAROUND(file,line,counter) ithare::kscope::KscopeSeed 348 | #define ITHARE_KSCOPE_INIT_COMBINED_PRNG(prng2,file,line,counter) ITHARE_KSCOPE_COMBINED_PRNG(prng2,ITHARE_KSCOPE_INIT_PRNG_WORKAROUND(file,line,counter)) 349 | 350 | #pragma message "MINOR DEGRADATION: __FILE__ is not used in ITHARE_KSCOPE_INIT_COMBINED_PRNG(). Problem is due to a bug in GCC, but is hopefully not TOO bad" 351 | 352 | #else//!CONSISTENT_XPLATFORM && !MSVC_BUG && !GCC_BUG 353 | 354 | #define ITHARE_KSCOPE_INIT_COMBINED_PRNG(prng2,file,line,counter) ITHARE_KSCOPE_COMBINED_PRNG(ITHARE_KSCOPE_INIT_PRNG(file,line,counter),prng2) 355 | #endif 356 | #define ITHARE_KSCOPE_RANDOM(prng,modifier,maxn) ithare::kscope::kscope_random(prng::lo,prng::hi,modifier,maxn) 357 | #define ITHARE_KSCOPE_RANDOM_UINT32(prng,modifier) ithare::kscope::kscope_random_uint32(prng::lo,prng::hi,modifier) 358 | #define ITHARE_KSCOPE_DUMMY_PRNG KscopeSeed<0,0,0> 359 | #ifdef ITHARE_KSCOPE_DBG_ENABLE_DBGPRINT 360 | //dbg_print helpers 361 | template 362 | std::string kscope_dbg_print_seed() { 363 | return std::string("<") + std::to_string(seed::lo) + "," + std::to_string(seed::hi) + ">"; 364 | } 365 | #endif 366 | 367 | #endif//ITHARE_KSCOPE_CRYPTO_PRNG 368 | }//namespace kscope 369 | }//namespace ithare 370 | 371 | #endif//ITHARE_KSCOPE_SEED 372 | 373 | #endif//#ifndef ithare_kscope_prng_h_included 374 | 375 | -------------------------------------------------------------------------------- /src/kscope_sample_extension.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_kscope_sample_extension_h_included 34 | #define ithare_kscope_kscope_sample_extension_h_included 35 | 36 | #ifdef ithare_kscope_kscope_h_included 37 | #error IF using kscope_sample_extension, it MUST be included BEFORE kscope.h. See test/officialtest.cpp for usage example 38 | #endif 39 | 40 | #include "impl/kscope_injection.h" 41 | 42 | #ifdef ITHARE_KSCOPE_SEED 43 | 44 | namespace ithare { namespace kscope { 45 | 46 | //version last+1 (="additional1"): rotl (using intrinsic, or asm, or non-intrinsic for surjection) 47 | //is a 'simple' injection, which uses KscopeSimpleInjectionHelper for cycle arithmetics (for less trivial examples with multiple dependent injections - you may need to look into impl/kscope_injection.h) 48 | template 49 | struct KscopeInjectionAdditionalVersion1Descr { 50 | using Traits = KscopeTraits; 51 | static constexpr KSCOPECYCLES own_min_injection_cycles = 1;//estimate in CPU cycles 52 | static constexpr KSCOPECYCLES own_min_surjection_cycles = 1;//estimate in CPU cycles 53 | static constexpr KSCOPECYCLES own_min_cycles = KscopeSimpleInjectionHelper::descriptor_own_min_cycles(own_min_injection_cycles,own_min_surjection_cycles); 54 | static constexpr KscopeDescriptor descr = Traits::is_bit_based // for this rotl injection, we DON'T want to deal with types-which-are-not-power-of-2; however, by requiring only Traits::is_bit_based we still have to deal with KscopeBitUint<> as our T; IF this is undesirable (and you want to restrict yourself only to uint8_t..uint64_t - check for Traits::is_built_in instead) 55 | && Traits::nbits > 1 ? //single-bit ones are not so interesting to rotate (and will cause trouble with our naive random generation attempts) 56 | KscopeDescriptor(own_min_cycles, 100)//'100' is a 'relative weight' of this injection; increase to use this injection more; kscope stock non-trivial injections have weight of '100' 57 | : KscopeDescriptor(nullptr);//an indicator NOT to use this injection 58 | }; 59 | 60 | template 61 | class KscopeInjectionVersion { 62 | //use '+2' etc. for subsequent injections 63 | using Traits = KscopeTraits; 64 | static_assert(Traits::nbits>1); 65 | public: 66 | 67 | struct RecursiveInjectionRequirements : public InjectionRequirements { 68 | static constexpr size_t exclude_version = ITHARE_KSCOPE_LAST_STOCK_INJECTION+1;//prevents _immediate_ RecursiveInjection from being ITHARE_KSCOPE_LAST_STOCK_INJECTION+1 (in practice - Good Thing(tm) unless you want long-chains-consisting-of-the-same-injection-over-and-over). If this is undesirable - assign size_t(-1) instead. 69 | }; 70 | 71 | constexpr static KSCOPECYCLES recursive_injection_cycles = KscopeSimpleInjectionHelper::recursive_injection_cycles(cycles,KscopeInjectionAdditionalVersion1Descr::own_min_cycles); 72 | using RecursiveInjection = KscopeInjection; 73 | using return_type = typename RecursiveInjection::return_type;//does NOT have to (but MAY) coincide with T 74 | constexpr static size_t SHIFT = //having SHIFT as size_t helps to deal with shifts in KscopeBitUint<> 75 | Context::template random_const< 76 | typename kscope_normalized_unsigned_integral_type::type /*MUST be one of uint*_t types, OR T; having it as non-normalized size_t will fail for those compilers where size_t is not 'the same' as _any_ of uint*_t (which MAY happen)*/ 77 | ,ITHARE_KSCOPE_NEW_PRNG(seed, 2),kscope_const_one_ok>(Traits::nbits); 78 | 79 | static_assert(SHIFT > 0); 80 | static_assert(SHIFT < Traits::nbits); 81 | 82 | //this is the REAL essence of our injection 83 | template 84 | ITHARE_KSCOPE_FORCEINLINE constexpr static T local_injection(T x) { 85 | return (x << SHIFT) | (x >> (Traits::nbits - SHIFT)); 86 | } 87 | #ifdef __GNUC__ //including __clang__ 88 | //NB: I do NOT claim asm below is optimal (it is irrelevant) 89 | // in particular, it maybe easily over-constrained (my knowledge of constraints is unfortunately very limited) 90 | // Heck, it can even have bugs-which-didn't-manifest-themselves-yet even under severe injection-based testing (I don't think so, but with __asm__ you can never be 100% sure :-( ) 91 | // What is important, is that using asm within kscope injection IS one way to TEST ASM CORRECTNESS (including constraints) 92 | #if defined(__i386__) || defined(__x86_64__) 93 | ITHARE_KSCOPE_FORCEINLINE static uint32_t rotr32(uint32_t x) { 94 | uint8_t sh = SHIFT; 95 | __asm__ ("rorl %1,%0" : "+r" (x) : "c" (sh) : "cc"); 96 | return x; 97 | } 98 | #endif 99 | #ifdef __x86_64__ 100 | ITHARE_KSCOPE_FORCEINLINE static uint64_t rotr64(uint64_t x) { 101 | uint8_t sh = SHIFT; 102 | __asm__ ("rorq %1,%0" : "+r" (x) : "c" (sh) : "cc"); 103 | return x; 104 | } 105 | #endif 106 | #endif 107 | template 108 | ITHARE_KSCOPE_FORCEINLINE constexpr static T local_surjection(T y) { 109 | if constexpr(flags&kscope_flag_is_constexpr) 110 | return (y >> SHIFT) | (y << (Traits::nbits - SHIFT)); 111 | else { 112 | #ifdef __GNUC__ //including __clang__ 113 | #if defined(__i386__) || defined(__x86_64__) 114 | if constexpr(Traits::nbits == 32) { 115 | return rotr32(y); 116 | } 117 | #endif 118 | #ifdef __x86_64__ 119 | if constexpr(Traits::nbits == 64) { 120 | return rotr64(y); 121 | } 122 | #endif 123 | #elif defined (_MSC_VER) 124 | if constexpr(Traits::nbits == 32) { 125 | return _rotr(y,SHIFT); 126 | } 127 | if constexpr(Traits::nbits == 64) { 128 | return _rotr64(y,SHIFT); 129 | } 130 | #endif 131 | return (y >> SHIFT) | (y << (Traits::nbits - SHIFT)); 132 | } 133 | } 134 | 135 | //some boilerplate stuff (NB: it is boilerplate only for trivial cases like our one) 136 | template 137 | ITHARE_KSCOPE_FORCEINLINE constexpr static return_type injection(T x) { 138 | ITHARE_KSCOPE_DECLAREPRNG_INFUNC seedc = ITHARE_KSCOPE_COMBINED_PRNG(seed, seed2); 139 | T y = local_injection(x); 140 | ITHARE_KSCOPE_DBG_ASSERT_SURJECTION_LOCAL("<1>", x, y); 141 | 142 | return_type ret = RecursiveInjection::template injection(y); 143 | return ret; 144 | } 145 | template 146 | ITHARE_KSCOPE_FORCEINLINE constexpr static T surjection(return_type y) { 147 | ITHARE_KSCOPE_DECLAREPRNG_INFUNC seedc = ITHARE_KSCOPE_COMBINED_PRNG(seed,seed2); 148 | T yy0 = RecursiveInjection::template surjection(y); 149 | return local_surjection(yy0); 150 | } 151 | 152 | static constexpr KSCOPEINJECTIONCAPS injection_caps = 0;//look for non-0 examples in impl/kscope_injection, IF you want to enable "shortcuts" 153 | 154 | #ifdef ITHARE_KSCOPE_DBG_ENABLE_DBGPRINT 155 | static void dbg_print(size_t offset = 0, const char* prefix = "") { 156 | std::cout << std::string(offset, ' ') << prefix << "KscopeInjectionVersion() << "," << kscope_dbg_print_seed() << "," << cycles << ">: nbits=" << Traits::nbits << " SHIFT=" << SHIFT << std::endl; 157 | RecursiveInjection::dbg_print(offset + 1); 158 | } 159 | #endif 160 | }; 161 | 162 | //More injections can go here (numbered ITHARE_KSCOPE_LAST_STOCK_INJECTION+2, ITHARE_KSCOPE_LAST_STOCK_INJECTION+3, ...) 163 | // DON'T forget to add their descriptors to ITHARE_KSCOPE_ADDITIONAL_INJECTION_DESCRIPTOR_LIST below 164 | 165 | }} //namespace ithare::kscope 166 | 167 | #define ITHARE_KSCOPE_ADDITIONAL_INJECTION_DESCRIPTOR_LIST \ 168 | KscopeInjectionAdditionalVersion1Descr::descr, 169 | 170 | #endif //ITHARE_KSCOPE_SEED 171 | 172 | #endif // ithare_kscope_kscope_sample_extension_h_included 173 | -------------------------------------------------------------------------------- /test/chachatest.cpp: -------------------------------------------------------------------------------- 1 | //ithare::kscope chachatest.cpp 2 | // adapted from tests/chachatest.c from LibreSSL 2.6.4 3 | 4 | #include "lest.hpp" 5 | #ifdef ITHARE_KSCOPE_TEST_EXTENSION 6 | #include ITHARE_KSCOPE_TEST_EXTENSION //MUST go BEFORE ../src/kscope.h 7 | #endif 8 | //NB: normally, in your own files you should use simple #include "your_extension.h", 9 | // #include MACRO above is to allow using the same test .cpp with external extensions 10 | 11 | #include "../src/kscope.h" 12 | #include "../kaleidoscoped/ssl/crypto/chacha/chacha.h" 13 | #include "../kaleidoscoped/nostd.h" 14 | 15 | #include "test.h" 16 | 17 | /* 18 | * Copyright (c) 2014 Joel Sing 19 | * 20 | * Permission to use, copy, modify, and distribute this software for any 21 | * purpose with or without fee is hereby granted, provided that the above 22 | * copyright notice and this permission notice appear in all copies. 23 | * 24 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 25 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 26 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 27 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 28 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 29 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 30 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 31 | */ 32 | 33 | struct chacha_tv { 34 | const char *desc; 35 | const uint8_t key[32]; 36 | const uint8_t iv[8]; 37 | const size_t len; 38 | const unsigned char out[512]; 39 | }; 40 | 41 | /* 42 | * Test vectors from: 43 | * http://tools.ietf.org/html/draft-strombergson-chacha-test-vectors-01 44 | */ 45 | constexpr chacha_tv chacha_test_vectors[] = { 46 | { 47 | "TC1: All zero key and IV", 48 | { 49 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 50 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 51 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 52 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 53 | }, 54 | { 55 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 56 | }, 57 | 64, 58 | { 59 | 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, 60 | 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28, 61 | 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, 62 | 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, 63 | 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d, 64 | 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, 65 | 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c, 66 | 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86, 67 | }, 68 | }, 69 | { 70 | "TC2: Single bit in key set, all zero IV", 71 | { 72 | 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 73 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 74 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 75 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 76 | }, 77 | { 78 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 79 | }, 80 | 64, 81 | { 82 | 0xc5, 0xd3, 0x0a, 0x7c, 0xe1, 0xec, 0x11, 0x93, 83 | 0x78, 0xc8, 0x4f, 0x48, 0x7d, 0x77, 0x5a, 0x85, 84 | 0x42, 0xf1, 0x3e, 0xce, 0x23, 0x8a, 0x94, 0x55, 85 | 0xe8, 0x22, 0x9e, 0x88, 0x8d, 0xe8, 0x5b, 0xbd, 86 | 0x29, 0xeb, 0x63, 0xd0, 0xa1, 0x7a, 0x5b, 0x99, 87 | 0x9b, 0x52, 0xda, 0x22, 0xbe, 0x40, 0x23, 0xeb, 88 | 0x07, 0x62, 0x0a, 0x54, 0xf6, 0xfa, 0x6a, 0xd8, 89 | 0x73, 0x7b, 0x71, 0xeb, 0x04, 0x64, 0xda, 0xc0, 90 | }, 91 | }, 92 | { 93 | "TC3: Single bit in IV set, all zero key", 94 | { 95 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 96 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 97 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 98 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 99 | }, 100 | { 101 | 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 102 | }, 103 | 64, 104 | { 105 | 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb, 106 | 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80, 107 | 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac, 108 | 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32, 109 | 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c, 110 | 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54, 111 | 0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d, 112 | 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b 113 | }, 114 | }, 115 | { 116 | "TC4: All bits in key and IV are set", 117 | { 118 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 119 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 120 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 121 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 122 | }, 123 | { 124 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 125 | }, 126 | 64, 127 | { 128 | 0xd9, 0xbf, 0x3f, 0x6b, 0xce, 0x6e, 0xd0, 0xb5, 129 | 0x42, 0x54, 0x55, 0x77, 0x67, 0xfb, 0x57, 0x44, 130 | 0x3d, 0xd4, 0x77, 0x89, 0x11, 0xb6, 0x06, 0x05, 131 | 0x5c, 0x39, 0xcc, 0x25, 0xe6, 0x74, 0xb8, 0x36, 132 | 0x3f, 0xea, 0xbc, 0x57, 0xfd, 0xe5, 0x4f, 0x79, 133 | 0x0c, 0x52, 0xc8, 0xae, 0x43, 0x24, 0x0b, 0x79, 134 | 0xd4, 0x90, 0x42, 0xb7, 0x77, 0xbf, 0xd6, 0xcb, 135 | 0x80, 0xe9, 0x31, 0x27, 0x0b, 0x7f, 0x50, 0xeb, 136 | }, 137 | }, 138 | { 139 | "TC5: Every even bit set in key and IV", 140 | { 141 | 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 142 | 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 143 | 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 144 | 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 145 | }, 146 | { 147 | 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 148 | }, 149 | 64, 150 | { 151 | 0xbe, 0xa9, 0x41, 0x1a, 0xa4, 0x53, 0xc5, 0x43, 152 | 0x4a, 0x5a, 0xe8, 0xc9, 0x28, 0x62, 0xf5, 0x64, 153 | 0x39, 0x68, 0x55, 0xa9, 0xea, 0x6e, 0x22, 0xd6, 154 | 0xd3, 0xb5, 0x0a, 0xe1, 0xb3, 0x66, 0x33, 0x11, 155 | 0xa4, 0xa3, 0x60, 0x6c, 0x67, 0x1d, 0x60, 0x5c, 156 | 0xe1, 0x6c, 0x3a, 0xec, 0xe8, 0xe6, 0x1e, 0xa1, 157 | 0x45, 0xc5, 0x97, 0x75, 0x01, 0x7b, 0xee, 0x2f, 158 | 0xa6, 0xf8, 0x8a, 0xfc, 0x75, 0x80, 0x69, 0xf7, 159 | }, 160 | }, 161 | { 162 | "TC6: Every odd bit set in key and IV", 163 | { 164 | 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 165 | 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 166 | 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 167 | 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 168 | }, 169 | { 170 | 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 171 | }, 172 | 64, 173 | { 174 | 0x9a, 0xa2, 0xa9, 0xf6, 0x56, 0xef, 0xde, 0x5a, 175 | 0xa7, 0x59, 0x1c, 0x5f, 0xed, 0x4b, 0x35, 0xae, 176 | 0xa2, 0x89, 0x5d, 0xec, 0x7c, 0xb4, 0x54, 0x3b, 177 | 0x9e, 0x9f, 0x21, 0xf5, 0xe7, 0xbc, 0xbc, 0xf3, 178 | 0xc4, 0x3c, 0x74, 0x8a, 0x97, 0x08, 0x88, 0xf8, 179 | 0x24, 0x83, 0x93, 0xa0, 0x9d, 0x43, 0xe0, 0xb7, 180 | 0xe1, 0x64, 0xbc, 0x4d, 0x0b, 0x0f, 0xb2, 0x40, 181 | 0xa2, 0xd7, 0x21, 0x15, 0xc4, 0x80, 0x89, 0x06, 182 | }, 183 | }, 184 | { 185 | "TC7: Sequence patterns in key and IV", 186 | { 187 | 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 188 | 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 189 | 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 190 | 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, 191 | }, 192 | { 193 | 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78, 194 | }, 195 | 64, 196 | { 197 | 0x9f, 0xad, 0xf4, 0x09, 0xc0, 0x08, 0x11, 0xd0, 198 | 0x04, 0x31, 0xd6, 0x7e, 0xfb, 0xd8, 0x8f, 0xba, 199 | 0x59, 0x21, 0x8d, 0x5d, 0x67, 0x08, 0xb1, 0xd6, 200 | 0x85, 0x86, 0x3f, 0xab, 0xbb, 0x0e, 0x96, 0x1e, 201 | 0xea, 0x48, 0x0f, 0xd6, 0xfb, 0x53, 0x2b, 0xfd, 202 | 0x49, 0x4b, 0x21, 0x51, 0x01, 0x50, 0x57, 0x42, 203 | 0x3a, 0xb6, 0x0a, 0x63, 0xfe, 0x4f, 0x55, 0xf7, 204 | 0xa2, 0x12, 0xe2, 0x16, 0x7c, 0xca, 0xb9, 0x31, 205 | }, 206 | }, 207 | { 208 | "TC8: key: 'All your base are belong to us!, IV: 'IETF2013'", 209 | { 210 | 0xc4, 0x6e, 0xc1, 0xb1, 0x8c, 0xe8, 0xa8, 0x78, 211 | 0x72, 0x5a, 0x37, 0xe7, 0x80, 0xdf, 0xb7, 0x35, 212 | 0x1f, 0x68, 0xed, 0x2e, 0x19, 0x4c, 0x79, 0xfb, 213 | 0xc6, 0xae, 0xbe, 0xe1, 0xa6, 0x67, 0x97, 0x5d, 214 | }, 215 | { 216 | 0x1a, 0xda, 0x31, 0xd5, 0xcf, 0x68, 0x82, 0x21, 217 | }, 218 | 64, 219 | { 220 | 0xf6, 0x3a, 0x89, 0xb7, 0x5c, 0x22, 0x71, 0xf9, 221 | 0x36, 0x88, 0x16, 0x54, 0x2b, 0xa5, 0x2f, 0x06, 222 | 0xed, 0x49, 0x24, 0x17, 0x92, 0x30, 0x2b, 0x00, 223 | 0xb5, 0xe8, 0xf8, 0x0a, 0xe9, 0xa4, 0x73, 0xaf, 224 | 0xc2, 0x5b, 0x21, 0x8f, 0x51, 0x9a, 0xf0, 0xfd, 225 | 0xd4, 0x06, 0x36, 0x2e, 0x8d, 0x69, 0xde, 0x7f, 226 | 0x54, 0xc6, 0x04, 0xa6, 0xe0, 0x0f, 0x35, 0x3f, 227 | 0x11, 0x0f, 0x77, 0x1b, 0xdc, 0xa8, 0xab, 0x92, 228 | }, 229 | }, 230 | }; 231 | 232 | #define N_VECTORS (sizeof(chacha_test_vectors) / sizeof(*chacha_test_vectors)) 233 | 234 | using namespace ithare::kscope::ssl; 235 | 236 | /* Single-shot ChaCha20 using CRYPTO_chacha_20 interface. */ 237 | static void 238 | crypto_chacha_20_test(const chacha_tv* tv, uint8_t* out0, uint8_t* in0) 239 | { 240 | assert(tv->len <= 64); 241 | //auto in = ITHARE_KSCOPE_INT_ARR_TO_KSCOPE_INT3X(64,in0,tv->len); 242 | //ITHARE_KSCOPE_INT3(uint8_t) out[64]; 243 | //auto key = ITHARE_KSCOPE_INT_ARR_TO_KSCOPE_INT3(tv->key); 244 | //auto iv = ITHARE_KSCOPE_INT_ARR_TO_KSCOPE_INT3(tv->iv); 245 | ITHARE_KSCOPE_CALL3(CRYPTO_chacha_20)(out0, in0, tv->len, tv->key, tv->iv, 0); 246 | //ithare::kscope::kscope_copyarr(out0,out,tv->len); 247 | } 248 | 249 | static void 250 | constexpr crypto_chacha_20_test_compile_time(const chacha_tv* tv, [[maybe_unused]] const uint8_t* expected_out, const uint8_t* in0) 251 | { 252 | assert(tv->len <= 64); 253 | //auto in = ithare::kscope::kscope_int_arr_to_ct_kscope_int<64 /*maximum value*/>(in0,tv->len /*actual value*/); 254 | //ITHARE_KSCOPE_INT_CONSTEXPR(uint8_t) out[64]; 255 | uint8_t out[64] = {}; 256 | //auto key = ithare::kscope::kscope_int_arr_to_ct_kscope_int(tv->key); 257 | //auto iv = ithare::kscope::kscope_int_arr_to_ct_kscope_int(tv->iv); 258 | ITHARE_KSCOPE_CALL_AS_CONSTEXPR(CRYPTO_chacha_20)(out, in0, tv->len, tv->key, tv->iv, 0); 259 | assert(ithare::kscope::kscope_cmparr(out,expected_out,tv->len) == 0); 260 | } 261 | 262 | /* Single-shot ChaCha20 using the ChaCha interface. */ 263 | static void 264 | chacha_ctx_full_test(const chacha_tv* tv, uint8_t *out0, uint8_t* in0) 265 | { 266 | ITHARE_KSCOPE_KSCOPECLASS(ChaCha_ctx) ctx; 267 | 268 | //auto key = ITHARE_KSCOPE_INT_ARR_TO_KSCOPE_INT3(tv->key); 269 | //auto iv = ITHARE_KSCOPE_INT_ARR_TO_KSCOPE_INT3(tv->iv); 270 | ITHARE_KSCOPE_CALL3(ChaCha_set_key)(&ctx, tv->key, 256); 271 | ITHARE_KSCOPE_CALL3(ChaCha_set_iv)(&ctx, tv->iv, ITHARE_KSCOPE_INTNULLPTR); 272 | assert(tv->len <= 64); 273 | //auto in = ITHARE_KSCOPE_INT_ARR_TO_KSCOPE_INT3X(64,in0,tv->len); 274 | //ITHARE_KSCOPE_INT3(uint8_t) out[64]; 275 | ITHARE_KSCOPE_CALL3(ChaCha)(&ctx, out0, in0, tv->len); 276 | //ithare::kscope::kscope_copyarr(out0,out,tv->len); 277 | } 278 | 279 | /* ChaCha20 with partial writes using the Chacha interface. */ 280 | static void 281 | chacha_ctx_partial_test(const chacha_tv* tv, uint8_t* out0, uint8_t* in0) 282 | { 283 | ITHARE_KSCOPE_KSCOPECLASS(ChaCha_ctx) ctx; 284 | size_t len, size = 0; 285 | assert(tv->len <= 64); 286 | //auto in1 = ITHARE_KSCOPE_INT_ARR_TO_KSCOPE_INT3X(64,in0,tv->len); 287 | //ITHARE_KSCOPE_PTR_OF_SAME_TYPE_AS(in1.arr) in = in1.arr; 288 | //ITHARE_KSCOPE_INT3(uint8_t) out1[64]; 289 | //ITHARE_KSCOPE_PTR_OF_SAME_TYPE_AS(out1) out = out1; 290 | 291 | //auto key = ITHARE_KSCOPE_INT_ARR_TO_KSCOPE_INT3(tv->key); 292 | //auto iv = ITHARE_KSCOPE_INT_ARR_TO_KSCOPE_INT3(tv->iv); 293 | ITHARE_KSCOPE_CALL3(ChaCha_set_key)(&ctx, tv->key, 256); 294 | ITHARE_KSCOPE_CALL3(ChaCha_set_iv)(&ctx, tv->iv, ITHARE_KSCOPE_INTNULLPTR); 295 | assert(tv->len > 0); 296 | len = tv->len - 1; 297 | while (len > 1) { 298 | size = len / 2; 299 | ITHARE_KSCOPE_CALL3(ChaCha)(&ctx, out0, in0, size); 300 | in0 += size; 301 | out0 += size; 302 | len -= size; 303 | } 304 | ITHARE_KSCOPE_CALL3(ChaCha)(&ctx, out0, in0, len + 1); 305 | //ithare::kscope::kscope_copyarr(out0,out1,tv->len); 306 | } 307 | 308 | /* ChaCha20 with single byte writes using the Chacha interface. */ 309 | static void 310 | chacha_ctx_single_test(const chacha_tv *tv, uint8_t* out0, uint8_t* in0) 311 | {//doing manual array copying here to test that it works too 312 | ITHARE_KSCOPE_KSCOPECLASS(ChaCha_ctx) ctx; 313 | assert(tv->len <= 64); 314 | auto in = ITHARE_KSCOPE_INT_ARR_TO_KSCOPE_INT3X(64,in0,tv->len); 315 | 316 | auto key = ITHARE_KSCOPE_INT_ARR_TO_KSCOPE_INT3(tv->key); 317 | auto iv = ITHARE_KSCOPE_INT_ARR_TO_KSCOPE_INT3(tv->iv); 318 | ITHARE_KSCOPE_CALL3(ChaCha_set_key)(&ctx, ITHARE_KSCOPE_INT_ARR(key), ITHARE_KSCOPE_INTLIT3(256)); 319 | ITHARE_KSCOPE_CALL3(ChaCha_set_iv)(&ctx, ITHARE_KSCOPE_INT_ARR(iv), ITHARE_KSCOPE_INTNULLPTR); 320 | ITHARE_KSCOPE_INT3(uint8_t) out[64]; 321 | for (size_t i = 0; i < tv->len; i++) 322 | ITHARE_KSCOPE_CALL3(ChaCha)(&ctx, &out[i], &ITHARE_KSCOPE_INT_ARR(in)[i], 1); 323 | ithare::kscope::kscope_copyarr(out0,out,tv->len); 324 | } 325 | 326 | #ifdef __GNUC__ //warnings in lest.hpp - can only disable :-( 327 | #pragma GCC diagnostic push 328 | #ifdef __clang__ 329 | #pragma GCC diagnostic ignored "-Wmissing-braces" 330 | #endif 331 | #pragma GCC diagnostic ignored "-Wunused-parameter" 332 | #endif 333 | 334 | #ifdef _MSC_VER //warnings in lest.hpp - can only disable :-( 335 | #pragma warning(push) 336 | #pragma warning(disable:4100) 337 | #endif 338 | 339 | const lest::test module[] = { 340 | CASE( "compile-time: crypto_chacha_20_test_compile_time()", ) 341 | {//pretty ugly; NOT recommended for practical usage (see KSCOPE_CT_* wrappers below for recommended usage of constexpr crypto) 342 | constexpr uint8_t in[64] = {}; 343 | constexpr uint8_t out[64] = {}; 344 | constexpr const chacha_tv* tv = &chacha_test_vectors[0]; 345 | static_assert(tv->len <= sizeof(in)); 346 | static_assert(tv->len <= sizeof(out)); 347 | crypto_chacha_20_test_compile_time(tv,tv->out,in); 348 | }, 349 | CASE( "compile-time: KSCOPE_CT_Chacha(); RECOMMENDED way to use compile-time crypto", ) 350 | { 351 | constexpr const chacha_tv* tv = &chacha_test_vectors[0]; 352 | #ifdef ITHARE_KSCOPE_WORKAROUND_FOR_GCC_BUG_84463 353 | constexpr ChaCha_ctx<> ctx1 = KSCOPE_CT_Chacha_set_key_iv(chacha_test_vectors[0].key,256,chacha_test_vectors[0].iv,nullptr); 354 | #else 355 | constexpr ChaCha_ctx<> ctx1 = KSCOPE_CT_Chacha_set_key_iv(tv->key,256,tv->iv,nullptr); 356 | #endif 357 | constexpr uint8_t in[64] = {}; 358 | static_assert(tv->len <= sizeof(in)); 359 | constexpr auto encrypted1 = KSCOPE_CT_Chacha(ctx1,in); 360 | constexpr ithare::kscope::KscopeArrayWrapper out = encrypted1.second; 361 | #ifdef ITHARE_KSCOPE_WORKAROUND_FOR_GCC_BUG_84463 362 | static_assert(ithare::kscope::kscope_cmparr(out.arr,chacha_test_vectors[0].out,tv->len) == 0); 363 | #else 364 | static_assert(ithare::kscope::kscope_cmparr(out.arr,tv->out,tv->len) == 0); 365 | #endif 366 | //constexpr ChaCha_ctx<> ctx2 = encrypted1.first; 367 | }, 368 | CASE( "crypto_chacha_20_test()", ) 369 | { 370 | for (size_t i = 0; i < N_VECTORS; i++) { 371 | uint8_t in[64]; 372 | uint8_t out[64]; 373 | const chacha_tv* tv = &chacha_test_vectors[i]; 374 | assert(tv->len <= sizeof(in)); 375 | assert(tv->len <= sizeof(out)); 376 | memset(in,0,sizeof(in)); 377 | crypto_chacha_20_test(tv,out,in); 378 | EXPECT(memcmp(out,tv->out,tv->len)==0); 379 | } 380 | }, 381 | CASE( "chacha_ctx_full_test()", ) 382 | { 383 | for (size_t i = 0; i < N_VECTORS; i++) { 384 | uint8_t in[64]; 385 | uint8_t out[64]; 386 | const chacha_tv* tv = &chacha_test_vectors[i]; 387 | assert(tv->len <= sizeof(in)); 388 | assert(tv->len <= sizeof(out)); 389 | memset(in,0,sizeof(in)); 390 | chacha_ctx_full_test(tv,out,in); 391 | EXPECT(memcmp(out,tv->out,tv->len)==0); 392 | } 393 | }, 394 | CASE( "chacha_ctx_partial_test()", ) 395 | { 396 | for (size_t i = 0; i < N_VECTORS; i++) { 397 | uint8_t in[64]; 398 | uint8_t out[64]; 399 | const chacha_tv* tv = &chacha_test_vectors[i]; 400 | assert(tv->len <= sizeof(in)); 401 | assert(tv->len <= sizeof(out)); 402 | memset(in,0,sizeof(in)); 403 | chacha_ctx_partial_test(tv,out,in); 404 | EXPECT(memcmp(out,tv->out,tv->len)==0); 405 | } 406 | }, 407 | CASE( "chacha_ctx_single_test()", ) 408 | { 409 | for (size_t i = 0; i < N_VECTORS; i++) { 410 | uint8_t in[64]; 411 | uint8_t out[64]; 412 | const chacha_tv* tv = &chacha_test_vectors[i]; 413 | assert(tv->len <= sizeof(in)); 414 | assert(tv->len <= sizeof(out)); 415 | memset(in,0,sizeof(in)); 416 | chacha_ctx_single_test(tv,out,in); 417 | EXPECT(memcmp(out,tv->out,tv->len)==0); 418 | } 419 | }, 420 | #ifdef ITHARE_KSCOPE_TEST_BENCHMARK 421 | CASE( "crypto_chacha_20() benchmark", ) 422 | { 423 | uint64_t dummy = 0;//to prevent optimizing out 424 | Benchmark b; 425 | for(int bench=0;bench<1000;++bench) { 426 | uint8_t in[64]; 427 | uint8_t out[64]; 428 | const chacha_tv* tv = &chacha_test_vectors[bench_test_prng(N_VECTORS)]; 429 | assert(tv->len <= sizeof(in)); 430 | assert(tv->len <= sizeof(out)); 431 | memset(in,0,sizeof(in)); 432 | crypto_chacha_20_test(tv,out,in); 433 | dummy += out[0]; 434 | } 435 | std::cout << "crypto_chacha_20() benchmark (dummy =" << dummy << "): " << b.us() << "ns/iteration" << std::endl; 436 | } 437 | #endif 438 | }; 439 | 440 | #ifdef _MSC_VER 441 | #pragma warning(pop) 442 | #endif 443 | 444 | #ifdef __GNUC__ 445 | #pragma GCC diagnostic pop 446 | #endif 447 | 448 | extern lest::tests& specification(); 449 | 450 | MODULE( specification(), module ) 451 | -------------------------------------------------------------------------------- /test/internaltest.cpp: -------------------------------------------------------------------------------- 1 | //File used for INTERNAL testing of ithare::kscope. 2 | // NEITHER use it, NOR consider practices here as 'good' ones ;-) 3 | 4 | #ifdef _MSC_VER 5 | #define _CRT_SECURE_NO_WARNINGS 6 | #endif 7 | 8 | //{ 9 | #define ITHARE_KSCOPE_SEED 0x0c7dfa61a871b133 10 | #define ITHARE_KSCOPE_SEED2 0xdacb5ca59a237d13 11 | 12 | //#define ITHARE_KSCOPE_CRYPTO_PRNG 13 | 14 | #define ITHARE_KSCOPE_CONSISTENT_XPLATFORM_IMPLICIT_SEEDS 15 | #define ITHARE_KSCOPE_ENABLE_AUTO_DBGPRINT 2 16 | //} internal debugging: should go BEFORE #include kscope.h 17 | 18 | #include "../src/kscope.h" 19 | #include //for benchmarking 20 | #include 21 | 22 | using namespace ithare::kscope; 23 | 24 | ITHARE_KSCOPE_DECLAREFUNC 25 | uint64_t factorial(uint64_t x) { 26 | ITHARE_KSCOPE_FINT(uint64_t) ret = 1; 27 | ITHARE_KSCOPE_FDBGPRINT(ret); 28 | for(size_t i=2; i <= x ; ++i ) { 29 | ret *= i; 30 | } 31 | return ret; 32 | } 33 | 34 | int main(int argc, char** argv) { 35 | uint64_t x = 20; 36 | if(argc>1) 37 | x = atoi(argv[1]); 38 | uint64_t f = ITHARE_KSCOPE_CALL6(factorial)(x); 39 | std::cout << "factorial(" << x << ")=" << f << std::endl; 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /test/nix/README.md: -------------------------------------------------------------------------------- 1 | To test your version of Clang or GCC, run randomtest.sh (optionally, you MAY export CXX=compiler-you-want-to-test 2 | before running randomtest.sh, default is g++) 3 | 4 | Currently supported platforms are Linux and Mac OS X (adding other platforms should be possible by patching *.sh 5 | and/or ../randomtestgen.cpp). BTW, such patches to support other platforms are **very** welcome. 6 | -------------------------------------------------------------------------------- /test/nix/benchtest.sh: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018, ITHare.com 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright notice, this 8 | # list of conditions and the following disclaimer. 9 | # 10 | # * Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # 14 | # * Neither the name of the copyright holder nor the names of its 15 | # contributors may be used to endorse or promote products derived from 16 | # this software without specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | CXX=${CXX:=g++} 30 | CXX_LIB="${CXX_LIB:=-lstdc++}" 31 | HIGHLIGHT="$(tput bold)$(tput setaf 2)$(tput rev)" 32 | NOHIGHLIGHT="$(tput sgr0)" 33 | echo "${HIGHLIGHT}===*** COMPILER BEING USED: CXX=${CXX} ***===${NOHIGHLIGHT}" 34 | $CXX --version 35 | 36 | echo "${HIGHLIGHT}===*** benchmark: DISABLE/FORCEINLINE ***===${NOHIGHLIGHT}" 37 | $CXX -DITHARE_KSCOPE_TEST_BENCHMARK -DITHARE_KSCOPE_DISABLE -O3 -DNDEBUG -std=c++1z -pedantic -pedantic-errors -Wall -Wextra -Werror -DITHARE_KSCOPE_TEST_EXTENSION=\"../src/kscope_sample_extension.h\" -DITHARE_KSCOPE_CONSISTENT_XPLATFORM_IMPLICIT_SEEDS ${CXX_LIB} -o randomtest ../officialtest.cpp ../chachatest.cpp 38 | printf "*** benchmark: DISABLE/FORCEINLINE\n" >bench.txt 39 | ./randomtest >>bench.txt 40 | 41 | echo "${HIGHLIGHT}===*** benchmark: DISABLE/NOFORCEINLINE ***===${NOHIGHLIGHT}" 42 | $CXX -DITHARE_KSCOPE_NOFORCEINLINE -DITHARE_KSCOPE_TEST_BENCHMARK -DITHARE_KSCOPE_DISABLE -O3 -DNDEBUG -std=c++1z -pedantic -pedantic-errors -Wall -Wextra -Werror -DITHARE_KSCOPE_TEST_EXTENSION=\"../src/kscope_sample_extension.h\" -DITHARE_KSCOPE_CONSISTENT_XPLATFORM_IMPLICIT_SEEDS ${CXX_LIB} -o randomtest ../officialtest.cpp ../chachatest.cpp 43 | printf "\n\n*** benchmark: DISABLE/NOFORCEINLINE\n" >>bench.txt 44 | ./randomtest >>bench.txt 45 | 46 | echo "${HIGHLIGHT}===*** benchmark: no SEED/FORCEINLINE ***===${NOHIGHLIGHT}" 47 | $CXX -DITHARE_KSCOPE_TEST_BENCHMARK -O3 -DNDEBUG -std=c++1z -pedantic -pedantic-errors -Wall -Wextra -Werror -DITHARE_KSCOPE_TEST_EXTENSION=\"../src/kscope_sample_extension.h\" -DITHARE_KSCOPE_CONSISTENT_XPLATFORM_IMPLICIT_SEEDS ${CXX_LIB} -o randomtest ../officialtest.cpp ../chachatest.cpp 48 | printf "\n\n*** benchmark: NO SEED/FORCEINLINE\n" >>bench.txt 49 | ./randomtest >>bench.txt 50 | 51 | echo "${HIGHLIGHT}===*** benchmark: no SEED/NOFORCEINLINE ***===${NOHIGHLIGHT}" 52 | $CXX -DITHARE_KSCOPE_NOFORCEINLINE -DITHARE_KSCOPE_TEST_BENCHMARK -O3 -DNDEBUG -std=c++1z -pedantic -pedantic-errors -Wall -Wextra -Werror -DITHARE_KSCOPE_TEST_EXTENSION=\"../src/kscope_sample_extension.h\" -DITHARE_KSCOPE_CONSISTENT_XPLATFORM_IMPLICIT_SEEDS ${CXX_LIB} -o randomtest ../officialtest.cpp ../chachatest.cpp 53 | printf "\n\n*** benchmark: NO SEED/NOFORCEINLINE\n" >>bench.txt 54 | ./randomtest >>bench.txt 55 | 56 | echo "${HIGHLIGHT}===*** benchmark: SEED/FORCEINLINE ***===${NOHIGHLIGHT}" 57 | $CXX -DITHARE_KSCOPE_TEST_BENCHMARK -O3 -DNDEBUG -std=c++1z -pedantic -pedantic-errors -Wall -Wextra -Werror -DITHARE_KSCOPE_TEST_EXTENSION=\"../src/kscope_sample_extension.h\" -DITHARE_KSCOPE_CONSISTENT_XPLATFORM_IMPLICIT_SEEDS -DITHARE_KSCOPE_SEED=0x4b295ebab3333abc -DITHARE_KSCOPE_SEED2=0x36e007a38ae8e0ea ${CXX_LIB} -o randomtest ../officialtest.cpp ../chachatest.cpp 58 | printf "\n\n*** benchmark: SEED/FORCEINLINE\n" >>bench.txt 59 | ./randomtest >>bench.txt 60 | 61 | echo "${HIGHLIGHT}===*** benchmark: SEED/NOFORCEINLINE ***===${NOHIGHLIGHT}" 62 | $CXX -DITHARE_KSCOPE_NOFORCEINLINE -DITHARE_KSCOPE_TEST_BENCHMARK -O3 -DNDEBUG -std=c++1z -pedantic -pedantic-errors -Wall -Wextra -Werror -DITHARE_KSCOPE_TEST_EXTENSION=\"../src/kscope_sample_extension.h\" -DITHARE_KSCOPE_CONSISTENT_XPLATFORM_IMPLICIT_SEEDS -DITHARE_KSCOPE_SEED=0x4b295ebab3333abc -DITHARE_KSCOPE_SEED2=0x36e007a38ae8e0ea ${CXX_LIB} -o randomtest ../officialtest.cpp ../chachatest.cpp 63 | printf "\n\n*** benchmark: SEED/NOFORCEINLINE\n" >>bench.txt 64 | ./randomtest >>bench.txt 65 | -------------------------------------------------------------------------------- /test/nix/build-official.sh: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018, ITHare.com 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # * Redistributions of source code must retain the above copyright notice, this 8 | # list of conditions and the following disclaimer. 9 | # 10 | # * Redistributions in binary form must reproduce the above copyright notice, 11 | # this list of conditions and the following disclaimer in the documentation 12 | # and/or other materials provided with the distribution. 13 | # 14 | # * Neither the name of the copyright holder nor the names of its 15 | # contributors may be used to endorse or promote products derived from 16 | # this software without specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | #release 30 | gcc -O3 -DNDEBUG -DITHARE_KSCOPE_SEED=1234567 -DITHARE_KSCOPE_DBG_RUNTIME_CHECKS -DITHARE_KSCOPE_ENABLE_AUTO_DBGPRINT=2 -o officialtest -std=c++1z -lstdc++ ../officialtest.cpp ../chachatest.cpp 31 | 32 | -------------------------------------------------------------------------------- /test/nix/randomtest.sh: -------------------------------------------------------------------------------- 1 | # no shebang - don't want to change current shell 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 | gen_sh="" 32 | if [ -z ${BASH_VERSINFO[0]} ]; then 33 | gen_sh="-gen_sh" 34 | fi 35 | if [ ${BASH_VERSINFO[0]} -lt 4 ]; then 36 | gen_sh="-gen_sh" 37 | fi 38 | 39 | nn=1024 40 | if [ $# -gt 0 ]; then 41 | nn=$1 42 | fi 43 | 44 | CXX="${CXX:=g++}" 45 | HOST_CXX="${HOST_CXX:=${CXX}}" 46 | CXX_LIB="${CXX_LIB:=-lstdc++}" 47 | 48 | ${HOST_CXX} -O2 -o randomtestgen -std=c++1z ${CXX_LIB} ../randomtestgen.cpp 49 | if [ ! $? -eq 0 ]; then 50 | exit 1 51 | fi 52 | 53 | ./randomtestgen -add32tests $gen_sh $nn >generatedrandomtest.sh 54 | if [ ! $? -eq 0 ]; then 55 | exit 1 56 | fi 57 | 58 | export CXX_LIB 59 | chmod 700 generatedrandomtest.sh 60 | ./generatedrandomtest.sh 61 | if [ ! $? -eq 0 ]; then 62 | exit 1 63 | fi 64 | 65 | rm generatedrandomtest.sh 66 | -------------------------------------------------------------------------------- /test/officialtest.cpp: -------------------------------------------------------------------------------- 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 | #include "lest.hpp" 34 | #ifdef ITHARE_KSCOPE_TEST_EXTENSION 35 | #include ITHARE_KSCOPE_TEST_EXTENSION //MUST go BEFORE ../src/kscope.h 36 | #endif 37 | //NB: normally, in your own files you should use simple #include "your_extension.h", 38 | // #include MACRO above is to allow using the same test .cpp with external extensions 39 | 40 | #include "../src/kscope.h" 41 | 42 | #include "test.h" 43 | 44 | #ifndef ITHARE_KSCOPE_TEST_NO_NAMESPACE 45 | using namespace ithare::kscope; 46 | #define ITKSCOPE 47 | #else 48 | #define ITKSCOPE ithare::kscope:: 49 | #endif 50 | 51 | class MyException { 52 | public: 53 | MyException(std::string msg) 54 | : message(msg) { 55 | } 56 | virtual const char* what() const { 57 | return message.c_str(); 58 | } 59 | 60 | private: 61 | std::string message; 62 | }; 63 | 64 | namespace ithare{ namespace kscope { 65 | 66 | ITHARE_KSCOPE_DECLAREFUNC_WITHPARAMS_INT 67 | ITHARE_KSCOPE_FINTP2(uint64_t) factorial(ITHARE_KSCOPE_DECLAREPARAM_INT(int64_t) x) { 68 | //DBGPRINT(x_) 69 | if (x < 0) { 70 | auto lit = ITHARE_KSCOPE_STRLIT3("Negative argument to factorial!"); ITHARE_KSCOPE_DBGPRINT(lit); 71 | throw MyException(lit); 72 | } 73 | ITHARE_KSCOPE_FINTM1(uint64_t) ret = 1; 74 | //DBGPRINT(ret) 75 | for (ITHARE_KSCOPE_FINTM1(int64_t) i = 1; i <= x; ++i) { 76 | //DBGPRINT(i); 77 | ret *= i; 78 | } 79 | return ret; 80 | } 81 | 82 | ITHARE_KSCOPE_NOINLINE ITHARE_KSCOPE_INT3(uint64_t) factorial(ITHARE_KSCOPE_INT3(int64_t) x) { 83 | return ITHARE_KSCOPE_CALL3(factorial)(x); 84 | } 85 | }}//namespace ithare::kscope 86 | 87 | /* 88 | //TODO: reinstate 89 | CASE("benchmarks") { 90 | #if !defined(ITHARE_KSCOPE_ENABLE_AUTO_DBGPRINT) || ITHARE_KSCOPE_ENABLE_AUTO_DBGPRINT == 2//excluding platform-specific stuff to avoid spurious changes to kscope.txt with -DITHARE_KSCOPE_ENABLE_AUTO_DBGPRINT 91 | { 92 | Benchmark bm0; 93 | for (size_t i = 0; i < NBENCH; ++i) { 94 | uint8_t inp[16] = { 0 }; 95 | uint8_t out[16] = { 0 }; 96 | test_chacha_cipher(inp, out); 97 | } 98 | std::cout << "chacha_cipher():" << ( bm0.us() * 1000 / NBENCH ) << " nanoseconds" << std::endl; 99 | } 100 | #endif 101 | } 102 | */ 103 | 104 | #ifdef __clang__ //warning in lest.hpp - can only disable :-( 105 | #pragma GCC diagnostic push 106 | #pragma GCC diagnostic ignored "-Wmissing-braces" 107 | #endif 108 | 109 | static const lest::test module[] = { 110 | CASE("types",) { 111 | //well, at least for common 32/64-bit platforms is should stand 112 | using TT1 = typename ITKSCOPE kscope_integral_operator_promoconv::type; 113 | static_assert(std::is_same::value); 114 | 115 | using TT1A = typename ITKSCOPE kscope_integral_operator_promoconv::type; 116 | static_assert(std::is_same::value); 117 | 118 | using TT2 = typename ITKSCOPE kscope_integral_operator_promoconv::type; 119 | static_assert(std::is_same::value); 120 | EXPECT((ITKSCOPE kscope_integral_operator_literal_cast_is_safe()==true)); 121 | EXPECT((ITKSCOPE kscope_integral_operator_literal_cast_is_safe() == false)); 122 | EXPECT((ITKSCOPE kscope_integral_operator_literal_cast_is_safe() == true)); 123 | 124 | using TT3 = typename ITKSCOPE kscope_integral_operator_promoconv::type; 125 | static_assert(std::is_same::value); 126 | EXPECT((ITKSCOPE kscope_integral_operator_literal_cast_is_safe()==true)); 127 | EXPECT((ITKSCOPE kscope_integral_operator_literal_cast_is_safe()==false)); 128 | 129 | using TT4 = typename ITKSCOPE kscope_integral_operator_promoconv::type; 130 | static_assert(std::is_same::value); 131 | EXPECT((ITKSCOPE kscope_integral_operator_literal_cast_is_safe()==false)); 132 | EXPECT((ITKSCOPE kscope_integral_operator_literal_cast_is_safe()==true)); 133 | EXPECT((ITKSCOPE kscope_integral_operator_literal_cast_is_safe()==true)); 134 | }, 135 | CASE("factorial()",) { 136 | auto f = ITKSCOPE ITHARE_KSCOPE_CALL4(factorial)(ITHARE_KSCOPE_INTLIT3(17)); ITHARE_KSCOPE_DBGPRINT(f); 137 | EXPECT(f==UINT64_C(355687428096000)); 138 | EXPECT( ITKSCOPE factorial(18) == UINT64_C(6402373705728000)); 139 | EXPECT( ITKSCOPE factorial(19) == UINT64_C(121645100408832000)); 140 | EXPECT( ITKSCOPE factorial(20) == UINT64_C(2432902008176640000)); 141 | EXPECT( ITKSCOPE factorial(21) == UINT64_C(14197454024290336768));//with wrap-around(!) 142 | EXPECT_THROWS_AS( ITKSCOPE factorial(-1),MyException); 143 | }, 144 | #ifdef ITHARE_KSCOPE_TEST_BENCHMARK 145 | CASE( "factorial() benchmark", ) { 146 | uint64_t dummy = 0;//to prevent optimizing out 147 | Benchmark b; 148 | for(int bench=0;bench<1000;++bench) { 149 | dummy += factorial(bench_test_prng(87)); 150 | EXPECT(true); 151 | } 152 | std::cout << "factorial() benchmark (dummy=" << dummy << "):" << b.us() << "ns/iteration" << std::endl; 153 | } 154 | #endif 155 | }; 156 | 157 | lest::tests& specification() { 158 | static lest::tests all_tests; 159 | return all_tests; 160 | } 161 | 162 | MODULE( specification(), module ) 163 | 164 | #ifdef __clang__ 165 | #pragma GCC diagnostic pop 166 | #endif 167 | 168 | int main(int argc, char** argv) { 169 | #if !defined(ITHARE_KSCOPE_ENABLE_AUTO_DBGPRINT) || ITHARE_KSCOPE_ENABLE_AUTO_DBGPRINT == 2//excluding platform-specific stuff to avoid spurious changes to kscope.txt with -DITHARE_KSCOPE_ENABLE_AUTO_DBGPRINT 170 | std::cout << "__cplusplus=" << __cplusplus << std::endl; 171 | #ifdef _MSC_VER 172 | std::cout << "_MSC_VER=" << _MSC_VER << " _MSC_FULL_VER=" << _MSC_FULL_VER << " _MSC_BUILD=" << _MSC_BUILD << std::endl; 173 | #endif 174 | #ifdef __GNUC__ 175 | std::cout << "__GNUC__=" << __GNUC__ << " __GNUC_MINOR__=" << __GNUC_MINOR__ << " __GNUC_PATCHLEVEL__=" << __GNUC_PATCHLEVEL__ << std::endl; 176 | #endif 177 | #ifdef __clang__ 178 | std::string modifier = ""; 179 | #ifdef __apple_build_version__ 180 | modifier = "__apple_build_version__: "; 181 | #endif 182 | std::cout << modifier << "__clang_major__=" << __clang_major__ << " __clang_minor__=" << __clang_minor__ << " __clang_patchlevel__=" << __clang_patchlevel__ << std::endl; 183 | #endif 184 | std::cout << "sizeof(void*) == " << sizeof(void*) << std::endl; 185 | #endif 186 | #ifdef ITHARE_KSCOPE_SEED 187 | std::cout << "ITHARE_KSCOPE_SEED=" << std::hex << ITHARE_KSCOPE_SEED << std::dec << std::endl; 188 | #endif 189 | #ifdef ITHARE_KSCOPE_SEED2 190 | std::cout << "ITHARE_KSCOPE_SEED2=" << std::hex << ITHARE_KSCOPE_SEED2 << std::dec << std::endl; 191 | #endif 192 | 193 | bench_test_prng_state = argc; 194 | return lest::run(specification(),argc,argv); 195 | } 196 | 197 | uint64_t bench_test_prng_state = 0; 198 | -------------------------------------------------------------------------------- /test/randomtestgen.cpp: -------------------------------------------------------------------------------- 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 | //TEST GENERATOR. Generates randomized command lines for a testing session 34 | // Using C++ to avoid writing the same logic twice in *nix .sh and Win* .bat 35 | 36 | #include "randomtestgen.h" 37 | 38 | int main(int argc, char** argv) { 39 | KscopeTestEnvironment kenv; 40 | KscopeTestGenerator kgen(kenv); 41 | return almost_main(kenv,kgen,argc,argv); 42 | } 43 | -------------------------------------------------------------------------------- /test/randomtestgen.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 | //TEST GENERATOR. Generates randomized command lines for a testing session 34 | // Using C++ to avoid writing the same logic twice in *nix .sh and Win* .bat 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | struct MultiString : public std::vector { 44 | MultiString() {} 45 | MultiString(std::initializer_list l) 46 | : std::vector(l) {} 47 | 48 | MultiString append(std::string s) { 49 | MultiString ret = *this; 50 | ret.push_back(s); 51 | return ret; 52 | } 53 | MultiString append(MultiString m) { 54 | MultiString ret = *this; 55 | for(std::string s:m) 56 | ret.push_back(s); 57 | return ret; 58 | } 59 | }; 60 | 61 | static const char* randomtest_files[] = { "officialtest.cpp", "chachatest.cpp", nullptr }; 62 | std::string make_file_list(const char* files[] /*ends with nullptr*/,std::string srcDir) { 63 | std::string ret = ""; 64 | for(size_t i=0; files[i] ; ++i ) { 65 | ret += " "; 66 | ret += srcDir; 67 | ret += files[i]; 68 | } 69 | return ret; 70 | } 71 | 72 | std::string replace_string(std::string subject, std::string search, std::string replace) {//adapted from https://stackoverflow.com/a/14678964 73 | size_t pos = 0; 74 | while ((pos = subject.find(search, pos)) != std::string::npos) { 75 | subject.replace(pos, search.length(), replace); 76 | pos += replace.length(); 77 | } 78 | return subject; 79 | } 80 | 81 | #if defined(__APPLE_CC__) || defined(__linux__) 82 | 83 | class KscopeTestEnvironment { 84 | public: 85 | enum class config { debug, release }; 86 | using Flags = uint32_t; 87 | constexpr static Flags flag_auto_dbg_print = 0x01; 88 | std::string src_dir_prefix = ""; 89 | bool gen_sh = false; 90 | 91 | virtual std::string root_test_dir() { return src_dir_prefix + "../"; } 92 | virtual std::string test_src_dir() { return src_dir_prefix + "../"; } 93 | virtual std::string file_list() { return make_file_list(randomtest_files,test_src_dir()); } 94 | 95 | virtual std::string always_define() {//relative to kscope/test 96 | return " -DITHARE_KSCOPE_TEST_EXTENSION=\"../src/kscope_sample_extension.h\""; 97 | } 98 | virtual std::string compiler_options_release() { 99 | return " -O3 -DNDEBUG -std=c++1z -pedantic -pedantic-errors -Wall -Wextra -Werror"; 100 | } 101 | virtual std::string linker_options_release() { 102 | return " ${CXX_LIB} -o randomtest"; 103 | } 104 | virtual std::string compiler_options_debug() { 105 | return " -std=c++1z -pedantic -pedantic-errors -Wall -Wextra -Werror"; 106 | } 107 | virtual std::string linker_options_debug() { 108 | return " ${CXX_LIB} -o randomtest"; 109 | } 110 | 111 | virtual MultiString build_release(MultiString defines,std::string opts) { 112 | std::string defs = ""; 113 | for(std::string s:defines) 114 | defs += " -DITHARE_KSCOPE_" + s; 115 | return MultiString{"$CXX" + compiler_options_release() + " -DITHARE_KSCOPE_TEST_EXTENSION=\"../src/kscope_sample_extension.h\"" + defs + opts + linker_options_release() + file_list()}; 116 | } 117 | virtual MultiString build_debug(MultiString defines,std::string opts) { 118 | std::string defs = ""; 119 | for(std::string s:defines) 120 | defs += " -DITHARE_KSCOPE_" + s; 121 | return MultiString{"$CXX" + compiler_options_debug() + " -DITHARE_KSCOPE_TEST_EXTENSION=\"../src/kscope_sample_extension.h\"" + defs + opts + linker_options_debug() + file_list()}; 122 | } 123 | virtual std::string build32_option() { 124 | return " -m32"; 125 | } 126 | virtual std::string gen_random64() { 127 | static FILE* frnd = fopen("/dev/urandom","rb"); 128 | if(frnd==0) { 129 | std::cout << "Cannot open /dev/urandom, aborting" << std::endl; 130 | abort(); 131 | } 132 | uint8_t buf[8]; 133 | size_t rd = fread(buf,sizeof(buf),1,frnd); 134 | if( rd != 1 ) { 135 | std::cout << "Problems reading from /dev/urandom, aborting" << std::endl; 136 | abort(); 137 | } 138 | 139 | char buf2[sizeof(buf)*2+1]; 140 | for(size_t i=0; i < sizeof(buf) ; ++i) { 141 | assert(buf[i]<=255); 142 | sprintf(&buf2[i*2],"%02x",buf[i]); 143 | } 144 | return std::string(buf2); 145 | } 146 | virtual std::string exit_check(std::string cmd_, bool expectok = true) { 147 | std::string cmd = replace_string(cmd_,"\"", "\\\\\\\"");//yes, it is this many backslashes required to get through 3 levels of de-escaping (C++ compiler, 'echo', and failedrandomtest.sh) 148 | if( expectok ) 149 | return std::string("if [ ! $? -eq 0 ]; then\n echo \"") + cmd + ( "\">failedrandomtest.sh\n exit 1\nfi"); 150 | else 151 | return std::string("if [ ! $? -ne 0 ]; then\n echo \"") + cmd + ( "\">failedrandomtest.sh\n exit 1\nfi"); 152 | } 153 | virtual std::string command(std::string cmd) { 154 | return replace_string(cmd,"\"", "\\\""); 155 | } 156 | virtual std::string echo(std::string s_,bool highlight=false) { 157 | std::string s = replace_string(s_,"\"", "\\\""); 158 | if(highlight) 159 | return std::string("echo \"${HIGHLIGHT}")+s+"${NOHIGHLIGHT}\""; 160 | else 161 | return std::string("echo \"" + s +"\""); 162 | } 163 | virtual std::string run(std::string redirect) { 164 | if(redirect!="") 165 | return std::string("${EXEC_PREFIX} ${PWD}/randomtest >")+redirect; 166 | else 167 | return std::string("${EXEC_PREFIX} ${PWD}/randomtest"); 168 | } 169 | virtual std::string check_exe(int nseeds,config cfg,Flags flags) { 170 | return ""; 171 | } 172 | virtual std::string cmp_files(std::string f1, std::string f2) { 173 | return std::string("diff ") + f1 + " " + f2 + " 2>&1 >/dev/null"; 174 | } 175 | virtual std::string setup() { 176 | if( !gen_sh ) { 177 | return 178 | std::string("# no shebang - don't want to change current shell") 179 | + "\nif [ -z ${BASH_VERSINFO[0]} ]; then" 180 | "\necho \"Bash version 4+ is required (to work with .sh or older bash, re-generate using randomtestgen -gen_sh)\"" 181 | "\nexit 1" 182 | "\nfi" 183 | "\nif [ ${BASH_VERSINFO[0]} -lt 4 ]; then" 184 | "\necho \"Bash version 4+ is required (to work with .sh or older bash, re-generate using randomtestgen -gen_sh)\"" 185 | "\nexit 1" 186 | "\nfi" 187 | + "\nCXX=${CXX:=g++}" 188 | + "\nHIGHLIGHT=\"$(tput bold)$(tput setaf 2)$(tput rev)\"" 189 | "\nNOHIGHLIGHT=\"$(tput sgr0)\"" 190 | + "\n" + echo("===*** COMPILER BEING USED: CXX=${CXX} ***===",true)+"\n$CXX --version" 191 | + "\nSTART=${1:-f1}" 192 | "\ncase $START in"; 193 | } 194 | else { 195 | return std::string("# no shebang - don't want to change current shell") 196 | + "\necho \"NOTICE: .sh version, start-from parameter is disabled\"" 197 | + "\nCXX=${CXX:=g++}" 198 | + "\nHIGHLIGHT=\"$(tput bold)$(tput setaf 2)$(tput rev)\"" 199 | "\nNOHIGHLIGHT=\"$(tput sgr0)\"" 200 | + "\n" + echo("===*** COMPILER BEING USED: CXX=${CXX} ***===",true)+"\n$CXX --version"; 201 | } 202 | } 203 | static int nlabels; 204 | virtual std::string label(std::string lab) { 205 | if( gen_sh ) 206 | return ""; 207 | if(nlabels++==0) 208 | return lab+")"; 209 | else 210 | return std::string(";&") 211 | + "\n"+lab+")"; 212 | } 213 | virtual std::string cleanup() { 214 | if (!gen_sh ) { 215 | return std::string("esac") 216 | + "\nrm randomtest"; 217 | } 218 | else 219 | return "rm randomtest"; 220 | } 221 | 222 | }; 223 | 224 | int KscopeTestEnvironment::nlabels = 0; 225 | #elif defined(_WIN32) 226 | #include 227 | class KscopeTestEnvironment { 228 | public: 229 | enum class config { debug, release }; 230 | using Flags = uint32_t; 231 | constexpr static Flags flag_auto_dbg_print = 0x01; 232 | std::string src_dir_prefix = ""; 233 | 234 | virtual std::string file_list() { return make_file_list(randomtest_files,test_src_dir()); } 235 | virtual std::string root_test_dir() { return src_dir_prefix + "..\\"; } 236 | virtual std::string test_src_dir() { return src_dir_prefix + "..\\"; } 237 | 238 | virtual std::string compiler_options_release() { 239 | return " /permissive- /GS /GL /W4 /Gy /Zc:wchar_t /Gm- /O2 /sdl /Zc:inline /fp:precise /DNDEBUG /D_CONSOLE /D_UNICODE /DUNICODE /errorReport:prompt /WX /Zc:forScope /GR- /Gd /Oi /MT /EHsc /nologo /diagnostics:classic /std:c++17 /cgthreads1"; 240 | //string is copy-pasted from Rel-NoPDB config with manually-added /cgthreads1 /INCREMENTAL:NO, /Fe, and /WX- replaced with /WX 241 | } 242 | virtual std::string linker_options_release() { 243 | return " /nologo /GL /INCREMENTAL:NO /Ferandomtest.exe"; 244 | } 245 | virtual std::string compiler_options_debug() { 246 | return " /permissive- /GS /W4 /Zc:wchar_t /ZI /Gm /Od /sdl /Zc:inline /fp:precise /D_DEBUG /D_CONSOLE /D_UNICODE /DUNICODE /errorReport:prompt /WX /Zc:forScope /RTC1 /Gd /MDd /EHsc /nologo /diagnostics:classic /std:c++17 /cgthreads1 /bigobj"; 247 | //string is copy-pasted from Debug config with manually-added /cgthreads1 /INCREMENTAL:NO /bigobj, /Fe, and /WX- replaced with /WX 248 | } 249 | virtual std::string linker_options_debug() { 250 | return " /nologo /ZI /INCREMENTAL:NO /Ferandomtest.exe"; 251 | } 252 | virtual MultiString build_release(MultiString defines,std::string opts) { 253 | //std::string defines = replace_string(defines_, " -D", " /D"); 254 | std::string defs = ""; 255 | for(std::string s:defines) 256 | defs += " -DITHARE_KSCOPE_" + s; 257 | return MultiString{"cl" + compiler_options_release() + " /DITHARE_KSCOPE_TEST_EXTENSION=\"../src/kscope_sample_extension.h\"" + defs + opts + linker_options_release() + file_list()}; 258 | } 259 | virtual MultiString build_debug(MultiString defines,std::string opts) { 260 | //std::string defines = replace_string(defines_, " -D", " /D"); 261 | std::string defs = ""; 262 | for(std::string s:defines) 263 | defs += " -DITHARE_KSCOPE_" + s; 264 | return MultiString{"cl" + compiler_options_debug() + " /DITHARE_KSCOPE_TEST_EXTENSION=\"../src/kscope_sample_extension.h\"" + defs + opts + linker_options_debug() + file_list()}; 265 | } 266 | virtual std::string build32_option() { 267 | std::cout << "no option to run both 32-bit and 64-bit testing for MSVC now, run testing without -add32tests in two different 'Tools command prompts' instead" << std::endl; 268 | abort(); 269 | } 270 | 271 | virtual std::string gen_random64() { 272 | static HCRYPTPROV prov = NULL; 273 | if (!prov) { 274 | BOOL ok = CryptAcquireContext(&prov,NULL,NULL,PROV_RSA_FULL,0); 275 | if (!ok) { 276 | std::cout << "CryptAcquireContext() returned error, aborting" << std::endl; 277 | abort(); 278 | } 279 | }; 280 | uint8_t buf[8]; 281 | BOOL ok = CryptGenRandom(prov, sizeof(buf), buf); 282 | if (!ok) { 283 | std::cout << "Problems calling CryptGenRandom(), aborting" << std::endl; 284 | abort(); 285 | } 286 | 287 | char buf2[sizeof(buf) * 2 + 1]; 288 | for (size_t i = 0; i < sizeof(buf); ++i) { 289 | assert(buf[i] <= 255); 290 | sprintf(&buf2[i * 2], "%02x", buf[i]); 291 | } 292 | return std::string(buf2); 293 | } 294 | virtual std::string exit_check(std::string cmd_,bool expectok = true) { 295 | std::string cmd = replace_string(cmd_,"\"", "\\\""); 296 | static int nextlabel = 1; 297 | if (expectok) { 298 | 299 | auto ret = std::string("IF NOT ERRORLEVEL 1 GOTO LABEL") + std::to_string(nextlabel) 300 | + "\nECHO " + replace_string(cmd,">","^>") + ">failedrandomtest.bat" 301 | + "\nEXIT /B\n:LABEL" + std::to_string(nextlabel); 302 | nextlabel++; 303 | return ret; 304 | } 305 | else { 306 | auto ret = std::string("IF ERRORLEVEL 1 GOTO LABEL") + std::to_string(nextlabel) 307 | + "\nECHO " + replace_string(cmd, ">", "^>") + ">failedrandomtest.bat" 308 | + "\nEXIT /B\n:LABEL" + std::to_string(nextlabel); 309 | nextlabel++; 310 | return ret; 311 | } 312 | } 313 | virtual std::string command(std::string cmd) { 314 | return replace_string(cmd,"\"", "\\\""); 315 | } 316 | virtual std::string echo(std::string s_,bool highlight=false) { 317 | std::string s = replace_string(s_,"\"", "\\\""); 318 | return std::string("ECHO ") + replace_string(s, ">", "^>"); 319 | } 320 | virtual std::string run(std::string redirect) { 321 | if(redirect!="") 322 | return std::string("randomtest.exe >")+redirect; 323 | else 324 | return std::string("randomtest.exe"); 325 | } 326 | virtual std::string check_exe(int nseeds,config cfg,Flags flags) { 327 | return ""; 328 | } 329 | virtual std::string cmp_files(std::string f1, std::string f2) { 330 | return std::string("fc ") + f1 + " " + f2 + " >nul"; 331 | } 332 | virtual std::string cleanup() { 333 | return std::string("del randomtest.exe"); 334 | } 335 | virtual std::string label(std::string lab) { 336 | return std::string(":") + lab; 337 | } 338 | std::string setup() { 339 | return "@ECHO OFF\nDEL *.PDB\nDEL *.IDB" 340 | "\nIF .%1==. GOTO CONT" 341 | "\nGOTO %1" 342 | "\n:CONT" ; 343 | } 344 | }; 345 | #else 346 | #error "Unrecognized platform for randomized testing" 347 | #endif 348 | 349 | class KscopeTestGenerator { 350 | protected: 351 | KscopeTestEnvironment* kenv; 352 | 353 | public: 354 | enum class write_output { none, stable, random, stable_first, stable_next }; 355 | bool add32tests = false; 356 | 357 | KscopeTestGenerator(KscopeTestEnvironment& kenv_) : kenv(&kenv_) { 358 | } 359 | 360 | virtual std::string project_name() { 361 | return "kscope"; 362 | } 363 | virtual MultiString fixed_seeds() { 364 | return MultiString{"SEED=0x4b295ebab3333abc","SEED2=0x36e007a38ae8e0ea"};//from random.org 365 | } 366 | virtual MultiString gen_seed() { 367 | return MultiString{"SEED=0x"+kenv->gen_random64()}; 368 | } 369 | 370 | virtual MultiString gen_seeds() { 371 | return gen_seed().append("SEED2=0x"+kenv->gen_random64()); 372 | } 373 | 374 | virtual void issue_command(std::string cmd) { 375 | std::cout << kenv->echo(cmd) << std::endl; 376 | std::cout << kenv->command(cmd) << std::endl; 377 | } 378 | 379 | virtual void build_check_run_check(MultiString cmds,int nseeds,KscopeTestEnvironment::config cfg,KscopeTestEnvironment::Flags flags,write_output wo) { 380 | for(std::string cmd:cmds) { 381 | issue_command(cmd); 382 | std::cout << kenv->exit_check(cmd) << std::endl; 383 | } 384 | std::cout << kenv->check_exe(nseeds,cfg,flags) << std::endl; 385 | 386 | std::string tofile = ""; 387 | switch (wo) { 388 | case write_output::none: 389 | break; 390 | case write_output::stable_first: 391 | tofile = kenv->root_test_dir() + "kscope.txt"; 392 | break; 393 | case write_output::stable_next: 394 | tofile = kenv->root_test_dir() + "kscope2.txt"; 395 | break; 396 | case write_output::random: 397 | tofile = "local_kscope.txt"; 398 | break; 399 | default: 400 | assert(false); 401 | } 402 | std::string cmdrun = kenv->run(tofile); 403 | issue_command(cmdrun); 404 | std::cout << kenv->exit_check(cmdrun) << std::endl; 405 | if(wo==write_output::stable_next) { 406 | std::string cmpfiles = kenv->cmp_files(kenv->root_test_dir() + "kscope.txt", kenv->root_test_dir() + "kscope2.txt"); 407 | issue_command(cmpfiles); 408 | std::cout << kenv->exit_check(cmpfiles) << std::endl; 409 | } 410 | } 411 | 412 | virtual MultiString seeds_by_num(int nseeds) { 413 | assert(nseeds >= -1 && nseeds <= 2); 414 | if(nseeds==1) 415 | return gen_seed(); 416 | else if(nseeds==2) 417 | return gen_seeds(); 418 | else if(nseeds==-1) 419 | return fixed_seeds(); 420 | assert(nseeds==0); 421 | return MultiString{}; 422 | } 423 | 424 | virtual MultiString build_cmd(KscopeTestEnvironment::config cfg,MultiString defs,std::string options="") { 425 | switch(cfg) { 426 | case KscopeTestEnvironment::config::debug: 427 | return kenv->build_debug(defs,options); 428 | case KscopeTestEnvironment::config::release: 429 | return kenv->build_release(defs,options); 430 | } 431 | assert(false); 432 | return MultiString{}; 433 | } 434 | 435 | virtual void insert_label(std::string label) { 436 | std::cout << kenv->label(label) << "\n"; 437 | } 438 | 439 | virtual void fixed_test(KscopeTestEnvironment::config cfg,MultiString defs,int nseeds,KscopeTestEnvironment::Flags flags=0,write_output wo=write_output::none) { 440 | assert(nseeds >= -1 && nseeds <= 2); 441 | write_output wox = wo; 442 | if(wo==write_output::stable){ 443 | assert(nseeds<0); 444 | wox = write_output::stable_first; 445 | } 446 | else { 447 | assert(nseeds>=0); 448 | } 449 | 450 | auto cmd1 = build_cmd(cfg, defs.append(seeds_by_num(nseeds))); 451 | build_check_run_check(cmd1,nseeds,cfg,flags,wox); 452 | if(wox==write_output::stable_first) 453 | wox = write_output::stable_next; 454 | auto cmd2 = build_cmd(cfg, defs.append(seeds_by_num(nseeds)).append("TEST_NO_NAMESPACE")); 455 | build_check_run_check(cmd2,nseeds,cfg,flags,wox); 456 | 457 | if(add32tests) { 458 | std::string m32 = kenv->build32_option(); 459 | auto cmd1 = build_cmd(cfg, defs.append(seeds_by_num(nseeds)),m32); 460 | build_check_run_check(cmd1,nseeds,cfg,flags,wox); 461 | auto cmd2 = build_cmd(cfg, defs.append(seeds_by_num(nseeds)).append("TEST_NO_NAMESPACE"),m32); 462 | build_check_run_check(cmd2,nseeds,cfg,flags,wox); 463 | } 464 | } 465 | 466 | virtual void gen_fixed_tests() { 467 | insert_label("f1"); 468 | std::cout << kenv->echo("=== "+project_name()+" Fixed Test 1/14 (DEBUG, -DITHARE_KSCOPE_ENABLE_AUTO_DBGPRINT, write_output::stable) ===",true) << std::endl; 469 | fixed_test(KscopeTestEnvironment::config::debug, MultiString{"CONSISTENT_XPLATFORM_IMPLICIT_SEEDS","ENABLE_AUTO_DBGPRINT"}, -1, KscopeTestEnvironment::flag_auto_dbg_print, write_output::stable); 470 | insert_label("f2"); 471 | std::cout << kenv->echo("=== "+project_name()+" Fixed Test 2/14 (RELEASE, -DITHARE_KSCOPE_ENABLE_AUTO_DBGPRINT=2, write_output::random)===",true) << std::endl; 472 | fixed_test(KscopeTestEnvironment::config::release, MultiString{"CONSISTENT_XPLATFORM_IMPLICIT_SEEDS","ENABLE_AUTO_DBGPRINT=2"}, 2, KscopeTestEnvironment::flag_auto_dbg_print,write_output::random); 473 | 474 | insert_label("f3"); 475 | std::cout << kenv->echo("=== "+project_name()+" Fixed Test 3/14 (DEBUG, ITHARE_KSCOPE_DISABLE) ===",true) << std::endl; 476 | fixed_test(KscopeTestEnvironment::config::debug,MultiString{"DISABLE"},0); 477 | insert_label("f4"); 478 | std::cout << kenv->echo("=== "+project_name()+" Fixed Test 4/14 (RELEASE, ITHARE_KSCOPE_DISABLE) ===",true) << std::endl; 479 | fixed_test(KscopeTestEnvironment::config::release,MultiString{"DISABLE"},0); 480 | 481 | insert_label("f5"); 482 | std::cout << kenv->echo("=== "+project_name()+" Fixed Test 5/14 (DEBUG, no ITHARE_KSCOPE_SEED) ===",true) << std::endl; 483 | fixed_test(KscopeTestEnvironment::config::debug,{},0); 484 | insert_label("f6"); 485 | std::cout << kenv->echo("=== "+project_name()+" Fixed Test 6/14 (RELEASE, no ITHARE_KSCOPE_SEED) ===",true) << std::endl; 486 | fixed_test(KscopeTestEnvironment::config::release,{},0); 487 | 488 | insert_label("f7"); 489 | std::cout << kenv->echo("=== "+project_name()+" Fixed Test 7/14 (DEBUG, single ITHARE_KSCOPE_SEED) ===",true) << std::endl; 490 | fixed_test(KscopeTestEnvironment::config::debug,{},1); 491 | insert_label("f8"); 492 | std::cout << kenv->echo("=== "+project_name()+" Fixed Test 8/14 (RELEASE, single ITHARE_KSCOPE_SEED) ===",true) << std::endl; 493 | fixed_test(KscopeTestEnvironment::config::release,{},1); 494 | 495 | insert_label("f9"); 496 | std::cout << kenv->echo("=== "+project_name()+" Fixed Test 9/14 (DEBUG) ===",true ) << std::endl; 497 | fixed_test(KscopeTestEnvironment::config::debug,{},2); 498 | insert_label("f10"); 499 | std::cout << kenv->echo("=== "+project_name()+" Fixed Test 10/14 (RELEASE) ===",true ) << std::endl; 500 | fixed_test(KscopeTestEnvironment::config::release,{},2); 501 | 502 | insert_label("f11"); 503 | std::cout << kenv->echo("=== "+project_name()+" Fixed Test 11/14 (DEBUG, -DITHARE_KSCOPE_DBG_RUNTIME_CHECKS) ===" ,true ) << std::endl; 504 | #if defined(_MSC_VER) 505 | std::cout << kenv->echo("*** SKIPPED -DITHARE_KSCOPE_DBG_RUNTIME_CHECKS FOR MSVC (cannot cope) ***",true) << std::endl; 506 | #else 507 | fixed_test(KscopeTestEnvironment::config::debug, MultiString{"DBG_RUNTIME_CHECKS"}, 2); 508 | #endif 509 | insert_label("f12"); 510 | std::cout << kenv->echo( "=== "+project_name()+" Fixed Test 12/14 (RELEASE, -DITHARE_KSCOPE_DBG_RUNTIME_CHECKS) ===" ,true ) << std::endl; 511 | #if defined(_MSC_VER) 512 | std::cout << kenv->echo("*** SKIPPED -DITHARE_KSCOPE_DBG_RUNTIME_CHECKS FOR MSVC (cannot cope) ***",true) << std::endl; 513 | #else 514 | fixed_test(KscopeTestEnvironment::config::release, MultiString{"DBG_RUNTIME_CHECKS"},2); 515 | #endif 516 | 517 | insert_label("f13"); 518 | std::cout << kenv->echo("=== "+project_name()+" Fixed Test 13/14 (DEBUG, -DITHARE_KSCOPE_CRYPTO_PRNG) ===",true) << std::endl; 519 | #if defined(_MSC_VER) && !defined(_M_X64) 520 | std::cout << kenv->echo("*** SKIPPED -DITHARE_KSCOPE_DBG_CRYPTO_PRNG FOR MSVC/x86 (cannot cope) ***",true) << std::endl; 521 | #else 522 | fixed_test(KscopeTestEnvironment::config::debug,MultiString{"CRYPTO_PRNG"},2); 523 | #endif 524 | insert_label("f14"); 525 | std::cout << kenv->echo("=== "+project_name()+" Fixed Test 14/14 (RELEASE, -DITHARE_KSCOPE_CRYPTO_PRNG) ===",true) << std::endl; 526 | #if defined(_MSC_VER) && !defined(_M_X64) 527 | std::cout << kenv->echo("*** SKIPPED -DITHARE_KSCOPE_DBG_CRYPTO_PRNG FOR MSVC/x86 (cannot cope) ***",true) << std::endl; 528 | #else 529 | fixed_test(KscopeTestEnvironment::config::release, MultiString{"CRYPTO_PRNG"}, 2); 530 | #endif 531 | } 532 | 533 | virtual void gen_random_tests(size_t n) { 534 | for (size_t i = 0; i < n; ++i) { 535 | KscopeTestEnvironment::config cfg = KscopeTestEnvironment::config::release; 536 | if (i % 4 == 0) 537 | cfg = KscopeTestEnvironment::config::debug; 538 | MultiString extra; 539 | std::string extraOpts = ""; 540 | if (i % 3 == 0) { //every third, non-exclusive 541 | bool rtchecks_ok = true; 542 | #if defined(_MSC_VER) 543 | rtchecks_ok = false;//cl doesn't seem to cope well with RUNTIME_CHECKS :-( 544 | #endif 545 | if(rtchecks_ok) 546 | extra.append("DBG_RUNTIME_CHECKS"); 547 | } 548 | if(add32tests && i%5 <=1) 549 | extraOpts += kenv->build32_option(); 550 | insert_label(std::string("r")+std::to_string(i+1)); 551 | std::cout << kenv->echo( std::string("=== " + project_name() + " Random Test ") + std::to_string(i+1) + "/" + std::to_string(n) + " ===", true ) << std::endl; 552 | MultiString defines = gen_seeds().append("CONSISTENT_XPLATFORM_IMPLICIT_SEEDS").append(extra); 553 | if( cfg == KscopeTestEnvironment::config::debug ) { 554 | build_check_run_check(kenv->build_debug(defines,extraOpts),2, KscopeTestEnvironment::config::debug,0,write_output::none); 555 | } 556 | else { 557 | assert(cfg == KscopeTestEnvironment::config::release); 558 | build_check_run_check(kenv->build_release(defines,extraOpts),2, KscopeTestEnvironment::config::release,0,write_output::none); 559 | } 560 | } 561 | } 562 | 563 | void gen_setup() { 564 | std::cout << kenv->setup() << std::endl; 565 | } 566 | 567 | void gen_cleanup() { 568 | std::cout << kenv->cleanup() << std::endl; 569 | } 570 | }; 571 | 572 | inline int usage() { 573 | std::cerr << "Usage:" << std::endl; 574 | std::cerr << "randomtestgen"; 575 | #if defined(__APPLE_CC__) || defined(__linux__) 576 | std::cerr << " [-gen_sh]"; 577 | #endif 578 | std::cerr << " [-add32tests] [-srcdirprefix] " << std::endl; 579 | return 1; 580 | } 581 | 582 | inline int almost_main(KscopeTestEnvironment& kenv, KscopeTestGenerator& kgen, int argc, char** argv) { 583 | int argcc = 1; 584 | while(argcc= argc) 606 | return usage(); 607 | char* end; 608 | unsigned long nrandom = strtoul(argv[argcc],&end,10); 609 | if(*end!=0) 610 | return usage(); 611 | 612 | kgen.gen_setup(); 613 | kgen.gen_fixed_tests(); 614 | 615 | kgen.gen_random_tests(nrandom); 616 | kgen.gen_cleanup(); 617 | return 0; 618 | } 619 | -------------------------------------------------------------------------------- /test/test.h: -------------------------------------------------------------------------------- 1 | #ifndef kscope_test_h_included 2 | #define kscope_test_h_included 3 | 4 | class Benchmark { 5 | std::chrono::high_resolution_clock::time_point start; 6 | 7 | public: 8 | Benchmark() { 9 | start = std::chrono::high_resolution_clock::now(); 10 | } 11 | int64_t us() { 12 | auto stop = std::chrono::high_resolution_clock::now(); 13 | auto length = std::chrono::duration_cast(stop - start); 14 | return (int64_t)length.count(); 15 | } 16 | }; 17 | 18 | extern uint64_t bench_test_prng_state;//will be initialized with argc, 100% preventing potential for compile-time calculations 19 | inline uint32_t bench_test_prng(uint32_t mx) {//MT-UNSAFE, but for benchmark tests we don't care 20 | bench_test_prng_state = bench_test_prng_state * UINT64_C(6364136223846793005) + 1; 21 | return (( bench_test_prng_state >> 32 ) & 0x7FFF'FFFF) % mx; 22 | } 23 | 24 | #endif //kscope_test_h_included 25 | -------------------------------------------------------------------------------- /test/win/README.md: -------------------------------------------------------------------------------- 1 | To test your version of x64 MSVC compiler, run randomtest.bat in "**x64** Native Tools Command Prompt for VS2017" 2 | 3 | To test your version of x86 MSVC compiler, run randomtest**32**.bat in "**x86** Native Tools Command Prompt for VS2017" 4 | -------------------------------------------------------------------------------- /test/win/officialtest/officialtest.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27130.2026 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "officialtest", "officialtest.vcxproj", "{D0222A18-7C45-4964-9F21-66A09B8F3539}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {D0222A18-7C45-4964-9F21-66A09B8F3539}.Debug|x64.ActiveCfg = Debug|x64 17 | {D0222A18-7C45-4964-9F21-66A09B8F3539}.Debug|x64.Build.0 = Debug|x64 18 | {D0222A18-7C45-4964-9F21-66A09B8F3539}.Debug|x86.ActiveCfg = Debug|Win32 19 | {D0222A18-7C45-4964-9F21-66A09B8F3539}.Debug|x86.Build.0 = Debug|Win32 20 | {D0222A18-7C45-4964-9F21-66A09B8F3539}.Release|x64.ActiveCfg = Release|x64 21 | {D0222A18-7C45-4964-9F21-66A09B8F3539}.Release|x64.Build.0 = Release|x64 22 | {D0222A18-7C45-4964-9F21-66A09B8F3539}.Release|x86.ActiveCfg = Release|Win32 23 | {D0222A18-7C45-4964-9F21-66A09B8F3539}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {60F859A9-E042-4CE1-819D-EC663D5E909E} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /test/win/officialtest/officialtest.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {D0222A18-7C45-4964-9F21-66A09B8F3539} 24 | Win32Proj 25 | official 26 | 10.0.16299.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v141 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v141 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v141 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v141 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | true 78 | 79 | 80 | false 81 | 82 | 83 | false 84 | 85 | 86 | 87 | NotUsing 88 | Level3 89 | Disabled 90 | true 91 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | true 93 | stdcpp17 94 | 95 | 96 | Console 97 | true 98 | 99 | 100 | 101 | 102 | NotUsing 103 | Level3 104 | Disabled 105 | true 106 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions);ITHARE_KSCOPE_SEED=1234567 107 | true 108 | stdcpp17 109 | /bigobj %(AdditionalOptions) 110 | 111 | 112 | Console 113 | true 114 | 115 | 116 | 117 | 118 | Use 119 | Level3 120 | MaxSpeed 121 | true 122 | true 123 | true 124 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 125 | true 126 | 127 | 128 | Console 129 | true 130 | true 131 | true 132 | 133 | 134 | 135 | 136 | NotUsing 137 | Level3 138 | MaxSpeed 139 | true 140 | true 141 | true 142 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions);ITHARE_KSCOPE_SEED=1234567 143 | true 144 | stdcpp17 145 | 146 | 147 | Console 148 | true 149 | true 150 | true 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /test/win/officialtest/officialtest.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | -------------------------------------------------------------------------------- /test/win/randomtest.bat: -------------------------------------------------------------------------------- 1 | @REM Copyright (c) 2018, ITHare.com 2 | @REM All rights reserved. 3 | @REM 4 | @REM Redistribution and use in source and binary forms, with or without 5 | @REM modification, are permitted provided that the following conditions are met: 6 | @REM 7 | @REM * Redistributions of source code must retain the above copyright notice, this 8 | @REM list of conditions and the following disclaimer. 9 | @REM 10 | @REM * Redistributions in binary form must reproduce the above copyright notice, 11 | @REM this list of conditions and the following disclaimer in the documentation 12 | @REM and/or other materials provided with the distribution. 13 | @REM 14 | @REM * Neither the name of the copyright holder nor the names of its 15 | @REM contributors may be used to endorse or promote products derived from 16 | @REM this software without specific prior written permission. 17 | @REM 18 | @REM THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | @REM AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | @REM IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | @REM DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | @REM FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | @REM DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | @REM SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | @REM CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | @REM OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | @REM OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | @ECHO OFF 30 | cl /EHsc advapi32.lib ..\randomtestgen.cpp 31 | SET NN=%1 32 | IF NOT .%1 == . GOTO LABEL0 33 | SET NN=1024 34 | :LABEL0 35 | 36 | IF NOT ERRORLEVEL 1 GOTO LABEL1 37 | EXIT /B 38 | :LABEL1 39 | 40 | randomtestgen.exe %NN% >generatedrandomtest.bat 41 | IF NOT ERRORLEVEL 1 GOTO LABEL2 42 | EXIT /B 43 | :LABEL2 44 | 45 | CALL generatedrandomtest.bat 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /test/win/randomtest32.bat: -------------------------------------------------------------------------------- 1 | @REM Copyright (c) 2018, ITHare.com 2 | @REM All rights reserved. 3 | @REM 4 | @REM Redistribution and use in source and binary forms, with or without 5 | @REM modification, are permitted provided that the following conditions are met: 6 | @REM 7 | @REM * Redistributions of source code must retain the above copyright notice, this 8 | @REM list of conditions and the following disclaimer. 9 | @REM 10 | @REM * Redistributions in binary form must reproduce the above copyright notice, 11 | @REM this list of conditions and the following disclaimer in the documentation 12 | @REM and/or other materials provided with the distribution. 13 | @REM 14 | @REM * Neither the name of the copyright holder nor the names of its 15 | @REM contributors may be used to endorse or promote products derived from 16 | @REM this software without specific prior written permission. 17 | @REM 18 | @REM THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | @REM AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | @REM IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | @REM DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | @REM FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | @REM DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | @REM SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | @REM CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | @REM OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | @REM OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | @ECHO OFF 30 | mkdir runtest32 31 | cd runtest32 32 | cl /EHsc advapi32.lib ..\..\randomtestgen.cpp 33 | SET NN=%1 34 | IF NOT .%1 == . GOTO LABEL0 35 | SET NN=1024 36 | :LABEL0 37 | 38 | IF NOT ERRORLEVEL 1 GOTO LABEL1 39 | EXIT /B 40 | :LABEL1 41 | 42 | randomtestgen.exe -srcdirprefix ..\ %NN% >generatedrandomtest.bat 43 | IF NOT ERRORLEVEL 1 GOTO LABEL2 44 | EXIT /B 45 | :LABEL2 46 | 47 | CALL generatedrandomtest.bat 48 | 49 | 50 | 51 | --------------------------------------------------------------------------------