Merge pull request #3579 from urbit/jb/ur-handles-ames

vere: adds/uses apis for repeated deserialization
This commit is contained in:
Joe Bryan 2020-09-29 11:16:48 -07:00 committed by GitHub
commit c551b2a9ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 721 additions and 456 deletions

View File

@ -117,25 +117,22 @@ _jam_bench(void)
gettimeofday(&b4, 0); gettimeofday(&b4, 0);
{ {
ur_dict64_t dic_u = {0}; ur_jam_t *jam_u = ur_jam_init(rot_u);
c3_d len_d; c3_d len_d;
c3_y* byt_y; c3_y* byt_y;
ur_dict64_grow((ur_root_t*)0, &dic_u, ur_fib10, ur_fib11);
for ( i_w = 0; i_w < max_w; i_w++ ) { for ( i_w = 0; i_w < max_w; i_w++ ) {
ur_jam_unsafe(rot_u, ref, &dic_u, &len_d, &byt_y); ur_jam_with(jam_u, ref, &len_d, &byt_y);
c3_free(byt_y); c3_free(byt_y);
ur_dict64_wipe(&dic_u);
} }
ur_dict_free((ur_dict_t*)&dic_u); ur_jam_done(jam_u);
} }
gettimeofday(&f2, 0); gettimeofday(&f2, 0);
timersub(&f2, &b4, &d0); timersub(&f2, &b4, &d0);
mil_w = (d0.tv_sec * 1000) + (d0.tv_usec / 1000); mil_w = (d0.tv_sec * 1000) + (d0.tv_usec / 1000);
fprintf(stderr, " jam cons unsafe: %u ms\r\n", mil_w); fprintf(stderr, " jam cons with: %u ms\r\n", mil_w);
} }
ur_root_free(rot_u); ur_root_free(rot_u);
@ -184,7 +181,6 @@ _cue_bench(void)
gettimeofday(&b4, 0); gettimeofday(&b4, 0);
{ {
u3_noun out;
c3_w len_w = u3r_met(3, vat); c3_w len_w = u3r_met(3, vat);
// XX assumes little-endian // XX assumes little-endian
// //
@ -193,8 +189,7 @@ _cue_bench(void)
: (c3_y*)((u3a_atom*)u3a_to_ptr(vat))->buf_w; : (c3_y*)((u3a_atom*)u3a_to_ptr(vat))->buf_w;
for ( i_w = 0; i_w < max_w; i_w++ ) { for ( i_w = 0; i_w < max_w; i_w++ ) {
u3s_cue_xeno(len_w, byt_y, &out); u3z(u3s_cue_xeno(len_w, byt_y));
u3z(out);
} }
} }
@ -208,8 +203,7 @@ _cue_bench(void)
gettimeofday(&b4, 0); gettimeofday(&b4, 0);
{ {
ur_dict32_t dic_u = {0}; u3_cue_xeno* sil_u = u3s_cue_xeno_init();
u3_noun out;
c3_w len_w = u3r_met(3, vat); c3_w len_w = u3r_met(3, vat);
// XX assumes little-endian // XX assumes little-endian
@ -218,21 +212,17 @@ _cue_bench(void)
? (c3_y*)&vat ? (c3_y*)&vat
: (c3_y*)((u3a_atom*)u3a_to_ptr(vat))->buf_w; : (c3_y*)((u3a_atom*)u3a_to_ptr(vat))->buf_w;
ur_dict32_grow((ur_root_t*)0, &dic_u, ur_fib10, ur_fib11);
for ( i_w = 0; i_w < max_w; i_w++ ) { for ( i_w = 0; i_w < max_w; i_w++ ) {
u3s_cue_xeno_unsafe(&dic_u, len_w, byt_y, &out); u3z(u3s_cue_xeno_with(sil_u, len_w, byt_y));
u3z(out);
ur_dict32_wipe(&dic_u);
} }
ur_dict_free((ur_dict_t*)&dic_u); u3s_cue_xeno_done(sil_u);
} }
gettimeofday(&f2, 0); gettimeofday(&f2, 0);
timersub(&f2, &b4, &d0); timersub(&f2, &b4, &d0);
mil_w = (d0.tv_sec * 1000) + (d0.tv_usec / 1000); mil_w = (d0.tv_sec * 1000) + (d0.tv_usec / 1000);
fprintf(stderr, " cue xeno unsafe: %u ms\r\n", mil_w); fprintf(stderr, " cue xeno with: %u ms\r\n", mil_w);
} }
{ {
@ -261,8 +251,7 @@ _cue_bench(void)
gettimeofday(&b4, 0); gettimeofday(&b4, 0);
{ {
ur_dict_t dic_u = {0}; ur_cue_test_t *t = ur_cue_test_init();
u3_noun out;
c3_w len_w = u3r_met(3, vat); c3_w len_w = u3r_met(3, vat);
// XX assumes little-endian // XX assumes little-endian
@ -271,20 +260,17 @@ _cue_bench(void)
? (c3_y*)&vat ? (c3_y*)&vat
: (c3_y*)((u3a_atom*)u3a_to_ptr(vat))->buf_w; : (c3_y*)((u3a_atom*)u3a_to_ptr(vat))->buf_w;
ur_dict_grow((ur_root_t*)0, &dic_u, ur_fib10, ur_fib11);
for ( i_w = 0; i_w < max_w; i_w++ ) { for ( i_w = 0; i_w < max_w; i_w++ ) {
ur_cue_test_unsafe(&dic_u, len_w, byt_y); ur_cue_test_with(t, len_w, byt_y);
ur_dict_wipe(&dic_u);
} }
ur_dict_free(&dic_u); ur_cue_test_done(t);
} }
gettimeofday(&f2, 0); gettimeofday(&f2, 0);
timersub(&f2, &b4, &d0); timersub(&f2, &b4, &d0);
mil_w = (d0.tv_sec * 1000) + (d0.tv_usec / 1000); mil_w = (d0.tv_sec * 1000) + (d0.tv_usec / 1000);
fprintf(stderr, " cue test unsafe: %u ms\r\n", mil_w); fprintf(stderr, " cue test with: %u ms\r\n", mil_w);
} }
{ {

View File

@ -1,11 +1,11 @@
/* i/n/serial.h /* i/n/serial.h
** **
*/ */
/* forward declarations /* opaque handles
*/ */
/* ur_dict32_s: off-loom 32-bit dictionary. /* u3_cue_xeno: handle for cue-ing with an off-loom dictionary.
*/ */
struct ur_dict32_s; typedef struct _u3_cue_xeno u3_cue_xeno;
/* Noun serialization. All noun arguments RETAINED. /* Noun serialization. All noun arguments RETAINED.
*/ */
@ -28,18 +28,33 @@
u3_noun u3_noun
u3s_cue(u3_atom a); u3s_cue(u3_atom a);
/* u3s_cue_xeno_unsafe(): cue onto the loom, all bookkeeping off-loom. /* u3s_cue_xeno_init_with(): initialize a cue_xeno handle as specified.
*/ */
c3_o u3_cue_xeno*
u3s_cue_xeno_unsafe(struct ur_dict32_s* dic_u, u3s_cue_xeno_init_with(c3_d pre_d, c3_d siz_d);
c3_d len_d,
const c3_y* byt_y,
u3_noun* out);
/* u3s_cue_xeno(): cue onto the loom, bookkeeping off the loom. /* u3s_cue_xeno_init(): initialize a cue_xeno handle.
*/ */
c3_o u3_cue_xeno*
u3s_cue_xeno(c3_d len_d, const c3_y* byt_y, u3_noun* out); u3s_cue_xeno_init(void);
/* u3s_cue_xeno_init(): cue on-loom, with off-loom dictionary in handle.
*/
u3_weak
u3s_cue_xeno_with(u3_cue_xeno* sil_u,
c3_d len_d,
const c3_y* byt_y);
/* u3s_cue_xeno_init(): dispose cue_xeno handle.
*/
void
u3s_cue_xeno_done(u3_cue_xeno* sil_u);
/* u3s_cue_xeno(): cue on-loom, with off-loom dictionary.
*/
u3_weak
u3s_cue_xeno(c3_d len_d,
const c3_y* byt_y);
/* u3s_cue_bytes(): cue bytes onto the loom. /* u3s_cue_bytes(): cue bytes onto the loom.
*/ */

View File

@ -130,6 +130,12 @@ ur_bsr_log(ur_bsr_t *bsr, uint8_t *out);
ur_cue_res_e ur_cue_res_e
ur_bsr_rub_len(ur_bsr_t *bsr, uint64_t *out); ur_bsr_rub_len(ur_bsr_t *bsr, uint64_t *out);
/*
** initialize bitstream-writer with prev/size for fibonacci growth.
*/
void
ur_bsw_init(ur_bsw_t *bsw, uint64_t prev, uint64_t size);
/* /*
** reallocate bitstream write buffer with max(fibonacci, step) growth. ** reallocate bitstream write buffer with max(fibonacci, step) growth.
*/ */
@ -142,6 +148,12 @@ ur_bsw_grow(ur_bsw_t *bsw, uint64_t step);
ur_bool_t ur_bool_t
ur_bsw_sane(ur_bsw_t *bsw); ur_bsw_sane(ur_bsw_t *bsw);
/*
** return bit-length, produce byte-buffer.
*/
uint64_t
ur_bsw_done(ur_bsw_t *bsw, uint64_t *len, uint8_t **byt);
/* /*
** write a bit ** write a bit
*/ */

View File

@ -111,6 +111,11 @@ typedef struct ur_nvec_s {
ur_nref* refs; ur_nref* refs;
} ur_nvec_t; } ur_nvec_t;
/*
** opaque handle for repeated traversal.
*/
typedef struct ur_walk_fore_s ur_walk_fore_t;
/* /*
** type-specific dictionary operations. ** type-specific dictionary operations.
** **
@ -231,4 +236,22 @@ ur_walk_fore(ur_root_t *r,
void (*atom)(ur_root_t*, ur_nref, void*), void (*atom)(ur_root_t*, ur_nref, void*),
ur_bool_t (*cell)(ur_root_t*, ur_nref, void*)); ur_bool_t (*cell)(ur_root_t*, ur_nref, void*));
ur_walk_fore_t*
ur_walk_fore_init_with(ur_root_t *r,
uint32_t s_prev,
uint32_t s_size);
ur_walk_fore_t*
ur_walk_fore_init(ur_root_t *r);
void
ur_walk_fore_with(ur_walk_fore_t *w,
ur_nref ref,
void *v,
void (*atom)(ur_root_t*, ur_nref, void*),
ur_bool_t (*cell)(ur_root_t*, ur_nref, void*));
void
ur_walk_fore_done(ur_walk_fore_t *w);
#endif #endif

View File

@ -4,16 +4,20 @@
#include <inttypes.h> #include <inttypes.h>
#include <ur/defs.h> #include <ur/defs.h>
#include <ur/bitstream.h> #include <ur/bitstream.h>
#include <ur/hashcons.h>
/* /*
** bit-wise serialization of a noun into a byte-buffer. ** bit-wise serialization of a noun into a byte-buffer.
** supports up to 64-bits of bit-addressed output (nearly 2 EiB). ** supports up to 64-bits of bit-addressed output (nearly 2 EiB).
** (as this is an impractical volume data, cursor overflow is not checked.) ** (as this is an impractical volume data, cursor overflow is not checked.)
** **
** unsafe variant is unsafe wrt its [dict] parameter, which must be empty, ** jam_with* api factors out stack/dict (re)allocation,
** but can be passed in order to skip reallocation inside hot loops. ** for better performance inside hot loops.
** **
*/ */
typedef struct ur_jam_s ur_jam_t;
uint64_t uint64_t
ur_jam_unsafe(ur_root_t *r, ur_jam_unsafe(ur_root_t *r,
ur_nref ref, ur_nref ref,
@ -22,35 +26,86 @@ ur_jam_unsafe(ur_root_t *r,
uint8_t **byt); uint8_t **byt);
uint64_t uint64_t
ur_jam(ur_root_t *r, ur_nref ref, uint64_t *len, uint8_t **byt); ur_jam(ur_root_t *r,
ur_nref ref,
uint64_t *len,
uint8_t **byt);
ur_jam_t*
ur_jam_init_with(ur_root_t *r,
uint64_t d_prev,
uint64_t d_size,
uint32_t s_prev,
uint32_t s_size);
ur_jam_t*
ur_jam_init(ur_root_t *r);
uint64_t
ur_jam_with(ur_jam_t *j,
ur_nref ref,
uint64_t *len,
uint8_t **byt);
void
ur_jam_done(ur_jam_t *j);
/* /*
** bitwise deserialization of a byte-buffer into a noun. ** bitwise deserialization of a byte-buffer into a noun.
** supports up to 62-bits of bit-addressed input (511 PiB). ** supports up to 62-bits of bit-addressed input (511 PiB).
** returns [ur_cue_good] on success. ** returns [ur_cue_good] on success.
** **
** unsafe variant is unsafe wrt its [dict] parameter, which must be empty, ** cue_with factors out stack/dict (re)allocation,
** (present in order to skip reallocation inside hot loops). ** for better performance of hot loops.
** **
** test variant does not allocate nouns, but merely parses the input. ** cue_test does not allocate nouns, but merely parses the input;
** cue_test_with* api factors out stack/dict (re)allocation,
** for better performance of repeated tests.
** **
*/ */
ur_cue_res_e
ur_cue_unsafe(ur_root_t *r, typedef struct ur_cue_test_s ur_cue_test_t;
ur_dict64_t *dict, typedef struct ur_cue_s ur_cue_t;
uint64_t len,
const uint8_t *byt,
ur_nref *out);
ur_cue_res_e ur_cue_res_e
ur_cue(ur_root_t *r, uint64_t len, const uint8_t *byt, ur_nref *out); ur_cue(ur_root_t *r, uint64_t len, const uint8_t *byt, ur_nref *out);
ur_cue_t*
ur_cue_init_with(ur_root_t *r,
uint64_t d_prev,
uint64_t d_size,
uint32_t s_prev,
uint32_t s_size);
ur_cue_t*
ur_cue_init(ur_root_t *r);
ur_cue_res_e ur_cue_res_e
ur_cue_test_unsafe(ur_dict_t *dict, ur_cue_with(ur_cue_t *c,
uint64_t len, uint64_t len,
const uint8_t *byt); const uint8_t *byt,
ur_nref *out);
void
ur_cue_done(ur_cue_t *c);
ur_bool_t ur_bool_t
ur_cue_test(uint64_t len, const uint8_t *byt); ur_cue_test(uint64_t len, const uint8_t *byt);
ur_cue_test_t*
ur_cue_test_init_with(uint64_t d_prev,
uint64_t d_size,
uint32_t s_prev,
uint32_t s_size);
ur_cue_test_t*
ur_cue_test_init(void);
ur_bool_t
ur_cue_test_with(ur_cue_test_t *t,
uint64_t len,
const uint8_t *byt);
void
ur_cue_test_done(ur_cue_test_t *t);
#endif #endif

View File

@ -470,7 +470,7 @@
uv_process_t cub_u; // process handle uv_process_t cub_u; // process handle
uv_process_options_t ops_u; // process configuration uv_process_options_t ops_u; // process configuration
uv_stdio_container_t cod_u[3]; // process options uv_stdio_container_t cod_u[3]; // process options
void* dic_u; // cue dictionary u3_cue_xeno* sil_u; // cue handle
time_t wen_t; // process creation time time_t wen_t; // process creation time
u3_mojo inn_u; // client's stdin u3_mojo inn_u; // client's stdin
u3_moat out_u; // client's stdout u3_moat out_u; // client's stdout

View File

@ -290,13 +290,10 @@ c3_d
u3s_jam_xeno(u3_noun a, c3_d* len_d, c3_y** byt_y) u3s_jam_xeno(u3_noun a, c3_d* len_d, c3_y** byt_y)
{ {
_jam_xeno_t jam_u = {0}; _jam_xeno_t jam_u = {0};
ur_bsw_init(&jam_u.rit_u, ur_fib11, ur_fib12);
jam_u.har_p = u3h_new(); jam_u.har_p = u3h_new();
jam_u.rit_u.prev = ur_fib11;
jam_u.rit_u.size = ur_fib12;
jam_u.rit_u.bytes = c3_calloc(jam_u.rit_u.size);
// as this is a hot path, we unsafely elide overflow checks // as this is a hot path, we unsafely elide overflow checks
// //
// a page-fault overflow detection system is urgently needed ... // a page-fault overflow detection system is urgently needed ...
@ -304,12 +301,9 @@ u3s_jam_xeno(u3_noun a, c3_d* len_d, c3_y** byt_y)
u3a_walk_fore_unsafe(a, &jam_u, _cs_jam_xeno_atom, u3a_walk_fore_unsafe(a, &jam_u, _cs_jam_xeno_atom,
_cs_jam_xeno_cell); _cs_jam_xeno_cell);
*len_d = jam_u.rit_u.fill + !!jam_u.rit_u.off;
*byt_y = jam_u.rit_u.bytes;
u3h_free(jam_u.har_p); u3h_free(jam_u.har_p);
return jam_u.rit_u.bits; return ur_bsw_done(&jam_u.rit_u, len_d, byt_y);
} }
#define CUE_ROOT 0 #define CUE_ROOT 0
@ -549,17 +543,10 @@ typedef struct _cue_frame_s {
c3_d bit_d; c3_d bit_d;
} _cue_frame_t; } _cue_frame_t;
typedef struct _cue_stack_s { /* _cs_cue_xeno_next(): read next value from bitstream, dictionary off-loom.
c3_w pre_w;
c3_w siz_w;
c3_w fil_w;
_cue_frame_t* fam_u;
} _cue_stack_t;
/* _cs_cue_xeno_next(): read next value from bitstream, bookkeeping off-loom.
*/ */
static inline ur_cue_res_e static inline ur_cue_res_e
_cs_cue_xeno_next(_cue_stack_t* tac_u, _cs_cue_xeno_next(u3a_pile* pil_u,
ur_bsr_t* red_u, ur_bsr_t* red_u,
ur_dict32_t* dic_u, ur_dict32_t* dic_u,
u3_noun* out) u3_noun* out)
@ -579,22 +566,11 @@ _cs_cue_xeno_next(_cue_stack_t* tac_u,
default: c3_assert(0); default: c3_assert(0);
case ur_jam_cell: { case ur_jam_cell: {
// reallocate the stack if full _cue_frame_t* fam_u = u3a_push(pil_u);
// u3a_pile_sane(pil_u);
if ( tac_u->fil_w == tac_u->siz_w ) {
c3_w nex_w = tac_u->pre_w + tac_u->siz_w;
tac_u->fam_u = c3_realloc(tac_u->fam_u, nex_w * sizeof(*tac_u->fam_u));
tac_u->pre_w = tac_u->siz_w;
tac_u->siz_w = nex_w;
}
// save a head-frame and read the head from the stream
//
{
_cue_frame_t* fam_u = &(tac_u->fam_u[tac_u->fil_w++]);
fam_u->ref = u3_none; fam_u->ref = u3_none;
fam_u->bit_d = bit_d; fam_u->bit_d = bit_d;
}
continue; continue;
} }
@ -636,7 +612,7 @@ _cs_cue_xeno_next(_cue_stack_t* tac_u,
c3_d byt_d = (len_d >> 3) + !!ur_mask_3(len_d); c3_d byt_d = (len_d >> 3) + !!ur_mask_3(len_d);
if ( 0xffffffffULL < byt_d) { if ( 0xffffffffULL < byt_d) {
return u3m_bail(c3__meme); return ur_cue_meme;
} }
// XX assumes little-endian // XX assumes little-endian
@ -656,21 +632,28 @@ _cs_cue_xeno_next(_cue_stack_t* tac_u,
} }
} }
/* u3s_cue_xeno_unsafe(): cue onto the loom, all bookkeeping off-loom. struct _u3_cue_xeno {
** ur_dict32_t dic_u;
** NB: unsafe wrt to [dic_u], which must be empty. };
/* _cs_cue_xeno(): cue on-loom, with off-loom dictionary in handle.
*/ */
c3_o static u3_weak
u3s_cue_xeno_unsafe(ur_dict32_t* dic_u, _cs_cue_xeno(u3_cue_xeno* sil_u,
c3_d len_d, c3_d len_d,
const c3_y* byt_y, const c3_y* byt_y)
u3_noun* out)
{ {
ur_bsr_t red_u = {0}; ur_bsr_t red_u = {0};
_cue_stack_t tac_u = {0}; ur_dict32_t* dic_u = &sil_u->dic_u;
u3a_pile pil_u;
_cue_frame_t* fam_u;
ur_cue_res_e res_e; ur_cue_res_e res_e;
u3_noun ref; u3_noun ref;
// initialize stack control
//
u3a_pile_prep(&pil_u, sizeof(*fam_u));
// init bitstream-reader // init bitstream-reader
// //
if ( ur_cue_good != (res_e = ur_bsr_init(&red_u, len_d, byt_y)) ) { if ( ur_cue_good != (res_e = ur_bsr_init(&red_u, len_d, byt_y)) ) {
@ -682,28 +665,24 @@ u3s_cue_xeno_unsafe(ur_dict32_t* dic_u,
return c3n; return c3n;
} }
// setup stack
//
tac_u.pre_w = ur_fib10;
tac_u.siz_w = ur_fib11;
tac_u.fam_u = c3_malloc(tac_u.siz_w * sizeof(*tac_u.fam_u));
// advance into stream // advance into stream
// //
res_e = _cs_cue_xeno_next(&tac_u, &red_u, dic_u, &ref); res_e = _cs_cue_xeno_next(&pil_u, &red_u, dic_u, &ref);
// process result // process cell results
// //
while ( tac_u.fil_w && (ur_cue_good == res_e) ) { if ( (c3n == u3a_pile_done(&pil_u))
// peek at the top of the stack && (ur_cue_good == res_e) )
// {
_cue_frame_t* fam_u = &(tac_u.fam_u[tac_u.fil_w - 1]); fam_u = u3a_peek(&pil_u);
do {
// f is a head-frame; stash result and read the tail from the stream // f is a head-frame; stash result and read the tail from the stream
// //
if ( u3_none == fam_u->ref ) { if ( u3_none == fam_u->ref ) {
fam_u->ref = ref; fam_u->ref = ref;
res_e = _cs_cue_xeno_next(&tac_u, &red_u, dic_u, &ref); res_e = _cs_cue_xeno_next(&pil_u, &red_u, dic_u, &ref);
fam_u = u3a_peek(&pil_u);
} }
// f is a tail-frame; pop the stack and continue // f is a tail-frame; pop the stack and continue
// //
@ -712,50 +691,94 @@ u3s_cue_xeno_unsafe(ur_dict32_t* dic_u,
ref = u3nc(fam_u->ref, ref); ref = u3nc(fam_u->ref, ref);
ur_dict32_put(rot_u, dic_u, fam_u->bit_d, ref); ur_dict32_put(rot_u, dic_u, fam_u->bit_d, ref);
tac_u.fil_w--; fam_u = u3a_pop(&pil_u);
} }
} }
while ( (c3n == u3a_pile_done(&pil_u))
&& (ur_cue_good == res_e) );
}
if ( ur_cue_good == res_e ) { if ( ur_cue_good == res_e ) {
*out = ref; return ref;
c3_free(tac_u.fam_u);
return c3y;
} }
else { // on failure, unwind the stack and dispose of intermediate nouns
// unwind the stack, disposing intermediate nouns
// //
while ( tac_u.fil_w ) { else if ( c3n == u3a_pile_done(&pil_u) ) {
_cue_frame_t* fam_u = &(tac_u.fam_u[--tac_u.fil_w]); do {
if ( u3_none != fam_u->ref ) { if ( u3_none != fam_u->ref ) {
u3z(fam_u->ref); u3z(fam_u->ref);
} }
fam_u = u3a_pop(&pil_u);
}
while ( c3n == u3a_pile_done(&pil_u) );
} }
c3_free(tac_u.fam_u); return u3_none;
return c3n;
}
} }
/* u3s_cue_xeno(): cue onto the loom, bookkeeping off the loom. /* u3s_cue_xeno_init_with(): initialize a cue_xeno handle as specified.
*/ */
c3_o u3_cue_xeno*
u3s_cue_xeno(c3_d len_d, const c3_y* byt_y, u3_noun* out) u3s_cue_xeno_init_with(c3_d pre_d, c3_d siz_d)
{ {
ur_dict32_t dic_u = {0}; u3_cue_xeno* sil_u;
c3_o ret_o;
c3_assert( &(u3H->rod_u) == u3R ); c3_assert( &(u3H->rod_u) == u3R );
// XX tune the initial dictionary size for less reallocation sil_u = c3_calloc(sizeof(*sil_u));
// ur_dict32_grow((ur_root_t*)0, &sil_u->dic_u, pre_d, siz_d);
ur_dict32_grow((ur_root_t*)0, &dic_u, ur_fib10, ur_fib11);
ret_o = u3s_cue_xeno_unsafe(&dic_u, len_d, byt_y, out); return sil_u;
}
ur_dict_free((ur_dict_t*)&dic_u); /* u3s_cue_xeno_init(): initialize a cue_xeno handle.
*/
u3_cue_xeno*
u3s_cue_xeno_init(void)
{
return u3s_cue_xeno_init_with(ur_fib10, ur_fib11);
}
return ret_o; /* u3s_cue_xeno_init(): cue on-loom, with off-loom dictionary in handle.
*/
u3_weak
u3s_cue_xeno_with(u3_cue_xeno* sil_u,
c3_d len_d,
const c3_y* byt_y)
{
u3_weak som;
c3_assert( &(u3H->rod_u) == u3R );
som = _cs_cue_xeno(sil_u, len_d, byt_y);
ur_dict32_wipe(&sil_u->dic_u);
return som;
}
/* u3s_cue_xeno_init(): dispose cue_xeno handle.
*/
void
u3s_cue_xeno_done(u3_cue_xeno* sil_u)
{
ur_dict_free((ur_dict_t*)&sil_u->dic_u);
c3_free(sil_u);
}
/* u3s_cue_xeno(): cue on-loom, with off-loom dictionary.
*/
u3_weak
u3s_cue_xeno(c3_d len_d,
const c3_y* byt_y)
{
u3_cue_xeno* sil_u;
u3_weak som;
c3_assert( &(u3H->rod_u) == u3R );
sil_u = u3s_cue_xeno_init();
som = _cs_cue_xeno(sil_u, len_d, byt_y);
u3s_cue_xeno_done(sil_u);
return som;
} }
/* _cs_cue_need(): bail on ur_cue_* read failures. /* _cs_cue_need(): bail on ur_cue_* read failures.
@ -794,11 +817,10 @@ _cs_cue_put(u3p(u3h_root) har_p, c3_d key_d, u3_noun val)
return val; return val;
} }
/* _cs_cue_full_next(): read next value from bitstream. /* _cs_cue_bytes_next(): read next value from bitstream.
*/ */
static inline u3_noun static inline u3_noun
_cs_cue_full_next(c3_ys mov, _cs_cue_bytes_next(u3a_pile* pil_u,
c3_ys off,
u3p(u3h_root) har_p, u3p(u3h_root) har_p,
ur_bsr_t* red_u) ur_bsr_t* red_u)
{ {
@ -812,31 +834,11 @@ _cs_cue_full_next(c3_ys mov,
default: c3_assert(0); default: c3_assert(0);
case ur_jam_cell: { case ur_jam_cell: {
// wind the stack _cue_frame_t* fam_u = u3a_push(pil_u);
// u3a_pile_sane(pil_u);
u3R->cap_p += mov;
// ensure we haven't overflowed (ie, run into the heap)
// (off==0 means we're on a north road)
//
if ( 0 == off ) {
if( !(u3R->cap_p > u3R->hat_p) ) {
u3m_bail(c3__meme);
}
}
else {
if( !(u3R->cap_p < u3R->hat_p) ) {
u3m_bail(c3__meme);
}
}
// save a head-frame and read the head from the stream
//
{
_cue_frame_t* fam_u = u3to(_cue_frame_t, u3R->cap_p + off);
fam_u->ref = u3_none; fam_u->ref = u3_none;
fam_u->bit_d = bit_d; fam_u->bit_d = bit_d;
}
continue; continue;
} }
@ -896,22 +898,18 @@ u3_noun
u3s_cue_bytes(c3_d len_d, const c3_y* byt_y) u3s_cue_bytes(c3_d len_d, const c3_y* byt_y)
{ {
ur_bsr_t red_u = {0}; ur_bsr_t red_u = {0};
u3a_pile pil_u;
_cue_frame_t* fam_u;
u3p(u3h_root) har_p;
u3_noun ref; u3_noun ref;
// initialize stack control
//
u3a_pile_prep(&pil_u, sizeof(*fam_u));
// initialize a hash table for dereferencing backrefs // initialize a hash table for dereferencing backrefs
// //
u3p(u3h_root) har_p = u3h_new(); har_p = u3h_new();
const u3_post top_p = u3R->cap_p;
// initialize signed stack offsets (relative to north/south road)
//
c3_ys mov, off;
{
c3_o nor_o = u3a_is_north(u3R);
c3_y wis_y = c3_wiseof(_cue_frame_t);
mov = ( c3y == nor_o ? -wis_y : wis_y );
off = ( c3y == nor_o ? 0 : -wis_y );
}
// init bitstream-reader // init bitstream-reader
// //
@ -925,29 +923,31 @@ u3s_cue_bytes(c3_d len_d, const c3_y* byt_y)
// advance into stream // advance into stream
// //
ref = _cs_cue_full_next(mov, off, har_p, &red_u); ref = _cs_cue_bytes_next(&pil_u, har_p, &red_u);
// process result // process cell results
// //
while ( top_p != u3R->cap_p ) { if ( c3n == u3a_pile_done(&pil_u) ) {
// peek at the top of the stack fam_u = u3a_peek(&pil_u);
//
_cue_frame_t* fam_u = u3to(_cue_frame_t, u3R->cap_p + off);
do {
// f is a head-frame; stash result and read the tail from the stream // f is a head-frame; stash result and read the tail from the stream
// //
if ( u3_none == fam_u->ref ) { if ( u3_none == fam_u->ref ) {
fam_u->ref = ref; fam_u->ref = ref;
ref = _cs_cue_full_next(mov, off, har_p, &red_u); ref = _cs_cue_bytes_next(&pil_u, har_p, &red_u);
fam_u = u3a_peek(&pil_u);
} }
// f is a tail-frame; pop the stack and continue // f is a tail-frame; pop the stack and continue
// //
else { else {
ref = u3nc(fam_u->ref, ref); ref = u3nc(fam_u->ref, ref);
_cs_cue_put(har_p, fam_u->bit_d, ref); _cs_cue_put(har_p, fam_u->bit_d, ref);
u3R->cap_p -= mov; fam_u = u3a_pop(&pil_u);
} }
} }
while ( c3n == u3a_pile_done(&pil_u) );
}
u3h_free(har_p); u3h_free(har_p);

View File

@ -9,26 +9,6 @@
#include "all.h" #include "all.h"
#include "ur/ur.h" #include "ur/ur.h"
/* _cu_met_3(): atom bytewidth a la u3r_met(3, ...)
*/
static inline c3_w
_cu_met_3(u3a_atom* vat_u)
{
c3_w len_w = vat_u->len_w;
c3_w* buf_w = vat_u->buf_w;
if ( !len_w ) {
return 0;
}
else {
c3_w gal_w = len_w - 1;
c3_w daz_w = buf_w[gal_w];
return (gal_w << 2)
+ ((daz_w >> 24) ? 4 : (daz_w >> 16) ? 3 : (daz_w >> 8) ? 2 : 1);
}
}
/* _cu_atom_to_ref(): allocate indirect atom off-loom. /* _cu_atom_to_ref(): allocate indirect atom off-loom.
*/ */
static inline ur_nref static inline ur_nref
@ -860,23 +840,20 @@ u3u_uncram(c3_c* dir_c, c3_d eve_d)
// XX errors are fatal, barring a full "u3m_reboot"-type operation. // XX errors are fatal, barring a full "u3m_reboot"-type operation.
// //
{ {
ur_dict32_t dic_u = {0};
u3_noun roc, cod, ref;
// XX tune the initial dictionary size for less reallocation // XX tune the initial dictionary size for less reallocation
// //
ur_dict32_grow((ur_root_t*)0, &dic_u, ur_fib33, ur_fib34); u3_cue_xeno* sil_u = u3s_cue_xeno_init_with(ur_fib33, ur_fib34);
u3_weak ref = u3s_cue_xeno_with(sil_u, len_d, byt_y);
u3_noun roc, cod;
if ( c3n == u3s_cue_xeno_unsafe(&dic_u, len_d, byt_y, &ref) ) { u3s_cue_xeno_done(sil_u);
if ( u3_none == ref ) {
fprintf(stderr, "uncram: failed to cue rock\r\n"); fprintf(stderr, "uncram: failed to cue rock\r\n");
ur_dict_free((ur_dict_t*)&dic_u);
c3_free(nam_c); c3_free(nam_c);
return c3n; return c3n;
} }
else if ( c3n == u3r_pq(ref, c3__fast, &roc, &cod) ) {
ur_dict_free((ur_dict_t*)&dic_u);
if ( c3n == u3r_pq(ref, c3__fast, &roc, &cod) ) {
fprintf(stderr, "uncram: failed: invalid rock format\r\n"); fprintf(stderr, "uncram: failed: invalid rock format\r\n");
u3z(ref); u3z(ref);
c3_free(nam_c); c3_free(nam_c);

View File

@ -367,12 +367,12 @@ _test_cue_spec(const c3_c* cap_c,
c3_i ret_i = 1; c3_i ret_i = 1;
{ {
ur_dict32_t dic_u = {0}; u3_noun pro = u3m_soft(0, u3s_cue_atom, u3i_bytes(len_w, byt_y));
u3_noun out; u3_noun tag, out;
ur_dict32_grow((ur_root_t*)0, &dic_u, ur_fib10, ur_fib11); u3x_cell(pro, &tag, &out);
if ( c3n == u3s_cue_xeno_unsafe(&dic_u, len_w, byt_y, &out) ) { if ( u3_blip != tag ) {
fprintf(stderr, "\033[31mcue %s fail 1\033[0m\r\n", cap_c); fprintf(stderr, "\033[31mcue %s fail 1\033[0m\r\n", cap_c);
ret_i = 0; ret_i = 0;
} }
@ -383,17 +383,13 @@ _test_cue_spec(const c3_c* cap_c,
ret_i = 0; ret_i = 0;
} }
u3z(out); u3z(pro);
ur_dict_free((ur_dict_t*)&dic_u);
} }
{ {
u3_noun pro = u3m_soft(0, u3s_cue_atom, u3i_bytes(len_w, byt_y)); u3_noun out;
u3_noun tag, out;
u3x_cell(pro, &tag, &out); if ( u3_none == (out = u3s_cue_xeno(len_w, byt_y)) ) {
if ( u3_blip != tag ) {
fprintf(stderr, "\033[31mcue %s fail 3\033[0m\r\n", cap_c); fprintf(stderr, "\033[31mcue %s fail 3\033[0m\r\n", cap_c);
ret_i = 0; ret_i = 0;
} }
@ -404,7 +400,7 @@ _test_cue_spec(const c3_c* cap_c,
ret_i = 0; ret_i = 0;
} }
u3z(pro); u3z(out);
} }
return ret_i; return ret_i;

View File

@ -11,7 +11,7 @@
** initialize helper for bitstream-writer tests. ** initialize helper for bitstream-writer tests.
*/ */
static void static void
_bsw_init(ur_bsw_t *bsw, uint64_t prev, uint64_t size) _bsw_reinit(ur_bsw_t *bsw, uint64_t prev, uint64_t size)
{ {
bsw->prev = prev; bsw->prev = prev;
bsw->size = size; bsw->size = size;
@ -58,7 +58,7 @@ _test_bsw_bit_ones(void)
{ {
int ret = 1; int ret = 1;
ur_bsw_t bsw = {0}; ur_bsw_t bsw = {0};
_bsw_init(&bsw, 1, 1); _bsw_reinit(&bsw, 1, 1);
ret &= _bsw_bit_check("bsw ones init", &bsw, 0x0, 0); ret &= _bsw_bit_check("bsw ones init", &bsw, 0x0, 0);
@ -104,7 +104,7 @@ _test_bsw_bit_zeros(void)
{ {
int ret = 1; int ret = 1;
ur_bsw_t bsw = {0}; ur_bsw_t bsw = {0};
_bsw_init(&bsw, 1, 1); _bsw_reinit(&bsw, 1, 1);
ret &= _bsw_bit_check("bsw zeros init", &bsw, 0x0, 0); ret &= _bsw_bit_check("bsw zeros init", &bsw, 0x0, 0);
@ -150,7 +150,7 @@ _test_bsw_bit_alt(void)
{ {
int ret = 1; int ret = 1;
ur_bsw_t bsw = {0}; ur_bsw_t bsw = {0};
_bsw_init(&bsw, 1, 1); _bsw_reinit(&bsw, 1, 1);
ret &= _bsw_bit_check("bsw alt init", &bsw, 0x0, 0); ret &= _bsw_bit_check("bsw alt init", &bsw, 0x0, 0);
@ -286,8 +286,8 @@ _test_bsw8_loop(const char* cap, uint8_t val)
for ( i = 0; i < 8; i++) { for ( i = 0; i < 8; i++) {
for ( j = 0; j <= 8; j++ ) { for ( j = 0; j <= 8; j++ ) {
_bsw_init(&a, 1, 1); _bsw_reinit(&a, 1, 1);
_bsw_init(&b, 1, 1); _bsw_reinit(&b, 1, 1);
a.off = a.bits = b.off = b.bits = i; a.off = a.bits = b.off = b.bits = i;
_bsw8_slow(&a, j, val); _bsw8_slow(&a, j, val);
@ -338,8 +338,8 @@ _test_bsw32_loop(const char* cap, uint32_t val)
for ( i = 0; i < 8; i++) { for ( i = 0; i < 8; i++) {
for ( j = 0; j <= 32; j++ ) { for ( j = 0; j <= 32; j++ ) {
_bsw_init(&a, 1, 1); _bsw_reinit(&a, 1, 1);
_bsw_init(&b, 1, 1); _bsw_reinit(&b, 1, 1);
a.off = a.bits = b.off = b.bits = i; a.off = a.bits = b.off = b.bits = i;
_bsw32_slow(&a, j, val); _bsw32_slow(&a, j, val);
@ -390,8 +390,8 @@ _test_bsw64_loop(const char* cap, uint64_t val)
for ( i = 0; i < 8; i++) { for ( i = 0; i < 8; i++) {
for ( j = 0; j <= 64; j++ ) { for ( j = 0; j <= 64; j++ ) {
_bsw_init(&a, 1, 1); _bsw_reinit(&a, 1, 1);
_bsw_init(&b, 1, 1); _bsw_reinit(&b, 1, 1);
a.off = a.bits = b.off = b.bits = i; a.off = a.bits = b.off = b.bits = i;
_bsw64_slow(&a, j, val); _bsw64_slow(&a, j, val);
@ -447,8 +447,8 @@ _test_bsw_bytes_loop(const char* cap, uint64_t len, uint8_t val)
for ( i = 0; i < 8; i++) { for ( i = 0; i < 8; i++) {
for ( j = 0; j < len_bit; j++ ) { for ( j = 0; j < len_bit; j++ ) {
_bsw_init(&a, 1, 1); _bsw_reinit(&a, 1, 1);
_bsw_init(&b, 1, 1); _bsw_reinit(&b, 1, 1);
a.off = a.bits = b.off = b.bits = i; a.off = a.bits = b.off = b.bits = i;
_bsw_bytes_slow(&a, j, byt); _bsw_bytes_slow(&a, j, byt);
@ -501,13 +501,13 @@ _test_bsw_bex()
int ret = 1; int ret = 1;
ur_bsw_t a = {0}; ur_bsw_t a = {0};
ur_bsw_t b = {0}; ur_bsw_t b = {0};
uint8_t i, l; uint8_t i;
uint32_t j, k; uint32_t j;
for ( i = 0; i < 8; i++) { for ( i = 0; i < 8; i++) {
for ( j = 0; j < 256; j++ ) { for ( j = 0; j < 256; j++ ) {
_bsw_init(&a, 1, 1); _bsw_reinit(&a, 1, 1);
_bsw_init(&b, 1, 1); _bsw_reinit(&b, 1, 1);
a.off = a.bits = b.off = b.bits = i; a.off = a.bits = b.off = b.bits = i;
_bsw_bex_slow(&a, j); _bsw_bex_slow(&a, j);
@ -1363,7 +1363,7 @@ _test_bsr_skip_any_loop(const char *cap, uint8_t len, uint8_t val)
uint64_t max = (len << 3) + 7; uint64_t max = (len << 3) + 7;
ur_bsr_t a, b; ur_bsr_t a, b;
uint8_t *bytes, *c; uint8_t *bytes, *c;
uint8_t i, j, k; uint8_t i, j;
c = malloc(1 + len); c = malloc(1 + len);
bytes = malloc(len); bytes = malloc(len);
@ -1510,7 +1510,7 @@ _test_bsr_log_loop(const char *cap, uint8_t len, uint8_t val)
int ret = 1; int ret = 1;
ur_bsr_t a, b; ur_bsr_t a, b;
uint8_t *bytes, c, d; uint8_t *bytes, c, d;
uint8_t i, j, k; uint8_t i, j;
ur_cue_res_e e, f; ur_cue_res_e e, f;
bytes = malloc(len); bytes = malloc(len);
@ -1602,7 +1602,7 @@ _test_bsr_tag_loop(const char *cap, uint8_t len, uint8_t val)
ur_bsr_t a, b; ur_bsr_t a, b;
uint8_t *bytes; uint8_t *bytes;
ur_cue_tag_e c, d; ur_cue_tag_e c, d;
uint8_t i, j, k; uint8_t i, j;
ur_cue_res_e e, f; ur_cue_res_e e, f;
bytes = malloc(len); bytes = malloc(len);

View File

@ -615,7 +615,6 @@ ur_bsr_log(ur_bsr_t *bsr, uint8_t *out)
} }
else { else {
uint8_t off = bsr->off; uint8_t off = bsr->off;
uint8_t rest = 8 - off;
const uint8_t *b = bsr->bytes; const uint8_t *b = bsr->bytes;
uint8_t byt = b[0] >> off; uint8_t byt = b[0] >> off;
uint8_t skip = 0; uint8_t skip = 0;
@ -625,13 +624,11 @@ ur_bsr_log(ur_bsr_t *bsr, uint8_t *out)
return _bsr_log_meme(bsr); return _bsr_log_meme(bsr);
} }
skip++; byt = b[++skip];
if ( skip == left ) { if ( skip == left ) {
return _bsr_set_gone(bsr, (skip << 3) - off); return _bsr_set_gone(bsr, (skip << 3) - off);
} }
byt = b[skip];
} }
{ {
@ -702,6 +699,20 @@ ur_bsr_rub_len(ur_bsr_t *bsr, uint64_t *out)
** of reallocating the output buffer. ** of reallocating the output buffer.
*/ */
void
ur_bsw_init(ur_bsw_t *bsw, uint64_t prev, uint64_t size)
{
bsw->prev = prev;
bsw->size = size;
bsw->bytes = calloc(size, 1);
if ( !bsw->bytes ) {
fprintf(stderr,
"ur: bitstream-init allocation failed, out of memory\r\n");
abort();
}
}
void void
ur_bsw_grow(ur_bsw_t *bsw, uint64_t step) ur_bsw_grow(ur_bsw_t *bsw, uint64_t step)
{ {
@ -729,6 +740,19 @@ ur_bsw_sane(ur_bsw_t *bsw)
&& ((bsw->fill << 3) + bsw->off == bsw->bits) ); && ((bsw->fill << 3) + bsw->off == bsw->bits) );
} }
uint64_t
ur_bsw_done(ur_bsw_t *bsw, uint64_t *len, uint8_t **byt)
{
uint64_t bits = bsw->bits;
*len = bsw->fill + !!bsw->off;
*byt = bsw->bytes;
memset(bsw, 0, sizeof(*bsw));
return bits;
}
static inline void static inline void
_bsw_bit_unsafe(ur_bsw_t *bsw, uint8_t bit) _bsw_bit_unsafe(ur_bsw_t *bsw, uint8_t bit)
{ {

View File

@ -526,18 +526,15 @@ ur_met(ur_root_t *r, uint8_t bloq, ur_nref ref)
case 0: return m_bit; case 0: return m_bit;
case 1: return ur_bloq_up1(m_bit); case 1: return ur_bloq_up1(m_bit);
case 2: return ur_bloq_up2(m_bit); case 2: return ur_bloq_up2(m_bit);
case 3: return ur_bloq_up3(m_bit);
{
uint64_t m_byt = ur_bloq_up3(m_bit);
case 3: return m_byt;
default: { default: {
uint64_t m_byt = ur_bloq_up3(m_bit);
uint8_t off = (bloq - 3); uint8_t off = (bloq - 3);
return (m_byt + ((1ULL << off) - 1)) >> off; return (m_byt + ((1ULL << off) - 1)) >> off;
} }
} }
} }
}
static ur_nref static ur_nref
_coin_unsafe(ur_atoms_t *atoms, ur_mug mug, uint64_t len, uint8_t *byt) _coin_unsafe(ur_atoms_t *atoms, ur_mug mug, uint64_t len, uint8_t *byt)
@ -894,6 +891,93 @@ ur_nvec_init(ur_nvec_t *v, uint64_t size)
v->refs = _oom("nvec_init", calloc(size, sizeof(ur_nref))); v->refs = _oom("nvec_init", calloc(size, sizeof(ur_nref)));
} }
/*
** define opaque struct ur_walk_fore_s (ie, ur_walk_fore_t)
*/
struct ur_walk_fore_s {
ur_root_t *r;
uint32_t prev;
uint32_t size;
uint32_t fill;
ur_nref *top;
};
ur_walk_fore_t*
ur_walk_fore_init_with(ur_root_t *r,
uint32_t s_prev,
uint32_t s_size)
{
ur_walk_fore_t *w = _oom("walk_fore", malloc(sizeof(*w)));
w->top = _oom("walk_fore", malloc(s_size * sizeof(*w->top)));
w->prev = s_prev;
w->size = s_size;
w->fill = 0;
w->r = r;
return w;
}
ur_walk_fore_t*
ur_walk_fore_init(ur_root_t *r)
{
return ur_walk_fore_init_with(r, ur_fib10, ur_fib11);
}
void
ur_walk_fore_with(ur_walk_fore_t *w,
ur_nref ref,
void *v,
void (*atom)(ur_root_t*, ur_nref, void*),
ur_bool_t (*cell)(ur_root_t*, ur_nref, void*))
{
ur_root_t *r = w->r;
ur_nref *don = w->top;
w->top += ++w->fill;
*w->top = ref;
while ( w->top != don ) {
// visit atom, pop stack
//
if ( !ur_deep(ref) ) {
atom(r, ref, v);
w->top--; w->fill--;
}
// visit cell, pop stack if false
//
else if ( !cell(r, ref, v) ) {
w->top--; w->fill--;
}
// push the tail, continue into the head
//
else {
*w->top = ur_tail(r, ref);
// reallocate "stack" if full
//
if ( w->size == w->fill ) {
uint32_t next = w->prev + w->size;
don = _oom("walk_fore", realloc(don, next * sizeof(*don)));
w->top = don + w->fill;
w->prev = w->size;
w->size = next;
}
w->top++; w->fill++;
*w->top = ur_head(r, ref);
}
ref = *w->top;
}
}
void
ur_walk_fore_done(ur_walk_fore_t *w)
{
free(w->top);
free(w);
}
void void
ur_walk_fore(ur_root_t *r, ur_walk_fore(ur_root_t *r,
ur_nref ref, ur_nref ref,
@ -901,46 +985,7 @@ ur_walk_fore(ur_root_t *r,
void (*atom)(ur_root_t*, ur_nref, void*), void (*atom)(ur_root_t*, ur_nref, void*),
ur_bool_t (*cell)(ur_root_t*, ur_nref, void*)) ur_bool_t (*cell)(ur_root_t*, ur_nref, void*))
{ {
uint64_t prev = ur_fib11, size = ur_fib12, fill = 0; ur_walk_fore_t *w = ur_walk_fore_init(r);
ur_nref *top, *don; ur_walk_fore_with(w, ref, v, atom, cell);
ur_walk_fore_done(w);
don = _oom("walk_fore", malloc(size * sizeof(*don)));
top = don + ++fill;
*top = ref;
while ( top != don ) {
// visit atom, pop stack
//
if ( !ur_deep(ref) ) {
atom(r, ref, v);
top--; fill--;
}
// visit cell, pop stack if false
//
else if ( !cell(r, ref, v) ) {
top--; fill--;
}
// push the tail, continue into the head
//
else {
*top = ur_tail(r, ref);
// reallocate "stack" if full
//
if ( size == fill ) {
uint64_t next = prev + size;
don = _oom("walk_fore", realloc(don, next * sizeof(*don)));
top = don + fill;
prev = size;
size = next;
}
top++; fill++;
*top = ur_head(r, ref);
}
ref = *top;
}
free(don);
} }

View File

@ -30,16 +30,21 @@ _bsw_atom(ur_root_t *r, ur_nref ref, ur_bsw_t *bsw, uint64_t len)
} }
} }
typedef struct _jam_s { /*
ur_dict64_t *dict; ** define opaque struct ur_jam_s (ie, ur_jam_t)
*/
struct ur_jam_s {
ur_root_t *r;
ur_walk_fore_t *w;
ur_dict64_t dict;
ur_bsw_t bsw; ur_bsw_t bsw;
} _jam_t; };
static void static void
_jam_atom(ur_root_t *r, ur_nref ref, void *ptr) _jam_atom(ur_root_t *r, ur_nref ref, void *ptr)
{ {
_jam_t *j = ptr; ur_jam_t *j = ptr;
ur_dict64_t *dict = j->dict; ur_dict64_t *dict = &j->dict;
ur_bsw_t *bsw = &j->bsw; ur_bsw_t *bsw = &j->bsw;
uint64_t bak, len = ur_met(r, 0, ref); uint64_t bak, len = ur_met(r, 0, ref);
@ -63,8 +68,8 @@ _jam_atom(ur_root_t *r, ur_nref ref, void *ptr)
static ur_bool_t static ur_bool_t
_jam_cell(ur_root_t *r, ur_nref ref, void *ptr) _jam_cell(ur_root_t *r, ur_nref ref, void *ptr)
{ {
_jam_t *j = ptr; ur_jam_t *j = ptr;
ur_dict64_t *dict = j->dict; ur_dict64_t *dict = &j->dict;
ur_bsw_t *bsw = &j->bsw; ur_bsw_t *bsw = &j->bsw;
uint64_t bak; uint64_t bak;
@ -80,40 +85,69 @@ _jam_cell(ur_root_t *r, ur_nref ref, void *ptr)
} }
} }
uint64_t static uint64_t
ur_jam_unsafe(ur_root_t *r, _jam(ur_jam_t *j,
ur_nref ref, ur_nref ref,
ur_dict64_t *dict,
uint64_t *len, uint64_t *len,
uint8_t **byt) uint8_t **byt)
{ {
_jam_t j = {0}; ur_bsw_init(&j->bsw, ur_fib11, ur_fib12);
ur_walk_fore_with(j->w, ref, j, _jam_atom, _jam_cell);
return ur_bsw_done(&j->bsw, len, byt);
}
j.dict = dict; ur_jam_t*
ur_jam_init_with(ur_root_t *r,
uint64_t d_prev,
uint64_t d_size,
uint32_t s_prev,
uint32_t s_size)
{
ur_jam_t *j = _oom("jam_init", calloc(sizeof(*j), 1));
j->w = ur_walk_fore_init_with(r, s_prev, s_size);
j->r = r;
j.bsw.prev = ur_fib11; ur_dict64_grow(r, &j->dict, d_prev, d_size);
j.bsw.size = ur_fib12;
j.bsw.bytes = _oom("jam", calloc(j.bsw.size, 1));
ur_walk_fore(r, ref, &j, _jam_atom, _jam_cell); return j;
}
*len = j.bsw.fill + !!j.bsw.off; ur_jam_t*
*byt = j.bsw.bytes; ur_jam_init(ur_root_t *r)
{
return j.bsw.bits; return ur_jam_init_with(r, ur_fib11, ur_fib12, // dict sizes
ur_fib10, ur_fib11); // stack sizes
} }
uint64_t uint64_t
ur_jam(ur_root_t *r, ur_nref ref, uint64_t *len, uint8_t **byt) ur_jam_with(ur_jam_t *j,
ur_nref ref,
uint64_t *len,
uint8_t **byt)
{ {
ur_dict64_t dict = {0}; uint64_t bits = _jam(j, ref, len, byt);
ur_dict64_grow(r, &dict, ur_fib11, ur_fib12); ur_dict64_wipe(&j->dict);
{
uint64_t bits = ur_jam_unsafe(r, ref, &dict, len, byt);
ur_dict_free((ur_dict_t*)&dict);
return bits; return bits;
} }
void
ur_jam_done(ur_jam_t *j)
{
ur_dict_free((ur_dict_t*)&j->dict);
free(j->w);
free(j);
}
uint64_t
ur_jam(ur_root_t *r,
ur_nref ref,
uint64_t *len,
uint8_t **byt)
{
ur_jam_t *j = ur_jam_init(r);
uint64_t bits = _jam(j, ref, len, byt);
ur_jam_done(j);
return bits;
} }
/* /*
@ -224,15 +258,25 @@ _cue_next(ur_root_t *r,
} }
} }
ur_cue_res_e /*
ur_cue_unsafe(ur_root_t *r, ** define opaque struct ur_cue_s (ie, ur_cue_t)
ur_dict64_t *dict, */
struct ur_cue_s {
ur_root_t *r;
_cue_stack_t s;
ur_dict64_t dict;
};
static ur_cue_res_e
_cue(ur_cue_t *c,
uint64_t len, uint64_t len,
const uint8_t *byt, const uint8_t *byt,
ur_nref *out) ur_nref *out)
{ {
ur_bsr_t bsr = {0}; ur_bsr_t bsr = {0};
_cue_stack_t s = {0}; ur_root_t *r = c->r;
_cue_stack_t *s = &c->s;
ur_dict64_t *dict = &c->dict;
ur_cue_res_e res; ur_cue_res_e res;
ur_nref ref; ur_nref ref;
@ -247,58 +291,99 @@ ur_cue_unsafe(ur_root_t *r,
return ur_cue_meme; return ur_cue_meme;
} }
// setup stack
//
s.prev = ur_fib10;
s.size = ur_fib11;
s.f = _oom("cue stack", malloc(s.size * sizeof(*s.f)));
// advance into stream // advance into stream
// //
res = _cue_next(r, &s, &bsr, dict, &ref); res = _cue_next(r, s, &bsr, dict, &ref);
// process result // process result
// //
while ( s.fill && (ur_cue_good == res) ) { while ( s->fill && (ur_cue_good == res) ) {
// peek at the top of the stack // peek at the top of the stack
// //
_cue_frame_t *f = &(s.f[s.fill - 1]); _cue_frame_t *f = &(s->f[s->fill - 1]);
// f is a head-frame; stash result and read the tail from the stream // f is a head-frame; stash result and read the tail from the stream
// //
if ( CUE_HEAD == f->ref ) { if ( CUE_HEAD == f->ref ) {
f->ref = ref; f->ref = ref;
res = _cue_next(r, &s, &bsr, dict, &ref); res = _cue_next(r, s, &bsr, dict, &ref);
} }
// f is a tail-frame; pop the stack and continue // f is a tail-frame; pop the stack and continue
// //
else { else {
ref = ur_cons(r, f->ref, ref); ref = ur_cons(r, f->ref, ref);
ur_dict64_put(r, dict, f->bits, (uint64_t)ref); ur_dict64_put(r, dict, f->bits, (uint64_t)ref);
s.fill--; s->fill--;
} }
} }
free(s.f);
if ( ur_cue_good == res ) { if ( ur_cue_good == res ) {
*out = ref; *out = ref;
} }
return res; return res;
} }
ur_cue_t*
ur_cue_init_with(ur_root_t *r,
uint64_t d_prev,
uint64_t d_size,
uint32_t s_prev,
uint32_t s_size)
{
ur_cue_t* c = _oom("cue_init", calloc(sizeof(*c), 1));
c->r = r;
ur_dict64_grow(r, &c->dict, d_prev, d_size);
c->s.prev = s_prev;
c->s.size = s_size;
c->s.f = _oom("cue_test_init", malloc(s_size * sizeof(*c->s.f)));
return c;
}
ur_cue_t*
ur_cue_init(ur_root_t *r)
{
return ur_cue_init_with(r, ur_fib11, ur_fib12, // dict sizes
ur_fib10, ur_fib11); // stack sizes
}
ur_cue_res_e
ur_cue_with(ur_cue_t *c,
uint64_t len,
const uint8_t *byt,
ur_nref *out)
{
ur_cue_res_e res = _cue(c, len, byt, out);
// XX check size, shrink if above threshold
//
ur_dict64_wipe(&c->dict);
c->s.fill = 0;
return res;
}
void
ur_cue_done(ur_cue_t *c)
{
ur_dict_free((ur_dict_t*)&c->dict);
free(c->s.f);
free(c);
}
ur_cue_res_e ur_cue_res_e
ur_cue(ur_root_t *r, ur_cue(ur_root_t *r,
uint64_t len, uint64_t len,
const uint8_t *byt, const uint8_t *byt,
ur_nref *out) ur_nref *out)
{ {
ur_dict64_t dict = {0}; ur_cue_t *c = ur_cue_init(r);
ur_dict64_grow(r, &dict, ur_fib11, ur_fib12); ur_cue_res_e res = _cue(c, len, byt, out);
ur_cue_res_e res = ur_cue_unsafe(r, &dict, len, byt, out); ur_cue_done(c);
ur_dict_free((ur_dict_t*)&dict);
return res; return res;
} }
@ -386,13 +471,22 @@ _cue_test_next(_cue_test_stack_t *s,
} }
} }
ur_cue_res_e /*
ur_cue_test_unsafe(ur_dict_t *dict, ** define opaque struct ur_cue_test_s (ie, ur_cue_test_t)
*/
struct ur_cue_test_s {
_cue_test_stack_t s;
ur_dict_t dict;
};
static ur_cue_res_e
_cue_test(ur_cue_test_t *t,
uint64_t len, uint64_t len,
const uint8_t *byt) const uint8_t *byt)
{ {
ur_bsr_t bsr = {0}; ur_bsr_t bsr = {0};
_cue_test_stack_t s = {0}; _cue_test_stack_t *s = &t->s;
ur_dict_t *dict = &t->dict;
ur_cue_res_e res; ur_cue_res_e res;
// init bitstream-reader // init bitstream-reader
@ -406,50 +500,87 @@ ur_cue_test_unsafe(ur_dict_t *dict,
return ur_cue_meme; return ur_cue_meme;
} }
// setup stack
//
s.prev = ur_fib10;
s.size = ur_fib11;
s.f = _oom("cue_test", malloc(s.size * sizeof(*s.f)));
// advance into stream // advance into stream
// //
res = _cue_test_next(&s, &bsr, dict); res = _cue_test_next(s, &bsr, dict);
// process result // process result
// //
while ( s.fill && (ur_cue_good == res) ) { while ( s->fill && (ur_cue_good == res) ) {
// peek at the top of the stack // peek at the top of the stack
// //
_cue_test_frame_t *f = &(s.f[s.fill - 1]); _cue_test_frame_t *f = &(s->f[s->fill - 1]);
// f is a head-frame; stash result and read the tail from the stream // f is a head-frame; stash result and read the tail from the stream
// //
if ( !f->tal ) { if ( !f->tal ) {
f->tal = 1; f->tal = 1;
res = _cue_test_next(&s, &bsr, dict); res = _cue_test_next(s, &bsr, dict);
} }
// f is a tail-frame; pop the stack and continue // f is a tail-frame; pop the stack and continue
// //
else { else {
ur_dict_put((ur_root_t*)0, dict, f->bits); ur_dict_put((ur_root_t*)0, dict, f->bits);
s.fill--; s->fill--;
} }
} }
free(s.f);
return res; return res;
} }
ur_cue_test_t*
ur_cue_test_init_with(uint64_t d_prev,
uint64_t d_size,
uint32_t s_prev,
uint32_t s_size)
{
ur_cue_test_t* t = _oom("cue_test_init", calloc(sizeof(*t), 1));
ur_dict_grow((ur_root_t*)0, &t->dict, d_prev, d_size);
t->s.prev = s_prev;
t->s.size = s_size;
t->s.f = _oom("cue_test_init", malloc(s_size * sizeof(*t->s.f)));
return t;
}
ur_cue_test_t*
ur_cue_test_init(void)
{
return ur_cue_test_init_with(ur_fib11, ur_fib12, // dict sizes
ur_fib10, ur_fib11); // stack sizes
}
ur_bool_t
ur_cue_test_with(ur_cue_test_t *t,
uint64_t len,
const uint8_t *byt)
{
ur_bool_t ret = ur_cue_good == _cue_test(t, len, byt);
// XX check size, shrink if above threshold
//
ur_dict_wipe(&t->dict);
t->s.fill = 0;
return ret;
}
void
ur_cue_test_done(ur_cue_test_t *t)
{
ur_dict_free(&t->dict);
free(t->s.f);
free(t);
}
ur_bool_t ur_bool_t
ur_cue_test(uint64_t len, const uint8_t *byt) ur_cue_test(uint64_t len, const uint8_t *byt)
{ {
ur_dict_t dict = {0}; ur_cue_test_t *t = ur_cue_test_init();
ur_dict_grow((ur_root_t*)0, &dict, ur_fib11, ur_fib12); ur_bool_t ret = ur_cue_good == _cue_test(t, len, byt);
ur_bool_t ret = ur_cue_good == ur_cue_test_unsafe(&dict, len, byt); ur_cue_test_done(t);
ur_dict_free(&dict);
return ret; return ret;
} }

View File

@ -12,6 +12,7 @@
#include "all.h" #include "all.h"
#include "vere/vere.h" #include "vere/vere.h"
#include "ur/serial.h"
/* u3_pact: ames packet, coming or going. /* u3_pact: ames packet, coming or going.
*/ */
@ -35,6 +36,8 @@
uv_udp_t wax_u; // uv_udp_t wax_u; //
uv_handle_t had_u; // uv_handle_t had_u; //
}; // }; //
ur_cue_test_t* tes_u; // cue-test handle
u3_cue_xeno* sil_u; // cue handle
c3_c* dns_c; // domain XX multiple/fallback c3_c* dns_c; // domain XX multiple/fallback
c3_d dop_d; // drop count c3_d dop_d; // drop count
c3_d fal_d; // crash count c3_d fal_d; // crash count
@ -365,8 +368,11 @@ _ames_serialize_packet(u3_panc* pac_u, c3_o dop_o)
u3_noun lon, bod; u3_noun lon, bod;
{ {
//NOTE we checked for cue safety in _ames_recv_cb //NOTE we checked for cue safety in _ames_recv_cb
u3_noun old = u3ke_cue(u3i_bytes(pac_u->bod_u.con_w, pac_u->bod_u.con_y)); //
u3x_cell(old, &lon, &bod); u3_weak old = u3s_cue_xeno_with(pac_u->sam_u->sil_u,
pac_u->bod_u.con_w,
pac_u->bod_u.con_y);
u3x_cell(u3x_good(old), &lon, &bod);
u3k(lon); u3k(bod); u3k(lon); u3k(bod);
u3z(old); u3z(old);
} }
@ -798,6 +804,7 @@ _ames_recv_cb(uv_udp_t* wax_u,
c3_d rec_d[2]; c3_d rec_d[2];
c3_w con_w = nrd_i - 4 - sen_y - rec_y; c3_w con_w = nrd_i - 4 - sen_y - rec_y;
c3_y* con_y = NULL; c3_y* con_y = NULL;
if ( c3y == pas_o ) { if ( c3y == pas_o ) {
u3_noun sen = u3i_bytes(sen_y, bod_y); u3_noun sen = u3i_bytes(sen_y, bod_y);
u3_noun rec = u3i_bytes(rec_y, bod_y + sen_y); u3_noun rec = u3i_bytes(rec_y, bod_y + sen_y);
@ -810,9 +817,7 @@ _ames_recv_cb(uv_udp_t* wax_u,
// ensure the content is cue-able // ensure the content is cue-able
// //
u3_noun pro = u3m_soft(0, u3ke_cue, u3i_bytes(con_w, con_y)); pas_o = ur_cue_test_with(sam_u->tes_u, con_w, con_y) ? c3y : c3n;
pas_o = (u3_blip == u3h(pro)) ? c3y : c3n;
u3z(pro);
} }
// if we can scry, // if we can scry,
@ -1165,6 +1170,9 @@ _ames_exit_cb(uv_handle_t* had_u)
u3h_free(sam_u->lax_p); u3h_free(sam_u->lax_p);
u3s_cue_xeno_done(sam_u->sil_u);
ur_cue_test_done(sam_u->tes_u);
c3_free(sam_u); c3_free(sam_u);
} }
@ -1225,6 +1233,9 @@ u3_ames_io_init(u3_pier* pir_u)
c3_assert( !uv_udp_init(u3L, &sam_u->wax_u) ); c3_assert( !uv_udp_init(u3L, &sam_u->wax_u) );
sam_u->wax_u.data = sam_u; sam_u->wax_u.data = sam_u;
sam_u->sil_u = u3s_cue_xeno_init();
sam_u->tes_u = ur_cue_test_init();
// Disable networking for fake ships // Disable networking for fake ships
// //
if ( c3y == sam_u->pir_u->fak_o ) { if ( c3y == sam_u->pir_u->fak_o ) {

View File

@ -713,17 +713,15 @@ _king_boot_ivory(void)
} }
{ {
ur_dict32_t dic_u = {0}; u3_cue_xeno* sil_u = u3s_cue_xeno_init_with(ur_fib27, ur_fib28);
u3_noun pil; u3_weak pil;
ur_dict32_grow((ur_root_t*)0, &dic_u, ur_fib27, ur_fib28); if ( u3_none == (pil = u3s_cue_xeno_with(sil_u, len_d, byt_y)) ) {
if ( c3n == u3s_cue_xeno_unsafe(&dic_u, len_d, byt_y, &pil) ) {
u3l_log("lite: unable to cue ivory pill\r\n"); u3l_log("lite: unable to cue ivory pill\r\n");
exit(1); exit(1);
} }
ur_dict_free((ur_dict_t*)&dic_u); u3s_cue_xeno_done(sil_u);
if ( c3n == u3v_boot_lite(pil)) { if ( c3n == u3v_boot_lite(pil)) {
u3l_log("lite: boot failed\r\n"); u3l_log("lite: boot failed\r\n");

View File

@ -74,7 +74,7 @@ _lord_stop_cb(void* ptr_v,
void (*exit_f)(void*) = god_u->cb_u.exit_f; void (*exit_f)(void*) = god_u->cb_u.exit_f;
void* exit_v = god_u->cb_u.ptr_v; void* exit_v = god_u->cb_u.ptr_v;
ur_dict_free((ur_dict_t*)god_u->dic_u); u3s_cue_xeno_done(god_u->sil_u);
c3_free(god_u); c3_free(god_u);
if ( exit_f ) { if ( exit_f ) {
@ -675,26 +675,23 @@ static void
_lord_on_plea(void* ptr_v, c3_d len_d, c3_y* byt_y) _lord_on_plea(void* ptr_v, c3_d len_d, c3_y* byt_y)
{ {
u3_lord* god_u = ptr_v; u3_lord* god_u = ptr_v;
ur_dict32_t* dic_u = god_u->dic_u; u3_noun tag, dat;
u3_noun tag, dat, jar = u3_blip; u3_weak jar;
c3_o ret_o;
#ifdef LORD_TRACE_CUE #ifdef LORD_TRACE_CUE
u3t_event_trace("king ipc cue", 'B'); u3t_event_trace("king ipc cue", 'B');
#endif #endif
ret_o = u3s_cue_xeno_unsafe(dic_u, len_d, byt_y, &jar); jar = u3s_cue_xeno_with(god_u->sil_u, len_d, byt_y);
// XX check if the dictionary grew too much and shrink?
//
ur_dict32_wipe(dic_u);
#ifdef LORD_TRACE_CUE #ifdef LORD_TRACE_CUE
u3t_event_trace("king ipc cue", 'E'); u3t_event_trace("king ipc cue", 'E');
#endif #endif
if ( (c3n == ret_o) if ( u3_none == jar ) {
|| (c3n == u3r_cell(jar, &tag, &dat)) ) return _lord_plea_foul(god_u, 0, u3_blip);
{ }
else if ( c3n == u3r_cell(jar, &tag, &dat) ) {
return _lord_plea_foul(god_u, 0, jar); return _lord_plea_foul(god_u, 0, jar);
} }
@ -1172,9 +1169,7 @@ u3_lord_init(c3_c* pax_c, c3_w wag_w, c3_d key_d[4], u3_lord_cb cb_u)
#endif #endif
{ {
ur_dict32_t* dic_u = c3_calloc(sizeof(*dic_u)); god_u->sil_u = u3s_cue_xeno_init();
ur_dict32_grow((ur_root_t*)0, dic_u, ur_fib10, ur_fib11);
god_u->dic_u = dic_u;
} }
// start reading from proc // start reading from proc

View File

@ -27,7 +27,7 @@
static u3_serf u3V; // one serf per process static u3_serf u3V; // one serf per process
static u3_moat inn_u; // input stream static u3_moat inn_u; // input stream
static u3_mojo out_u; // output stream static u3_mojo out_u; // output stream
static ur_dict32_t dic_u; // cue dictionary static u3_cue_xeno* sil_u; // cue handle
#undef SERF_TRACE_JAM #undef SERF_TRACE_JAM
#undef SERF_TRACE_CUE #undef SERF_TRACE_CUE
@ -107,8 +107,8 @@ _cw_serf_step_trace(void)
static void static void
_cw_serf_writ(void* vod_p, c3_d len_d, c3_y* byt_y) _cw_serf_writ(void* vod_p, c3_d len_d, c3_y* byt_y)
{ {
u3_noun ret, jar; u3_weak jar;
c3_o ret_o; u3_noun ret;
_cw_serf_step_trace(); _cw_serf_step_trace();
@ -116,16 +116,13 @@ _cw_serf_writ(void* vod_p, c3_d len_d, c3_y* byt_y)
u3t_event_trace("serf ipc cue", 'B'); u3t_event_trace("serf ipc cue", 'B');
#endif #endif
ret_o = u3s_cue_xeno_unsafe(&dic_u, len_d, byt_y, &jar); jar = u3s_cue_xeno_with(sil_u, len_d, byt_y);
// XX check if the dictionary grew too much and shrink?
//
ur_dict32_wipe(&dic_u);
#ifdef SERF_TRACE_CUE #ifdef SERF_TRACE_CUE
u3t_event_trace("serf ipc cue", 'E'); u3t_event_trace("serf ipc cue", 'E');
#endif #endif
if ( (c3n == ret_o) if ( (u3_none == jar)
|| (c3n == u3_serf_writ(&u3V, jar, &ret)) ) || (c3n == u3_serf_writ(&u3V, jar, &ret)) )
{ {
_cw_serf_fail(0, -1, "bad jar"); _cw_serf_fail(0, -1, "bad jar");
@ -165,7 +162,7 @@ _cw_serf_stdio(c3_i* inn_i, c3_i* out_i)
static void static void
_cw_serf_exit(void) _cw_serf_exit(void)
{ {
ur_dict_free((ur_dict_t*)&dic_u); u3s_cue_xeno_done(sil_u);
u3t_trace_close(); u3t_trace_close();
} }
@ -239,7 +236,7 @@ _cw_serf_commence(c3_i argc, c3_c* argv[])
uv_stream_set_blocking((uv_stream_t*)&out_u.pyp_u, 1); uv_stream_set_blocking((uv_stream_t*)&out_u.pyp_u, 1);
} }
ur_dict32_grow((ur_root_t*)0, &dic_u, ur_fib10, ur_fib11); sil_u = u3s_cue_xeno_init();
// set up writing // set up writing
// //