summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2020-06-30 23:56:34 -0700
committerKaz Kylheku <kaz@kylheku.com>2020-06-30 23:56:34 -0700
commit4e6f86a1ce67142c3f21ac60fdddcbc6fb6c3a22 (patch)
tree392e2dbf5b7ff1b4ea8f7c2dfe88bb53bbff5ec5
parentf9258408cb85cdc2fecfe19fbd3e5c902bd907ba (diff)
downloadtxr-4e6f86a1ce67142c3f21ac60fdddcbc6fb6c3a22.tar.gz
txr-4e6f86a1ce67142c3f21ac60fdddcbc6fb6c3a22.tar.bz2
txr-4e6f86a1ce67142c3f21ac60fdddcbc6fb6c3a22.zip
crc32: add optional initial crc argument.
This allows a CRC-32 calculation over multiple objects in multiple steps. * chksum.c (crc32_stream, crc32_buf, crc32_str, crc32): Take additional argument. (chksum_init): Add optional argument to registration of crc32-stream and crc32 intrinsics. * chksum.h (crc32_stream, crc32): Declarations updated. * txr.1: Doc updated; two examples added.
-rw-r--r--chksum.c22
-rw-r--r--chksum.h4
-rw-r--r--txr.138
3 files changed, 47 insertions, 17 deletions
diff --git a/chksum.c b/chksum.c
index d4f3c4d2..ad277f82 100644
--- a/chksum.c
+++ b/chksum.c
@@ -241,12 +241,12 @@ val sha256_end(val ctx, val buf_in)
return buf;
}
-val crc32_stream(val stream, val nbytes)
+val crc32_stream(val stream, val nbytes, val init)
{
val self = lit("crc32-stream");
- u32_t crc = 0;
val buf = iobuf_get();
val bfsz = length_buf(buf);
+ u32_t crc = if3(missingp(init), 0, c_u32(init, self));
if (null_or_missing_p(nbytes)) {
for (;;) {
@@ -284,12 +284,12 @@ val crc32_stream(val stream, val nbytes)
return unum(crc);
}
-static val crc32_buf(val buf, val self)
+static val crc32_buf(val buf, val init, val self)
{
ucnum len = c_unum(buf->b.len, self);
mem_t *data = buf->b.data;
const size_t szmax = convert(size_t, -1) / 4 + 1;
- u32_t crc = 0;
+ u32_t crc = if3(missingp(init), 0, c_u32(init, self));
while (len >= szmax) {
crc = crc32_cont(data, szmax, crc);
@@ -303,14 +303,14 @@ static val crc32_buf(val buf, val self)
return unum(crc);
}
-static val crc32_str(val str)
+static val crc32_str(val str, val init)
{
val s = make_byte_input_stream(str);
- return crc32_stream(s, nil);
+ return crc32_stream(s, nil, init);
}
-val crc32(val obj)
+val crc32(val obj, val init)
{
val self = lit("sha256");
@@ -318,9 +318,9 @@ val crc32(val obj)
case STR:
case LSTR:
case LIT:
- return crc32_str(obj);
+ return crc32_str(obj, init);
case BUF:
- return crc32_buf(obj, self);
+ return crc32_buf(obj, init, self);
default:
uw_throwf(error_s, lit("~a: cannot hash ~s, only buffer and strings"),
self, obj, nao);
@@ -514,8 +514,8 @@ void chksum_init(void)
reg_fun(intern(lit("sha256-begin"), user_package), func_n0(sha256_begin));
reg_fun(intern(lit("sha256-hash"), user_package), func_n2(sha256_hash));
reg_fun(intern(lit("sha256-end"), user_package), func_n2o(sha256_end, 1));
- reg_fun(intern(lit("crc32-stream"), user_package), func_n2o(crc32_stream, 1));
- reg_fun(intern(lit("crc32"), user_package), func_n1(crc32));
+ reg_fun(intern(lit("crc32-stream"), user_package), func_n3o(crc32_stream, 1));
+ reg_fun(intern(lit("crc32"), user_package), func_n2o(crc32, 1));
reg_fun(intern(lit("md5-stream"), user_package), func_n3o(md5_stream, 1));
reg_fun(intern(lit("md5"), user_package), func_n2o(md5, 1));
reg_fun(intern(lit("md5-begin"), user_package), func_n0(md5_begin));
diff --git a/chksum.h b/chksum.h
index 6ec364e5..33cc9c67 100644
--- a/chksum.h
+++ b/chksum.h
@@ -30,8 +30,8 @@ val sha256(val obj, val buf);
val sha256_begin(void);
val sha256_hash(val ctx, val obj);
val sha256_end(val ctx, val buf);
-val crc32_stream(val stream, val nbytes);
-val crc32(val obj);
+val crc32_stream(val stream, val nbytes, val init);
+val crc32(val obj, val init);
val md5_stream(val stream, val nbytes, val buf);
val md5(val obj, val buf_in);
val md5_begin(void);
diff --git a/txr.1 b/txr.1
index accc3a7c..05c96ae7 100644
--- a/txr.1
+++ b/txr.1
@@ -55574,7 +55574,7 @@ savings time).
.coNP Function @ crc32-stream
.synb
-.mets (crc32-stream < stream <> [ nbytes ])
+.mets (crc32-stream < stream >> [ nbytes <> [ crc-prev ]])
.syne
.desc
The
@@ -55590,11 +55590,19 @@ integer. It gives the number of bytes which should be read
and included in the sum. If the argument is omitted, then bytes are read
until the end of the stream.
-The CRC-32 is returned as a non-negative integer.
+The optional
+.meta crc-prev
+argument defaults to zero. It is fully documented under the
+.code crc32
+function.
+
+The
+.code crc32-stream
+functions returns the calculated CRC-32 as a non-negative integer.
.coNP Function @ crc32
.synb
-.mets (crc32 << obj )
+.mets (crc32 < obj <> [ crc-prev ])
.syne
.desc
The
@@ -55613,7 +55621,29 @@ If
is a character string, then the sum is calculated over the bytes
which constitute its UTF-8 representation.
-The CRC-32 is returned as a non-negative integer.
+The optional
+.meta crc-prev
+argument defaults to zero. If specified, it should be a nonnegative integer in
+the 32 bit range. This argument is useful when a single CRC-32 must be
+calculated in multiple operations over several objects. The first call should
+specify a value of zero, or omit the argument. To continue the checksum,
+each subsequent call to the function should pass as the
+.meta crc-prev
+argument the CRC-32 obtained from the previous call.
+
+The
+.code crc32
+function returns the calculated CRC-32 as a non-negative integer.
+
+.TP* Examples:
+
+.mono
+ ;; Single operation
+ (crc32 "ABCD") --> 3675725989
+
+ ;; In two steps, demonstrating crc-prev argument:
+ (crc32 "CD" (crc32 "AB")) -> 3675725989
+.onom
.coNP Functions @ sha256-stream and @ md5-stream
.synb