diff options
author | polwex <polwex@sortug.com> | 2025-10-05 21:56:51 +0700 |
---|---|---|
committer | polwex <polwex@sortug.com> | 2025-10-05 21:56:51 +0700 |
commit | fcedfddf00b3f994e4f4e40332ac7fc192c63244 (patch) | |
tree | 51d38e62c7bdfcc5f9a5e9435fe820c93cfc9a3d /vere/pkg/noun/jets/e/zlib.c |
claude is gud
Diffstat (limited to 'vere/pkg/noun/jets/e/zlib.c')
-rw-r--r-- | vere/pkg/noun/jets/e/zlib.c | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/vere/pkg/noun/jets/e/zlib.c b/vere/pkg/noun/jets/e/zlib.c new file mode 100644 index 0000000..89937df --- /dev/null +++ b/vere/pkg/noun/jets/e/zlib.c @@ -0,0 +1,225 @@ +/// @file + +#include <allocate.h> +#include <stdio.h> +#include "zlib.h" + +#include "jets/q.h" +#include "jets/w.h" + +#include "noun.h" + +static void* +zlib_malloc(voidpf opaque, uInt items, uInt size) +{ + size_t len = items * size; + void* result = u3a_malloc(len); + return result; +} + +static void +zlib_free(voidpf opaque, voidpf address) +{ + u3a_free(address); +} + +u3_noun +_decompress(u3_atom pos, u3_noun octs, int window_bits) +{ + u3_atom p_octs = u3h(octs); + u3_atom q_octs = u3t(octs); + + c3_w p_octs_w, pos_w; + + if ( c3n == u3r_safe_word(p_octs, &p_octs_w) ) { + return u3_none; + } + if (c3n == u3r_safe_word(pos, &pos_w)) { + return u3_none; + } + + c3_w len_w = u3r_met(3, q_octs); + + int leading_zeros = 0; + + if (p_octs_w > len_w) { + leading_zeros = p_octs_w - len_w; + } + else { + len_w = p_octs_w; + } + + // Bytestream exhausted + // + if (pos_w >= len_w) { + return u3_none; + } + + c3_y* input; + + if (c3y == u3a_is_cat(q_octs)) { + input = (c3_y*)&q_octs + pos_w; + } + else { + u3a_atom* vat_u = u3a_to_ptr(q_octs); + input = (c3_y*)vat_u->buf_w + pos_w; + } + + int ret; + z_stream strm; + + if (pos_w < len_w) { + strm.avail_in = (len_w - pos_w); + } + else { + strm.avail_in = 0; + } + + strm.zalloc = zlib_malloc; + strm.zfree = zlib_free; + strm.opaque = Z_NULL; + strm.next_in = input; + + ret = inflateInit2(&strm, window_bits); + + if (ret != Z_OK) { + u3l_log("%i", ret); + u3l_log("%s", strm.msg); + return u3m_bail(c3__exit); + } + + c3_w chunk_w = len_w / 10; + u3i_slab sab_u; + +#define INIT_SZ 16384 + strm.avail_out = INIT_SZ; + u3i_slab_init(&sab_u, 3, INIT_SZ); + strm.next_out = sab_u.buf_y; + + void* this_address = strm.next_out; + +#define ZEROS_SZ 256 + c3_y zeros[ZEROS_SZ]; + + if (leading_zeros) { + memset(zeros, 0, ZEROS_SZ); + } + + while ((ret = inflate(&strm, Z_FINISH)) == Z_BUF_ERROR) { + + // Output exhausted: reallocate + // + if (strm.avail_out == 0) { + strm.avail_out = chunk_w; + + u3i_slab_grow(&sab_u, 3, strm.total_out + chunk_w); + strm.next_out = sab_u.buf_y + strm.total_out; + } + + // Input exhausted: input leading zeros? + // + if (strm.avail_in == 0) { + + if (leading_zeros) { + // Position in the stream exceeded atom bytes, + // but is still below stream length + // + if (strm.total_in + pos_w >= len_w + && strm.total_in + pos_w < p_octs_w) { + + c3_w rem_w = p_octs_w - (strm.total_in + pos_w); + strm.next_in = zeros; + + if (rem_w > ZEROS_SZ) { + strm.avail_in = ZEROS_SZ; + } + else { + strm.avail_in = rem_w; + } + } + else { + u3l_log("%i", ret); + u3l_log("%s", strm.msg); + inflateEnd(&strm); + u3i_slab_free(&sab_u); + return u3m_bail(c3__exit); + } + } + else { + u3l_log("%i", ret); + u3l_log("%s", strm.msg); + inflateEnd(&strm); + u3i_slab_free(&sab_u); + return u3m_bail(c3__exit); + } + } + } + if (ret != Z_STREAM_END) { + u3l_log("%i", ret); + u3l_log("%s", strm.msg); + inflateEnd(&strm); + u3i_slab_free(&sab_u); + return u3m_bail(c3__exit); + } + ret = inflateEnd(&strm); + + if (ret != Z_OK) { + u3l_log("%i", ret); + u3l_log("%s", strm.msg); + u3i_slab_free(&sab_u); + return u3m_bail(c3__exit); + } + + u3_noun decompressed_octs = u3nc(strm.total_out, u3i_slab_mint(&sab_u)); + u3_noun new_pos = pos_w + strm.total_in; + u3_noun new_stream = u3nc(u3i_word(new_pos), u3k(octs)); + + return u3nc(decompressed_octs, new_stream); +} + +u3_noun +u3qe_decompress_gzip(u3_atom pos, u3_noun octs) +{ + return _decompress(pos, octs, 31); +} +u3_noun +u3qe_decompress_zlib(u3_atom pos, u3_noun octs) +{ + return _decompress(pos, octs, 15); +} + +u3_noun +u3we_decompress_gzip(u3_noun cor) +{ + u3_atom pos; + u3_noun octs; + + u3_noun a = u3r_at(u3x_sam, cor); + u3x_cell(a, &pos, &octs); + + if(_(u3a_is_atom(pos)) && _(u3a_is_cell(octs))) { + return u3qe_decompress_gzip(pos, octs); + } + + else { + return u3m_bail(c3__exit); + } +} + +u3_noun +u3we_decompress_zlib(u3_noun cor) +{ + u3_atom pos; + u3_noun octs; + + u3_noun a = u3r_at(u3x_sam, cor); + u3x_cell(a, &pos, &octs); + + if(_(u3a_is_atom(pos)) && _(u3a_is_cell(octs))) { + return u3qe_decompress_zlib(pos, octs); + } + + else { + return u3m_bail(c3__exit); + } +} |