Commit 6e2e909b authored by Christian Helmich's avatar Christian Helmich Committed by Wouter van Oortmerssen

template specialized Hash functions for 16-bit hash types (#4631)

added access to HashFunction for 16 bit
parent b24c0b07
......@@ -57,13 +57,28 @@ template<typename T> T HashFnv1a(const char *input) {
return hash;
}
template<typename T> struct NamedHashFunction {
template <> inline uint16_t HashFnv1<uint16_t>(const char *input) {
uint32_t hash = HashFnv1<uint32_t>(input);
return (hash >> 16) ^ (hash & 0xffff);
}
template <> inline uint16_t HashFnv1a<uint16_t>(const char *input) {
uint32_t hash = HashFnv1a<uint32_t>(input);
return (hash >> 16) ^ (hash & 0xffff);
}
template <typename T> struct NamedHashFunction {
const char *name;
typedef T (*HashFunction)(const char *);
HashFunction function;
};
const NamedHashFunction<uint16_t> kHashFunctions16[] = {
{ "fnv1_16", HashFnv1<uint16_t> },
{ "fnv1a_16", HashFnv1a<uint16_t> },
};
const NamedHashFunction<uint32_t> kHashFunctions32[] = {
{ "fnv1_32", HashFnv1<uint32_t> },
{ "fnv1a_32", HashFnv1a<uint32_t> },
......@@ -74,6 +89,17 @@ const NamedHashFunction<uint64_t> kHashFunctions64[] = {
{ "fnv1a_64", HashFnv1a<uint64_t> },
};
inline NamedHashFunction<uint16_t>::HashFunction FindHashFunction16(
const char *name) {
std::size_t size = sizeof(kHashFunctions16) / sizeof(kHashFunctions16[0]);
for (std::size_t i = 0; i < size; ++i) {
if (std::strcmp(name, kHashFunctions16[i].name) == 0) {
return kHashFunctions16[i].function;
}
}
return nullptr;
}
inline NamedHashFunction<uint32_t>::HashFunction FindHashFunction32(
const char *name) {
std::size_t size = sizeof(kHashFunctions32) / sizeof(kHashFunctions32[0]);
......
......@@ -26,8 +26,15 @@ int main(int argc, char *argv[]) {
const char *name = argv[0];
if (argc <= 1) {
printf("%s HASH [OPTION]... STRING... [-- STRING...]\n", name);
printf("Available hashing algorithms:\n 32 bit:\n");
size_t size = sizeof(flatbuffers::kHashFunctions32) /
printf("Available hashing algorithms:\n");
printf(" 16 bit:\n");
size_t size = sizeof(flatbuffers::kHashFunctions16) /
sizeof(flatbuffers::kHashFunctions16[0]);
for (size_t i = 0; i < size; ++i) {
printf(" * %s\n", flatbuffers::kHashFunctions16[i].name);
}
printf(" 32 bit:\n");
size = sizeof(flatbuffers::kHashFunctions32) /
sizeof(flatbuffers::kHashFunctions32[0]);
for (size_t i = 0; i < size; ++i) {
printf(" * %s\n", flatbuffers::kHashFunctions32[i].name);
......@@ -48,12 +55,14 @@ int main(int argc, char *argv[]) {
const char *hash_algorithm = argv[1];
flatbuffers::NamedHashFunction<uint16_t>::HashFunction hash_function16 =
flatbuffers::FindHashFunction16(hash_algorithm);
flatbuffers::NamedHashFunction<uint32_t>::HashFunction hash_function32 =
flatbuffers::FindHashFunction32(hash_algorithm);
flatbuffers::NamedHashFunction<uint64_t>::HashFunction hash_function64 =
flatbuffers::FindHashFunction64(hash_algorithm);
if (!hash_function32 && !hash_function64) {
if (!hash_function16 && !hash_function32 && !hash_function64) {
printf("\"%s\" is not a known hash algorithm.\n", hash_algorithm);
return 0;
}
......@@ -87,7 +96,9 @@ int main(int argc, char *argv[]) {
ss << std::hex;
ss << "0x";
}
if (hash_function32)
if (hash_function16)
ss << hash_function16(arg);
else if (hash_function32)
ss << hash_function32(arg);
else if (hash_function64)
ss << hash_function64(arg);
......
......@@ -681,6 +681,13 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
auto hash_name = field->attributes.Lookup("hash");
if (hash_name) {
switch ((type.base_type == BASE_TYPE_VECTOR) ? type.element : type.base_type) {
case BASE_TYPE_SHORT:
case BASE_TYPE_USHORT: {
if (FindHashFunction16(hash_name->constant.c_str()) == nullptr)
return Error("Unknown hashing algorithm for 16 bit types: " +
hash_name->constant);
break;
}
case BASE_TYPE_INT:
case BASE_TYPE_UINT: {
if (FindHashFunction32(hash_name->constant.c_str()) == nullptr)
......@@ -697,7 +704,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
}
default:
return Error(
"only int, uint, long and ulong data types support hashing.");
"only short, ushort, int, uint, long and ulong data types support hashing.");
}
}
auto cpp_type = field->attributes.Lookup("cpp_type");
......@@ -1278,6 +1285,18 @@ CheckedError Parser::ParseHash(Value &e, FieldDef *field) {
assert(field);
Value *hash_name = field->attributes.Lookup("hash");
switch (e.type.base_type) {
case BASE_TYPE_SHORT: {
auto hash = FindHashFunction16(hash_name->constant.c_str());
int16_t hashed_value = static_cast<int16_t>(hash(attribute_.c_str()));
e.constant = NumToString(hashed_value);
break;
}
case BASE_TYPE_USHORT: {
auto hash = FindHashFunction16(hash_name->constant.c_str());
uint16_t hashed_value = hash(attribute_.c_str());
e.constant = NumToString(hashed_value);
break;
}
case BASE_TYPE_INT: {
auto hash = FindHashFunction32(hash_name->constant.c_str());
int32_t hashed_value = static_cast<int32_t>(hash(attribute_.c_str()));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment