#ifndef BASE32_H
#define BASE32_H
static const uint8_t b32rmap[256] = {
0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff,
0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
static const uint8_t b32rmap_special = 0xf0;
nonnull_all
static really_inline int32_t parse_base32(
parser_t *parser,
const type_info_t *type,
const rdata_info_t *field,
rdata_t *rdata,
const token_t *token)
{
uint32_t state = 0;
size_t length = (token->length * 5) / 8;
if (length > 255 || (uintptr_t)rdata->limit - (uintptr_t)rdata->octets < (length + 1))
SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
*rdata->octets++ = (uint8_t)length;
const char *p = token->data;
for (;; p++) {
const uint8_t ofs = b32rmap[(uint8_t)*p];
if (ofs >= b32rmap_special)
break;
switch (state) {
case 0:
*rdata->octets = (uint8_t)(ofs << 3);
state = 1;
break;
case 1:
*rdata->octets++ |= (uint8_t)(ofs >> 2);
*rdata->octets = (uint8_t)(ofs << 6);
state = 2;
break;
case 2:
*rdata->octets |= (uint8_t)(ofs << 1);
state = 3;
break;
case 3:
*rdata->octets++ |= (uint8_t)(ofs >> 4);
*rdata->octets = (uint8_t)(ofs << 4);
state = 4;
break;
case 4:
*rdata->octets++ |= (uint8_t)(ofs >> 1);
*rdata->octets = (uint8_t)(ofs << 7);
state = 5;
break;
case 5:
*rdata->octets |= (uint8_t)(ofs << 2);
state = 6;
break;
case 6:
*rdata->octets++ |= (uint8_t)(ofs >> 3);
*rdata->octets = (uint8_t)(ofs << 5);
state = 7;
break;
case 7:
*rdata->octets++ |= ofs;
state = 0;
break;
}
}
if (p != token->data + token->length)
SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
return 0;
}
#endif