Merge pull request #3577 from urbit/jb/base16-jets

vere: adds jets for en/decoding base16
This commit is contained in:
Joe Bryan 2020-10-06 10:52:23 -07:00 committed by GitHub
commit 6b5be2b5cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 512 additions and 0 deletions

View File

@ -152,6 +152,9 @@
u3_noun u3qe_reco(u3_atom has, u3_atom sig_v, u3_atom sig_r, u3_atom sig_s);
u3_noun u3qe_sign(u3_atom has, u3_atom prv);
u3_noun u3qe_en_base16(u3_atom len, u3_atom dat);
u3_noun u3qe_de_base16(u3_atom inp);
u3_noun u3qeo_raw(u3_atom, u3_atom);
u3_noun u3qef_drg(u3_noun, u3_atom);

View File

@ -181,6 +181,9 @@
u3_noun u3we_sign(u3_noun);
u3_noun u3we_reco(u3_noun);
u3_noun u3we_en_base16(u3_noun);
u3_noun u3we_de_base16(u3_noun);
u3_noun u3we_bend_fun(u3_noun);
u3_noun u3we_cold_fun(u3_noun);
u3_noun u3we_cook_fun(u3_noun);

View File

@ -368,6 +368,14 @@
u3r_mp(mpz_t a_mp,
u3_atom b);
/* u3r_short():
**
** Return short (a_w) of (b).
*/
c3_s
u3r_short(c3_w a_w,
u3_atom b);
/* u3r_word():
**
** Return word (a_w) of (b).

View File

@ -57,6 +57,11 @@
# define u3x_peg(a_w, b_w) \
( (a_w << u3x_dep(b_w)) | (b_w &~ (1 << u3x_dep(b_w))) )
/* u3x_atom(): atom or exit.
*/
# define u3x_atom(a) \
( (c3y == u3a_is_cell(a)) ? u3m_bail(c3__exit) : a )
/** Functions.
**/
/** u3x_*: read, but bail with c3__exit on a crash.

153
pkg/urbit/jets/e/base.c Normal file
View File

@ -0,0 +1,153 @@
/* j/5/base.c
**
*/
#include "all.h"
const c3_y hex_y[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
u3_noun
u3qe_en_base16(u3_atom len, u3_atom dat)
{
if ( c3n == u3a_is_cat(len) ) {
return u3m_bail(c3__fail);
}
else {
c3_w len_w = (c3_w)len;
u3i_slab sab_u;
u3i_slab_bare(&sab_u, 4, len_w);
sab_u.buf_w[sab_u.len_w - 1] = 0;
{
c3_y* buf_y = sab_u.buf_y;
c3_y inp_y;
while ( len_w-- ) {
inp_y = u3r_byte(len_w, dat);
*buf_y++ = hex_y[inp_y >> 4];
*buf_y++ = hex_y[inp_y & 0xf];
}
}
return u3i_slab_moot_bytes(&sab_u);
}
}
static inline c3_o
_of_hex_digit(c3_y inp_y, c3_y* out_y)
{
if ( inp_y >= '0' && inp_y <= '9' ) {
*out_y = inp_y - '0';
return c3y;
}
else if ( inp_y >= 'a' && inp_y <= 'f' ) {
*out_y = inp_y - 87;
return c3y;
}
else if ( inp_y >= 'A' && inp_y <= 'F' ) {
*out_y = inp_y - 55;
return c3y;
}
return c3n;
}
static inline c3_o
_of_hex_odd(u3_atom inp, c3_w len_w, c3_w byt_w, c3_y* buf_y)
{
c3_y low_y, hig_y, lit_y, hit_y;
hig_y = u3r_byte(--byt_w, inp);
while ( --len_w ) {
low_y = u3r_byte(--byt_w, inp);
if ( (c3n == _of_hex_digit(low_y, &lit_y))
|| (c3n == _of_hex_digit(hig_y, &hit_y)) )
{
return c3n;
}
else {
*buf_y++ = (hit_y & 0xf) ^ (lit_y << 4);
}
hig_y = u3r_byte(--byt_w, inp);
}
if ( c3n == _of_hex_digit(hig_y, &hit_y) ) {
return c3n;
}
else {
*buf_y = hit_y & 0xf;
}
return c3y;
}
static inline c3_o
_of_hex_even(u3_atom inp, c3_w len_w, c3_y* buf_y)
{
c3_y lit_y, hit_y;
c3_s inp_s;
while ( len_w-- ) {
inp_s = u3r_short(len_w, inp);
if ( (c3n == _of_hex_digit(inp_s & 0xff, &lit_y))
|| (c3n == _of_hex_digit(inp_s >> 8, &hit_y)) )
{
return c3n;
}
else {
*buf_y++ = (hit_y & 0xf) ^ (lit_y << 4);
}
}
return c3y;
}
u3_noun
u3qe_de_base16(u3_atom inp)
{
c3_w len_w = u3r_met(4, inp);
u3i_slab sab_u;
u3i_slab_bare(&sab_u, 3, len_w);
sab_u.buf_w[sab_u.len_w - 1] = 0;
// even byte-length input can be parsed in aligned, 16-bit increments,
// but odd byte-length input cannot, and is expressed more simply in bytes.
//
{
c3_w byt_w = u3r_met(3, inp);
c3_o ret_o = ( byt_w & 1 )
? _of_hex_odd(inp, len_w, byt_w, sab_u.buf_y)
: _of_hex_even(inp, len_w, sab_u.buf_y);
if ( c3n == ret_o ) {
u3i_slab_free(&sab_u);
return u3_nul;
}
else {
u3_noun dat = u3i_slab_mint_bytes(&sab_u);
return u3nt(u3_nul, u3i_word(len_w), dat);
}
}
}
u3_noun
u3we_en_base16(u3_noun cor)
{
u3_noun a, b;
u3x_mean(cor, u3x_sam_2, &a, u3x_sam_3, &b, 0);
return u3qe_en_base16(u3x_atom(a), u3x_atom(b));
}
u3_noun
u3we_de_base16(u3_noun cor)
{
u3_noun sam = u3x_at(u3x_sam, cor);
return u3qe_de_base16(u3x_atom(sam));
}

View File

@ -15,6 +15,33 @@
#include "all.h"
static u3j_harm _141_hex_mimes_base16_en_a[] = {{".2", u3we_en_base16}, {}};
static c3_c* _141_hex_mimes_base16_en_ha[] = {
0
};
static u3j_harm _141_hex_mimes_base16_de_a[] = {{".2", u3we_de_base16}, {}};
static c3_c* _141_hex_mimes_base16_de_ha[] = {
0
};
static u3j_core _141_hex_mimes_base16_d[] =
{ { "en", 7, _141_hex_mimes_base16_en_a, 0, _141_hex_mimes_base16_en_ha },
{ "de", 7, _141_hex_mimes_base16_de_a, 0, _141_hex_mimes_base16_de_ha },
{}
};
static c3_c* _141_hex_mimes_base16_ha[] = {
0
};
static u3j_core _141_hex_mimes_d[] =
{ { "base16", 3, 0, _141_hex_mimes_base16_d, _141_hex_mimes_base16_ha },
{}
};
static c3_c* _141_hex_mimes_ha[] = {
0
};
static u3j_harm _141_hex_aes_ecba_en_a[] = {{".2", u3wea_ecba_en}, {}};
static c3_c* _141_hex_aes_ecba_en_ha[] = {
"a4eaaead7ffeb213cf8d611f20d7be4786b34f31a27f41c77538125992107c2d",
@ -397,6 +424,7 @@ static u3j_core _141_hex_d[] =
{ "blake", 31, 0, _141_hex_blake_d, _141_hex_blake_ha },
{ "ripemd", 31, 0, _141_hex_ripe_d, _141_hex_ripe_ha },
{ "secp", 31, 0, _141_hex_secp_d, _141_hex_secp_ha },
{ "mimes", 31, 0, _141_hex_mimes_d, _141_hex_mimes_ha },
{}
};
static c3_c* _141_hex_ha[] = {

View File

@ -1195,6 +1195,39 @@ u3r_mp(mpz_t a_mp,
}
}
/* u3r_short():
**
** Return short (a_w) of (b).
*/
c3_s
u3r_short(c3_w a_w,
u3_atom b)
{
c3_assert( u3_none != b );
c3_assert( c3y == u3a_is_atom(b) );
if ( c3y == u3a_is_cat(b) ) {
switch ( a_w ) {
case 0: return b & 0xffff;
case 1: return b >> 16;
default: return 0;
}
}
else {
u3a_atom* b_u = u3a_to_ptr(b);
c3_w nix_w = a_w >> 1;
if ( nix_w >= b_u->len_w ) {
return 0;
}
else {
c3_w wor_w = b_u->buf_w[nix_w];
return ( a_w & 1 ) ? (wor_w >> 16) : (wor_w & 0xffff);
}
}
}
/* u3r_word():
**
** Return word (a_w) of (b).

279
pkg/urbit/tests/jet_tests.c Normal file
View File

@ -0,0 +1,279 @@
#include "all.h"
/* _setup(): prepare for tests.
*/
static void
_setup(void)
{
u3m_init();
u3m_pave(c3y, c3n);
}
static c3_i
_test_en_base16(void)
{
c3_i ret_i = 1;
{
u3_atom dat = 0xaa;
u3_atom pro = u3qe_en_base16(u3r_met(3, dat), dat);
if ( c3n == u3r_sing_c("aa", pro) ) {
fprintf(stderr, "en_base16: fail (a)\r\n");
ret_i = 0;
}
u3z(pro);
}
{
u3_atom dat = 0x1234;
u3_atom pro = u3qe_en_base16(u3r_met(3, dat), dat);
if ( c3n == u3r_sing_c("1234", pro) ) {
fprintf(stderr, "en_base16: fail (b)\r\n");
ret_i = 0;
}
u3z(pro);
}
{
u3_atom dat = 0xf012;
u3_atom pro = u3qe_en_base16(u3r_met(3, dat), dat);
if ( c3n == u3r_sing_c("f012", pro) ) {
fprintf(stderr, "en_base16: fail (c)\r\n");
ret_i = 0;
}
u3z(pro);
}
{
u3_atom dat = 0x10b;
u3_atom pro = u3qe_en_base16(u3r_met(3, dat), dat);
if ( c3n == u3r_sing_c("010b", pro) ) {
fprintf(stderr, "en_base16: fail (d)\r\n");
ret_i = 0;
}
u3z(pro);
}
{
u3_atom pro = u3qe_en_base16(3, 0x1234);
if ( c3n == u3r_sing_c("001234", pro) ) {
fprintf(stderr, "en_base16: fail (e)\r\n");
ret_i = 0;
}
u3z(pro);
}
{
u3_atom pro = u3qe_en_base16(1, 0x1234);
if ( c3n == u3r_sing_c("34", pro) ) {
fprintf(stderr, "en_base16: fail (f)\r\n");
ret_i = 0;
}
u3z(pro);
}
return ret_i;
}
static c3_i
_test_de_base16(void)
{
c3_i ret_i = 1;
{
u3_noun inp = u3i_string("aa");
u3_noun pro = u3qe_de_base16(inp);
u3_atom len, dat;
if ( c3n == u3r_pq(pro, u3_nul, &len, &dat) ) {
fprintf(stderr, "de_base16: fail cell (a)\r\n");
ret_i = 0;
}
if ( 1 != len ) {
fprintf(stderr, "de_base16: fail len (a)\r\n");
ret_i = 0;
}
if ( 0xaa != dat ) {
fprintf(stderr, "de_base16: fail dat (a)\r\n");
ret_i = 0;
}
u3z(inp); u3z(pro);
}
{
u3_noun inp = u3i_string("1234");
u3_noun pro = u3qe_de_base16(inp);
u3_atom len, dat;
if ( c3n == u3r_pq(pro, u3_nul, &len, &dat) ) {
fprintf(stderr, "de_base16: fail cell (b)\r\n");
ret_i = 0;
}
if ( 2 != len ) {
fprintf(stderr, "de_base16: fail len (b)\r\n");
ret_i = 0;
}
if ( 0x1234 != dat ) {
fprintf(stderr, "de_base16: fail dat (b)\r\n");
ret_i = 0;
}
u3z(inp); u3z(pro);
}
{
u3_noun inp = u3i_string("f012");
u3_noun pro = u3qe_de_base16(inp);
u3_atom len, dat;
if ( c3n == u3r_pq(pro, u3_nul, &len, &dat) ) {
fprintf(stderr, "de_base16: fail cell (c)\r\n");
ret_i = 0;
}
if ( 2 != len ) {
fprintf(stderr, "de_base16: fail len (c)\r\n");
ret_i = 0;
}
if ( 0xf012 != dat ) {
fprintf(stderr, "de_base16: fail dat (c)\r\n");
ret_i = 0;
}
u3z(inp); u3z(pro);
}
{
u3_noun inp = u3i_string("010b");
u3_noun pro = u3qe_de_base16(inp);
u3_atom len, dat;
if ( c3n == u3r_pq(pro, u3_nul, &len, &dat) ) {
fprintf(stderr, "de_base16: fail cell (d)\r\n");
ret_i = 0;
}
if ( 2 != len ) {
fprintf(stderr, "de_base16: fail len (d)\r\n");
ret_i = 0;
}
if ( 0x10b != dat ) {
fprintf(stderr, "de_base16: fail dat (d)\r\n");
ret_i = 0;
}
u3z(inp); u3z(pro);
}
{
u3_noun inp = u3i_string("10b");
u3_noun pro = u3qe_de_base16(inp);
u3_atom len, dat;
if ( c3n == u3r_pq(pro, u3_nul, &len, &dat) ) {
fprintf(stderr, "de_base16: fail cell (e)\r\n");
ret_i = 0;
}
if ( 2 != len ) {
fprintf(stderr, "de_base16: fail len (e)\r\n");
ret_i = 0;
}
if ( 0x10b != dat ) {
fprintf(stderr, "de_base16: fail dat (e)\r\n");
ret_i = 0;
}
u3z(inp); u3z(pro);
}
{
u3_noun inp = u3i_string("001234");
u3_noun pro = u3qe_de_base16(inp);
u3_atom len, dat;
if ( c3n == u3r_pq(pro, u3_nul, &len, &dat) ) {
fprintf(stderr, "de_base16: fail cell (f)\r\n");
ret_i = 0;
}
if ( 3 != len ) {
fprintf(stderr, "de_base16: fail len (f)\r\n");
ret_i = 0;
}
if ( 0x1234 != dat ) {
fprintf(stderr, "de_base16: fail dat (f)\r\n");
ret_i = 0;
}
u3z(inp); u3z(pro);
}
return ret_i;
}
static c3_i
_test_base16(void)
{
c3_i ret_i = 1;
ret_i &= _test_en_base16();
ret_i &= _test_de_base16();
return ret_i;
}
static c3_i
_test_jets(void)
{
c3_i ret_i = 1;
if ( !_test_base16() ) {
fprintf(stderr, "test jets: base16: failed\r\n");
ret_i = 0;
}
return ret_i;
}
/* main(): run all test cases.
*/
int
main(int argc, char* argv[])
{
_setup();
if ( !_test_jets() ) {
fprintf(stderr, "test jets: failed\r\n");
exit(1);
}
// GC
//
u3m_grab(u3_none);
fprintf(stderr, "test jets: ok\r\n");
return 0;
}