mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-12-15 10:02:47 +03:00
ur: refactors unsafe cue variants into a handle-based api
This commit is contained in:
parent
06cf6386aa
commit
efe4479f23
@ -261,8 +261,7 @@ _cue_bench(void)
|
||||
gettimeofday(&b4, 0);
|
||||
|
||||
{
|
||||
ur_dict_t dic_u = {0};
|
||||
u3_noun out;
|
||||
ur_cue_test_t *t = ur_cue_test_init();
|
||||
|
||||
c3_w len_w = u3r_met(3, vat);
|
||||
// XX assumes little-endian
|
||||
@ -271,20 +270,17 @@ _cue_bench(void)
|
||||
? (c3_y*)&vat
|
||||
: (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++ ) {
|
||||
ur_cue_test_unsafe(&dic_u, len_w, byt_y);
|
||||
ur_dict_wipe(&dic_u);
|
||||
ur_cue_test_with(t, len_w, byt_y);
|
||||
}
|
||||
|
||||
ur_dict_free(&dic_u);
|
||||
ur_cue_test_done(t);
|
||||
}
|
||||
|
||||
gettimeofday(&f2, 0);
|
||||
timersub(&f2, &b4, &d0);
|
||||
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);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -29,28 +29,58 @@ ur_jam(ur_root_t *r, ur_nref ref, uint64_t *len, uint8_t **byt);
|
||||
** supports up to 62-bits of bit-addressed input (511 PiB).
|
||||
** returns [ur_cue_good] on success.
|
||||
**
|
||||
** unsafe variant is unsafe wrt its [dict] parameter, which must be empty,
|
||||
** (present in order to skip reallocation inside hot loops).
|
||||
** cue_with factors out stack/dict (re)allocation,
|
||||
** 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,
|
||||
ur_dict64_t *dict,
|
||||
uint64_t len,
|
||||
const uint8_t *byt,
|
||||
ur_nref *out);
|
||||
|
||||
typedef struct ur_cue_test_s ur_cue_test_t;
|
||||
typedef struct ur_cue_s ur_cue_t;
|
||||
|
||||
ur_cue_res_e
|
||||
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_test_unsafe(ur_dict_t *dict,
|
||||
uint64_t len,
|
||||
const uint8_t *byt);
|
||||
ur_cue_with(ur_cue_t *c,
|
||||
uint64_t len,
|
||||
const uint8_t *byt,
|
||||
ur_nref *out);
|
||||
|
||||
void
|
||||
ur_cue_done(ur_cue_t *c);
|
||||
|
||||
ur_bool_t
|
||||
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
|
||||
|
@ -216,15 +216,25 @@ _cue_next(ur_root_t *r,
|
||||
}
|
||||
}
|
||||
|
||||
ur_cue_res_e
|
||||
ur_cue_unsafe(ur_root_t *r,
|
||||
ur_dict64_t *dict,
|
||||
uint64_t len,
|
||||
const uint8_t *byt,
|
||||
ur_nref *out)
|
||||
/*
|
||||
** define opaque struct ur_cue_s (ie, ur_cue_t)
|
||||
*/
|
||||
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,
|
||||
const uint8_t *byt,
|
||||
ur_nref *out)
|
||||
{
|
||||
ur_bsr_t bsr = {0};
|
||||
_cue_stack_t s = {0};
|
||||
ur_bsr_t bsr = {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_nref ref;
|
||||
|
||||
@ -239,58 +249,99 @@ ur_cue_unsafe(ur_root_t *r,
|
||||
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
|
||||
//
|
||||
res = _cue_next(r, &s, &bsr, dict, &ref);
|
||||
res = _cue_next(r, s, &bsr, dict, &ref);
|
||||
|
||||
// process result
|
||||
//
|
||||
while ( s.fill && (ur_cue_good == res) ) {
|
||||
while ( s->fill && (ur_cue_good == res) ) {
|
||||
// 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
|
||||
//
|
||||
if ( CUE_HEAD == f->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
|
||||
//
|
||||
else {
|
||||
ref = ur_cons(r, f->ref, ref);
|
||||
ur_dict64_put(r, dict, f->bits, (uint64_t)ref);
|
||||
s.fill--;
|
||||
s->fill--;
|
||||
}
|
||||
}
|
||||
|
||||
free(s.f);
|
||||
|
||||
if ( ur_cue_good == res ) {
|
||||
*out = ref;
|
||||
}
|
||||
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(ur_root_t *r,
|
||||
uint64_t len,
|
||||
const uint8_t *byt,
|
||||
ur_nref *out)
|
||||
{
|
||||
ur_dict64_t dict = {0};
|
||||
ur_dict64_grow(r, &dict, ur_fib11, ur_fib12);
|
||||
ur_cue_t *c = ur_cue_init(r);
|
||||
ur_cue_res_e res = _cue(c, len, byt, out);
|
||||
|
||||
ur_cue_res_e res = ur_cue_unsafe(r, &dict, len, byt, out);
|
||||
|
||||
ur_dict_free((ur_dict_t*)&dict);
|
||||
ur_cue_done(c);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -378,14 +429,23 @@ _cue_test_next(_cue_test_stack_t *s,
|
||||
}
|
||||
}
|
||||
|
||||
ur_cue_res_e
|
||||
ur_cue_test_unsafe(ur_dict_t *dict,
|
||||
uint64_t len,
|
||||
const uint8_t *byt)
|
||||
/*
|
||||
** 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,
|
||||
const uint8_t *byt)
|
||||
{
|
||||
ur_bsr_t bsr = {0};
|
||||
_cue_test_stack_t s = {0};
|
||||
ur_cue_res_e res;
|
||||
ur_bsr_t bsr = {0};
|
||||
_cue_test_stack_t *s = &t->s;
|
||||
ur_dict_t *dict = &t->dict;
|
||||
ur_cue_res_e res;
|
||||
|
||||
// init bitstream-reader
|
||||
//
|
||||
@ -398,50 +458,87 @@ ur_cue_test_unsafe(ur_dict_t *dict,
|
||||
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
|
||||
//
|
||||
res = _cue_test_next(&s, &bsr, dict);
|
||||
res = _cue_test_next(s, &bsr, dict);
|
||||
|
||||
// process result
|
||||
//
|
||||
while ( s.fill && (ur_cue_good == res) ) {
|
||||
while ( s->fill && (ur_cue_good == res) ) {
|
||||
// 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
|
||||
//
|
||||
if ( !f->tal ) {
|
||||
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
|
||||
//
|
||||
else {
|
||||
ur_dict_put((ur_root_t*)0, dict, f->bits);
|
||||
s.fill--;
|
||||
s->fill--;
|
||||
}
|
||||
}
|
||||
|
||||
free(s.f);
|
||||
|
||||
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_cue_test(uint64_t len, const uint8_t *byt)
|
||||
{
|
||||
ur_dict_t dict = {0};
|
||||
ur_dict_grow((ur_root_t*)0, &dict, ur_fib11, ur_fib12);
|
||||
ur_cue_test_t *t = ur_cue_test_init();
|
||||
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_dict_free(&dict);
|
||||
ur_cue_test_done(t);
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user