diff --git a/.gitignore b/.gitignore
index 4de281a3..551b03ae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,11 @@ include/hotstuff/config.h
/test/test_secp256k1
/test/test_concurrent_queue
core
+
+.idea/
+
+hotstuff-keygen_bls
+
+hotstuff.cbp
+
+log*
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c6af4bd5..245e03a2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -22,6 +22,16 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/salticidae/cmake
add_subdirectory(salticidae)
include_directories(salticidae/include)
+INCLUDE_DIRECTORIES(bls/src)
+INCLUDE_DIRECTORIES(bls/build/contrib/relic/include)
+INCLUDE_DIRECTORIES(bls/contrib/relic/include)
+
+add_library( blstmp STATIC IMPORTED )
+set_target_properties( blstmp PROPERTIES IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/bls/build/src/libblstmp.a )
+
+add_library( relic_s STATIC IMPORTED )
+set_target_properties( relic_s PROPERTIES IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/bls/build/contrib/relic/lib/librelic_s.a )
+
find_package(OpenSSL REQUIRED)
find_package(Threads REQUIRED)
@@ -91,11 +101,16 @@ endif()
# build tools
add_executable(hotstuff-keygen
src/hotstuff_keygen.cpp)
-target_link_libraries(hotstuff-keygen hotstuff_static)
+target_link_libraries(hotstuff-keygen hotstuff_static blstmp relic_s)
+
+add_executable(hotstuff-keygen_bls
+ src/hotstuff_keygen_bls.cpp)
+target_link_libraries(hotstuff-keygen_bls hotstuff_static blstmp relic_s)
+
add_executable(hotstuff-tls-keygen
src/hotstuff_tls_keygen.cpp)
-target_link_libraries(hotstuff-tls-keygen hotstuff_static)
+target_link_libraries(hotstuff-tls-keygen hotstuff_static blstmp relic_s)
find_package(Doxygen)
if (DOXYGEN_FOUND)
diff --git a/bls/build/contrib/relic/include/relic_conf.h b/bls/build/contrib/relic/include/relic_conf.h
new file mode 100644
index 00000000..9930e104
--- /dev/null
+++ b/bls/build/contrib/relic/include/relic_conf.h
@@ -0,0 +1,722 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (C) 2007-2019 RELIC Authors
+ *
+ * This file is part of RELIC. RELIC is legal property of its developers,
+ * whose names are not listed here. Please refer to the COPYRIGHT file
+ * for contact information.
+ *
+ * RELIC is free software; you can redistribute it and/or modify it under the
+ * terms of the version 2.1 (or later) of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; or version 2.0 of the Apache
+ * License as published by the Apache Software Foundation. See the LICENSE files
+ * for more details.
+ *
+ * RELIC is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the LICENSE files for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public or the
+ * Apache License along with RELIC. If not, see
+ * or .
+ */
+
+/**
+ * @file
+ *
+ * Project configuration.
+ *
+ * @version $Id: relic_conf.h.in 45 2009-07-04 23:45:48Z dfaranha $
+ * @ingroup relic
+ */
+
+#ifndef RLC_CONF_H
+#define RLC_CONF_H
+
+/** Project version. */
+#define RLC_VERSION "0.5.0"
+
+/** Debugging support. */
+/* #undef DEBUG */
+/** Profiling support. */
+/* #undef PROFL */
+/** Error handling support. */
+/* #undef CHECK */
+/** Verbose error messages. */
+/* #undef VERBS */
+/** Build with overhead estimation. */
+/* #undef OVERH */
+/** Build documentation. */
+#define DOCUM
+/** Build only the selected algorithms. */
+/* #undef STRIP */
+/** Build with printing disabled. */
+#define QUIET
+/** Build with colored output. */
+#define COLOR
+/** Build with big-endian support. */
+/* #undef BIGED */
+/** Build shared library. */
+/* #undef SHLIB */
+/** Build static library. */
+#define STLIB
+
+/** Number of times each test is ran. */
+#define TESTS 0
+/** Number of times each benchmark is ran. */
+#define BENCH 0
+
+/** Number of available cores. */
+#define CORES 1
+
+/** Atmel AVR ATMega128 8-bit architecture. */
+#define AVR 1
+/** MSP430 16-bit architecture. */
+#define MSP 2
+/** ARM 32-bit architecture. */
+#define ARM 3
+/** Intel x86-compatible 32-bit architecture. */
+#define X86 4
+/** AMD64-compatible 64-bit architecture. */
+#define X64 5
+/** Architecture. */
+#define ARCH X64
+
+/** Size of word in this architecture. */
+#define WSIZE 64
+
+/** Byte boundary to align digit vectors. */
+#define ALIGN 1
+
+/** Build multiple precision integer module. */
+#define WITH_BN
+/** Build prime field module. */
+#define WITH_FP
+/** Build prime field extension module. */
+#define WITH_FPX
+/** Build binary field module. */
+#define WITH_FB
+/** Build prime elliptic curve module. */
+#define WITH_EP
+/** Build prime field extension elliptic curve module. */
+#define WITH_EPX
+/** Build binary elliptic curve module. */
+#define WITH_EB
+/** Build elliptic Edwards curve module. */
+#define WITH_ED
+/** Build elliptic curve cryptography module. */
+#define WITH_EC
+/** Build pairings over prime curves module. */
+#define WITH_PP
+/** Build pairing-based cryptography module. */
+#define WITH_PC
+/** Build block ciphers. */
+#define WITH_BC
+/** Build hash functions. */
+#define WITH_MD
+/** Build cryptographic protocols. */
+#define WITH_CP
+
+/** Easy C-only backend. */
+#define EASY 1
+/** GMP backend. */
+#define GMP 2
+/** Arithmetic backend. */
+#define ARITH EASY
+
+/** Required precision in bits. */
+#define BN_PRECI 1024
+/** A multiple precision integer can store w words. */
+#define SINGLE 0
+/** A multiple precision integer can store the result of an addition. */
+#define CARRY 1
+/** A multiple precision integer can store the result of a multiplication. */
+#define DOUBLE 2
+/** Effective size of a multiple precision integer. */
+#define BN_MAGNI DOUBLE
+/** Number of Karatsuba steps. */
+#define BN_KARAT 0
+
+/** Schoolbook multiplication. */
+#define BASIC 1
+/** Comba multiplication. */
+#define COMBA 2
+/** Chosen multiple precision multiplication method. */
+#define BN_MUL COMBA
+
+/** Schoolbook squaring. */
+#define BASIC 1
+/** Comba squaring. */
+#define COMBA 2
+/** Reuse multiplication for squaring. */
+#define MULTP 4
+/** Chosen multiple precision multiplication method. */
+#define BN_SQR COMBA
+
+/** Division modular reduction. */
+#define BASIC 1
+/** Barrett modular reduction. */
+#define BARRT 2
+/** Montgomery modular reduction. */
+#define MONTY 3
+/** Pseudo-Mersenne modular reduction. */
+#define PMERS 4
+/** Chosen multiple precision modular reduction method. */
+#define BN_MOD MONTY
+
+/** Binary modular exponentiation. */
+#define BASIC 1
+/** Sliding window modular exponentiation. */
+#define SLIDE 2
+/** Montgomery powering ladder. */
+#define MONTY 3
+/** Chosen multiple precision modular exponentiation method. */
+#define BN_MXP SLIDE
+
+/** Basic Euclidean GCD Algorithm. */
+#define BASIC 1
+/** Lehmer's fast GCD Algorithm. */
+#define LEHME 2
+/** Stein's binary GCD Algorithm. */
+#define STEIN 3
+/** Chosen multiple precision greatest common divisor method. */
+#define BN_GCD BASIC
+
+/** Basic prime generation. */
+#define BASIC 1
+/** Safe prime generation. */
+#define SAFEP 2
+/** Strong prime generation. */
+#define STRON 3
+/** Chosen prime generation algorithm. */
+#define BN_GEN BASIC
+
+/** Multiple precision arithmetic method */
+#define BN_METHD "COMBA;COMBA;MONTY;SLIDE;BASIC;BASIC"
+
+/** Prime field size in bits. */
+#define FP_PRIME 381
+/** Number of Karatsuba steps. */
+#define FP_KARAT 0
+/** Prefer Pseudo-Mersenne primes over random primes. */
+/* #undef FP_PMERS */
+/** Use -1 as quadratic non-residue. */
+#define FP_QNRES
+/** Width of window processing for exponentiation methods. */
+#define FP_WIDTH 4
+
+/** Schoolbook addition. */
+#define BASIC 1
+/** Integrated modular addtion. */
+#define INTEG 3
+/** Chosen prime field multiplication method. */
+#define FP_ADD INTEG
+
+/** Schoolbook multiplication. */
+#define BASIC 1
+/** Comba multiplication. */
+#define COMBA 2
+/** Integrated modular multiplication. */
+#define INTEG 3
+/** Chosen prime field multiplication method. */
+#define FP_MUL INTEG
+
+/** Schoolbook squaring. */
+#define BASIC 1
+/** Comba squaring. */
+#define COMBA 2
+/** Integrated modular squaring. */
+#define INTEG 3
+/** Reuse multiplication for squaring. */
+#define MULTP 4
+/** Chosen prime field multiplication method. */
+#define FP_SQR INTEG
+
+/** Division-based reduction. */
+#define BASIC 1
+/** Fast reduction modulo special form prime. */
+#define QUICK 2
+/** Montgomery modular reduction. */
+#define MONTY 3
+/** Chosen prime field reduction method. */
+#define FP_RDC MONTY
+
+/** Inversion by Fermat's Little Theorem. */
+#define BASIC 1
+/** Binary inversion. */
+#define BINAR 2
+/** Integrated modular multiplication. */
+#define MONTY 3
+/** Extended Euclidean algorithm. */
+#define EXGCD 4
+/** Constant-time inversion by Bernstein-Yang division steps. */
+#define DIVST 5
+/** Use implementation provided by the lower layer. */
+#define LOWER 8
+/** Chosen prime field inversion method. */
+#define FP_INV LOWER
+
+/** Binary modular exponentiation. */
+#define BASIC 1
+/** Sliding window modular exponentiation. */
+#define SLIDE 2
+/** Constant-time Montgomery powering ladder. */
+#define MONTY 3
+/** Chosen multiple precision modular exponentiation method. */
+#define FP_EXP SLIDE
+
+/** Prime field arithmetic method */
+#define FP_METHD "INTEG;INTEG;INTEG;MONTY;LOWER;SLIDE"
+
+/** Basic quadratic extension field arithmetic. */
+#define BASIC 1
+/** Integrated extension field arithmetic. */
+#define INTEG 3
+/* Chosen extension field arithmetic method. */
+#define FPX_QDR INTEG
+
+/** Basic cubic extension field arithmetic. */
+#define BASIC 1
+/** Integrated extension field arithmetic. */
+#define INTEG 3
+/* Chosen extension field arithmetic method. */
+#define FPX_CBC INTEG
+
+/** Basic quadratic extension field arithmetic. */
+#define BASIC 1
+/** Lazy-reduced extension field arithmetic. */
+#define LAZYR 2
+/* Chosen extension field arithmetic method. */
+#define FPX_RDC LAZYR
+
+/** Prime extension field arithmetic method */
+#define FPX_METHD "INTEG;INTEG;LAZYR"
+
+/** Irreducible polynomial size in bits. */
+#define FB_POLYN 283
+/** Number of Karatsuba steps. */
+#define FB_KARAT 0
+/** Prefer trinomials over pentanomials. */
+#define FB_TRINO
+/** Prefer square-root friendly polynomials. */
+/* #undef FB_SQRTF */
+/** Precompute multiplication table for sqrt(z). */
+#define FB_PRECO
+/** Width of window processing for exponentiation methods. */
+#define FB_WIDTH 4
+
+/** Shift-and-add multiplication. */
+#define BASIC 1
+/** Lopez-Dahab multiplication. */
+#define LODAH 2
+/** Integrated modular multiplication. */
+#define INTEG 3
+/** Chosen binary field multiplication method. */
+#define FB_MUL LODAH
+
+/** Basic squaring. */
+#define BASIC 1
+/** Table-based squaring. */
+#define QUICK 2
+/** Integrated modular squaring. */
+#define INTEG 3
+/** Chosen binary field squaring method. */
+#define FB_SQR QUICK
+
+/** Shift-and-add modular reduction. */
+#define BASIC 1
+/** Fast reduction modulo a trinomial or pentanomial. */
+#define QUICK 2
+/** Chosen binary field modular reduction method. */
+#define FB_RDC QUICK
+
+/** Square root by repeated squaring. */
+#define BASIC 1
+/** Fast square root extraction. */
+#define QUICK 2
+/** Chosen binary field modular reduction method. */
+#define FB_SRT QUICK
+
+/** Trace by repeated squaring. */
+#define BASIC 1
+/** Fast trace computation. */
+#define QUICK 2
+/** Chosen trace computation method. */
+#define FB_TRC QUICK
+
+/** Solve by half-trace computation. */
+#define BASIC 1
+/** Solve with precomputed half-traces. */
+#define QUICK 2
+/** Chosen method to solve a quadratic equation. */
+#define FB_SLV QUICK
+
+/** Inversion by Fermat's Little Theorem. */
+#define BASIC 1
+/** Binary inversion. */
+#define BINAR 2
+/** Almost inverse algorithm. */
+#define ALMOS 3
+/** Extended Euclidean algorithm. */
+#define EXGCD 4
+/** Itoh-Tsuji inversion. */
+#define ITOHT 5
+/** Hardware-friendly inversion by Brunner-Curiger-Hofstetter.*/
+#define BRUCH 6
+/** Constant-time version of almost inverse. */
+#define CTAIA 7
+/** Use implementation provided by the lower layer. */
+#define LOWER 8
+/** Chosen binary field inversion method. */
+#define FB_INV EXGCD
+
+/** Binary modular exponentiation. */
+#define BASIC 1
+/** Sliding window modular exponentiation. */
+#define SLIDE 2
+/** Constant-time Montgomery powering ladder. */
+#define MONTY 3
+/** Chosen multiple precision modular exponentiation method. */
+#define FB_EXP SLIDE
+
+/** Iterated squaring/square-root by consecutive squaring/square-root. */
+#define BASIC 1
+/** Iterated squaring/square-root by table-based method. */
+#define QUICK 2
+/** Chosen method to solve a quadratic equation. */
+#define FB_ITR QUICK
+
+/** Binary field arithmetic method */
+#define FB_METHD "LODAH;QUICK;QUICK;QUICK;QUICK;QUICK;EXGCD;SLIDE;QUICK"
+
+/** Support for ordinary curves. */
+/* #undef EP_PLAIN */
+/** Support for supersingular curves. */
+/* #undef EP_SUPER */
+/** Support for prime curves with efficient endormorphisms. */
+#define EP_ENDOM
+/** Use mixed coordinates. */
+#define EP_MIXED
+/** Build precomputation table for generator. */
+#define EP_PRECO
+/** Enable isogeny map for SSWU map-to-curve. */
+#define EP_CTMAP
+/** Width of precomputation table for fixed point methods. */
+#define EP_DEPTH 4
+/** Width of window processing for unknown point methods. */
+#define EP_WIDTH 4
+
+/** Affine coordinates. */
+#define BASIC 1
+/** Projective coordinates. */
+#define PROJC 2
+/** Chosen prime elliptic curve coordinate method. */
+#define EP_ADD PROJC
+
+/** Binary point multiplication. */
+#define BASIC 1
+/** Sliding window. */
+#define SLIDE 2
+/** Montgomery powering ladder. */
+#define MONTY 3
+/** Left-to-right Width-w NAF. */
+#define LWNAF 4
+/** Left-to-right Width-w NAF. */
+#define LWREG 5
+/** Chosen prime elliptic curve point multiplication method. */
+#define EP_MUL LWNAF
+
+/** Binary point multiplication. */
+#define BASIC 1
+/** Single-table comb method. */
+#define COMBS 2
+/** Double-table comb method. */
+#define COMBD 3
+/** Left-to-right Width-w NAF. */
+#define LWNAF 4
+/** Chosen prime elliptic curve point multiplication method. */
+#define EP_FIX COMBS
+
+/** Basic simultaneouns point multiplication. */
+#define BASIC 1
+/** Shamir's trick. */
+#define TRICK 2
+/** Interleaving of w-(T)NAFs. */
+#define INTER 3
+/** Joint sparse form. */
+#define JOINT 4
+/** Chosen prime elliptic curve simulteanous point multiplication method. */
+#define EP_SIM INTER
+
+/** Prime elliptic curve arithmetic method. */
+#define EP_METHD "PROJC;LWNAF;COMBS;INTER"
+
+/** Support for ordinary curves without endormorphisms. */
+#define EB_PLAIN
+/** Support for Koblitz anomalous binary curves. */
+#define EB_KBLTZ
+/** Use mixed coordinates. */
+#define EB_MIXED
+/** Build precomputation table for generator. */
+#define EB_PRECO
+/** Width of precomputation table for fixed point methods. */
+#define EB_DEPTH 4
+/** Width of window processing for unknown point methods. */
+#define EB_WIDTH 4
+
+/** Binary elliptic curve arithmetic method. */
+#define EB_METHD "PROJC;LWNAF;COMBS;INTER"
+
+/** Affine coordinates. */
+#define BASIC 1
+/** López-Dahab Projective coordinates. */
+#define PROJC 2
+/** Chosen binary elliptic curve coordinate method. */
+#define EB_ADD PROJC
+
+/** Binary point multiplication. */
+#define BASIC 1
+/** López-Dahab point multiplication. */
+#define LODAH 2
+/** Halving. */
+#define HALVE 3
+/** Left-to-right width-w (T)NAF. */
+#define LWNAF 4
+/** Right-to-left width-w (T)NAF. */
+#define RWNAF 5
+/** Chosen binary elliptic curve point multiplication method. */
+#define EB_MUL LWNAF
+
+/** Binary point multiplication. */
+#define BASIC 1
+/** Single-table comb method. */
+#define COMBS 2
+/** Double-table comb method. */
+#define COMBD 3
+/** Left-to-right Width-w NAF. */
+#define LWNAF 4
+/** Chosen binary elliptic curve point multiplication method. */
+#define EB_FIX COMBS
+
+/** Basic simultaneouns point multiplication. */
+#define BASIC 1
+/** Shamir's trick. */
+#define TRICK 2
+/** Interleaving of w-(T)NAFs. */
+#define INTER 3
+/** Joint sparse form. */
+#define JOINT 4
+/** Chosen binary elliptic curve simulteanous point multiplication method. */
+#define EB_SIM INTER
+
+/** Build precomputation table for generator. */
+#define ED_PRECO
+/** Width of precomputation table for fixed point methods. */
+#define ED_DEPTH 4
+/** Width of window processing for unknown point methods. */
+#define ED_WIDTH 4
+
+/** Edwards elliptic curve arithmetic method. */
+#define ED_METHD "PROJC;LWNAF;COMBS;INTER"
+
+/** Affine coordinates. */
+#define BASIC 1
+/** Simple projective twisted Edwards coordinates */
+#define PROJC 2
+/** Extended projective twisted Edwards coordinates */
+#define EXTND 3
+/** Chosen binary elliptic curve coordinate method. */
+#define ED_ADD PROJC
+
+/** Binary point multiplication. */
+#define BASIC 1
+/** Sliding window. */
+#define SLIDE 2
+/** Montgomery powering ladder. */
+#define MONTY 3
+/** Left-to-right Width-w NAF. */
+#define LWNAF 4
+/** Left-to-right Width-w NAF. */
+#define LWREG 5
+/** Chosen prime elliptic twisted Edwards curve point multiplication method. */
+#define ED_MUL LWNAF
+
+/** Binary point multiplication. */
+#define BASIC 1
+/** Single-table comb method. */
+#define COMBS 2
+/** Double-table comb method. */
+#define COMBD 3
+/** Left-to-right Width-w NAF. */
+#define LWNAF 4
+/** Chosen prime elliptic twisted Edwards curve point multiplication method. */
+#define ED_FIX COMBS
+
+/** Basic simultaneouns point multiplication. */
+#define BASIC 1
+/** Shamir's trick. */
+#define TRICK 2
+/** Interleaving of w-(T)NAFs. */
+#define INTER 3
+/** Joint sparse form. */
+#define JOINT 4
+/** Chosen prime elliptic curve simulteanous point multiplication method. */
+#define ED_SIM INTER
+
+/** Prime curves. */
+#define PRIME 1
+/** Binary curves. */
+#define CHAR2 2
+/** Edwards curves */
+#define EDDIE 3
+/** Chosen elliptic curve type. */
+#define EC_CUR PRIME
+
+/** Chosen elliptic curve cryptography method. */
+#define EC_METHD "PRIME"
+/** Prefer curves with efficient endomorphisms. */
+/* #undef EC_ENDOM */
+
+/** Basic quadratic extension field arithmetic. */
+#define BASIC 1
+/** Lazy-reduced extension field arithmetic. */
+#define LAZYR 2
+/* Chosen extension field arithmetic method. */
+#define PP_EXT LAZYR
+
+/** Bilinear pairing method. */
+#define PP_METHD "LAZYR;OATEP"
+
+/** Tate pairing. */
+#define TATEP 1
+/** Weil pairing. */
+#define WEILP 2
+/** Optimal ate pairing. */
+#define OATEP 3
+/** Chosen pairing method over prime elliptic curves. */
+#define PP_MAP OATEP
+
+/** SHA-224 hash function. */
+#define SH224 2
+/** SHA-256 hash function. */
+#define SH256 3
+/** SHA-384 hash function. */
+#define SH384 4
+/** SHA-512 hash function. */
+#define SH512 5
+/** BLAKE2s-160 hash function. */
+#define B2S160 6
+/** BLAKE2s-256 hash function. */
+#define B2S256 7
+/** Chosen hash function. */
+#define MD_MAP SH256
+
+/** Choice of hash function. */
+#define MD_METHD "SH256"
+
+/** RSA without padding. */
+#define BASIC 1
+/** RSA PKCS#1 v1.5 padding. */
+#define PKCS1 2
+/** RSA PKCS#1 v2.1 padding. */
+#define PKCS2 3
+/** Chosen RSA padding method. */
+#define CP_RSAPD PKCS1
+
+/** Slow RSA decryption/signature. */
+#define BASIC 1
+/** Fast RSA decryption/signature with CRT. */
+#define QUICK 2
+/** Chosen RSA method. */
+#define CP_RSA QUICK
+
+/** Standard ECDSA. */
+#define BASIC 1
+/** ECDSA with fast verification. */
+#define QUICK 2
+/** Chosen ECDSA method. */
+#define CP_ECDSA
+
+/** Automatic memory allocation. */
+#define AUTO 1
+/** Dynamic memory allocation. */
+#define DYNAMIC 2
+/** Stack memory allocation. */
+#define STACK 3
+/** Chosen memory allocation policy. */
+#define ALLOC AUTO
+
+/** NIST HASH-DRBG generator. */
+#define HASHD 1
+/** Intel RdRand instruction. */
+#define RDRND 2
+/** Operating system underlying generator. */
+#define UDEV 3
+/** Override library generator with the callback. */
+#define CALL 4
+/** Chosen random generator. */
+#define RAND HASHD
+
+/** Standard C library generator. */
+#define LIBC 1
+/** Intel RdRand instruction. */
+#define RDRND 2
+/** Device node generator. */
+#define UDEV 3
+/** Use Windows' CryptGenRandom. */
+#define WCGR 4
+/** Chosen random generator seeder. */
+#define SEED UDEV
+
+/** GNU/Linux operating system. */
+#define LINUX 1
+/** FreeBSD operating system. */
+#define FREEBSD 2
+/** Windows operating system. */
+#define MACOSX 3
+/** Windows operating system. */
+#define WINDOWS 4
+/** Android operating system. */
+#define DROID 5
+/* Arduino platform. */
+#define DUINO 6
+/** Detected operation system. */
+#define OPSYS LINUX
+
+/** OpenMP multithreading support. */
+#define OPENMP 1
+/** POSIX multithreading support. */
+#define PTHREAD 2
+/** Chosen multithreading API. */
+#define MULTI PTHREAD
+
+/** Per-process high-resolution timer. */
+#define HREAL 1
+/** Per-process high-resolution timer. */
+#define HPROC 2
+/** Per-thread high-resolution timer. */
+#define HTHRD 3
+/** POSIX-compatible timer. */
+#define POSIX 4
+/** ANSI-compatible timer. */
+#define ANSI 5
+/** Cycle-counting timer. */
+#define CYCLE 6
+/** Chosen timer. */
+#define TIMER CYCLE
+
+/** Prefix to identity this build of the library. */
+/* #undef LABEL */
+
+#ifndef ASM
+
+#include "relic_label.h"
+
+/**
+ * Prints the project options selected at build time.
+ */
+void conf_print(void);
+
+#endif /* ASM */
+
+#endif /* !RLC_CONF_H */
diff --git a/bls/build/contrib/relic/lib/librelic_s.a b/bls/build/contrib/relic/lib/librelic_s.a
new file mode 100644
index 00000000..f41c2d2b
Binary files /dev/null and b/bls/build/contrib/relic/lib/librelic_s.a differ
diff --git a/bls/build/libbls.a b/bls/build/libbls.a
new file mode 100644
index 00000000..bb1d83fb
Binary files /dev/null and b/bls/build/libbls.a differ
diff --git a/bls/build/src/libbls.a b/bls/build/src/libbls.a
new file mode 100644
index 00000000..f49fee19
Binary files /dev/null and b/bls/build/src/libbls.a differ
diff --git a/bls/build/src/libblstmp.a b/bls/build/src/libblstmp.a
new file mode 100644
index 00000000..12b7349d
Binary files /dev/null and b/bls/build/src/libblstmp.a differ
diff --git a/bls/contrib/catch/catch.hpp b/bls/contrib/catch/catch.hpp
new file mode 100644
index 00000000..aacc5601
--- /dev/null
+++ b/bls/contrib/catch/catch.hpp
@@ -0,0 +1,13286 @@
+/*
+ * Catch v2.2.3
+ * Generated: 2018-06-06 23:11:57.601416
+ * ----------------------------------------------------------
+ * This file has been merged from multiple headers. Please don't edit it directly
+ * Copyright (c) 2018 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
+#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
+// start catch.hpp
+
+
+#define CATCH_VERSION_MAJOR 2
+#define CATCH_VERSION_MINOR 2
+#define CATCH_VERSION_PATCH 3
+
+#ifdef __clang__
+# pragma clang system_header
+#elif defined __GNUC__
+# pragma GCC system_header
+#endif
+
+// start catch_suppress_warnings.h
+
+#ifdef __clang__
+# ifdef __ICC // icpc defines the __clang__ macro
+# pragma warning(push)
+# pragma warning(disable: 161 1682)
+# else // __ICC
+# pragma clang diagnostic ignored "-Wunused-variable"
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wpadded"
+# pragma clang diagnostic ignored "-Wswitch-enum"
+# pragma clang diagnostic ignored "-Wcovered-switch-default"
+# endif
+#elif defined __GNUC__
+# pragma GCC diagnostic ignored "-Wparentheses"
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wunused-variable"
+# pragma GCC diagnostic ignored "-Wpadded"
+#endif
+// end catch_suppress_warnings.h
+#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
+# define CATCH_IMPL
+# define CATCH_CONFIG_ALL_PARTS
+#endif
+
+// In the impl file, we want to have access to all parts of the headers
+// Can also be used to sanely support PCHs
+#if defined(CATCH_CONFIG_ALL_PARTS)
+# define CATCH_CONFIG_EXTERNAL_INTERFACES
+# if defined(CATCH_CONFIG_DISABLE_MATCHERS)
+# undef CATCH_CONFIG_DISABLE_MATCHERS
+# endif
+# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
+#endif
+
+#if !defined(CATCH_CONFIG_IMPL_ONLY)
+// start catch_platform.h
+
+#ifdef __APPLE__
+# include
+# if TARGET_OS_OSX == 1
+# define CATCH_PLATFORM_MAC
+# elif TARGET_OS_IPHONE == 1
+# define CATCH_PLATFORM_IPHONE
+# endif
+
+#elif defined(linux) || defined(__linux) || defined(__linux__)
+# define CATCH_PLATFORM_LINUX
+
+#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__)
+# define CATCH_PLATFORM_WINDOWS
+#endif
+
+// end catch_platform.h
+
+#ifdef CATCH_IMPL
+# ifndef CLARA_CONFIG_MAIN
+# define CLARA_CONFIG_MAIN_NOT_DEFINED
+# define CLARA_CONFIG_MAIN
+# endif
+#endif
+
+// start catch_user_interfaces.h
+
+namespace Catch {
+ unsigned int rngSeed();
+}
+
+// end catch_user_interfaces.h
+// start catch_tag_alias_autoregistrar.h
+
+// start catch_common.h
+
+// start catch_compiler_capabilities.h
+
+// Detect a number of compiler features - by compiler
+// The following features are defined:
+//
+// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
+// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
+// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
+// ****************
+// Note to maintainers: if new toggles are added please document them
+// in configuration.md, too
+// ****************
+
+// In general each macro has a _NO_ form
+// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature.
+// Many features, at point of detection, define an _INTERNAL_ macro, so they
+// can be combined, en-mass, with the _NO_ forms later.
+
+#ifdef __cplusplus
+
+# if __cplusplus >= 201402L
+# define CATCH_CPP14_OR_GREATER
+# endif
+
+# if __cplusplus >= 201703L
+# define CATCH_CPP17_OR_GREATER
+# endif
+
+#endif
+
+#if defined(CATCH_CPP17_OR_GREATER)
+# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
+#endif
+
+#ifdef __clang__
+
+# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+ _Pragma( "clang diagnostic push" ) \
+ _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \
+ _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"")
+# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
+ _Pragma( "clang diagnostic pop" )
+
+# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
+ _Pragma( "clang diagnostic push" ) \
+ _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
+# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
+ _Pragma( "clang diagnostic pop" )
+
+#endif // __clang__
+
+////////////////////////////////////////////////////////////////////////////////
+// Assume that non-Windows platforms support posix signals by default
+#if !defined(CATCH_PLATFORM_WINDOWS)
+ #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// We know some environments not to support full POSIX signals
+#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__)
+ #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
+#endif
+
+#ifdef __OS400__
+# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
+# define CATCH_CONFIG_COLOUR_NONE
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// Android somehow still does not support std::to_string
+#if defined(__ANDROID__)
+# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// Not all Windows environments support SEH properly
+#if defined(__MINGW32__)
+# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// Cygwin
+#ifdef __CYGWIN__
+
+// Required for some versions of Cygwin to declare gettimeofday
+// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
+# define _BSD_SOURCE
+
+#endif // __CYGWIN__
+
+////////////////////////////////////////////////////////////////////////////////
+// Visual C++
+#ifdef _MSC_VER
+
+# if _MSC_VER >= 1900 // Visual Studio 2015 or newer
+# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
+# endif
+
+// Universal Windows platform does not support SEH
+// Or console colours (or console at all...)
+# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
+# define CATCH_CONFIG_COLOUR_NONE
+# else
+# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
+# endif
+
+#endif // _MSC_VER
+
+////////////////////////////////////////////////////////////////////////////////
+
+// DJGPP
+#ifdef __DJGPP__
+# define CATCH_INTERNAL_CONFIG_NO_WCHAR
+#endif // __DJGPP__
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Use of __COUNTER__ is suppressed during code analysis in
+// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly
+// handled by it.
+// Otherwise all supported compilers support COUNTER macro,
+// but user still might want to turn it off
+#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L )
+ #define CATCH_INTERNAL_CONFIG_COUNTER
+#endif
+
+#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
+# define CATCH_CONFIG_COUNTER
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH)
+# define CATCH_CONFIG_WINDOWS_SEH
+#endif
+// This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
+#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
+# define CATCH_CONFIG_POSIX_SIGNALS
+#endif
+// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions.
+#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR)
+# define CATCH_CONFIG_WCHAR
+#endif
+
+#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING)
+# define CATCH_CONFIG_CPP11_TO_STRING
+#endif
+
+#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
+# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
+#endif
+
+#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
+# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
+# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
+#endif
+#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS)
+# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
+# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
+#endif
+
+// end catch_compiler_capabilities.h
+#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
+#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
+#ifdef CATCH_CONFIG_COUNTER
+# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
+#else
+# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
+#endif
+
+#include
+#include
+#include
+
+namespace Catch {
+
+ struct CaseSensitive { enum Choice {
+ Yes,
+ No
+ }; };
+
+ class NonCopyable {
+ NonCopyable( NonCopyable const& ) = delete;
+ NonCopyable( NonCopyable && ) = delete;
+ NonCopyable& operator = ( NonCopyable const& ) = delete;
+ NonCopyable& operator = ( NonCopyable && ) = delete;
+
+ protected:
+ NonCopyable();
+ virtual ~NonCopyable();
+ };
+
+ struct SourceLineInfo {
+
+ SourceLineInfo() = delete;
+ SourceLineInfo( char const* _file, std::size_t _line ) noexcept
+ : file( _file ),
+ line( _line )
+ {}
+
+ SourceLineInfo( SourceLineInfo const& other ) = default;
+ SourceLineInfo( SourceLineInfo && ) = default;
+ SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
+ SourceLineInfo& operator = ( SourceLineInfo && ) = default;
+
+ bool empty() const noexcept;
+ bool operator == ( SourceLineInfo const& other ) const noexcept;
+ bool operator < ( SourceLineInfo const& other ) const noexcept;
+
+ char const* file;
+ std::size_t line;
+ };
+
+ std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
+
+ // Use this in variadic streaming macros to allow
+ // >> +StreamEndStop
+ // as well as
+ // >> stuff +StreamEndStop
+ struct StreamEndStop {
+ std::string operator+() const;
+ };
+ template
+ T const& operator + ( T const& value, StreamEndStop ) {
+ return value;
+ }
+}
+
+#define CATCH_INTERNAL_LINEINFO \
+ ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) )
+
+// end catch_common.h
+namespace Catch {
+
+ struct RegistrarForTagAliases {
+ RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
+ };
+
+} // end namespace Catch
+
+#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \
+ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+ namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \
+ CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
+
+// end catch_tag_alias_autoregistrar.h
+// start catch_test_registry.h
+
+// start catch_interfaces_testcase.h
+
+#include
+#include
+
+namespace Catch {
+
+ class TestSpec;
+
+ struct ITestInvoker {
+ virtual void invoke () const = 0;
+ virtual ~ITestInvoker();
+ };
+
+ using ITestCasePtr = std::shared_ptr;
+
+ class TestCase;
+ struct IConfig;
+
+ struct ITestCaseRegistry {
+ virtual ~ITestCaseRegistry();
+ virtual std::vector const& getAllTests() const = 0;
+ virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0;
+ };
+
+ bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
+ std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config );
+ std::vector const& getAllTestCasesSorted( IConfig const& config );
+
+}
+
+// end catch_interfaces_testcase.h
+// start catch_stringref.h
+
+#include
+#include
+#include
+
+namespace Catch {
+
+ class StringData;
+
+ /// A non-owning string class (similar to the forthcoming std::string_view)
+ /// Note that, because a StringRef may be a substring of another string,
+ /// it may not be null terminated. c_str() must return a null terminated
+ /// string, however, and so the StringRef will internally take ownership
+ /// (taking a copy), if necessary. In theory this ownership is not externally
+ /// visible - but it does mean (substring) StringRefs should not be shared between
+ /// threads.
+ class StringRef {
+ public:
+ using size_type = std::size_t;
+
+ private:
+ friend struct StringRefTestAccess;
+
+ char const* m_start;
+ size_type m_size;
+
+ char* m_data = nullptr;
+
+ void takeOwnership();
+
+ static constexpr char const* const s_empty = "";
+
+ public: // construction/ assignment
+ StringRef() noexcept
+ : StringRef( s_empty, 0 )
+ {}
+
+ StringRef( StringRef const& other ) noexcept
+ : m_start( other.m_start ),
+ m_size( other.m_size )
+ {}
+
+ StringRef( StringRef&& other ) noexcept
+ : m_start( other.m_start ),
+ m_size( other.m_size ),
+ m_data( other.m_data )
+ {
+ other.m_data = nullptr;
+ }
+
+ StringRef( char const* rawChars ) noexcept;
+
+ StringRef( char const* rawChars, size_type size ) noexcept
+ : m_start( rawChars ),
+ m_size( size )
+ {}
+
+ StringRef( std::string const& stdString ) noexcept
+ : m_start( stdString.c_str() ),
+ m_size( stdString.size() )
+ {}
+
+ ~StringRef() noexcept {
+ delete[] m_data;
+ }
+
+ auto operator = ( StringRef const &other ) noexcept -> StringRef& {
+ delete[] m_data;
+ m_data = nullptr;
+ m_start = other.m_start;
+ m_size = other.m_size;
+ return *this;
+ }
+
+ operator std::string() const;
+
+ void swap( StringRef& other ) noexcept;
+
+ public: // operators
+ auto operator == ( StringRef const& other ) const noexcept -> bool;
+ auto operator != ( StringRef const& other ) const noexcept -> bool;
+
+ auto operator[] ( size_type index ) const noexcept -> char;
+
+ public: // named queries
+ auto empty() const noexcept -> bool {
+ return m_size == 0;
+ }
+ auto size() const noexcept -> size_type {
+ return m_size;
+ }
+
+ auto numberOfCharacters() const noexcept -> size_type;
+ auto c_str() const -> char const*;
+
+ public: // substrings and searches
+ auto substr( size_type start, size_type size ) const noexcept -> StringRef;
+
+ // Returns the current start pointer.
+ // Note that the pointer can change when if the StringRef is a substring
+ auto currentData() const noexcept -> char const*;
+
+ private: // ownership queries - may not be consistent between calls
+ auto isOwned() const noexcept -> bool;
+ auto isSubstring() const noexcept -> bool;
+ };
+
+ auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string;
+ auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string;
+ auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string;
+
+ auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&;
+ auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&;
+
+ inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {
+ return StringRef( rawChars, size );
+ }
+
+} // namespace Catch
+
+// end catch_stringref.h
+namespace Catch {
+
+template
+class TestInvokerAsMethod : public ITestInvoker {
+ void (C::*m_testAsMethod)();
+public:
+ TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {}
+
+ void invoke() const override {
+ C obj;
+ (obj.*m_testAsMethod)();
+ }
+};
+
+auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*;
+
+template
+auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* {
+ return new(std::nothrow) TestInvokerAsMethod( testAsMethod );
+}
+
+struct NameAndTags {
+ NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept;
+ StringRef name;
+ StringRef tags;
+};
+
+struct AutoReg : NonCopyable {
+ AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept;
+ ~AutoReg();
+};
+
+} // end namespace Catch
+
+#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param)
+#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__
+#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
+#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
+
+#if defined(CATCH_CONFIG_DISABLE)
+ #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
+ static void TestName()
+ #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
+ namespace{ \
+ struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \
+ void test(); \
+ }; \
+ } \
+ void TestName::test()
+
+#endif
+
+ ///////////////////////////////////////////////////////////////////////////////
+ #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
+ static void TestName(); \
+ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
+ CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
+ static void TestName()
+ #define INTERNAL_CATCH_TESTCASE( ... ) \
+ INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
+
+ ///////////////////////////////////////////////////////////////////////////////
+ #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
+ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
+ CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
+
+ ///////////////////////////////////////////////////////////////////////////////
+ #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
+ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+ namespace{ \
+ struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \
+ void test(); \
+ }; \
+ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
+ } \
+ CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
+ void TestName::test()
+ #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
+ INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
+
+ ///////////////////////////////////////////////////////////////////////////////
+ #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
+ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
+ CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
+
+// end catch_test_registry.h
+// start catch_capture.hpp
+
+// start catch_assertionhandler.h
+
+// start catch_assertioninfo.h
+
+// start catch_result_type.h
+
+namespace Catch {
+
+ // ResultWas::OfType enum
+ struct ResultWas { enum OfType {
+ Unknown = -1,
+ Ok = 0,
+ Info = 1,
+ Warning = 2,
+
+ FailureBit = 0x10,
+
+ ExpressionFailed = FailureBit | 1,
+ ExplicitFailure = FailureBit | 2,
+
+ Exception = 0x100 | FailureBit,
+
+ ThrewException = Exception | 1,
+ DidntThrowException = Exception | 2,
+
+ FatalErrorCondition = 0x200 | FailureBit
+
+ }; };
+
+ bool isOk( ResultWas::OfType resultType );
+ bool isJustInfo( int flags );
+
+ // ResultDisposition::Flags enum
+ struct ResultDisposition { enum Flags {
+ Normal = 0x01,
+
+ ContinueOnFailure = 0x02, // Failures fail test, but execution continues
+ FalseTest = 0x04, // Prefix expression with !
+ SuppressFail = 0x08 // Failures are reported but do not fail the test
+ }; };
+
+ ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs );
+
+ bool shouldContinueOnFailure( int flags );
+ inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
+ bool shouldSuppressFailure( int flags );
+
+} // end namespace Catch
+
+// end catch_result_type.h
+namespace Catch {
+
+ struct AssertionInfo
+ {
+ StringRef macroName;
+ SourceLineInfo lineInfo;
+ StringRef capturedExpression;
+ ResultDisposition::Flags resultDisposition;
+
+ // We want to delete this constructor but a compiler bug in 4.8 means
+ // the struct is then treated as non-aggregate
+ //AssertionInfo() = delete;
+ };
+
+} // end namespace Catch
+
+// end catch_assertioninfo.h
+// start catch_decomposer.h
+
+// start catch_tostring.h
+
+#include
+#include
+#include
+#include
+// start catch_stream.h
+
+#include
+#include
+#include
+
+namespace Catch {
+
+ std::ostream& cout();
+ std::ostream& cerr();
+ std::ostream& clog();
+
+ class StringRef;
+
+ struct IStream {
+ virtual ~IStream();
+ virtual std::ostream& stream() const = 0;
+ };
+
+ auto makeStream( StringRef const &filename ) -> IStream const*;
+
+ class ReusableStringStream {
+ std::size_t m_index;
+ std::ostream* m_oss;
+ public:
+ ReusableStringStream();
+ ~ReusableStringStream();
+
+ auto str() const -> std::string;
+
+ template
+ auto operator << ( T const& value ) -> ReusableStringStream& {
+ *m_oss << value;
+ return *this;
+ }
+ auto get() -> std::ostream& { return *m_oss; }
+
+ static void cleanup();
+ };
+}
+
+// end catch_stream.h
+
+#ifdef __OBJC__
+// start catch_objc_arc.hpp
+
+#import
+
+#ifdef __has_feature
+#define CATCH_ARC_ENABLED __has_feature(objc_arc)
+#else
+#define CATCH_ARC_ENABLED 0
+#endif
+
+void arcSafeRelease( NSObject* obj );
+id performOptionalSelector( id obj, SEL sel );
+
+#if !CATCH_ARC_ENABLED
+inline void arcSafeRelease( NSObject* obj ) {
+ [obj release];
+}
+inline id performOptionalSelector( id obj, SEL sel ) {
+ if( [obj respondsToSelector: sel] )
+ return [obj performSelector: sel];
+ return nil;
+}
+#define CATCH_UNSAFE_UNRETAINED
+#define CATCH_ARC_STRONG
+#else
+inline void arcSafeRelease( NSObject* ){}
+inline id performOptionalSelector( id obj, SEL sel ) {
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
+#endif
+ if( [obj respondsToSelector: sel] )
+ return [obj performSelector: sel];
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+ return nil;
+}
+#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
+#define CATCH_ARC_STRONG __strong
+#endif
+
+// end catch_objc_arc.hpp
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless
+#endif
+
+// We need a dummy global operator<< so we can bring it into Catch namespace later
+struct Catch_global_namespace_dummy {};
+std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy);
+
+namespace Catch {
+ // Bring in operator<< from global namespace into Catch namespace
+ using ::operator<<;
+
+ namespace Detail {
+
+ extern const std::string unprintableString;
+
+ std::string rawMemoryToString( const void *object, std::size_t size );
+
+ template
+ std::string rawMemoryToString( const T& object ) {
+ return rawMemoryToString( &object, sizeof(object) );
+ }
+
+ template
+ class IsStreamInsertable {
+ template
+ static auto test(int)
+ -> decltype(std::declval() << std::declval(), std::true_type());
+
+ template
+ static auto test(...)->std::false_type;
+
+ public:
+ static const bool value = decltype(test(0))::value;
+ };
+
+ template
+ std::string convertUnknownEnumToString( E e );
+
+ template
+ typename std::enable_if<
+ !std::is_enum::value && !std::is_base_of::value,
+ std::string>::type convertUnstreamable( T const& ) {
+ return Detail::unprintableString;
+ }
+ template
+ typename std::enable_if<
+ !std::is_enum::value && std::is_base_of::value,
+ std::string>::type convertUnstreamable(T const& ex) {
+ return ex.what();
+ }
+
+ template
+ typename std::enable_if<
+ std::is_enum::value
+ , std::string>::type convertUnstreamable( T const& value ) {
+ return convertUnknownEnumToString( value );
+ }
+
+#if defined(_MANAGED)
+ //! Convert a CLR string to a utf8 std::string
+ template
+ std::string clrReferenceToString( T^ ref ) {
+ if (ref == nullptr)
+ return std::string("null");
+ auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());
+ cli::pin_ptr p = &bytes[0];
+ return std::string(reinterpret_cast(p), bytes->Length);
+ }
+#endif
+
+ } // namespace Detail
+
+ // If we decide for C++14, change these to enable_if_ts
+ template
+ struct StringMaker {
+ template
+ static
+ typename std::enable_if<::Catch::Detail::IsStreamInsertable::value, std::string>::type
+ convert(const Fake& value) {
+ ReusableStringStream rss;
+ // NB: call using the function-like syntax to avoid ambiguity with
+ // user-defined templated operator<< under clang.
+ rss.operator<<(value);
+ return rss.str();
+ }
+
+ template
+ static
+ typename std::enable_if::value, std::string>::type
+ convert( const Fake& value ) {
+#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
+ return Detail::convertUnstreamable(value);
+#else
+ return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);
+#endif
+ }
+ };
+
+ namespace Detail {
+
+ // This function dispatches all stringification requests inside of Catch.
+ // Should be preferably called fully qualified, like ::Catch::Detail::stringify
+ template
+ std::string stringify(const T& e) {
+ return ::Catch::StringMaker::type>::type>::convert(e);
+ }
+
+ template
+ std::string convertUnknownEnumToString( E e ) {
+ return ::Catch::Detail::stringify(static_cast::type>(e));
+ }
+
+#if defined(_MANAGED)
+ template
+ std::string stringify( T^ e ) {
+ return ::Catch::StringMaker::convert(e);
+ }
+#endif
+
+ } // namespace Detail
+
+ // Some predefined specializations
+
+ template<>
+ struct StringMaker {
+ static std::string convert(const std::string& str);
+ };
+#ifdef CATCH_CONFIG_WCHAR
+ template<>
+ struct StringMaker {
+ static std::string convert(const std::wstring& wstr);
+ };
+#endif
+
+ template<>
+ struct StringMaker {
+ static std::string convert(char const * str);
+ };
+ template<>
+ struct StringMaker {
+ static std::string convert(char * str);
+ };
+
+#ifdef CATCH_CONFIG_WCHAR
+ template<>
+ struct StringMaker {
+ static std::string convert(wchar_t const * str);
+ };
+ template<>
+ struct StringMaker {
+ static std::string convert(wchar_t * str);
+ };
+#endif
+
+ // TBD: Should we use `strnlen` to ensure that we don't go out of the buffer,
+ // while keeping string semantics?
+ template
+ struct StringMaker {
+ static std::string convert(char const* str) {
+ return ::Catch::Detail::stringify(std::string{ str });
+ }
+ };
+ template
+ struct StringMaker {
+ static std::string convert(signed char const* str) {
+ return ::Catch::Detail::stringify(std::string{ reinterpret_cast(str) });
+ }
+ };
+ template
+ struct StringMaker {
+ static std::string convert(unsigned char const* str) {
+ return ::Catch::Detail::stringify(std::string{ reinterpret_cast(str) });
+ }
+ };
+
+ template<>
+ struct StringMaker {
+ static std::string convert(int value);
+ };
+ template<>
+ struct StringMaker {
+ static std::string convert(long value);
+ };
+ template<>
+ struct StringMaker {
+ static std::string convert(long long value);
+ };
+ template<>
+ struct StringMaker {
+ static std::string convert(unsigned int value);
+ };
+ template<>
+ struct StringMaker {
+ static std::string convert(unsigned long value);
+ };
+ template<>
+ struct StringMaker {
+ static std::string convert(unsigned long long value);
+ };
+
+ template<>
+ struct StringMaker {
+ static std::string convert(bool b);
+ };
+
+ template<>
+ struct StringMaker {
+ static std::string convert(char c);
+ };
+ template<>
+ struct StringMaker {
+ static std::string convert(signed char c);
+ };
+ template<>
+ struct StringMaker {
+ static std::string convert(unsigned char c);
+ };
+
+ template<>
+ struct StringMaker {
+ static std::string convert(std::nullptr_t);
+ };
+
+ template<>
+ struct StringMaker {
+ static std::string convert(float value);
+ };
+ template<>
+ struct StringMaker {
+ static std::string convert(double value);
+ };
+
+ template
+ struct StringMaker {
+ template
+ static std::string convert(U* p) {
+ if (p) {
+ return ::Catch::Detail::rawMemoryToString(p);
+ } else {
+ return "nullptr";
+ }
+ }
+ };
+
+ template
+ struct StringMaker {
+ static std::string convert(R C::* p) {
+ if (p) {
+ return ::Catch::Detail::rawMemoryToString(p);
+ } else {
+ return "nullptr";
+ }
+ }
+ };
+
+#if defined(_MANAGED)
+ template
+ struct StringMaker {
+ static std::string convert( T^ ref ) {
+ return ::Catch::Detail::clrReferenceToString(ref);
+ }
+ };
+#endif
+
+ namespace Detail {
+ template
+ std::string rangeToString(InputIterator first, InputIterator last) {
+ ReusableStringStream rss;
+ rss << "{ ";
+ if (first != last) {
+ rss << ::Catch::Detail::stringify(*first);
+ for (++first; first != last; ++first)
+ rss << ", " << ::Catch::Detail::stringify(*first);
+ }
+ rss << " }";
+ return rss.str();
+ }
+ }
+
+#ifdef __OBJC__
+ template<>
+ struct StringMaker {
+ static std::string convert(NSString * nsstring) {
+ if (!nsstring)
+ return "nil";
+ return std::string("@") + [nsstring UTF8String];
+ }
+ };
+ template<>
+ struct StringMaker {
+ static std::string convert(NSObject* nsObject) {
+ return ::Catch::Detail::stringify([nsObject description]);
+ }
+
+ };
+ namespace Detail {
+ inline std::string stringify( NSString* nsstring ) {
+ return StringMaker::convert( nsstring );
+ }
+
+ } // namespace Detail
+#endif // __OBJC__
+
+} // namespace Catch
+
+//////////////////////////////////////////////////////
+// Separate std-lib types stringification, so it can be selectively enabled
+// This means that we do not bring in
+
+#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)
+# define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
+# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
+# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
+#endif
+
+// Separate std::pair specialization
+#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER)
+#include
+namespace Catch {
+ template
+ struct StringMaker > {
+ static std::string convert(const std::pair& pair) {
+ ReusableStringStream rss;
+ rss << "{ "
+ << ::Catch::Detail::stringify(pair.first)
+ << ", "
+ << ::Catch::Detail::stringify(pair.second)
+ << " }";
+ return rss.str();
+ }
+ };
+}
+#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
+
+// Separate std::tuple specialization
+#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
+#include
+namespace Catch {
+ namespace Detail {
+ template<
+ typename Tuple,
+ std::size_t N = 0,
+ bool = (N < std::tuple_size::value)
+ >
+ struct TupleElementPrinter {
+ static void print(const Tuple& tuple, std::ostream& os) {
+ os << (N ? ", " : " ")
+ << ::Catch::Detail::stringify(std::get(tuple));
+ TupleElementPrinter::print(tuple, os);
+ }
+ };
+
+ template<
+ typename Tuple,
+ std::size_t N
+ >
+ struct TupleElementPrinter {
+ static void print(const Tuple&, std::ostream&) {}
+ };
+
+ }
+
+ template
+ struct StringMaker> {
+ static std::string convert(const std::tuple& tuple) {
+ ReusableStringStream rss;
+ rss << '{';
+ Detail::TupleElementPrinter>::print(tuple, rss.get());
+ rss << " }";
+ return rss.str();
+ }
+ };
+}
+#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
+
+namespace Catch {
+ struct not_this_one {}; // Tag type for detecting which begin/ end are being selected
+
+ // Import begin/ end from std here so they are considered alongside the fallback (...) overloads in this namespace
+ using std::begin;
+ using std::end;
+
+ not_this_one begin( ... );
+ not_this_one end( ... );
+
+ template
+ struct is_range {
+ static const bool value =
+ !std::is_same())), not_this_one>::value &&
+ !std::is_same())), not_this_one>::value;
+ };
+
+#if defined(_MANAGED) // Managed types are never ranges
+ template
+ struct is_range {
+ static const bool value = false;
+ };
+#endif
+
+ template
+ std::string rangeToString( Range const& range ) {
+ return ::Catch::Detail::rangeToString( begin( range ), end( range ) );
+ }
+
+ // Handle vector specially
+ template
+ std::string rangeToString( std::vector const& v ) {
+ ReusableStringStream rss;
+ rss << "{ ";
+ bool first = true;
+ for( bool b : v ) {
+ if( first )
+ first = false;
+ else
+ rss << ", ";
+ rss << ::Catch::Detail::stringify( b );
+ }
+ rss << " }";
+ return rss.str();
+ }
+
+ template
+ struct StringMaker::value && !::Catch::Detail::IsStreamInsertable::value>::type> {
+ static std::string convert( R const& range ) {
+ return rangeToString( range );
+ }
+ };
+
+ template
+ struct StringMaker {
+ static std::string convert(T const(&arr)[SZ]) {
+ return rangeToString(arr);
+ }
+ };
+
+} // namespace Catch
+
+// Separate std::chrono::duration specialization
+#if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
+#include
+#include
+#include
+
+namespace Catch {
+
+template
+struct ratio_string {
+ static std::string symbol();
+};
+
+template
+std::string ratio_string::symbol() {
+ Catch::ReusableStringStream rss;
+ rss << '[' << Ratio::num << '/'
+ << Ratio::den << ']';
+ return rss.str();
+}
+template <>
+struct ratio_string {
+ static std::string symbol();
+};
+template <>
+struct ratio_string {
+ static std::string symbol();
+};
+template <>
+struct ratio_string {
+ static std::string symbol();
+};
+template <>
+struct ratio_string {
+ static std::string symbol();
+};
+template <>
+struct ratio_string {
+ static std::string symbol();
+};
+template <>
+struct ratio_string {
+ static std::string symbol();
+};
+
+ ////////////
+ // std::chrono::duration specializations
+ template
+ struct StringMaker> {
+ static std::string convert(std::chrono::duration const& duration) {
+ ReusableStringStream rss;
+ rss << duration.count() << ' ' << ratio_string::symbol() << 's';
+ return rss.str();
+ }
+ };
+ template
+ struct StringMaker>> {
+ static std::string convert(std::chrono::duration> const& duration) {
+ ReusableStringStream rss;
+ rss << duration.count() << " s";
+ return rss.str();
+ }
+ };
+ template
+ struct StringMaker>> {
+ static std::string convert(std::chrono::duration> const& duration) {
+ ReusableStringStream rss;
+ rss << duration.count() << " m";
+ return rss.str();
+ }
+ };
+ template
+ struct StringMaker>> {
+ static std::string convert(std::chrono::duration> const& duration) {
+ ReusableStringStream rss;
+ rss << duration.count() << " h";
+ return rss.str();
+ }
+ };
+
+ ////////////
+ // std::chrono::time_point specialization
+ // Generic time_point cannot be specialized, only std::chrono::time_point
+ template
+ struct StringMaker> {
+ static std::string convert(std::chrono::time_point const& time_point) {
+ return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch";
+ }
+ };
+ // std::chrono::time_point specialization
+ template
+ struct StringMaker> {
+ static std::string convert(std::chrono::time_point const& time_point) {
+ auto converted = std::chrono::system_clock::to_time_t(time_point);
+
+#ifdef _MSC_VER
+ std::tm timeInfo = {};
+ gmtime_s(&timeInfo, &converted);
+#else
+ std::tm* timeInfo = std::gmtime(&converted);
+#endif
+
+ auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
+ char timeStamp[timeStampSize];
+ const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
+
+#ifdef _MSC_VER
+ std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
+#else
+ std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
+#endif
+ return std::string(timeStamp);
+ }
+ };
+}
+#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+// end catch_tostring.h
+#include
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
+#pragma warning(disable:4018) // more "signed/unsigned mismatch"
+#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
+#pragma warning(disable:4180) // qualifier applied to function type has no meaning
+#endif
+
+namespace Catch {
+
+ struct ITransientExpression {
+ auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
+ auto getResult() const -> bool { return m_result; }
+ virtual void streamReconstructedExpression( std::ostream &os ) const = 0;
+
+ ITransientExpression( bool isBinaryExpression, bool result )
+ : m_isBinaryExpression( isBinaryExpression ),
+ m_result( result )
+ {}
+
+ // We don't actually need a virtual destructor, but many static analysers
+ // complain if it's not here :-(
+ virtual ~ITransientExpression();
+
+ bool m_isBinaryExpression;
+ bool m_result;
+
+ };
+
+ void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );
+
+ template
+ class BinaryExpr : public ITransientExpression {
+ LhsT m_lhs;
+ StringRef m_op;
+ RhsT m_rhs;
+
+ void streamReconstructedExpression( std::ostream &os ) const override {
+ formatReconstructedExpression
+ ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) );
+ }
+
+ public:
+ BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )
+ : ITransientExpression{ true, comparisonResult },
+ m_lhs( lhs ),
+ m_op( op ),
+ m_rhs( rhs )
+ {}
+ };
+
+ template
+ class UnaryExpr : public ITransientExpression {
+ LhsT m_lhs;
+
+ void streamReconstructedExpression( std::ostream &os ) const override {
+ os << Catch::Detail::stringify( m_lhs );
+ }
+
+ public:
+ explicit UnaryExpr( LhsT lhs )
+ : ITransientExpression{ false, lhs ? true : false },
+ m_lhs( lhs )
+ {}
+ };
+
+ // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int)
+ template
+ auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast(lhs == rhs); }
+ template
+ auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast( rhs ); }
+ template
+ auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast( rhs ); }
+ template
+ auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; }
+ template
+ auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; }
+
+ template
+ auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast(lhs != rhs); }
+ template
+ auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast( rhs ); }
+ template
+ auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast( rhs ); }
+ template
+ auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; }
+ template
+ auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; }
+
+ template
+ class ExprLhs {
+ LhsT m_lhs;
+ public:
+ explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
+
+ template
+ auto operator == ( RhsT const& rhs ) -> BinaryExpr const {
+ return { compareEqual( m_lhs, rhs ), m_lhs, "==", rhs };
+ }
+ auto operator == ( bool rhs ) -> BinaryExpr const {
+ return { m_lhs == rhs, m_lhs, "==", rhs };
+ }
+
+ template
+ auto operator != ( RhsT const& rhs ) -> BinaryExpr const {
+ return { compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs };
+ }
+ auto operator != ( bool rhs ) -> BinaryExpr const {
+ return { m_lhs != rhs, m_lhs, "!=", rhs };
+ }
+
+ template
+ auto operator > ( RhsT const& rhs ) -> BinaryExpr const {
+ return { static_cast(m_lhs > rhs), m_lhs, ">", rhs };
+ }
+ template
+ auto operator < ( RhsT const& rhs ) -> BinaryExpr const {
+ return { static_cast(m_lhs < rhs), m_lhs, "<", rhs };
+ }
+ template
+ auto operator >= ( RhsT const& rhs ) -> BinaryExpr const {
+ return { static_cast(m_lhs >= rhs), m_lhs, ">=", rhs };
+ }
+ template
+ auto operator <= ( RhsT const& rhs ) -> BinaryExpr const {
+ return { static_cast(m_lhs <= rhs), m_lhs, "<=", rhs };
+ }
+
+ auto makeUnaryExpr() const -> UnaryExpr {
+ return UnaryExpr{ m_lhs };
+ }
+ };
+
+ void handleExpression( ITransientExpression const& expr );
+
+ template
+ void handleExpression( ExprLhs const& expr ) {
+ handleExpression( expr.makeUnaryExpr() );
+ }
+
+ struct Decomposer {
+ template
+ auto operator <= ( T const& lhs ) -> ExprLhs {
+ return ExprLhs{ lhs };
+ }
+
+ auto operator <=( bool value ) -> ExprLhs {
+ return ExprLhs{ value };
+ }
+ };
+
+} // end namespace Catch
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+// end catch_decomposer.h
+// start catch_interfaces_capture.h
+
+#include
+
+namespace Catch {
+
+ class AssertionResult;
+ struct AssertionInfo;
+ struct SectionInfo;
+ struct SectionEndInfo;
+ struct MessageInfo;
+ struct Counts;
+ struct BenchmarkInfo;
+ struct BenchmarkStats;
+ struct AssertionReaction;
+
+ struct ITransientExpression;
+
+ struct IResultCapture {
+
+ virtual ~IResultCapture();
+
+ virtual bool sectionStarted( SectionInfo const& sectionInfo,
+ Counts& assertions ) = 0;
+ virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
+ virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
+
+ virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0;
+ virtual void benchmarkEnded( BenchmarkStats const& stats ) = 0;
+
+ virtual void pushScopedMessage( MessageInfo const& message ) = 0;
+ virtual void popScopedMessage( MessageInfo const& message ) = 0;
+
+ virtual void handleFatalErrorCondition( StringRef message ) = 0;
+
+ virtual void handleExpr
+ ( AssertionInfo const& info,
+ ITransientExpression const& expr,
+ AssertionReaction& reaction ) = 0;
+ virtual void handleMessage
+ ( AssertionInfo const& info,
+ ResultWas::OfType resultType,
+ StringRef const& message,
+ AssertionReaction& reaction ) = 0;
+ virtual void handleUnexpectedExceptionNotThrown
+ ( AssertionInfo const& info,
+ AssertionReaction& reaction ) = 0;
+ virtual void handleUnexpectedInflightException
+ ( AssertionInfo const& info,
+ std::string const& message,
+ AssertionReaction& reaction ) = 0;
+ virtual void handleIncomplete
+ ( AssertionInfo const& info ) = 0;
+ virtual void handleNonExpr
+ ( AssertionInfo const &info,
+ ResultWas::OfType resultType,
+ AssertionReaction &reaction ) = 0;
+
+ virtual bool lastAssertionPassed() = 0;
+ virtual void assertionPassed() = 0;
+
+ // Deprecated, do not use:
+ virtual std::string getCurrentTestName() const = 0;
+ virtual const AssertionResult* getLastResult() const = 0;
+ virtual void exceptionEarlyReported() = 0;
+ };
+
+ IResultCapture& getResultCapture();
+}
+
+// end catch_interfaces_capture.h
+namespace Catch {
+
+ struct TestFailureException{};
+ struct AssertionResultData;
+ struct IResultCapture;
+ class RunContext;
+
+ class LazyExpression {
+ friend class AssertionHandler;
+ friend struct AssertionStats;
+ friend class RunContext;
+
+ ITransientExpression const* m_transientExpression = nullptr;
+ bool m_isNegated;
+ public:
+ LazyExpression( bool isNegated );
+ LazyExpression( LazyExpression const& other );
+ LazyExpression& operator = ( LazyExpression const& ) = delete;
+
+ explicit operator bool() const;
+
+ friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&;
+ };
+
+ struct AssertionReaction {
+ bool shouldDebugBreak = false;
+ bool shouldThrow = false;
+ };
+
+ class AssertionHandler {
+ AssertionInfo m_assertionInfo;
+ AssertionReaction m_reaction;
+ bool m_completed = false;
+ IResultCapture& m_resultCapture;
+
+ public:
+ AssertionHandler
+ ( StringRef macroName,
+ SourceLineInfo const& lineInfo,
+ StringRef capturedExpression,
+ ResultDisposition::Flags resultDisposition );
+ ~AssertionHandler() {
+ if ( !m_completed ) {
+ m_resultCapture.handleIncomplete( m_assertionInfo );
+ }
+ }
+
+ template
+ void handleExpr( ExprLhs const& expr ) {
+ handleExpr( expr.makeUnaryExpr() );
+ }
+ void handleExpr( ITransientExpression const& expr );
+
+ void handleMessage(ResultWas::OfType resultType, StringRef const& message);
+
+ void handleExceptionThrownAsExpected();
+ void handleUnexpectedExceptionNotThrown();
+ void handleExceptionNotThrownAsExpected();
+ void handleThrowingCallSkipped();
+ void handleUnexpectedInflightException();
+
+ void complete();
+ void setCompleted();
+
+ // query
+ auto allowThrows() const -> bool;
+ };
+
+ void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString );
+
+} // namespace Catch
+
+// end catch_assertionhandler.h
+// start catch_message.h
+
+#include
+
+namespace Catch {
+
+ struct MessageInfo {
+ MessageInfo( std::string const& _macroName,
+ SourceLineInfo const& _lineInfo,
+ ResultWas::OfType _type );
+
+ std::string macroName;
+ std::string message;
+ SourceLineInfo lineInfo;
+ ResultWas::OfType type;
+ unsigned int sequence;
+
+ bool operator == ( MessageInfo const& other ) const;
+ bool operator < ( MessageInfo const& other ) const;
+ private:
+ static unsigned int globalCount;
+ };
+
+ struct MessageStream {
+
+ template
+ MessageStream& operator << ( T const& value ) {
+ m_stream << value;
+ return *this;
+ }
+
+ ReusableStringStream m_stream;
+ };
+
+ struct MessageBuilder : MessageStream {
+ MessageBuilder( std::string const& macroName,
+ SourceLineInfo const& lineInfo,
+ ResultWas::OfType type );
+
+ template
+ MessageBuilder& operator << ( T const& value ) {
+ m_stream << value;
+ return *this;
+ }
+
+ MessageInfo m_info;
+ };
+
+ class ScopedMessage {
+ public:
+ explicit ScopedMessage( MessageBuilder const& builder );
+ ~ScopedMessage();
+
+ MessageInfo m_info;
+ };
+
+} // end namespace Catch
+
+// end catch_message.h
+#if !defined(CATCH_CONFIG_DISABLE)
+
+#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
+ #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__
+#else
+ #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
+#endif
+
+#if defined(CATCH_CONFIG_FAST_COMPILE)
+
+///////////////////////////////////////////////////////////////////////////////
+// Another way to speed-up compilation is to omit local try-catch for REQUIRE*
+// macros.
+#define INTERNAL_CATCH_TRY
+#define INTERNAL_CATCH_CATCH( capturer )
+
+#else // CATCH_CONFIG_FAST_COMPILE
+
+#define INTERNAL_CATCH_TRY try
+#define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); }
+
+#endif
+
+#define INTERNAL_CATCH_REACT( handler ) handler.complete();
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
+ do { \
+ Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
+ INTERNAL_CATCH_TRY { \
+ CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
+ catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \
+ CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
+ } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
+ INTERNAL_CATCH_REACT( catchAssertionHandler ) \
+ } while( (void)0, false && static_cast( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look
+ // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
+ INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
+ if( Catch::getResultCapture().lastAssertionPassed() )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \
+ INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
+ if( !Catch::getResultCapture().lastAssertionPassed() )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
+ do { \
+ Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
+ try { \
+ static_cast(__VA_ARGS__); \
+ catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
+ } \
+ catch( ... ) { \
+ catchAssertionHandler.handleUnexpectedInflightException(); \
+ } \
+ INTERNAL_CATCH_REACT( catchAssertionHandler ) \
+ } while( false )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
+ do { \
+ Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
+ if( catchAssertionHandler.allowThrows() ) \
+ try { \
+ static_cast(__VA_ARGS__); \
+ catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
+ } \
+ catch( ... ) { \
+ catchAssertionHandler.handleExceptionThrownAsExpected(); \
+ } \
+ else \
+ catchAssertionHandler.handleThrowingCallSkipped(); \
+ INTERNAL_CATCH_REACT( catchAssertionHandler ) \
+ } while( false )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
+ do { \
+ Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
+ if( catchAssertionHandler.allowThrows() ) \
+ try { \
+ static_cast(expr); \
+ catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
+ } \
+ catch( exceptionType const& ) { \
+ catchAssertionHandler.handleExceptionThrownAsExpected(); \
+ } \
+ catch( ... ) { \
+ catchAssertionHandler.handleUnexpectedInflightException(); \
+ } \
+ else \
+ catchAssertionHandler.handleThrowingCallSkipped(); \
+ INTERNAL_CATCH_REACT( catchAssertionHandler ) \
+ } while( false )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
+ do { \
+ Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
+ catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
+ INTERNAL_CATCH_REACT( catchAssertionHandler ) \
+ } while( false )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_INFO( macroName, log ) \
+ Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );
+
+///////////////////////////////////////////////////////////////////////////////
+// Although this is matcher-based, it can be used with just a string
+#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
+ do { \
+ Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
+ if( catchAssertionHandler.allowThrows() ) \
+ try { \
+ static_cast(__VA_ARGS__); \
+ catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
+ } \
+ catch( ... ) { \
+ Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher ); \
+ } \
+ else \
+ catchAssertionHandler.handleThrowingCallSkipped(); \
+ INTERNAL_CATCH_REACT( catchAssertionHandler ) \
+ } while( false )
+
+#endif // CATCH_CONFIG_DISABLE
+
+// end catch_capture.hpp
+// start catch_section.h
+
+// start catch_section_info.h
+
+// start catch_totals.h
+
+#include
+
+namespace Catch {
+
+ struct Counts {
+ Counts operator - ( Counts const& other ) const;
+ Counts& operator += ( Counts const& other );
+
+ std::size_t total() const;
+ bool allPassed() const;
+ bool allOk() const;
+
+ std::size_t passed = 0;
+ std::size_t failed = 0;
+ std::size_t failedButOk = 0;
+ };
+
+ struct Totals {
+
+ Totals operator - ( Totals const& other ) const;
+ Totals& operator += ( Totals const& other );
+
+ Totals delta( Totals const& prevTotals ) const;
+
+ int error = 0;
+ Counts assertions;
+ Counts testCases;
+ };
+}
+
+// end catch_totals.h
+#include
+
+namespace Catch {
+
+ struct SectionInfo {
+ SectionInfo
+ ( SourceLineInfo const& _lineInfo,
+ std::string const& _name,
+ std::string const& _description = std::string() );
+
+ std::string name;
+ std::string description;
+ SourceLineInfo lineInfo;
+ };
+
+ struct SectionEndInfo {
+ SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds );
+
+ SectionInfo sectionInfo;
+ Counts prevAssertions;
+ double durationInSeconds;
+ };
+
+} // end namespace Catch
+
+// end catch_section_info.h
+// start catch_timer.h
+
+#include
+
+namespace Catch {
+
+ auto getCurrentNanosecondsSinceEpoch() -> uint64_t;
+ auto getEstimatedClockResolution() -> uint64_t;
+
+ class Timer {
+ uint64_t m_nanoseconds = 0;
+ public:
+ void start();
+ auto getElapsedNanoseconds() const -> uint64_t;
+ auto getElapsedMicroseconds() const -> uint64_t;
+ auto getElapsedMilliseconds() const -> unsigned int;
+ auto getElapsedSeconds() const -> double;
+ };
+
+} // namespace Catch
+
+// end catch_timer.h
+#include
+
+namespace Catch {
+
+ class Section : NonCopyable {
+ public:
+ Section( SectionInfo const& info );
+ ~Section();
+
+ // This indicates whether the section should be executed or not
+ explicit operator bool() const;
+
+ private:
+ SectionInfo m_info;
+
+ std::string m_name;
+ Counts m_assertions;
+ bool m_sectionIncluded;
+ Timer m_timer;
+ };
+
+} // end namespace Catch
+
+ #define INTERNAL_CATCH_SECTION( ... ) \
+ if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
+
+// end catch_section.h
+// start catch_benchmark.h
+
+#include
+#include
+
+namespace Catch {
+
+ class BenchmarkLooper {
+
+ std::string m_name;
+ std::size_t m_count = 0;
+ std::size_t m_iterationsToRun = 1;
+ uint64_t m_resolution;
+ Timer m_timer;
+
+ static auto getResolution() -> uint64_t;
+ public:
+ // Keep most of this inline as it's on the code path that is being timed
+ BenchmarkLooper( StringRef name )
+ : m_name( name ),
+ m_resolution( getResolution() )
+ {
+ reportStart();
+ m_timer.start();
+ }
+
+ explicit operator bool() {
+ if( m_count < m_iterationsToRun )
+ return true;
+ return needsMoreIterations();
+ }
+
+ void increment() {
+ ++m_count;
+ }
+
+ void reportStart();
+ auto needsMoreIterations() -> bool;
+ };
+
+} // end namespace Catch
+
+#define BENCHMARK( name ) \
+ for( Catch::BenchmarkLooper looper( name ); looper; looper.increment() )
+
+// end catch_benchmark.h
+// start catch_interfaces_exception.h
+
+// start catch_interfaces_registry_hub.h
+
+#include
+#include
+
+namespace Catch {
+
+ class TestCase;
+ struct ITestCaseRegistry;
+ struct IExceptionTranslatorRegistry;
+ struct IExceptionTranslator;
+ struct IReporterRegistry;
+ struct IReporterFactory;
+ struct ITagAliasRegistry;
+ class StartupExceptionRegistry;
+
+ using IReporterFactoryPtr = std::shared_ptr;
+
+ struct IRegistryHub {
+ virtual ~IRegistryHub();
+
+ virtual IReporterRegistry const& getReporterRegistry() const = 0;
+ virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
+ virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
+
+ virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
+
+ virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
+ };
+
+ struct IMutableRegistryHub {
+ virtual ~IMutableRegistryHub();
+ virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0;
+ virtual void registerListener( IReporterFactoryPtr const& factory ) = 0;
+ virtual void registerTest( TestCase const& testInfo ) = 0;
+ virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
+ virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
+ virtual void registerStartupException() noexcept = 0;
+ };
+
+ IRegistryHub& getRegistryHub();
+ IMutableRegistryHub& getMutableRegistryHub();
+ void cleanUp();
+ std::string translateActiveException();
+
+}
+
+// end catch_interfaces_registry_hub.h
+#if defined(CATCH_CONFIG_DISABLE)
+ #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \
+ static std::string translatorName( signature )
+#endif
+
+#include
+#include
+#include
+
+namespace Catch {
+ using exceptionTranslateFunction = std::string(*)();
+
+ struct IExceptionTranslator;
+ using ExceptionTranslators = std::vector>;
+
+ struct IExceptionTranslator {
+ virtual ~IExceptionTranslator();
+ virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
+ };
+
+ struct IExceptionTranslatorRegistry {
+ virtual ~IExceptionTranslatorRegistry();
+
+ virtual std::string translateActiveException() const = 0;
+ };
+
+ class ExceptionTranslatorRegistrar {
+ template
+ class ExceptionTranslator : public IExceptionTranslator {
+ public:
+
+ ExceptionTranslator( std::string(*translateFunction)( T& ) )
+ : m_translateFunction( translateFunction )
+ {}
+
+ std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {
+ try {
+ if( it == itEnd )
+ std::rethrow_exception(std::current_exception());
+ else
+ return (*it)->translate( it+1, itEnd );
+ }
+ catch( T& ex ) {
+ return m_translateFunction( ex );
+ }
+ }
+
+ protected:
+ std::string(*m_translateFunction)( T& );
+ };
+
+ public:
+ template
+ ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
+ getMutableRegistryHub().registerTranslator
+ ( new ExceptionTranslator( translateFunction ) );
+ }
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
+ static std::string translatorName( signature ); \
+ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+ namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \
+ CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
+ static std::string translatorName( signature )
+
+#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
+
+// end catch_interfaces_exception.h
+// start catch_approx.h
+
+#include
+#include
+
+namespace Catch {
+namespace Detail {
+
+ class Approx {
+ private:
+ bool equalityComparisonImpl(double other) const;
+
+ public:
+ explicit Approx ( double value );
+
+ static Approx custom();
+
+ template ::value>::type>
+ Approx operator()( T const& value ) {
+ Approx approx( static_cast(value) );
+ approx.epsilon( m_epsilon );
+ approx.margin( m_margin );
+ approx.scale( m_scale );
+ return approx;
+ }
+
+ template ::value>::type>
+ explicit Approx( T const& value ): Approx(static_cast(value))
+ {}
+
+ template ::value>::type>
+ friend bool operator == ( const T& lhs, Approx const& rhs ) {
+ auto lhs_v = static_cast(lhs);
+ return rhs.equalityComparisonImpl(lhs_v);
+ }
+
+ template ::value>::type>
+ friend bool operator == ( Approx const& lhs, const T& rhs ) {
+ return operator==( rhs, lhs );
+ }
+
+ template ::value>::type>
+ friend bool operator != ( T const& lhs, Approx const& rhs ) {
+ return !operator==( lhs, rhs );
+ }
+
+ template ::value>::type>
+ friend bool operator != ( Approx const& lhs, T const& rhs ) {
+ return !operator==( rhs, lhs );
+ }
+
+ template ::value>::type>
+ friend bool operator <= ( T const& lhs, Approx const& rhs ) {
+ return static_cast(lhs) < rhs.m_value || lhs == rhs;
+ }
+
+ template ::value>::type>
+ friend bool operator <= ( Approx const& lhs, T const& rhs ) {
+ return lhs.m_value < static_cast(rhs) || lhs == rhs;
+ }
+
+ template ::value>::type>
+ friend bool operator >= ( T const& lhs, Approx const& rhs ) {
+ return static_cast(lhs) > rhs.m_value || lhs == rhs;
+ }
+
+ template ::value>::type>
+ friend bool operator >= ( Approx const& lhs, T const& rhs ) {
+ return lhs.m_value > static_cast(rhs) || lhs == rhs;
+ }
+
+ template