diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2019-06-24 06:21:28 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2019-06-24 06:21:28 -0700 |
commit | ec6aa3e26fe599d7ce87f7addc2a63b58621eab0 (patch) | |
tree | e9eb5147df0da6f3f6462df71f603a191df11a4c /chksum.c | |
parent | f4af19feab59a5c9d6a045d34fbc7ebd4592999b (diff) | |
download | txr-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.c | 87 |
1 files changed, 87 insertions, 0 deletions
@@ -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)); } |