summaryrefslogtreecommitdiffstats
path: root/chksum.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-06-24 06:21:28 -0700
committerKaz Kylheku <kaz@kylheku.com>2019-06-24 06:21:28 -0700
commitec6aa3e26fe599d7ce87f7addc2a63b58621eab0 (patch)
treee9eb5147df0da6f3f6462df71f603a191df11a4c /chksum.c
parentf4af19feab59a5c9d6a045d34fbc7ebd4592999b (diff)
downloadtxr-ec6aa3e26fe599d7ce87f7addc2a63b58621eab0.tar.gz
txr-ec6aa3e26fe599d7ce87f7addc2a63b58621eab0.tar.bz2
txr-ec6aa3e26fe599d7ce87f7addc2a63b58621eab0.zip
New: CRC-32 functions.
* Makefile (OBJS): Add chksums/crc32.o. * chksum.c (crc32_stream, crc32): New functions. (chksum_init): Register crc32-stream and crc32 intrinsic functions. * chksums/crc32.c, chksums/crc32.h: New files. * txr.1: Documented.
Diffstat (limited to 'chksum.c')
-rw-r--r--chksum.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/chksum.c b/chksum.c
index 78af6b8d..588bdf92 100644
--- a/chksum.c
+++ b/chksum.c
@@ -44,6 +44,7 @@
#include "utf8.h"
#include "buf.h"
#include "chksums/sha256.h"
+#include "chksums/crc32.h"
#include "chksum.h"
val sha256_stream(val stream, val nbytes)
@@ -135,8 +136,94 @@ val sha256(val obj)
}
}
+val crc32_stream(val stream, val nbytes)
+{
+ u32_t crc = 0;
+ val bfsz = num_fast(BUFSIZ);
+ val buf = make_buf(bfsz, nil, nil);
+
+ if (null_or_missing_p(nbytes)) {
+ for (;;) {
+ val read = fill_buf(buf, zero, stream);
+ cnum rd = c_num(read);
+
+ if (!rd)
+ break;
+
+ crc = crc32_cont(buf->b.data, rd, crc);
+ }
+ } else {
+ while (ge(nbytes, bfsz)) {
+ val read = fill_buf(buf, zero, stream);
+ cnum rd = c_num(read);
+
+ if (zerop(read))
+ break;
+
+ crc = crc32_cont(buf->b.data, rd, crc);
+ nbytes = minus(nbytes, read);
+ }
+
+ buf_set_length(buf, nbytes, nil);
+
+ {
+ val read = fill_buf(buf, zero, stream);
+ cnum rd = c_num(read);
+ if (rd)
+ crc = crc32_cont(buf->b.data, rd, crc);
+ }
+ }
+
+ return unum(crc);
+}
+
+static val crc32_buf(val buf, val self)
+{
+ ucnum len = c_unum(buf->b.len);
+ mem_t *data = buf->b.data;
+ const size_t szmax = convert(size_t, -1) / 4 + 1;
+ u32_t crc = 0;
+
+ while (len >= szmax) {
+ crc = crc32_cont(data, szmax, crc);
+ data += szmax;
+ len -= szmax;
+ }
+
+ if (len > 0)
+ crc = crc32_cont(data, len, crc);
+
+ return unum(crc);
+}
+
+static val crc32_str(val str, val self)
+{
+ val s = make_byte_input_stream(str);
+ return crc32_stream(s, nil);
+}
+
+
+val crc32(val obj)
+{
+ val self = lit("sha256");
+
+ switch (type(obj)) {
+ case STR:
+ case LSTR:
+ case LIT:
+ return crc32_str(obj, self);
+ case BUF:
+ return crc32_buf(obj, self);
+ default:
+ uw_throwf(error_s, lit("~a: cannot hash ~s, only buffer and strings"),
+ self, obj, nao);
+ }
+}
+
void chksum_init(void)
{
reg_fun(intern(lit("sha256-stream"), user_package), func_n2o(sha256_stream, 1));
reg_fun(intern(lit("sha256"), user_package), func_n1(sha256));
+ reg_fun(intern(lit("crc32-stream"), user_package), func_n2o(crc32_stream, 1));
+ reg_fun(intern(lit("crc32"), user_package), func_n1(crc32));
}