#ifndef TYPE_H
#define TYPE_H
#define V(code) { &(types[0].name), 0 }
#define T(code) { &(types[code].name), 1 }
#define C(code) { &(classes[code].name), 2 }
static const struct {
const mnemonic_t *mnemonic;
int32_t code;
} types_and_classes[256] = {
V(0), V(0), V(0), V(0), V(0), V(0), T(34), V(0),
V(0), V(0), T(30), V(0), V(0), T(57), V(0), T(16),
V(0), V(0), T(56), T(14), T(12), V(0), V(0), T(13),
T(61), V(0), T(105), V(0), V(0), V(0), T(32), T(258),
V(0), T(107), T(47), V(0), V(0), V(0), T(17), V(0),
T(257), V(0), V(0), V(0), V(0), V(0), V(0), V(0),
T(65), V(0), V(0), T(18), V(0), T(1), V(0), T(263),
V(0), V(0), V(0), V(0), T(51), V(0), V(0), T(106),
T(3), V(0), V(0), T(31), V(0), V(0), V(0), V(0),
V(0), T(50), T(44), T(104), T(10), V(0), V(0), V(0),
V(0), V(0), T(55), V(0), T(28), V(0), V(0), V(0),
V(0), V(0), V(0), V(0), V(0), V(0), V(0), T(39),
T(35), V(0), V(0), T(5), T(29), T(262), V(0), V(0),
T(109), V(0), T(264), V(0), V(0), V(0), V(0), V(0),
V(0), T(21), V(0), V(0), V(0), V(0), V(0), V(0),
T(37), C(1), T(58), V(0), V(0), V(0), V(0), V(0),
V(0), V(0), V(0), C(3), V(0), T(52), T(11), T(20),
V(0), T(261), V(0), V(0), V(0), T(48), V(0), V(0),
V(0), T(25), C(2), T(43), V(0), V(0), C(4), T(60),
V(0), V(0), T(7), T(2), V(0), V(0), T(46), T(22),
V(0), V(0), V(0), V(0), V(0), V(0), V(0), T(64),
V(0), T(260), V(0), V(0), V(0), V(0), T(38), V(0),
V(0), T(259), T(59), V(0), V(0), V(0), T(42), T(36),
T(8), T(15), V(0), T(26), T(27), T(6), V(0), T(99),
V(0), V(0), V(0), V(0), V(0), V(0), V(0), T(53),
T(9), T(63), T(33), V(0), T(271), T(270), V(0), T(40),
V(0), V(0), T(24), T(19), V(0), V(0), V(0), V(0),
V(0), V(0), V(0), T(108), V(0), V(0), V(0), T(62),
V(0), V(0), V(0), V(0), V(0), T(66), T(4), V(0),
V(0), V(0), T(256), V(0), T(49), V(0), V(0), V(0),
V(0), V(0), T(45), V(0), V(0), T(23), V(0), V(0),
V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0)
};
#undef V
#undef T
#undef C
nonnull_all
static really_inline int32_t scan_generic_type(
const char *data, size_t length, uint16_t *code, const mnemonic_t **mnemonic)
{
if (scan_int16(data + 4, length - 4, code) == 0)
return -1;
if (*code <= 258)
*mnemonic = &types[*code].name;
else if (*code == 32769)
*mnemonic = &types[259].name;
else
*mnemonic = &types[0].name;
return 1;
}
nonnull_all
static really_inline int32_t scan_generic_class(
const char *data, size_t length, uint16_t *code, const mnemonic_t **mnemonic)
{
if (scan_int16(data + 5, length - 5, code) == 0)
return -1;
if (*code <= 4)
*mnemonic = &classes[*code].name;
else
*mnemonic = &classes[0].name;
return 2;
}
#if BYTE_ORDER == LITTLE_ENDIAN
# define TYPE (0x45505954llu)
# define TYPE_MASK (0xffffffffllu)
# define CLASS (0x5353414c43llu)
# define CLASS_MASK (0xffffffffffllu)
#else
# define TYPE (0x5459504500000000llu)
# define TYPE_MASK (0xffffffff00000000llu)
# define CLASS (0x434c415353000000llu)
# define CLASS_MASK (0xffffffffff000000llu)
#endif
static const int8_t zero_masks[48] = {
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
static really_inline uint8_t hash(uint64_t prefix)
{
prefix = le64toh(prefix);
uint32_t value = (uint32_t)((prefix >> 32) ^ prefix);
return (uint8_t)((value * 3537259401ull) >> 32);
}
nonnull_all
static really_inline int32_t scan_type_or_class(
const char *data, size_t length, uint16_t *code, const mnemonic_t **mnemonic)
{
uint64_t input0, input1;
static const uint64_t letter_mask = 0x4040404040404040llu;
memcpy(&input0, data, 8);
memcpy(&input1, data + 8, 8);
input0 = input0 & ~((input0 & letter_mask) >> 1);
input1 = input1 & ~((input1 & letter_mask) >> 1);
length &= 0x1f;
const uint8_t *zero_mask = (const uint8_t *)&zero_masks[32 - (length & 0x1f)];
uint64_t zero_mask0, zero_mask1;
memcpy(&zero_mask0, zero_mask, 8);
memcpy(&zero_mask1, zero_mask + 8, 8);
input0 &= zero_mask0;
input1 &= zero_mask1;
const uint8_t index = hash(input0);
*code = (uint16_t)types_and_classes[index].mnemonic->value;
*mnemonic = types_and_classes[index].mnemonic;
uint64_t name0, name1;
memcpy(&name0, (*mnemonic)->key.data, 8);
memcpy(&name1, (*mnemonic)->key.data + 8, 8);
if (likely(((input0 ^ name0) | (input1 ^ name1)) == 0) && *code)
return types_and_classes[index].code;
else if ((input0 & TYPE_MASK) == TYPE)
return scan_generic_type(data, length, code, mnemonic);
else if ((input0 & CLASS_MASK) == CLASS)
return scan_generic_class(data, length, code, mnemonic);
return 0;
}
nonnull_all
static really_inline int32_t scan_type(
const char *data, size_t length, uint16_t *code, const mnemonic_t **mnemonic)
{
uint64_t input0, input1;
static const uint64_t letter_mask = 0x4040404040404040llu;
memcpy(&input0, data, 8);
memcpy(&input1, data + 8, 8);
input0 = input0 & ~((input0 & letter_mask) >> 1);
input1 = input1 & ~((input1 & letter_mask) >> 1);
length &= 0x1f;
const uint8_t *zero_mask = (const uint8_t *)&zero_masks[32 - (length & 0x1f)];
uint64_t zero_mask0, zero_mask1;
memcpy(&zero_mask0, zero_mask, 8);
memcpy(&zero_mask1, zero_mask + 8, 8);
input0 &= zero_mask0;
input1 &= zero_mask1;
const uint8_t index = hash(input0);
*code = (uint16_t)types_and_classes[index].mnemonic->value;
*mnemonic = types_and_classes[index].mnemonic;
uint64_t name0, name1;
memcpy(&name0, (*mnemonic)->key.data, 8);
memcpy(&name1, (*mnemonic)->key.data + 8, 8);
if (likely(((input0 ^ name0) | (input1 ^ name1)) == 0) && *code)
return types_and_classes[index].code;
else if ((input0 & TYPE_MASK) == TYPE)
return scan_generic_type(data, length, code, mnemonic);
return 0;
}
#undef TYPE
#undef TYPE_MASK
#undef CLASS
#undef CLASS_MASK
#endif