1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
/// @file
#include "jets/q.h"
#include "jets/w.h"
#include "noun.h"
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++ = u3s_dit_y[inp_y >> 4];
*buf_y++ = u3s_dit_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));
}
|