diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2025-04-15 19:56:23 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2025-04-15 19:56:23 -0700 |
commit | f440625e1421cca677a33d232d92d7bd35e83515 (patch) | |
tree | 7432f34fc085e6449c04e78bab4aee675afea3f8 | |
parent | 5947a426342c513a6155c65b393b961d23a57f2a (diff) | |
download | txr-f440625e1421cca677a33d232d92d7bd35e83515.tar.gz txr-f440625e1421cca677a33d232d92d7bd35e83515.tar.bz2 txr-f440625e1421cca677a33d232d92d7bd35e83515.zip |
chksum: support stream arguments in more places.
* chksum.c (sha1_stream_read, sha256_stream_read,
md5_stream_read): New static function.
(sha1_stream_impl, sha256_stream_impl, md5_stream_impl):
Logic moved into new functions.
(sha1, sha256, md5): Support stream argument, via corresponding
stream_impl function, passing nil as the size to snarf the
whole stream. This could have been implemented without
the above refactoring. In other words, the _stream functions
only need to be used now when a limit on the number of
bytes must be specified.
(sha1_hash, sha256_hash, md5_hash): Support a stream
argument.
* gencksum.txr: All above chksum.c changes actually
generated from here.
* tests/013/chksum.tl: New tests.
* txr.1: Documentation updated.
-rw-r--r-- | chksum.c | 108 | ||||
-rw-r--r-- | genchksum.txr | 36 | ||||
-rw-r--r-- | tests/013/chksum.tl | 9 | ||||
-rw-r--r-- | txr.1 | 22 |
4 files changed, 136 insertions, 39 deletions
@@ -91,13 +91,11 @@ static val chksum_ensure_buf(val self, val buf_in, static val sha1_ctx_s, sha256_ctx_s, md5_ctx_s; static struct cobj_class *sha1_ctx_cls, *sha256_ctx_cls, *md5_ctx_cls; -static void sha1_stream_impl(val stream, val nbytes, - unsigned char *hash, val self) +static void sha1_stream_read(SHA1_t *ctx, val stream, + val nbytes, val self) { - SHA1_t ctx; val buf = iobuf_get(); val bfsz = length_buf(buf); - SHA1_init(&ctx); if (null_or_missing_p(nbytes)) { for (;;) { @@ -107,7 +105,7 @@ static void sha1_stream_impl(val stream, val nbytes, if (!rd) break; - SHA1_update(&ctx, buf->b.data, rd); + SHA1_update(ctx, buf->b.data, rd); } } else { while (ge(nbytes, bfsz)) { @@ -117,7 +115,7 @@ static void sha1_stream_impl(val stream, val nbytes, if (zerop(read)) break; - SHA1_update(&ctx, buf->b.data, rd); + SHA1_update(ctx, buf->b.data, rd); nbytes = minus(nbytes, read); } @@ -127,14 +125,24 @@ static void sha1_stream_impl(val stream, val nbytes, val read = fill_buf(buf, zero, stream); cnum rd = c_num(read, self); if (rd) - SHA1_update(&ctx, buf->b.data, rd); + SHA1_update(ctx, buf->b.data, rd); } } - SHA1_final(&ctx, hash); iobuf_put(buf); } +static void sha1_stream_impl(val stream, val nbytes, + unsigned char *hash, val self) +{ + SHA1_t ctx; + SHA1_init(&ctx); + + sha1_stream_read(&ctx, stream, nbytes, self); + + SHA1_final(&ctx, hash); +} + val sha1_stream(val stream, val nbytes, val buf_in) { val self = lit("sha1-stream"); @@ -192,6 +200,12 @@ val sha1(val obj, val buf_in) case BUF: sha1_buf(obj, hash, self); return buf; + case COBJ: + if (streamp(obj)) { + sha1_stream_impl(obj, nil, hash, self); + return buf; + } + /* fallthrough */ default: uw_throwf(error_s, lit("~a: cannot hash ~s, " @@ -255,6 +269,12 @@ val sha1_hash(val ctx, val obj) SHA1_update(pctx, &uc, 1); } break; + case COBJ: + if (streamp(obj)) { + sha1_stream_read(pctx, obj, nil, self); + break; + } + /* fallthrough */ default: uw_throwf(error_s, lit("~a: cannot hash ~s, " "only buffer and strings"), @@ -277,13 +297,11 @@ val sha1_end(val ctx, val buf_in) return buf; } -static void sha256_stream_impl(val stream, val nbytes, - unsigned char *hash, val self) +static void sha256_stream_read(SHA256_t *ctx, val stream, + val nbytes, val self) { - SHA256_t ctx; val buf = iobuf_get(); val bfsz = length_buf(buf); - SHA256_init(&ctx); if (null_or_missing_p(nbytes)) { for (;;) { @@ -293,7 +311,7 @@ static void sha256_stream_impl(val stream, val nbytes, if (!rd) break; - SHA256_update(&ctx, buf->b.data, rd); + SHA256_update(ctx, buf->b.data, rd); } } else { while (ge(nbytes, bfsz)) { @@ -303,7 +321,7 @@ static void sha256_stream_impl(val stream, val nbytes, if (zerop(read)) break; - SHA256_update(&ctx, buf->b.data, rd); + SHA256_update(ctx, buf->b.data, rd); nbytes = minus(nbytes, read); } @@ -313,14 +331,24 @@ static void sha256_stream_impl(val stream, val nbytes, val read = fill_buf(buf, zero, stream); cnum rd = c_num(read, self); if (rd) - SHA256_update(&ctx, buf->b.data, rd); + SHA256_update(ctx, buf->b.data, rd); } } - SHA256_final(&ctx, hash); iobuf_put(buf); } +static void sha256_stream_impl(val stream, val nbytes, + unsigned char *hash, val self) +{ + SHA256_t ctx; + SHA256_init(&ctx); + + sha256_stream_read(&ctx, stream, nbytes, self); + + SHA256_final(&ctx, hash); +} + val sha256_stream(val stream, val nbytes, val buf_in) { val self = lit("sha256-stream"); @@ -378,6 +406,12 @@ val sha256(val obj, val buf_in) case BUF: sha256_buf(obj, hash, self); return buf; + case COBJ: + if (streamp(obj)) { + sha256_stream_impl(obj, nil, hash, self); + return buf; + } + /* fallthrough */ default: uw_throwf(error_s, lit("~a: cannot hash ~s, " @@ -441,6 +475,12 @@ val sha256_hash(val ctx, val obj) SHA256_update(pctx, &uc, 1); } break; + case COBJ: + if (streamp(obj)) { + sha256_stream_read(pctx, obj, nil, self); + break; + } + /* fallthrough */ default: uw_throwf(error_s, lit("~a: cannot hash ~s, " "only buffer and strings"), @@ -463,13 +503,11 @@ val sha256_end(val ctx, val buf_in) return buf; } -static void md5_stream_impl(val stream, val nbytes, - unsigned char *hash, val self) +static void md5_stream_read(MD5_t *ctx, val stream, + val nbytes, val self) { - MD5_t ctx; val buf = iobuf_get(); val bfsz = length_buf(buf); - MD5_init(&ctx); if (null_or_missing_p(nbytes)) { for (;;) { @@ -479,7 +517,7 @@ static void md5_stream_impl(val stream, val nbytes, if (!rd) break; - MD5_update(&ctx, buf->b.data, rd); + MD5_update(ctx, buf->b.data, rd); } } else { while (ge(nbytes, bfsz)) { @@ -489,7 +527,7 @@ static void md5_stream_impl(val stream, val nbytes, if (zerop(read)) break; - MD5_update(&ctx, buf->b.data, rd); + MD5_update(ctx, buf->b.data, rd); nbytes = minus(nbytes, read); } @@ -499,14 +537,24 @@ static void md5_stream_impl(val stream, val nbytes, val read = fill_buf(buf, zero, stream); cnum rd = c_num(read, self); if (rd) - MD5_update(&ctx, buf->b.data, rd); + MD5_update(ctx, buf->b.data, rd); } } - MD5_final(&ctx, hash); iobuf_put(buf); } +static void md5_stream_impl(val stream, val nbytes, + unsigned char *hash, val self) +{ + MD5_t ctx; + MD5_init(&ctx); + + md5_stream_read(&ctx, stream, nbytes, self); + + MD5_final(&ctx, hash); +} + val md5_stream(val stream, val nbytes, val buf_in) { val self = lit("md5-stream"); @@ -564,6 +612,12 @@ val md5(val obj, val buf_in) case BUF: md5_buf(obj, hash, self); return buf; + case COBJ: + if (streamp(obj)) { + md5_stream_impl(obj, nil, hash, self); + return buf; + } + /* fallthrough */ default: uw_throwf(error_s, lit("~a: cannot hash ~s, " @@ -627,6 +681,12 @@ val md5_hash(val ctx, val obj) MD5_update(pctx, &uc, 1); } break; + case COBJ: + if (streamp(obj)) { + md5_stream_read(pctx, obj, nil, self); + break; + } + /* fallthrough */ default: uw_throwf(error_s, lit("~a: cannot hash ~s, " "only buffer and strings"), diff --git a/genchksum.txr b/genchksum.txr index d3de9815..8d5509d2 100644 --- a/genchksum.txr +++ b/genchksum.txr @@ -56,13 +56,11 @@ static val @(rep)@{s.cname}_ctx_s, @(last)@{s.cname}_ctx_s;@(end) static struct cobj_class @(rep)*@{s.cname}_ctx_cls, @(last)*@{s.cname}_ctx_cls;@(end) @(repeat) -static void @{s.cname}_stream_impl(val stream, val nbytes, - unsigned char *hash, val self) +static void @{s.cname}_stream_read(@{s.type} *ctx, val stream, + val nbytes, val self) { - @{s.type} ctx; val buf = iobuf_get(); val bfsz = length_buf(buf); - @{s.init}(&ctx); if (null_or_missing_p(nbytes)) { for (;;) { @@ -72,7 +70,7 @@ static void @{s.cname}_stream_impl(val stream, val nbytes, if (!rd) break; - @{s.update}(&ctx, buf->b.data, rd); + @{s.update}(ctx, buf->b.data, rd); } } else { while (ge(nbytes, bfsz)) { @@ -82,7 +80,7 @@ static void @{s.cname}_stream_impl(val stream, val nbytes, if (zerop(read)) break; - @{s.update}(&ctx, buf->b.data, rd); + @{s.update}(ctx, buf->b.data, rd); nbytes = minus(nbytes, read); } @@ -92,14 +90,24 @@ static void @{s.cname}_stream_impl(val stream, val nbytes, val read = fill_buf(buf, zero, stream); cnum rd = c_num(read, self); if (rd) - @{s.update}(&ctx, buf->b.data, rd); + @{s.update}(ctx, buf->b.data, rd); } } - @{s.final}(&ctx, hash); iobuf_put(buf); } +static void @{s.cname}_stream_impl(val stream, val nbytes, + unsigned char *hash, val self) +{ + @{s.type} ctx; + @{s.init}(&ctx); + + @{s.cname}_stream_read(&ctx, stream, nbytes, self); + + @{s.final}(&ctx, hash); +} + val @{s.cname}_stream(val stream, val nbytes, val buf_in) { val self = lit("@{s.cname}-stream"); @@ -157,6 +165,12 @@ val @{s.cname}(val obj, val buf_in) case BUF: @{s.cname}_buf(obj, hash, self); return buf; + case COBJ: + if (streamp(obj)) { + @{s.cname}_stream_impl(obj, nil, hash, self); + return buf; + } + /* fallthrough */ default: uw_throwf(error_s, lit("~a: cannot hash ~s, " @@ -220,6 +234,12 @@ val @{s.cname}_hash(val ctx, val obj) @{s.update}(pctx, &uc, 1); } break; + case COBJ: + if (streamp(obj)) { + @{s.cname}_stream_read(pctx, obj, nil, self); + break; + } + /* fallthrough */ default: uw_throwf(error_s, lit("~a: cannot hash ~s, " "only buffer and strings"), diff --git a/tests/013/chksum.tl b/tests/013/chksum.tl index 6c9e7add..7b4be59e 100644 --- a/tests/013/chksum.tl +++ b/tests/013/chksum.tl @@ -33,8 +33,13 @@ [updatefn ctx piece]) [endfn ctx])) (h3 (let ((s (make-buf-stream testbuf))) - [streamfn s]))) + [streamfn s])) + (h4 (let ((ctx [begfn]) + (s (make-buf-stream testbuf))) + [updatefn ctx s] + [endfn ctx]))) (mtest (equal h0 h1) t (equal h0 h2) t - (equal h0 h3) t))) + (equal h0 h3) t + (equal h0 h4) t))) @@ -72331,7 +72331,7 @@ and .code sha256 function calculate, respectively, the NIST SHA-1 and SHA-256 digests over .metn obj , -which may be a character string or a buffer. +which may be a string, buffer or stream. Similarly, the .code md5 @@ -72346,9 +72346,18 @@ in that buffer, according to its current length. If .meta obj -is a character string, then the digest is calculated over the bytes +is a string, then the digest is calculated over the bytes which constitute its UTF-8 representation. +If +.meta obj +is a stream, then the digest is calculated over the stream, as if +by a call to the appropriate choice among the functions +.codn sha1-stream , +.code sha256-stream +or +.codn md5-stream . + If the .meta buf argument is omitted, the digest value is returned as a new, @@ -72391,7 +72400,8 @@ by including into the digest calculation. The .meta obj argument may be: a character or character string, whose UTF-8 representation is -digested; a buffer object, whose contents are digested; or an integer, +digested; a buffer object, whose contents are digested; a stream, +which is likewise digested; or an integer, representing a byte value in the range 0 to 255 included in the digest. The .code sha1-hash @@ -72448,7 +72458,8 @@ by including into the digest calculation. The .meta obj argument may be: a character or character string, whose UTF-8 representation is -digested; a buffer object, whose contents are digested; or an integer, +digested; a buffer object, whose contents are digested; a stream, +which is likewise digested; or an integer, representing a byte value in the range 0 to 255 included in the digest. The .code sha256-hash @@ -72505,7 +72516,8 @@ by including into the digest calculation. The .meta obj argument may be: a character or character string, whose UTF-8 representation is -digested; a buffer object, whose contents are digested; or an integer, +digested; a buffer object, whose contents are digested; a stream, +which is likewise digested; or an integer, representing a byte value in the range 0 to 255 included in the digest. The .code md5-hash |