mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-02 04:04:19 +00:00
template specialized Hash functions for 16-bit hash types (#4631)
added access to HashFunction for 16 bit
This commit is contained in:
committed by
Wouter van Oortmerssen
parent
b24c0b07a3
commit
6e2e909b5c
@@ -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()));
|
||||
|
||||
Reference in New Issue
Block a user