From 16b63f8cdf5b488ab2f4b0e029478b01a2d6b8a8 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 10 Jul 2018 09:20:25 +0200 Subject: Add support for hashing ifdstream --- libbutl/sha1.cxx | 20 ++++++++++++++++++++ libbutl/sha1.mxx | 10 ++++++++++ libbutl/sha256.cxx | 18 ++++++++++++++++++ libbutl/sha256.mxx | 10 ++++++++++ tests/sha1/driver.cxx | 38 ++++++++++++++++++++++++++++++++++---- tests/sha256/driver.cxx | 32 ++++++++++++++++++++++++++++++-- 6 files changed, 122 insertions(+), 6 deletions(-) diff --git a/libbutl/sha1.cxx b/libbutl/sha1.cxx index 8fdb833..af1f260 100644 --- a/libbutl/sha1.cxx +++ b/libbutl/sha1.cxx @@ -42,6 +42,8 @@ extern "C" #define SHA1_Update(x, y, z) sha1_loop((x), (const uint8_t *)(y), (z)) #define SHA1_Final(x, y) sha1_result((y), (char(&)[20])(x)) +#include + #ifndef __cpp_lib_modules #include #include @@ -53,12 +55,16 @@ extern "C" #ifdef __cpp_modules module butl.sha1; +// Only imports additional to interface. #ifdef __clang__ #ifdef __cpp_lib_modules import std.core; #endif #endif +import butl.fdstream; +#else +#include #endif using namespace std; @@ -78,6 +84,20 @@ namespace butl SHA1_Update (reinterpret_cast (buf_), b, n); } + void sha1:: + append (ifdstream& is) + { + fdbuf* buf (dynamic_cast (is.rdbuf ())); + assert (buf != nullptr); + + while (is.peek () != ifdstream::traits_type::eof () && is.good ()) + { + size_t n (buf->egptr () - buf->gptr ()); + append (buf->gptr (), n); + buf->gbump (static_cast (n)); + } + } + const sha1::digest_type& sha1:: binary () const { diff --git a/libbutl/sha1.mxx b/libbutl/sha1.mxx index a3b75d7..ea4d240 100644 --- a/libbutl/sha1.mxx +++ b/libbutl/sha1.mxx @@ -28,6 +28,8 @@ import std.core; LIBBUTL_MODEXPORT namespace butl { + class ifdstream; + // SHA1 checksum calculator. // // For a single chunk of data a sum can be obtained in one line, for @@ -64,6 +66,14 @@ LIBBUTL_MODEXPORT namespace butl explicit sha1 (const char* s): sha1 () {append (s);} + // Append stream. + // + void + append (ifdstream&); + + explicit + sha1 (ifdstream& i): sha1 () {append (i);} + // Extract result. // // It can be obtained as either a 20-byte binary digest or as a 40- diff --git a/libbutl/sha256.cxx b/libbutl/sha256.cxx index a688a15..c4556e7 100644 --- a/libbutl/sha256.cxx +++ b/libbutl/sha256.cxx @@ -27,6 +27,8 @@ extern "C" #include "sha256c.c" } +#include + #ifndef __cpp_lib_modules #include #include @@ -53,8 +55,10 @@ import std.core; #endif import butl.utility; // *case() +import butl.fdstream; #else #include +#include #endif using namespace std; @@ -74,6 +78,20 @@ namespace butl SHA256_Update (reinterpret_cast (buf_), b, n); } + void sha256:: + append (ifdstream& is) + { + fdbuf* buf (dynamic_cast (is.rdbuf ())); + assert (buf != nullptr); + + while (is.peek () != ifdstream::traits_type::eof () && is.good ()) + { + size_t n (buf->egptr () - buf->gptr ()); + append (buf->gptr (), n); + buf->gbump (static_cast (n)); + } + } + const sha256::digest_type& sha256:: binary () const { diff --git a/libbutl/sha256.mxx b/libbutl/sha256.mxx index ba8eeea..c0c8a84 100644 --- a/libbutl/sha256.mxx +++ b/libbutl/sha256.mxx @@ -29,6 +29,8 @@ import std.core; LIBBUTL_MODEXPORT namespace butl { + class ifdstream; + // SHA256 checksum calculator. // // For a single chunk of data a sum can be obtained in one line, for @@ -98,6 +100,14 @@ LIBBUTL_MODEXPORT namespace butl append (&x, len); } + // Append stream. + // + void + append (ifdstream&); + + explicit + sha256 (ifdstream& i): sha256 () {append (i);} + // Extract result. // // It can be obtained as either a 32-byte binary digest or as a 64- diff --git a/tests/sha1/driver.cxx b/tests/sha1/driver.cxx index 5d53faa..92a8443 100644 --- a/tests/sha1/driver.cxx +++ b/tests/sha1/driver.cxx @@ -6,7 +6,7 @@ #ifndef __cpp_lib_modules #include -#include +#include // size_t #endif // Other includes. @@ -14,11 +14,16 @@ #ifdef __cpp_modules #ifdef __cpp_lib_modules import std.core; -import std.io; #endif import butl.sha1; +import butl.path; +import butl.fdstream; +import butl.filesystem; #else #include +#include +#include +#include // auto_rmfile #endif using namespace std; @@ -37,8 +42,32 @@ main () "40bd001563085fc35165329ea1ff5c5ecbdbbeef"); { + string s; + for (size_t i (0); i < 1024; ++i) + s += "0123456789"; + + path p (path::temp_path ("butl-sha1")); + + auto_rmfile pr; // Always remove the file after the stream is closed. + ofdstream os (p); + pr = auto_rmfile (p); + + os << s; + os.close (); + + ifdstream is (p); + + assert (string (sha1 (is).string ()) == + sha1 (s.c_str (), s.size ()).string ()); + + assert (is.eof ()); + is.close (); + } + + { sha1 h ("123"); - assert (string (h.string ()) == "cc320164df1a2130045a28f08d3b88bc5bbcc43a"); + assert (string (h.string ()) == + "cc320164df1a2130045a28f08d3b88bc5bbcc43a"); assert (h.abbreviated_string (10) == "cc320164df"); assert (h.abbreviated_string (41) == h.string ()); @@ -53,6 +82,7 @@ main () auto& b (h.binary ()); assert (b[0] == 0x58 && b[19] == 0xfd); - assert (string (h.string ()) == "58c596bafad8d007952934af1db9abc5401d4dfd"); + assert (string (h.string ()) == + "58c596bafad8d007952934af1db9abc5401d4dfd"); } } diff --git a/tests/sha256/driver.cxx b/tests/sha256/driver.cxx index 5653e05..908b6ec 100644 --- a/tests/sha256/driver.cxx +++ b/tests/sha256/driver.cxx @@ -6,7 +6,7 @@ #ifndef __cpp_lib_modules #include -#include +#include // size_t #endif // Other includes. @@ -14,11 +14,16 @@ #ifdef __cpp_modules #ifdef __cpp_lib_modules import std.core; -import std.io; #endif +import butl.path; import butl.sha256; +import butl.fdstream; +import butl.filesystem; #else +#include #include +#include +#include // auto_rmfile #endif using namespace std; @@ -37,6 +42,29 @@ main () "a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3"); { + string s; + for (size_t i (0); i < 1024; ++i) + s += "0123456789"; + + path p (path::temp_path ("butl-sha256")); + + auto_rmfile pr; // Always remove the file after the stream is closed. + ofdstream os (p); + pr = auto_rmfile (p); + + os << s; + os.close (); + + ifdstream is (p); + + assert (string (sha256 (is).string ()) == + sha256 (s.c_str (), s.size ()).string ()); + + assert (is.eof ()); + is.close (); + } + + { sha256 h ("123"); assert (string (h.string ()) == -- cgit v1.1