From fcedfddf00b3f994e4f4e40332ac7fc192c63244 Mon Sep 17 00:00:00 2001 From: polwex Date: Sun, 5 Oct 2025 21:56:51 +0700 Subject: claude is gud --- vere/pkg/noun/jets/e/bytestream.c | 1247 +++++++++++++++++++++++++++++++++++++ 1 file changed, 1247 insertions(+) create mode 100644 vere/pkg/noun/jets/e/bytestream.c (limited to 'vere/pkg/noun/jets/e/bytestream.c') diff --git a/vere/pkg/noun/jets/e/bytestream.c b/vere/pkg/noun/jets/e/bytestream.c new file mode 100644 index 0000000..71761e1 --- /dev/null +++ b/vere/pkg/noun/jets/e/bytestream.c @@ -0,0 +1,1247 @@ +#include +#include +#include +#include +#include +#include +#include + +// XX do not crash on indirect atoms, but default to Hoon +// XX use u3i_word to imprison all indirect atoms +// +static void +_x_octs(u3_noun octs, u3_atom* p_octs, u3_atom* q_octs) { + + if (c3n == u3r_mean(octs, + 2, p_octs, + 3, q_octs, 0)){ + u3m_bail(c3__exit); + } + + if (c3n == u3a_is_atom(*p_octs) || + c3n == u3a_is_atom(*q_octs)) { + u3m_bail(c3__exit); + } +} +static c3_o +_x_octs_buffer(u3_atom* p_octs, u3_atom *q_octs, + c3_w* p_octs_w, c3_y** buf_y, + c3_w* len_w, c3_w* lead_w) +{ + if (c3n == u3r_safe_word(*p_octs, p_octs_w)) { + return c3n; + } + + *len_w = u3r_met(3, *q_octs); + + if (c3y == u3a_is_cat(*q_octs)) { + *buf_y = (c3_y*)q_octs; + } + else { + u3a_atom* ptr_a = u3a_to_ptr(*q_octs); + *buf_y = (c3_y*)ptr_a->buf_w; + } + + *lead_w = 0; + + if (*p_octs_w > *len_w) { + *lead_w = *p_octs_w - *len_w; + } + else { + *len_w = *p_octs_w; + } + + return c3y; +} + +u3_noun +_qe_bytestream_rip_octs(u3_atom p_octs, u3_atom q_octs) { + + c3_w p_octs_w, len_w, lead_w; + c3_y* buf_y; + + if (c3n == _x_octs_buffer(&p_octs, &q_octs, + &p_octs_w, &buf_y, + &len_w, &lead_w)){ + return u3_none; + } + + if (p_octs_w == 0) { + return u3_nul; + } + + u3_noun rip = u3_nul; + + while (lead_w--) { + rip = u3nc(0x0, rip); + } + + buf_y += len_w - 1; + + while (len_w--) { + rip = u3nc(*(buf_y--), rip); + } + + return rip; +} + +u3_noun +u3we_bytestream_rip_octs(u3_noun cor){ + + u3_noun sam = u3x_at(u3x_sam, cor); + + u3_atom p_octs, q_octs; + _x_octs(sam, &p_octs, &q_octs); + + return _qe_bytestream_rip_octs(p_octs, q_octs); + +} + +u3_noun +_qe_bytestream_cat_octs(u3_noun octs_a, u3_noun octs_b) { + + u3_atom p_octs_a, p_octs_b; + u3_atom q_octs_a, q_octs_b; + + _x_octs(octs_a, &p_octs_a, &q_octs_a); + _x_octs(octs_b, &p_octs_b, &q_octs_b); + + c3_w p_octs_a_w, p_octs_b_w; + c3_w len_w, lem_w; + c3_w lead_w, leaf_w; + + c3_y* sea_y; + c3_y* seb_y; + + if (c3n == _x_octs_buffer(&p_octs_a, &q_octs_a, + &p_octs_a_w, &sea_y, + &len_w, &lead_w)) { + return u3_none; + } + + if (c3n == _x_octs_buffer(&p_octs_b, &q_octs_b, + &p_octs_b_w, &seb_y, + &lem_w, &leaf_w)) { + return u3_none; + } + + if (p_octs_a_w == 0) { + return u3k(octs_b); + } + + if (p_octs_b_w == 0) { + return u3k(octs_a); + } + + c3_d p_octs_d = p_octs_a_w + p_octs_b_w; + + u3_noun ret; + + // Both a and b are 0. + // + if (len_w == 0 && lem_w == 0) { + ret = u3nc(u3i_chub(p_octs_d), u3i_word(0)); + } + else { + u3i_slab sab_u; + + u3i_slab_bare(&sab_u, 3, (c3_d)p_octs_a_w + lem_w); + sab_u.buf_w[sab_u.len_w - 1] = 0; + + memcpy(sab_u.buf_y, sea_y, len_w); + memset(sab_u.buf_y + len_w, 0, lead_w); + memcpy(sab_u.buf_y + p_octs_a_w, seb_y, lem_w); + + u3_noun q_octs = u3i_slab_moot(&sab_u); + ret = u3nc(u3i_chub(p_octs_d), q_octs); + } + return ret; +} + +u3_noun +u3we_bytestream_cat_octs(u3_noun cor) { + + u3_noun octs_a, octs_b; + + u3x_mean(cor, u3x_sam_2, &octs_a, u3x_sam_3, &octs_b, 0); + + return _qe_bytestream_cat_octs(octs_a, octs_b); + +} + +u3_noun +_qe_bytestream_can_octs(u3_noun octs_list) { + + if (u3_nul == octs_list) { + return u3nc(0, 0); + } + + if (u3_nul == u3t(octs_list)) { + return u3k(u3h(octs_list)); + } + + /* We can octs in two steps: + * first loop iteration computes the total required + * buffer size in bytes, factoring in the leading bytes + * of the final octs. The second loop iterates over each octs, + * copying the data to the output buffer. + */ + + // Compute total size + // + c3_d tot_d = 0; + + u3_noun octs_list_start = octs_list; + u3_noun octs = u3_none; + // Last non-zero octs + u3_noun last_octs = u3_none; + + while (octs_list != u3_nul) { + + octs = u3h(octs_list); + + if (c3n == u3a_is_atom(u3h(octs)) || + c3n == u3a_is_atom(u3t(octs))) { + u3m_bail(c3__exit); + } + c3_w p_octs_w; + + if (c3n == u3r_safe_word(u3h(octs), &p_octs_w)) { + u3z(octs_list); + return u3_none; + } + // Check for overflow + // + if ( p_octs_w > (UINT64_MAX - tot_d)){ + return u3_none; + } + tot_d += p_octs_w; + + octs_list = u3t(octs_list); + } + + // Compute leading zeros of last non-zero octs -- the buffer + // size is decreased by this much. + // + // =leading-zeros (sub p.octs (met 3 q.octs)) + // + // p.octs fits into a word -- this has been verified + // in the loop above. + // + // The resulting buf_len_w is correct only if the last + // octs is non-zero: but at the return u3i_slab_mint + // takes care of trimming. + // + c3_w last_lead_w = (u3r_word(0, u3h(octs)) - u3r_met(3, u3t(octs))); + c3_d buf_len_w = tot_d - last_lead_w; + + if (buf_len_w == 0) { + return u3nc(u3i_word(tot_d), 0); + } + + u3i_slab sab_u; + u3i_slab_bare(&sab_u, 3, buf_len_w); + c3_y* buf_y = sab_u.buf_y; + + sab_u.buf_w[sab_u.len_w - 1] = 0; + + c3_y* sea_y; + u3_atom p_octs, q_octs; + c3_w p_octs_w, q_octs_w; + c3_w len_w, lead_w; + + // Bytes written so far + // + c3_d wit_d = 0; + + octs_list = octs_list_start; + + while (octs_list != u3_nul) { + + octs = u3h(octs_list); + + _x_octs(octs, &p_octs, &q_octs); + if (c3n == _x_octs_buffer(&p_octs, &q_octs, + &p_octs_w, &sea_y, + &len_w, &lead_w)){ + return u3_none; + } + + if (p_octs_w == 0) { + octs_list = u3t(octs_list); + continue; + } + + memcpy(buf_y, sea_y, len_w); + buf_y += len_w; + wit_d += len_w; + + // More bytes to follow, write leading zeros + // + if (wit_d < buf_len_w) { + memset(buf_y, 0, lead_w); + buf_y += lead_w; + wit_d += lead_w; + } + + octs_list = u3t(octs_list); + } + + u3_assert((buf_y - sab_u.buf_y) == buf_len_w); + + return u3nc(u3i_chub(tot_d), u3i_slab_mint(&sab_u)); +} + +u3_noun +u3we_bytestream_can_octs(u3_noun cor) +{ + u3_noun octs_list; + + u3x_mean(cor, u3x_sam_1, &octs_list, 0); + + return _qe_bytestream_can_octs(octs_list); +} +u3_noun +_qe_bytestream_skip_line(u3_atom pos, u3_noun octs) +{ + c3_w pos_w; + + if (c3n == u3r_safe_word(pos, &pos_w)) { + return u3_none; + } + + u3_atom p_octs, q_octs; + + _x_octs(octs, &p_octs, &q_octs); + + c3_w p_octs_w; + c3_w len_w, lead_w; + + c3_y* sea_y; + + if (c3n == _x_octs_buffer(&p_octs, &q_octs, + &p_octs_w, &sea_y, + &len_w, &lead_w)) { + return u3_none; + } + + while (pos_w < len_w) { + if (*(sea_y + pos_w) == '\n') { + break; + } + pos_w++; + } + // Newline not found, position at the end + if (*(sea_y + pos_w) != '\n') { + pos_w = p_octs; + } + else { + pos_w++; + } + + return u3nc(u3i_word(pos_w), u3k(octs)); +} +u3_noun +u3we_bytestream_skip_line(u3_noun cor) +{ + + u3_atom pos; + u3_noun octs; + + u3x_mean(cor, u3x_sam_2, &pos, u3x_sam_3, &octs, 0); + + return _qe_bytestream_skip_line(pos, octs); + +} +u3_noun +_qe_bytestream_find_byte(u3_atom bat, u3_atom pos, u3_noun octs) +{ + c3_w bat_w, pos_w; + + if (c3n == u3r_safe_word(bat, &bat_w) || bat_w > 0xff) { + return u3_none; + } + if (c3n == u3r_safe_word(pos, &pos_w)) { + return u3_none; + } + + u3_atom p_octs, q_octs; + + _x_octs(octs, &p_octs, &q_octs); + + c3_w p_octs_w; + c3_w len_w, lead_w; + + c3_y* sea_y; + + if (c3n == _x_octs_buffer(&p_octs, &q_octs, + &p_octs_w, &sea_y, + &len_w, &lead_w)) { + return u3_none; + } + + while (pos_w < len_w) { + + if (*(sea_y + pos_w) == bat_w) { + return u3nc(u3_nul, u3i_word(pos_w)); + } + + pos_w++; + } + // Here we are sure that: + // (1) bat_w has not been found + // (2) therefore pos_w == len_w + // + // If bat_w == 0, and there is still input + // in the stream, it means pos_w points at + // the first leading zero. + // + if (pos_w < p_octs && bat_w == 0) { + return u3nc(u3_nul, u3i_word(pos_w)); + } + + return u3_nul; +} +u3_noun +u3we_bytestream_find_byte(u3_noun cor) +{ + u3_atom bat; + u3_atom pos; + u3_noun octs; + + u3x_mean(cor, u3x_sam_2, &bat, + u3x_sam_6, &pos, + u3x_sam_7, &octs, 0); + + return _qe_bytestream_find_byte(bat, pos, octs); +} +u3_noun +_qe_bytestream_seek_byte(u3_atom bat, u3_atom pos, u3_noun octs) +{ + c3_w bat_w, pos_w; + + if (c3n == u3r_safe_word(bat, &bat_w) || bat_w > 0xff) { + return u3_none; + } + if (c3n == u3r_safe_word(pos, &pos_w)) { + return u3_none; + } + + u3_atom p_octs, q_octs; + + _x_octs(octs, &p_octs, &q_octs); + + c3_w p_octs_w; + c3_w len_w, lead_w; + + c3_y* sea_y; + + if (c3n == _x_octs_buffer(&p_octs, &q_octs, + &p_octs_w, &sea_y, + &len_w, &lead_w)) { + return u3_none; + } + + while (pos_w < len_w) { + + if (*(sea_y + pos_w) == bat_w) { + u3_noun idx = u3nc(u3_nul, u3i_word(pos_w)); + u3_noun new_bays = u3nc(u3i_word(pos_w), u3k(octs)); + return u3nc(idx, new_bays); + } + + pos_w++; + } + + // find leading zero: see comment in *_find_byte + // + if (pos_w < p_octs && bat_w == 0) { + u3_noun idx = u3nc(u3_nul, u3i_word(pos_w)); + u3_noun new_bays = u3nc(u3i_word(pos_w), u3k(octs)); + return u3nc(idx, new_bays); + } + + return u3nc(u3_nul, u3nc(u3k(pos), u3k(octs))); + +} +u3_noun +u3we_bytestream_seek_byte(u3_noun cor) +{ + u3_atom bat; + u3_atom pos; + u3_noun octs; + + u3x_mean(cor, u3x_sam_2, &bat, + u3x_sam_6, &pos, + u3x_sam_7, &octs, 0); + + return _qe_bytestream_seek_byte(bat, pos, octs); +} + +u3_noun +_qe_bytestream_read_byte(u3_atom pos, u3_noun octs) +{ + c3_w pos_w; + + if (c3n == u3r_safe_word(pos, &pos_w)) { + return u3_none; + } + + u3_atom p_octs, q_octs; + + _x_octs(octs, &p_octs, &q_octs); + + c3_w p_octs_w; + c3_w len_w, lead_w; + + c3_y* sea_y; + + if (c3n == _x_octs_buffer(&p_octs, &q_octs, + &p_octs_w, &sea_y, + &len_w, &lead_w)) { + return u3_none; + } + + if (pos_w + 1 > p_octs_w) { + u3m_bail(c3__exit); + } + + c3_y bat_y; + + if (pos_w < len_w) { + bat_y = *(sea_y + pos_w); + } + else { + bat_y = 0; + } + + u3_noun new_bays = u3nc(u3i_word(pos_w + 1), u3k(octs)); + + return u3nc(bat_y, new_bays); +} + +u3_noun +u3we_bytestream_read_byte(u3_noun cor) +{ + u3_atom pos; + u3_noun octs; + + u3x_mean(cor, u3x_sam_2, &pos, + u3x_sam_3, &octs, 0); + + return _qe_bytestream_read_byte(pos, octs); +} + +u3_noun +_qe_bytestream_read_octs(u3_atom n, u3_atom pos, u3_noun octs) +{ + c3_w n_w, pos_w; + + if (c3n == u3r_safe_word(n, &n_w)) { + return u3_none; + } + + if (c3n == u3r_safe_word(pos, &pos_w)) { + return u3_none; + } + + if (n_w == 0) { + return u3nc(u3nc(0,0), u3nc(u3k(pos), u3k(octs))); + } + + u3_atom p_octs, q_octs; + + _x_octs(octs, &p_octs, &q_octs); + + c3_w p_octs_w; + c3_w len_w, lead_w; + + c3_y* sea_y; + + if (c3n == _x_octs_buffer(&p_octs, &q_octs, + &p_octs_w, &sea_y, + &len_w, &lead_w)) { + return u3_none; + } + + if (pos_w + n_w > p_octs_w) { + u3m_bail(c3__exit); + } + + // Number of bytes to read, excluding leading zeros + // + c3_w red_w = n_w; + + if (pos_w + n_w > len_w) { + if (pos_w < len_w) { + red_w = len_w - pos_w; + } + // leading zeros - nothing to read + // + else { + red_w = 0; + } + } + + u3_noun read_octs; + + if (red_w == 0) { + read_octs = u3nc(u3i_word(n_w), 0); + } + else { + u3i_slab sab_u; + u3i_slab_bare(&sab_u, 3, n_w); + sab_u.buf_w[sab_u.len_w - 1] = 0; + + memcpy(sab_u.buf_y, sea_y + pos_w, red_w); + + if (red_w < n_w) { + memset(sab_u.buf_y + red_w, 0, (n_w - red_w)); + } + + read_octs = u3nc(u3i_word(n_w), u3i_slab_moot(&sab_u)); + } + + u3_noun new_bays = u3nc(u3i_word(pos_w + n_w), u3k(octs)); + + return u3nc(read_octs, new_bays); +} + +u3_noun +u3we_bytestream_read_octs(u3_noun cor) +{ + u3_atom n; + u3_atom pos; + u3_noun octs; + + u3x_mean(cor, u3x_sam_2, &n, + u3x_sam_6, &pos, + u3x_sam_7, &octs, 0); + + return _qe_bytestream_read_octs(n, pos, octs); +} + + +u3_noun +_qe_peek_octs(c3_w n_w, c3_w pos_w, c3_w p_octs_w, c3_y* sea_y, + c3_w len_w) +{ + if (n_w == 0) { + return u3nc(0, 0); + } + + if (pos_w + n_w > p_octs_w) { + return u3m_bail(c3__exit); + } + + // Read leading zeros only + // + if (pos_w >= len_w) { + return u3nc(u3i_word(n_w), 0); + } + // Number of remaining buffer bytes + c3_w reb_w = len_w - pos_w; + + u3i_slab sab_u; + c3_w my_len_w; + + if (n_w < reb_w) { + my_len_w = n_w; + } + else { + my_len_w = reb_w; + } + u3i_slab_bare(&sab_u, 3, my_len_w); + sab_u.buf_w[sab_u.len_w - 1] = 0; + memcpy(sab_u.buf_y, sea_y + pos_w, my_len_w); + + return u3nc(u3i_word(n_w), u3i_slab_moot(&sab_u)); +} +u3_noun _qe_bytestream_chunk(u3_atom size, u3_noun pos, u3_noun octs) +{ + c3_w size_w, pos_w; + + if (c3n == u3r_safe_word(size, &size_w)) { + return u3_none; + } + + if (size_w == 0) { + return u3_nul; + } + + if (c3n == u3r_safe_word(pos, &pos_w)) { + return u3_none; + } + + u3_atom p_octs, q_octs; + + _x_octs(octs, &p_octs, &q_octs); + + c3_w p_octs_w; + c3_w len_w, lead_w; + + c3_y* sea_y; + + if (c3n == _x_octs_buffer(&p_octs, &q_octs, + &p_octs_w, &sea_y, + &len_w, &lead_w)) { + return u3_none; + } + + u3_noun hun = u3_nul; + + while (pos_w < p_octs) { + // Remaining bytes + // + c3_w rem = (p_octs - pos_w); + + if (rem < size) { + u3_noun octs = _qe_peek_octs(rem, pos_w, p_octs_w, sea_y, + len_w); + hun = u3nc(octs, hun); + pos_w += rem; + } + else { + u3_noun octs = _qe_peek_octs(size, pos_w, p_octs_w, sea_y, + len_w); + hun = u3nc(octs, hun); + pos_w += size; + } + } + + return u3kb_flop(hun); +} + +u3_noun +u3we_bytestream_chunk(u3_noun cor) +{ + u3_atom size; + u3_atom pos; + u3_noun octs; + + u3x_mean(cor, u3x_sam_2, &size, + u3x_sam_6, &pos, + u3x_sam_7, &octs, 0); + + return _qe_bytestream_chunk(size, pos, octs); +} + +u3_noun +_qe_bytestream_extract(u3_noun sea, u3_noun rac) +{ + u3_atom pos; + u3_noun octs; + + u3x_mean(sea, 2, &pos, 3, &octs, 0); + + c3_w pos_w; + + if (c3n == u3r_safe_word(pos, &pos_w)) { + return u3_none; + } + + u3_atom p_octs, q_octs; + + _x_octs(octs, &p_octs, &q_octs); + + c3_w p_octs_w; + c3_w len_w, lead_w; + + c3_y* sea_y; + + if (c3n == _x_octs_buffer(&p_octs, &q_octs, + &p_octs_w, &sea_y, + &len_w, &lead_w)) { + return u3_none; + } + + u3_noun dal = u3_nul; + + u3_noun new_sea = u3_none; + + while (pos_w < p_octs_w) { + new_sea = u3nc(u3i_word(pos_w), u3k(octs)); + u3_noun ext = u3x_good(u3n_slam_on(u3k(rac), new_sea)); + + u3_atom sip, ken; + c3_w sip_w, ken_w; + + u3x_mean(ext, 2, &sip, 3, &ken, 0); + + if (c3n == u3r_safe_word(sip, &sip_w)) { + // XX is u3z necessary here? + // does memory get freed on bail? + // + u3l_log("bytestream: sip fail"); + u3z(dal); + u3z(ext); + return u3_none; + } + + if (c3n == u3r_safe_word(ken, &ken_w)) { + u3l_log("bytestream: ken fail"); + u3z(dal); + u3z(ext); + return u3_none; + } + + u3z(ext); + + if (sip_w == 0 && ken_w == 0) { + break; + } + + if (pos_w + sip_w > p_octs_w) { + u3z(dal); + return u3_none; + } + + pos_w += sip_w; + + if (ken_w == 0) { + continue; + } + + u3_noun octs = _qe_peek_octs(ken_w, pos_w, p_octs_w, sea_y, len_w); + pos_w += ken_w; + dal = u3nc(octs, dal); + } + + new_sea = u3nc(u3i_word(pos_w), u3k(octs)); + + return u3nc(u3kb_flop(dal), new_sea); +} +u3_noun +u3we_bytestream_extract(u3_noun cor) +{ + u3_noun sea; + u3_noun rac; + + u3x_mean(cor, u3x_sam_2, &sea, + u3x_sam_3, &rac, 0); + + return _qe_bytestream_extract(sea, rac); +} + +u3_noun +_qe_bytestream_fuse_extract(u3_noun sea, u3_noun rac) +{ + u3_atom pos; + u3_noun octs; + + u3x_mean(sea, 2, &pos, 3, &octs, 0); + + c3_w pos_w; + + if (c3n == u3r_safe_word(pos, &pos_w)) { + return u3_none; + } + + u3_atom p_octs, q_octs; + + _x_octs(octs, &p_octs, &q_octs); + + c3_w p_octs_w; + c3_w len_w, lead_w; + + c3_y* sea_y; + + if (c3n == _x_octs_buffer(&p_octs, &q_octs, + &p_octs_w, &sea_y, + &len_w, &lead_w)) { + return u3_none; + } + + u3_noun dal = u3_nul; + + u3_noun new_sea = u3_none; + + while (pos_w < p_octs_w) { + new_sea = u3nc(u3i_word(pos_w), u3k(octs)); + u3_noun ext = u3x_good(u3n_slam_on(u3k(rac), new_sea)); + + u3_atom sip, ken; + c3_w sip_w, ken_w; + + u3x_mean(ext, 2, &sip, 3, &ken, 0); + + if (c3n == u3r_safe_word(sip, &sip_w)) { + // XX is u3z necessary here? + // does memory get freed on bail? + // + u3l_log("bytestream: sip fail"); + u3z(dal); + u3z(ext); + return u3_none; + } + if (c3n == u3r_safe_word(ken, &ken_w)) { + u3l_log("bytestream: ken fail"); + u3z(dal); + u3z(ext); + return u3_none; + } + + u3z(ext); + + if (sip_w == 0 && ken_w == 0) { + break; + } + + if (pos_w + sip_w > p_octs_w) { + u3z(dal); + return u3_none; + } + + pos_w += sip_w; + + if (ken_w == 0) { + continue; + } + + u3_noun octs = _qe_peek_octs(ken_w, pos_w, p_octs_w, sea_y, len_w); + pos_w += ken_w; + dal = u3nc(octs, dal); + } + + u3_noun lad = u3kb_flop(dal); + u3_noun data = _qe_bytestream_can_octs(lad); + u3z(lad); + + new_sea = u3nc(u3i_word(pos_w), u3k(octs)); + + return u3nc(data, new_sea); +} + +u3_noun +u3we_bytestream_fuse_extract(u3_noun cor) +{ + u3_noun sea; + u3_noun rac; + + u3x_mean(cor, u3x_sam_2, &sea, + u3x_sam_3, &rac, 0); + + return _qe_bytestream_fuse_extract(sea, rac); +} + +#define BITS_D (sizeof(c3_d)*8) + +u3_noun +_qe_bytestream_need_bits(u3_atom n, u3_noun bits) +{ + u3_atom num, bit; + u3_noun bays; + + u3x_mean(bits, 2, &num, + 6, &bit, + 7, &bays, 0); + + + c3_w n_w, num_w; + c3_d bit_d; + + if (c3n == u3r_safe_word(n, &n_w)) { + return u3_none; + } + if (c3n == u3r_safe_word(num, &num_w)) { + return u3_none; + } + if (c3n == u3r_safe_chub(bit, &bit_d)) { + return u3_none; + } + + if (num_w >= n_w) { + return u3k(bits); + } + + // How many bytes to read + // + c3_w need_bits_w = n_w - num_w; + + // Requires indirect atom, drop to Hoon + // + if (need_bits_w > BITS_D) { + return u3_none; + } + + c3_w need_bytes_w = need_bits_w / 8; + + if (need_bits_w % 8) { + need_bytes_w += 1; + } + + c3_w pos_w; + u3_atom pos; + u3_noun octs; + + + u3x_mean(bays, 2, &pos, 3, &octs, 0); + + if (c3n == u3r_safe_word(pos, &pos_w)) { + return u3_none; + } + + u3_atom p_octs, q_octs; + + _x_octs(octs, &p_octs, &q_octs); + + c3_w p_octs_w; + c3_w len_w, lead_w; + + c3_y* sea_y; + + if (c3n == _x_octs_buffer(&p_octs, &q_octs, + &p_octs_w, &sea_y, + &len_w, &lead_w)) { + return u3_none; + } + + if (pos_w + need_bytes_w > p_octs_w) { + u3m_bail(c3__exit); + } + + while (need_bytes_w--) { + + if (pos_w < len_w) { + bit_d += *(sea_y + pos_w) << num_w; + } + num_w += 8; + pos_w++; + + u3_assert(num_w <= BITS_D); + } + + u3_noun new_bays = u3nc(u3i_word(pos_w), u3k(octs)); + + return u3nt(u3i_word(num_w), u3i_chub(bit_d), new_bays); +} +// +$ bits $+ bits +// $: num=@ud +// bit=@ub +// =bays +// == +u3_noun +u3we_bytestream_need_bits(u3_noun cor) +{ + u3_atom n; + u3_noun bits; + + u3x_mean(cor, u3x_sam_2, &n, + u3x_sam_3, &bits, 0); + + return _qe_bytestream_need_bits(n, bits); +} + +u3_noun +_qe_bytestream_drop_bits(u3_atom n, u3_noun bits) +{ + + u3_atom num, bit; + u3_noun bays; + + u3x_mean(bits, 2, &num, + 6, &bit, + 7, &bays, 0); + + c3_w n_w, num_w; + c3_d bit_d; + + if (c3n == u3r_safe_word(n, &n_w)) { + return u3_none; + } + if (c3n == u3r_safe_word(num, &num_w)) { + return u3_none; + } + if (c3n == u3r_safe_chub(bit, &bit_d)) { + return u3_none; + } + + if(n_w == 0) { + return u3k(bits); + } + + c3_w dop_w = n_w; + + if (dop_w > num_w) { + dop_w = num_w; + } + + bit_d >>= dop_w; + num_w -= dop_w; + + return u3nt(u3i_word(num_w), u3i_chub(bit_d), u3k(bays)); +} +u3_noun +u3we_bytestream_drop_bits(u3_noun cor) +{ + u3_atom n; + u3_noun bits; + + u3x_mean(cor, u3x_sam_2, &n, + u3x_sam_3, &bits, 0); + + return _qe_bytestream_drop_bits(n, bits); +} + +u3_noun +_qe_bytestream_peek_bits(u3_atom n, u3_noun bits) +{ + + u3_atom num, bit; + u3_noun bays; + + u3x_mean(bits, 2, &num, + 6, &bit, + 7, &bays, 0); + + c3_w n_w, num_w; + c3_d bit_d; + + if (c3n == u3r_safe_word(n, &n_w)) { + return u3_none; + } + if (c3n == u3r_safe_word(num, &num_w)) { + return u3_none; + } + if (c3n == u3r_safe_chub(bit, &bit_d)) { + return u3_none; + } + + if (n_w == 0) { + return u3i_word(0); + } + + if (n_w > num_w) { + u3m_bail(c3__exit); + } + + if (n_w > BITS_D) { + return u3_none; + } + + if (n_w == BITS_D) { + return u3i_chub(bit_d); + } + else { + c3_d mak_d = ((c3_d)1 << n_w) - 1; + + return u3i_chub(bit_d & mak_d); + } +} +u3_noun +u3we_bytestream_peek_bits(u3_noun cor) +{ + u3_atom n; + u3_noun bits; + + u3x_mean(cor, u3x_sam_2, &n, + u3x_sam_3, &bits, 0); + + return _qe_bytestream_peek_bits(n, bits); +} + +u3_noun +_qe_bytestream_read_bits(u3_atom n, u3_noun bits) +{ + + u3_atom num, bit; + u3_noun bays; + + u3x_mean(bits, 2, &num, + 6, &bit, + 7, &bays, 0); + + c3_w n_w, num_w; + c3_d bit_d; + + if (c3n == u3r_safe_word(n, &n_w)) { + return u3_none; + } + if (c3n == u3r_safe_word(num, &num_w)) { + return u3_none; + } + if (c3n == u3r_safe_chub(bit, &bit_d)) { + return u3_none; + } + + if (n_w > num_w) { + u3m_bail(c3__exit); + } + + if (n_w > BITS_D) { + return u3_none; + } + + c3_d bet_d = 0; + + if (n_w == BITS_D) { + bet_d = bit_d; + } + else { + c3_d mak_d = ((c3_d)1 << n_w) - 1; + bet_d = bit_d & mak_d; + } + + bit_d >>= n_w; + num_w -= n_w; + + u3_noun new_bits = u3nt(u3i_word(num_w), u3i_chub(bit_d), u3k(bays)); + + return u3nc(u3i_chub(bet_d), new_bits); +} + +u3_noun +u3we_bytestream_read_bits(u3_noun cor) +{ + u3_atom n; + u3_noun bits; + + u3x_mean(cor, u3x_sam_2, &n, + u3x_sam_3, &bits, 0); + + return _qe_bytestream_read_bits(n, bits); +} + +u3_noun +_qe_bytestream_byte_bits(u3_noun bits) +{ + + u3_atom num, bit; + u3_noun bays; + + u3x_mean(bits, 2, &num, + 6, &bit, + 7, &bays, 0); + + c3_w num_w; + c3_d bit_d; + + if (c3n == u3r_safe_word(num, &num_w)) { + return u3_none; + } + if (c3n == u3r_safe_chub(bit, &bit_d)) { + return u3_none; + } + + c3_y rem_y = num_w & 0x7; + + if (rem_y == 0) { + return u3k(bits); + } + + u3_noun new_bits = u3nt(u3i_word(num_w - rem_y), + u3i_chub(bit_d >> rem_y), + u3k(bays)); + + return new_bits; +} + +u3_noun +u3we_bytestream_byte_bits(u3_noun cor) +{ + u3_noun bits; + + u3x_mean(cor, u3x_sam, &bits, 0); + + return _qe_bytestream_byte_bits(bits); +} -- cgit v1.2.3