aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbutl/sha256.hxx38
-rw-r--r--tests/sha256/driver.cxx37
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");