diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2023-07-09 09:00:26 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2023-07-09 09:00:26 -0700 |
commit | feb8eefb2fc97e5f8ccc831f28ef10e67717ec22 (patch) | |
tree | 4ef3b27f5372d1ce1b0d74f6a1ef48494946628c /chksum.c | |
parent | f48e22cfb4de514a02ef20da8ff863a175c3dc87 (diff) | |
download | txr-feb8eefb2fc97e5f8ccc831f28ef10e67717ec22.tar.gz txr-feb8eefb2fc97e5f8ccc831f28ef10e67717ec22.tar.bz2 txr-feb8eefb2fc97e5f8ccc831f28ef10e67717ec22.zip |
chksum: generate with TXR.
A giant macro that generates numerous functions and variables
is hell for anyone who has to debug the code. The right
approach is external code generation, where the result is
a clean source file that is checked into the repository.
* genchksum.txr: New file.
* chksum.c: Now generated.
(chksum_impl): Macro and its invocations removed.
(sha1_stream_impl, sha1_stream, sha1_szmax_upd,
sha1_buf, sha1_str, sha1, sha1_ops,
sha1_begin,
sha1_utf8_byte_callback, sha1_hash,
sha1_end): These are directly defined again.
(sha256_stream_impl, sha256_stream, sha256_szmax_upd,
sha256_buf, sha256_str, sha256, sha256_ops,
sha256_begin,
sha256_utf8_byte_callback, sha256_hash,
sha256_end): Likewise.
generated by macro.
md5_stream_impl, md5_stream,
md5_szmax_upd,
md5_buf, md5_str, md5, md5_ops,
md5_begin,
md5_utf8_byte_callback, md5_hash,
md5_end): Likewise.
Diffstat (limited to 'chksum.c')
-rw-r--r-- | chksum.c | 765 |
1 files changed, 552 insertions, 213 deletions
@@ -1,3 +1,5 @@ +/* This file is generated by genchksum.txr */ + /* Copyright 2019-2023 * Kaz Kylheku <kaz@kylheku.com> * Vancouver, Canada @@ -68,223 +70,560 @@ static val chksum_ensure_buf(val self, val buf_in, } } -#define chksum_impl(nameroot, ctx_type, \ - hash_name, digest_len, chksum_init, \ - chksum_update, chksum_final) \ - \ - static void nameroot ## _stream_impl(val stream, \ - val nbytes, \ - unsigned char *hash, \ - val self) \ - { \ - ctx_type ctx; \ - val buf = iobuf_get(); \ - val bfsz = length_buf(buf); \ - chksum_init(&ctx); \ - \ - if (null_or_missing_p(nbytes)) { \ - for (;;) { \ - val read = fill_buf(buf, zero, stream); \ - cnum rd = c_num(read, self); \ - \ - if (!rd) \ - break; \ - \ - chksum_update(&ctx, buf->b.data, rd); \ - } \ - } else { \ - while (ge(nbytes, bfsz)) { \ - val read = fill_buf(buf, zero, stream); \ - cnum rd = c_num(read, self); \ - \ - if (zerop(read)) \ - break; \ - \ - chksum_update(&ctx, buf->b.data, rd); \ - nbytes = minus(nbytes, read); \ - } \ - \ - buf_set_length(buf, nbytes, nil); \ - \ - { \ - val read = fill_buf(buf, zero, stream); \ - cnum rd = c_num(read, self); \ - if (rd) \ - chksum_update(&ctx, buf->b.data, rd); \ - } \ - } \ - \ - chksum_final(&ctx, hash); \ - iobuf_put(buf); \ - } \ - \ - val nameroot ## _stream(val stream, val nbytes, val buf_in) \ - { \ - val self = lit(#nameroot "-stream"); \ - unsigned char *hash; \ - val buf = chksum_ensure_buf(self, buf_in, \ - num_fast(digest_len), \ - &hash, lit(hash_name)); \ - nameroot ## _stream_impl(stream, nbytes, hash, self); \ - return buf; \ - } \ - \ - static void nameroot ## _szmax_upd(ctx_type *pctx, \ - mem_t *data, ucnum len) \ - { \ - const size_t szmax = convert(size_t, -1) / 4 + 1; \ - while (len >= szmax) { \ - chksum_update(pctx, data, szmax); \ - data += szmax; \ - len -= szmax; \ - } \ - if (len > 0) \ - chksum_update(pctx, data, len); \ - } \ - \ - static void nameroot ## _buf(val buf, unsigned char *hash, \ - val self) \ - { \ - ctx_type ctx; \ - chksum_init(&ctx); \ - nameroot ## _szmax_upd(&ctx, buf->b.data, \ - c_unum(buf->b.len, self)); \ - chksum_final(&ctx, hash); \ - } \ - \ - static void nameroot ## _str(val str, unsigned char *hash, \ - val self) \ - { \ - char *s = utf8_dup_to(c_str(str, self)); \ - ctx_type ctx; \ - chksum_init(&ctx); \ - chksum_update(&ctx, coerce(const unsigned char *, s), \ - strlen(s)); \ - free(s); \ - chksum_final(&ctx, hash); \ - } \ - \ - val nameroot(val obj, val buf_in) \ - { \ - val self = lit(#nameroot); \ - unsigned char *hash; \ - val buf = chksum_ensure_buf(self, buf_in, \ - num_fast(digest_len), \ - &hash, lit(hash_name)); \ - switch (type(obj)) { \ - case STR: \ - case LSTR: \ - case LIT: \ - nameroot ## _str(obj, hash, self); \ - return buf; \ - case BUF: \ - nameroot ## _buf(obj, hash, self); \ - return buf; \ - default: \ - uw_throwf(error_s, \ - lit("~a: cannot hash ~s, " \ - "only buffer and strings"), \ - self, obj, nao); \ - } \ - } \ - \ - static struct cobj_ops nameroot ## _ops = \ - cobj_ops_init(cobj_equal_handle_op, \ - cobj_print_op, \ - cobj_destroy_free_op, \ - cobj_mark_op, \ - cobj_handle_hash_op); \ - \ - val nameroot ## _begin(void) \ - { \ - ctx_type *pctx = coerce(ctx_type *, \ - chk_malloc(sizeof *pctx)); \ - chksum_init(pctx); \ - return cobj(coerce(mem_t *, pctx), \ - nameroot ## _ctx_cls, &nameroot ## _ops); \ - } \ - \ - static int nameroot ## _utf8_byte_callback(int b, \ - mem_t *ctx) \ - { \ - ctx_type *pctx = coerce(ctx_type *, ctx); \ - unsigned char uc = b; \ - chksum_update(pctx, &uc, 1); \ - return 1; \ - } \ - \ - val nameroot ## _hash(val ctx, val obj) \ - { \ - val self = lit(#nameroot "-hash"); \ - ctx_type *pctx = coerce(ctx_type *, \ - cobj_handle(self, ctx, \ - nameroot ## \ - _ctx_cls)); \ - switch (type(obj)) { \ - case STR: \ - case LSTR: \ - case LIT: \ - { \ - char *str = utf8_dup_to(c_str(obj, self)); \ - chksum_update(pctx, \ - coerce(const unsigned char *, str), \ - strlen(str)); \ - free(str); \ - } \ - break; \ - case BUF: \ - nameroot ## _szmax_upd(pctx, obj->b.data, \ - c_unum(obj->b.len, self)); \ - break; \ - case CHR: \ - utf8_encode(c_ch(obj), \ - nameroot ## _utf8_byte_callback, \ - coerce(mem_t *, pctx)); \ - break; \ - case NUM: \ - { \ - cnum n = c_num(obj, self); \ - unsigned char uc = n; \ - if (n < 0 || n > 255) \ - uw_throwf(error_s, \ - lit("~a: byte value ~s out of range"), \ - self, obj, nao); \ - chksum_update(pctx, &uc, 1); \ - } \ - break; \ - default: \ - uw_throwf(error_s, lit("~a: cannot hash ~s, " \ - "only buffer and strings"), \ - self, obj, nao); \ - } \ - \ - return obj; \ - } \ - \ - val nameroot ## _end(val ctx, val buf_in) \ - { \ - val self = lit(#nameroot "-end"); \ - unsigned char *hash; \ - ctx_type *pctx = coerce(ctx_type *, \ - cobj_handle(self, ctx, \ - nameroot ## \ - _ctx_cls)); \ - val buf = chksum_ensure_buf(self, buf_in, \ - num_fast(digest_len), \ - &hash, lit(hash_name)); \ - chksum_final(pctx, hash); \ - chksum_init(pctx); \ - return buf; \ +static void sha1_stream_impl(val stream, val nbytes, + unsigned char *hash, val self) +{ + SHA1_t ctx; + val buf = iobuf_get(); + val bfsz = length_buf(buf); + SHA1_init(&ctx); + + if (null_or_missing_p(nbytes)) { + for (;;) { + val read = fill_buf(buf, zero, stream); + cnum rd = c_num(read, self); + + if (!rd) + break; + + SHA1_update(&ctx, buf->b.data, rd); + } + } else { + while (ge(nbytes, bfsz)) { + val read = fill_buf(buf, zero, stream); + cnum rd = c_num(read, self); + + if (zerop(read)) + break; + + SHA1_update(&ctx, buf->b.data, rd); + nbytes = minus(nbytes, read); + } + + buf_set_length(buf, nbytes, nil); + + { + val read = fill_buf(buf, zero, stream); + cnum rd = c_num(read, self); + if (rd) + SHA1_update(&ctx, buf->b.data, rd); + } + } + + SHA1_final(&ctx, hash); + iobuf_put(buf); +} + +val sha1_stream(val stream, val nbytes, val buf_in) +{ + val self = lit("sha1-stream"); + unsigned char *hash; + val buf = chksum_ensure_buf(self, buf_in, + num_fast(SHA1_DIGEST_LENGTH), + &hash, lit("SHA-1")); + sha1_stream_impl(stream, nbytes, hash, self); + return buf; +} + +static void sha1_szmax_upd(SHA1_t *pctx, mem_t *data, ucnum len) +{ + const size_t szmax = convert(size_t, -1) / 4 + 1; + while (len >= szmax) { + SHA1_update(pctx, data, szmax); + data += szmax; + len -= szmax; + } + if (len > 0) + SHA1_update(pctx, data, len); +} + +static void sha1_buf(val buf, unsigned char *hash, val self) +{ + SHA1_t ctx; + SHA1_init(&ctx); + sha1_szmax_upd(&ctx, buf->b.data, c_unum(buf->b.len, self)); + SHA1_final(&ctx, hash); +} + +static void sha1_str(val str, unsigned char *hash, val self) +{ + char *s = utf8_dup_to(c_str(str, self)); + SHA1_t ctx; + SHA1_init(&ctx); + SHA1_update(&ctx, coerce(const unsigned char *, s), strlen(s)); + free(s); + SHA1_final(&ctx, hash); +} + +val sha1(val obj, val buf_in) +{ + val self = lit("sha1"); + unsigned char *hash; + val buf = chksum_ensure_buf(self, buf_in, + num_fast(SHA1_DIGEST_LENGTH), + &hash, lit("SHA-1")); + switch (type(obj)) { + case STR: + case LSTR: + case LIT: + sha1_str(obj, hash, self); + return buf; + case BUF: + sha1_buf(obj, hash, self); + return buf; + default: + uw_throwf(error_s, + lit("~a: cannot hash ~s, " + "only buffer and strings"), + self, obj, nao); } +} -chksum_impl(sha1, SHA1_t, "SHA-1", SHA1_DIGEST_LENGTH, - SHA1_init, SHA1_update, SHA1_final); +static struct cobj_ops sha1_ops = cobj_ops_init(cobj_equal_handle_op, + cobj_print_op, + cobj_destroy_free_op, + cobj_mark_op, + cobj_handle_hash_op); -chksum_impl(sha256, SHA256_t, "SHA-256", SHA256_DIGEST_LENGTH, - SHA256_init, SHA256_update, SHA256_final); +val sha1_begin(void) +{ + SHA1_t *pctx = coerce(SHA1_t *, chk_malloc(sizeof *pctx)); + SHA1_init(pctx); + return cobj(coerce(mem_t *, pctx), sha1_ctx_cls, &sha1_ops); +} -chksum_impl(md5, MD5_t, "MD5", MD5_DIGEST_LENGTH, - MD5_init, MD5_update, MD5_final); +static int sha1_utf8_byte_callback(int b, mem_t *ctx) +{ + SHA1_t *pctx = coerce(SHA1_t *, ctx); + unsigned char uc = b; + SHA1_update(pctx, &uc, 1); + return 1; +} + +val sha1_hash(val ctx, val obj) +{ + val self = lit("sha1-hash"); + SHA1_t *pctx = coerce(SHA1_t *, + cobj_handle(self, ctx, sha1_ctx_cls)); + switch (type(obj)) { + case STR: + case LSTR: + case LIT: + { + char *str = utf8_dup_to(c_str(obj, self)); + SHA1_update(pctx, coerce(const unsigned char *, str), strlen(str)); + free(str); + } + break; + case BUF: + sha1_szmax_upd(pctx, obj->b.data, c_unum(obj->b.len, self)); + break; + case CHR: + utf8_encode(c_ch(obj), sha1_utf8_byte_callback, + coerce(mem_t *, pctx)); + break; + case NUM: + { + cnum n = c_num(obj, self); + unsigned char uc = n; + if (n < 0 || n > 255) + uw_throwf(error_s, + lit("~a: byte value ~s out of range"), + self, obj, nao); + SHA1_update(pctx, &uc, 1); + } + break; + default: + uw_throwf(error_s, lit("~a: cannot hash ~s, " + "only buffer and strings"), + self, obj, nao); + } + + return obj; +} + +val sha1_end(val ctx, val buf_in) +{ + val self = lit("sha1-end"); + unsigned char *hash; + SHA1_t *pctx = coerce(SHA1_t *, + cobj_handle(self, ctx, sha1_ctx_cls)); + val buf = chksum_ensure_buf(self, buf_in, num_fast(SHA1_DIGEST_LENGTH), + &hash, lit("SHA-1")); + SHA1_final(pctx, hash); + SHA1_init(pctx); + return buf; +} + +static void sha256_stream_impl(val stream, val nbytes, + unsigned char *hash, val self) +{ + SHA256_t ctx; + val buf = iobuf_get(); + val bfsz = length_buf(buf); + SHA256_init(&ctx); + + if (null_or_missing_p(nbytes)) { + for (;;) { + val read = fill_buf(buf, zero, stream); + cnum rd = c_num(read, self); + + if (!rd) + break; + + SHA256_update(&ctx, buf->b.data, rd); + } + } else { + while (ge(nbytes, bfsz)) { + val read = fill_buf(buf, zero, stream); + cnum rd = c_num(read, self); + + if (zerop(read)) + break; + + SHA256_update(&ctx, buf->b.data, rd); + nbytes = minus(nbytes, read); + } + + buf_set_length(buf, nbytes, nil); + + { + val read = fill_buf(buf, zero, stream); + cnum rd = c_num(read, self); + if (rd) + SHA256_update(&ctx, buf->b.data, rd); + } + } + + SHA256_final(&ctx, hash); + iobuf_put(buf); +} + +val sha256_stream(val stream, val nbytes, val buf_in) +{ + val self = lit("sha256-stream"); + unsigned char *hash; + val buf = chksum_ensure_buf(self, buf_in, + num_fast(SHA256_DIGEST_LENGTH), + &hash, lit("SHA-256")); + sha256_stream_impl(stream, nbytes, hash, self); + return buf; +} + +static void sha256_szmax_upd(SHA256_t *pctx, mem_t *data, ucnum len) +{ + const size_t szmax = convert(size_t, -1) / 4 + 1; + while (len >= szmax) { + SHA256_update(pctx, data, szmax); + data += szmax; + len -= szmax; + } + if (len > 0) + SHA256_update(pctx, data, len); +} + +static void sha256_buf(val buf, unsigned char *hash, val self) +{ + SHA256_t ctx; + SHA256_init(&ctx); + sha256_szmax_upd(&ctx, buf->b.data, c_unum(buf->b.len, self)); + SHA256_final(&ctx, hash); +} + +static void sha256_str(val str, unsigned char *hash, val self) +{ + char *s = utf8_dup_to(c_str(str, self)); + SHA256_t ctx; + SHA256_init(&ctx); + SHA256_update(&ctx, coerce(const unsigned char *, s), strlen(s)); + free(s); + SHA256_final(&ctx, hash); +} + +val sha256(val obj, val buf_in) +{ + val self = lit("sha256"); + unsigned char *hash; + val buf = chksum_ensure_buf(self, buf_in, + num_fast(SHA256_DIGEST_LENGTH), + &hash, lit("SHA-256")); + switch (type(obj)) { + case STR: + case LSTR: + case LIT: + sha256_str(obj, hash, self); + return buf; + case BUF: + sha256_buf(obj, hash, self); + return buf; + default: + uw_throwf(error_s, + lit("~a: cannot hash ~s, " + "only buffer and strings"), + self, obj, nao); + } +} + +static struct cobj_ops sha256_ops = cobj_ops_init(cobj_equal_handle_op, + cobj_print_op, + cobj_destroy_free_op, + cobj_mark_op, + cobj_handle_hash_op); + +val sha256_begin(void) +{ + SHA256_t *pctx = coerce(SHA256_t *, chk_malloc(sizeof *pctx)); + SHA256_init(pctx); + return cobj(coerce(mem_t *, pctx), sha256_ctx_cls, &sha256_ops); +} + +static int sha256_utf8_byte_callback(int b, mem_t *ctx) +{ + SHA256_t *pctx = coerce(SHA256_t *, ctx); + unsigned char uc = b; + SHA256_update(pctx, &uc, 1); + return 1; +} + +val sha256_hash(val ctx, val obj) +{ + val self = lit("sha256-hash"); + SHA256_t *pctx = coerce(SHA256_t *, + cobj_handle(self, ctx, sha256_ctx_cls)); + switch (type(obj)) { + case STR: + case LSTR: + case LIT: + { + char *str = utf8_dup_to(c_str(obj, self)); + SHA256_update(pctx, coerce(const unsigned char *, str), strlen(str)); + free(str); + } + break; + case BUF: + sha256_szmax_upd(pctx, obj->b.data, c_unum(obj->b.len, self)); + break; + case CHR: + utf8_encode(c_ch(obj), sha256_utf8_byte_callback, + coerce(mem_t *, pctx)); + break; + case NUM: + { + cnum n = c_num(obj, self); + unsigned char uc = n; + if (n < 0 || n > 255) + uw_throwf(error_s, + lit("~a: byte value ~s out of range"), + self, obj, nao); + SHA256_update(pctx, &uc, 1); + } + break; + default: + uw_throwf(error_s, lit("~a: cannot hash ~s, " + "only buffer and strings"), + self, obj, nao); + } + + return obj; +} + +val sha256_end(val ctx, val buf_in) +{ + val self = lit("sha256-end"); + unsigned char *hash; + SHA256_t *pctx = coerce(SHA256_t *, + cobj_handle(self, ctx, sha256_ctx_cls)); + val buf = chksum_ensure_buf(self, buf_in, num_fast(SHA256_DIGEST_LENGTH), + &hash, lit("SHA-256")); + SHA256_final(pctx, hash); + SHA256_init(pctx); + return buf; +} + +static void md5_stream_impl(val stream, val nbytes, + unsigned char *hash, val self) +{ + MD5_t ctx; + val buf = iobuf_get(); + val bfsz = length_buf(buf); + MD5_init(&ctx); + + if (null_or_missing_p(nbytes)) { + for (;;) { + val read = fill_buf(buf, zero, stream); + cnum rd = c_num(read, self); + + if (!rd) + break; + + MD5_update(&ctx, buf->b.data, rd); + } + } else { + while (ge(nbytes, bfsz)) { + val read = fill_buf(buf, zero, stream); + cnum rd = c_num(read, self); + + if (zerop(read)) + break; + + MD5_update(&ctx, buf->b.data, rd); + nbytes = minus(nbytes, read); + } + + buf_set_length(buf, nbytes, nil); + + { + val read = fill_buf(buf, zero, stream); + cnum rd = c_num(read, self); + if (rd) + MD5_update(&ctx, buf->b.data, rd); + } + } + + MD5_final(&ctx, hash); + iobuf_put(buf); +} + +val md5_stream(val stream, val nbytes, val buf_in) +{ + val self = lit("md5-stream"); + unsigned char *hash; + val buf = chksum_ensure_buf(self, buf_in, + num_fast(MD5_DIGEST_LENGTH), + &hash, lit("MD5")); + md5_stream_impl(stream, nbytes, hash, self); + return buf; +} + +static void md5_szmax_upd(MD5_t *pctx, mem_t *data, ucnum len) +{ + const size_t szmax = convert(size_t, -1) / 4 + 1; + while (len >= szmax) { + MD5_update(pctx, data, szmax); + data += szmax; + len -= szmax; + } + if (len > 0) + MD5_update(pctx, data, len); +} + +static void md5_buf(val buf, unsigned char *hash, val self) +{ + MD5_t ctx; + MD5_init(&ctx); + md5_szmax_upd(&ctx, buf->b.data, c_unum(buf->b.len, self)); + MD5_final(&ctx, hash); +} + +static void md5_str(val str, unsigned char *hash, val self) +{ + char *s = utf8_dup_to(c_str(str, self)); + MD5_t ctx; + MD5_init(&ctx); + MD5_update(&ctx, coerce(const unsigned char *, s), strlen(s)); + free(s); + MD5_final(&ctx, hash); +} + +val md5(val obj, val buf_in) +{ + val self = lit("md5"); + unsigned char *hash; + val buf = chksum_ensure_buf(self, buf_in, + num_fast(MD5_DIGEST_LENGTH), + &hash, lit("MD5")); + switch (type(obj)) { + case STR: + case LSTR: + case LIT: + md5_str(obj, hash, self); + return buf; + case BUF: + md5_buf(obj, hash, self); + return buf; + default: + uw_throwf(error_s, + lit("~a: cannot hash ~s, " + "only buffer and strings"), + self, obj, nao); + } +} + +static struct cobj_ops md5_ops = cobj_ops_init(cobj_equal_handle_op, + cobj_print_op, + cobj_destroy_free_op, + cobj_mark_op, + cobj_handle_hash_op); + +val md5_begin(void) +{ + MD5_t *pctx = coerce(MD5_t *, chk_malloc(sizeof *pctx)); + MD5_init(pctx); + return cobj(coerce(mem_t *, pctx), md5_ctx_cls, &md5_ops); +} + +static int md5_utf8_byte_callback(int b, mem_t *ctx) +{ + MD5_t *pctx = coerce(MD5_t *, ctx); + unsigned char uc = b; + MD5_update(pctx, &uc, 1); + return 1; +} + +val md5_hash(val ctx, val obj) +{ + val self = lit("md5-hash"); + MD5_t *pctx = coerce(MD5_t *, + cobj_handle(self, ctx, md5_ctx_cls)); + switch (type(obj)) { + case STR: + case LSTR: + case LIT: + { + char *str = utf8_dup_to(c_str(obj, self)); + MD5_update(pctx, coerce(const unsigned char *, str), strlen(str)); + free(str); + } + break; + case BUF: + md5_szmax_upd(pctx, obj->b.data, c_unum(obj->b.len, self)); + break; + case CHR: + utf8_encode(c_ch(obj), md5_utf8_byte_callback, + coerce(mem_t *, pctx)); + break; + case NUM: + { + cnum n = c_num(obj, self); + unsigned char uc = n; + if (n < 0 || n > 255) + uw_throwf(error_s, + lit("~a: byte value ~s out of range"), + self, obj, nao); + MD5_update(pctx, &uc, 1); + } + break; + default: + uw_throwf(error_s, lit("~a: cannot hash ~s, " + "only buffer and strings"), + self, obj, nao); + } + + return obj; +} + +val md5_end(val ctx, val buf_in) +{ + val self = lit("md5-end"); + unsigned char *hash; + MD5_t *pctx = coerce(MD5_t *, + cobj_handle(self, ctx, md5_ctx_cls)); + val buf = chksum_ensure_buf(self, buf_in, num_fast(MD5_DIGEST_LENGTH), + &hash, lit("MD5")); + MD5_final(pctx, hash); + MD5_init(pctx); + return buf; +} val crc32_stream(val stream, val nbytes, val init) { |