Skip to content

Commit

Permalink
zlib jets: bytestream decompression
Browse files Browse the repository at this point in the history
  • Loading branch information
mikolajpp committed Aug 19, 2024
1 parent 008a91d commit 63ac476
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 74 deletions.
208 changes: 140 additions & 68 deletions pkg/noun/jets/e/zlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,139 +10,211 @@
#include "noun.h"

static void*
gzip_malloc(voidpf opaque, uInt items, uInt size)
zlib_malloc(voidpf opaque, uInt items, uInt size)
{
size_t len = items * size;
void* result = u3a_malloc(len);
return result;
}

static void
gzip_free(voidpf opaque, voidpf address)
zlib_free(voidpf opaque, voidpf address)
{
u3a_free(address);
}

u3_noun
u3qe_gunzip(u3_noun zipped_octs)
_decompress(u3_atom pos, u3_noun octs, int window_bits)
{
u3_atom head = u3h(zipped_octs);
u3_atom tail = u3t(zipped_octs);
c3_w tel_w = u3r_met(3, tail);
c3_w hed_w;
if ( c3n == u3r_safe_word(head, &hed_w) ) {
return u3m_bail(c3__fail);
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_c* input;

if (c3y == u3a_is_cat(tail)) {
input = &tail;
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 {
u3a_atom* vat_u = u3a_to_ptr(tail);
input = (c3_y*)vat_u->buf_w;
len_w = p_octs_w;
}

// Bytestream exhausted
//
if (pos_w >= len_w) {
return u3_none;
}

if ( tel_w > hed_w ) {
return u3m_error("subtract-underflow");
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;

int leading_zeros = hed_w - tel_w;

if (leading_zeros > 0) {
strm.avail_in = hed_w - leading_zeros;
if (pos_w < len_w) {
strm.avail_in = (len_w - pos_w);
}
else {
strm.avail_in = hed_w;
strm.avail_in = 0;
}

strm.zalloc = gzip_malloc;
strm.zfree = gzip_free;
strm.zalloc = zlib_malloc;
strm.zfree = zlib_free;
strm.opaque = Z_NULL;
strm.next_in = input;

ret = inflateInit2(&strm, 16);
if (ret != 0) {
ret = inflateInit2(&strm, window_bits);

if (ret != Z_OK) {
u3l_log("%i", ret);
u3l_log("%s", strm.msg);
return u3m_bail(c3__exit);
}

uint chunk = hed_w / 10;
strm.avail_out = 16384;
strm.next_out = u3a_malloc(16384);
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;
ret = inflate(&strm, Z_FINISH);

if (strm.total_in + leading_zeros == hed_w) {
int zero = 0;
strm.next_in = &zero;
for (int i=0; i<leading_zeros; i++) {
strm.avail_in = 1;
ret = inflate(&strm, Z_FINISH);
}
}

if (((ret > -5 && ret < 0) || ret == 2) || (strm.avail_in == 0 && ret == Z_BUF_ERROR)) {
u3l_log("%i", ret);
u3l_log("%s", strm.msg);
return u3m_bail(c3__exit);
}
#define ZEROS_SZ 256
c3_y zeros[ZEROS_SZ];

while (strm.avail_in > 0) {
strm.avail_out = chunk;
if (leading_zeros) {
memset(zeros, 0, ZEROS_SZ);
}

this_address = u3a_realloc(this_address, (strm.total_out + chunk));
strm.next_out = this_address + strm.total_out;
while ((ret = inflate(&strm, Z_FINISH)) == Z_BUF_ERROR) {

ret = inflate(&strm, Z_FINISH);
// Output exhausted: reallocate
//
if (strm.avail_out == 0) {
strm.avail_out = chunk_w;

if ((ret > -5 && ret < 0) || ret == 2) {
u3l_log("%i", ret);
u3l_log("%s", strm.msg);
return u3m_bail(c3__exit);
u3i_slab_grow(&sab_u, 3, strm.total_out + chunk_w);
strm.next_out = sab_u.buf_y + strm.total_out;
}
}

if (strm.total_in + leading_zeros == hed_w) {
int zero = 0;
strm.next_in = &zero;
for (int i=0; i<leading_zeros; i++) {
strm.avail_in = 1;
ret = inflate(&strm, Z_FINISH);
// 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);
return u3m_bail(c3__exit);
}
}
else {
u3l_log("%i", ret);
u3l_log("%s", strm.msg);
inflateEnd(&strm);
return u3m_bail(c3__exit);
}
}
}

if (ret < 0 || ret == 2) {
if (ret != Z_STREAM_END) {
u3l_log("%i", ret);
u3l_log("%s", strm.msg);
inflateEnd(&strm);
return u3m_bail(c3__exit);
}

u3_noun unzipped_octs = u3nc(strm.total_out, u3i_bytes(strm.total_out, this_address));
ret = inflateEnd(&strm);

if (ret < 0 || ret == 2) {
if (ret != Z_OK) {
u3l_log("%i", ret);
u3l_log("%s", strm.msg);
return u3m_bail(c3__exit);
}

return unzipped_octs;
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_gunzip(u3_noun cor)
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 ( _(u3du(a)) ) {
return u3qe_gunzip(a);
if(_(u3a_is_atom(pos)) && _(u3a_is_cell(octs))) {
return u3qe_decompress_zlib(pos, octs);
}

else {
return u3m_bail(c3__exit);
}
Expand Down
4 changes: 3 additions & 1 deletion pkg/noun/jets/q.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,9 @@
u3_noun u3qes_equ(u3_atom, u3_atom);
u3_noun u3qes_gte(u3_atom, u3_atom);
u3_noun u3qes_gth(u3_atom, u3_atom);
u3_noun u3qe_gunzip(u3_noun);

u3_noun u3qe_decompress_zlib(u3_atom, u3_noun);
u3_noun u3qe_decompress_gzip(u3_atom, u3_noun);

/** Tier 6.
**/
Expand Down
12 changes: 8 additions & 4 deletions pkg/noun/jets/tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,12 @@ static c3_c* _140_hex_lune_ha[] = {
};
static u3j_harm _137_hex__crc32_a[] = {{".2", u3we_crc32}, {}};
static u3j_core _137_hex__crc_d[] = {{"crc32", 7, _137_hex__crc32_a, 0, no_hashes }, {}};
static u3j_harm _139_hex__gunzip_a[] = {{".2", u3we_gunzip}, {}};
static u3j_core _139_hex__unzip_d[] = {{"gunzip", 7, _139_hex__gunzip_a, 0, no_hashes }, {}};
static u3j_harm _139_hex__decompress_zlib_a[] = {{".2", u3we_decompress_zlib}, {}};
static u3j_harm _139_hex__decompress_gzip_a[] = {{".2", u3we_decompress_gzip}, {}};
static u3j_core _139_hex__zlib_d[] = {
{"decompress-zlib", 7, _139_hex__decompress_zlib_a, 0, no_hashes },
{"decompress-gzip", 7, _139_hex__decompress_gzip_a, 0, no_hashes },
{}};
static u3j_harm _140_hex_coed__ed_puck_a[] = {{".2", u3wee_puck}, {}};
static c3_c* _140_hex_coed__ed_puck_ha[] = {
"1bc694675842345c50b0e20a2193bb5bcbb42f163fc832431a3d1822a81e4c98",
Expand Down Expand Up @@ -2349,9 +2353,9 @@ static u3j_core _138_hex_d[] =
{ "leer", 63, _140_hex_leer_a, 0, no_hashes },
{ "loss", 63, _140_hex_loss_a, 0, no_hashes },
{ "lune", 127, _140_hex_lune_a, 0, no_hashes },
// XX move me to 137 when it exists
// XX move me to 137 when it exists
{ "crc", 31, 0, _137_hex__crc_d, no_hashes },
{ "gzip", 31, 0, _139_hex__unzip_d, no_hashes },
{ "zlib", 31, 0, _139_hex__zlib_d, no_hashes },

{ "coed", 63, 0, _140_hex_coed_d, no_hashes },
{ "aes", 31, 0, _140_hex_aes_d, no_hashes },
Expand Down
4 changes: 3 additions & 1 deletion pkg/noun/jets/w.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,10 @@
u3_noun u3wes_equ(u3_noun);
u3_noun u3wes_gte(u3_noun);
u3_noun u3wes_gth(u3_noun);

u3_noun u3we_crc32(u3_noun);
u3_noun u3we_gunzip(u3_noun);
u3_noun u3we_decompress_zlib(u3_noun);
u3_noun u3we_decompress_gzip(u3_noun);

/** Tier 6.
**/
Expand Down

0 comments on commit 63ac476

Please sign in to comment.