From c09cd7512491cee1e82c1ad8128ce9fd4bc3f79b Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 22 Sep 2017 23:32:28 +0200 Subject: Initial modularization with both Clang and VC hacks Note: gave up on VC about half way though. --- libbutl/sha256.mxx | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 libbutl/sha256.mxx (limited to 'libbutl/sha256.mxx') diff --git a/libbutl/sha256.mxx b/libbutl/sha256.mxx new file mode 100644 index 0000000..c5e5864 --- /dev/null +++ b/libbutl/sha256.mxx @@ -0,0 +1,146 @@ +// file : libbutl/sha256.mxx -*- C++ -*- +// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef __cpp_modules +#pragma once +#endif + +// C includes. + +#ifndef __cpp_lib_modules +#include +#include // size_t +#include +#include // strlen(), memcpy() +#include // enable_if, is_integral +#endif + +// Other includes. + +#ifdef __cpp_modules +export module butl.sha256; +#ifdef __cpp_lib_modules +import std.core; +#endif +#endif + +#include + +LIBBUTL_MODEXPORT namespace butl +{ + // SHA256 checksum calculator. + // + // For a single chunk of data a sum can be obtained in one line, for + // example: + // + // cerr << sha256 ("123").string () << endl; + // + class LIBBUTL_SYMEXPORT sha256 + { + public: + sha256 (); + + // Append binary data. + // + void + append (const void*, std::size_t); + + sha256 (const void* b, std::size_t n): sha256 () {append (b, n);} + + // Append string. + // + // Note that the hash includes the '\0' terminator. Failed that, a call + // with an empty string will be indistinguishable from no call at all. + // + void + append (const std::string& s) {append (s.c_str (), s.size () + 1);} + + void + append (const char* s) {append (s, std::strlen (s) + 1);} + + explicit + sha256 (const std::string& s): sha256 () {append (s);} + + explicit + sha256 (const char* s): sha256 () {append (s);} + + // Append an integral type with a fast path optimization (see + // SHA256_Update() for details). + // + void + append (char c) + { + std::uint32_t r ((ctx_.count >> 3) & 0x3f); + + if (1 < 64 - r) + { + ctx_.buf[r] = static_cast (c); + ctx_.count += 8; + } + else + append (&c, 1); + } + + template + typename std::enable_if::value>::type + append (T x) + { + const std::size_t len (sizeof (x)); + std::uint32_t r ((ctx_.count >> 3) & 0x3f); + + if (len < 64 - r) + { + std::memcpy (&ctx_.buf[r], &x, sizeof (x)); + ctx_.count += len << 3; + } + else + append (&x, len); + } + + // Extract result. + // + // It can be obtained as either a 32-byte binary digest or as a 64- + // character hex-encoded C-string. + // + using digest_type = std::uint8_t[32]; + + const digest_type& + binary () const; + + const char* + string () const; + + private: + struct context // Note: identical to SHA256_CTX. + { + uint32_t state[8]; + uint64_t count; + uint8_t buf[64]; + }; + + union + { + mutable context ctx_; + mutable char buf_[sizeof (context)]; // Also used to store string rep. + }; + + mutable digest_type bin_; + mutable bool done_; + }; + + // Convert a SHA256 string representation (64 hex digits) to the fingerprint + // canonical representation (32 colon-separated upper case hex digit pairs, + // like 01:AB:CD:...). Throw invalid_argument if the argument is not a valid + // SHA256 string. + // + LIBBUTL_SYMEXPORT std::string + sha256_to_fingerprint (const std::string&); + + // Convert a fingerprint (32 colon-separated hex digit pairs) to the SHA256 + // string representation (64 lower case hex digits). Throw invalid_argument + // if the argument is not a valid fingerprint. + // + LIBBUTL_SYMEXPORT std::string + fingerprint_to_sha256 (const std::string&); +} -- cgit v1.1