diff options
-rw-r--r-- | libbutl/sha256.hxx | 38 | ||||
-rw-r--r-- | tests/sha256/driver.cxx | 37 |
2 files changed, 61 insertions, 14 deletions
diff --git a/libbutl/sha256.hxx b/libbutl/sha256.hxx index e81b87b..459b46c 100644 --- a/libbutl/sha256.hxx +++ b/libbutl/sha256.hxx @@ -6,9 +6,10 @@ #define LIBBUTL_SHA256_HXX #include <string> -#include <cstring> // strlen() +#include <cstring> // strlen(), memcpy() #include <cstdint> -#include <cstddef> // size_t +#include <cstddef> // size_t +#include <type_traits> // enable_if, is_integral #include <libbutl/export.hxx> @@ -50,6 +51,39 @@ namespace butl 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<std::uint8_t> (c); + ctx_.count += 8; + } + else + append (&c, 1); + } + + template <typename T> + typename std::enable_if<std::is_integral<T>::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- diff --git a/tests/sha256/driver.cxx b/tests/sha256/driver.cxx index 5686898..2d2f963 100644 --- a/tests/sha256/driver.cxx +++ b/tests/sha256/driver.cxx @@ -26,18 +26,31 @@ main () assert (string (sha256 ("123", 3).string ()) == "a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3"); - sha256 h; - h.append ("1"); - h.append (string ("2")); - h.append ("3", 1); - - auto& b (h.binary ()); - assert (b[0] == 0x20 && b[31] == 0x9d); - - string s (h.string ()); - assert (s == - "204d9db65789fbede7829ed77f72ba1f0fe21a833d95abad4849b82f33a69b9d"); - + { + sha256 h; + h.append ("1"); + h.append (string ("2")); + h.append ("3", 1); + + auto& b (h.binary ()); + assert (b[0] == 0x20 && b[31] == 0x9d); + + string s (h.string ()); + assert (s == + "204d9db65789fbede7829ed77f72ba1f0fe21a833d95abad4849b82f33a69b9d"); + } + + // Test fast path. + // + { + char c ('X'); + sha256 h; + h.append (c); + assert (string (h.string ()) == sha256 (&c, 1).string ()); + } + + // + // string fp ("F4:9D:C0:02:C6:B6:62:06:A5:48:AE:87:35:32:95:64:C2:B8:C9:6D:9B:" "28:85:6D:EF:CA:FA:7F:04:B5:4F:A6"); |