mirror of
https://github.com/thunderbrewhq/squall.git
synced 2026-02-04 00:49:08 +00:00
feat(str): add SStrHash
This commit is contained in:
parent
a2959efef5
commit
0f453bd413
3 changed files with 150 additions and 0 deletions
|
|
@ -50,6 +50,13 @@ int32_t s_initialized;
|
|||
|
||||
double s_realDigit[20][10];
|
||||
|
||||
const uint32_t s_hashtable[16] = {
|
||||
0x486E26EE, 0xDCAA16B3, 0xE1918EEF, 0x202DAFDB,
|
||||
0x341C7DC7, 0x1C365303, 0x40EF2D37, 0x65FD5E49,
|
||||
0xD6057177, 0x904ECE93, 0x1C38024F, 0x98FD323B,
|
||||
0xE3061AE7, 0xA39B0FA1, 0x9797F25F, 0xE4444563,
|
||||
};
|
||||
|
||||
void GetNextTextUpper(uint32_t* orig, const char** string, uint32_t* upper) {
|
||||
uint8_t byte = **string;
|
||||
int32_t v3 = bytesFromUTF8[byte];
|
||||
|
|
@ -349,6 +356,42 @@ char* SStrDupA(const char* string, const char* filename, uint32_t linenumber) {
|
|||
return dup;
|
||||
}
|
||||
|
||||
uint32_t SStrHash(const char* string, uint32_t flags, uint32_t seed) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
uint32_t result = seed ? seed : 0x7FED7FED;
|
||||
uint32_t adjust = 0xEEEEEEEE;
|
||||
uint32_t ch;
|
||||
|
||||
if (flags & SSTR_HASH_CASESENSITIVE) {
|
||||
for (; *string; string++) {
|
||||
ch = *string;
|
||||
|
||||
result = (s_hashtable[ch / 16] - s_hashtable[ch % 16]) ^ (adjust + result);
|
||||
adjust = 33 * adjust + result + ch + 3;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (; *string; string++) {
|
||||
ch = *string;
|
||||
|
||||
if (ch >= 'a' && ch <= 'z') {
|
||||
ch -= 32;
|
||||
}
|
||||
|
||||
if (ch == '/') {
|
||||
ch = '\\';
|
||||
}
|
||||
|
||||
result = (s_hashtable[ch / 16] - s_hashtable[ch % 16]) ^ (adjust + result);
|
||||
adjust = 33 * adjust + result + ch + 3;
|
||||
}
|
||||
}
|
||||
return result ? result : 1;
|
||||
}
|
||||
|
||||
uint32_t SStrHashHT(const char* string) {
|
||||
char normalized[0x400];
|
||||
char* buf = normalized;
|
||||
|
|
|
|||
|
|
@ -5,9 +5,13 @@
|
|||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
#define STORM_MAX_PATH 260
|
||||
#define STORM_MAX_STR 0x7FFFFFFF
|
||||
|
||||
#define SSTR_HASH_CASESENSITIVE 1
|
||||
|
||||
|
||||
char* SStrChr(char* string, char search);
|
||||
|
||||
const char* SStrChr(const char* string, char search);
|
||||
|
|
@ -24,6 +28,8 @@ size_t SStrCopy(char* dest, const char* source, size_t destsize = STORM_MAX_STR)
|
|||
|
||||
char* SStrDupA(const char* string, const char* filename, uint32_t linenumber);
|
||||
|
||||
uint32_t SStrHash(const char* string, uint32_t flags = 0, uint32_t seed = 0);
|
||||
|
||||
uint32_t SStrHashHT(const char* string);
|
||||
|
||||
size_t SStrLen(const char* string);
|
||||
|
|
|
|||
101
test/String.cpp
101
test/String.cpp
|
|
@ -247,6 +247,107 @@ TEST_CASE("SStrDupA", "[string]") {
|
|||
}
|
||||
}
|
||||
|
||||
struct TestHash {
|
||||
const char *str;
|
||||
uint32_t hash;
|
||||
};
|
||||
|
||||
TEST_CASE("SStrHash", "[string]") {
|
||||
SECTION("hashes strings with case insensitivity") {
|
||||
// Results obtained by directly calling Starcraft 1.17's SStrHash
|
||||
auto testcase = GENERATE(
|
||||
TestHash{ "bloop bloop", 0x3EB42E62 },
|
||||
TestHash{ "BLOOP bloop", 0x3EB42E62 },
|
||||
TestHash{ "Objects\\CameraHelper\\CameraHelper.mdx", 0xE99A51F5 },
|
||||
TestHash{ "Objects/CameraHelper/CameraHelper.mdx", 0xE99A51F5 },
|
||||
TestHash{ "abcdefghijklmnopqrstuvwxyz", 0x29564240 },
|
||||
TestHash{ "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0x29564240 },
|
||||
TestHash{ "123456789~!@#$%^&*()_+`-=[]{}|;':\",.<>?", 0x54E31141 },
|
||||
TestHash{ "/", 0x57EC56C7 },
|
||||
TestHash{ "\\", 0x57EC56C7 },
|
||||
TestHash{ "\r\n\t ", 0x89351E43 }
|
||||
);
|
||||
|
||||
auto hash = SStrHash(testcase.str);
|
||||
CHECK(hash == testcase.hash);
|
||||
}
|
||||
|
||||
SECTION("hashes strings with case sensitivity") {
|
||||
// Results obtained by directly calling Starcraft 1.17's SStrHash
|
||||
auto testcase = GENERATE(
|
||||
TestHash{ "bloop bloop", 0x4E7D519E },
|
||||
TestHash{ "BLOOP bloop", 0x307459CC },
|
||||
TestHash{ "Objects\\CameraHelper\\CameraHelper.mdx", 0x5202C0C5 },
|
||||
TestHash{ "Objects/CameraHelper/CameraHelper.mdx", 0x58BD40A9 },
|
||||
TestHash{ "abcdefghijklmnopqrstuvwxyz", 0xEF065306 },
|
||||
TestHash{ "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0x29564240 },
|
||||
TestHash{ "123456789~!@#$%^&*()_+`-=[]{}|;':\",.<>?", 0x54E31141 },
|
||||
TestHash{ "/", 0x93912757 },
|
||||
TestHash{ "\\", 0x57EC56C7 },
|
||||
TestHash{ "\r\n\t ", 0x89351E43 }
|
||||
);
|
||||
|
||||
auto hash = SStrHash(testcase.str, SSTR_HASH_CASESENSITIVE);
|
||||
CHECK(hash == testcase.hash);
|
||||
}
|
||||
|
||||
SECTION("hashes strings with fixed seeds case insensitive") {
|
||||
// Results obtained by directly calling Starcraft 1.17's SStrHash
|
||||
auto testcase = GENERATE(
|
||||
TestHash{ "bloop bloop", 0xDD85B006 },
|
||||
TestHash{ "BLOOP bloop", 0xDD85B006 },
|
||||
TestHash{ "Objects\\CameraHelper\\CameraHelper.mdx", 0x0EA7F863 },
|
||||
TestHash{ "Objects/CameraHelper/CameraHelper.mdx", 0x0EA7F863 },
|
||||
TestHash{ "abcdefghijklmnopqrstuvwxyz", 0x4BAB46BC },
|
||||
TestHash{ "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0x4BAB46BC },
|
||||
TestHash{ "123456789~!@#$%^&*()_+`-=[]{}|;':\",.<>?", 0x2A52D7D3 },
|
||||
TestHash{ "/", 0xD7DED775 },
|
||||
TestHash{ "\\", 0xD7DED775 },
|
||||
TestHash{ "\r\n\t ", 0xC0038449 }
|
||||
);
|
||||
|
||||
auto hash = SStrHash(testcase.str, 0, 123);
|
||||
CHECK(hash == testcase.hash);
|
||||
}
|
||||
|
||||
SECTION("hashes strings with fixed seeds case sensitive") {
|
||||
// Results obtained by directly calling Starcraft 1.17's SStrHash
|
||||
auto testcase = GENERATE(
|
||||
TestHash{ "bloop bloop", 0x96187662 },
|
||||
TestHash{ "BLOOP bloop", 0xC421E888 },
|
||||
TestHash{ "Objects\\CameraHelper\\CameraHelper.mdx", 0x625F6763 },
|
||||
TestHash{ "Objects/CameraHelper/CameraHelper.mdx", 0xC2A7DFE7 },
|
||||
TestHash{ "abcdefghijklmnopqrstuvwxyz", 0x4018029E },
|
||||
TestHash{ "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0x4BAB46BC },
|
||||
TestHash{ "123456789~!@#$%^&*()_+`-=[]{}|;':\",.<>?", 0x2A52D7D3 },
|
||||
TestHash{ "/", 0x13A3A6E5 },
|
||||
TestHash{ "\\", 0xD7DED775 },
|
||||
TestHash{ "\r\n\t ", 0xC0038449 }
|
||||
);
|
||||
|
||||
auto hash = SStrHash(testcase.str, SSTR_HASH_CASESENSITIVE, 123);
|
||||
CHECK(hash == testcase.hash);
|
||||
}
|
||||
|
||||
SECTION("hashing empty string with seed of 0 gives default seed") {
|
||||
auto hash = SStrHash("", 0, 0);
|
||||
CHECK(hash == 0x7FED7FED);
|
||||
|
||||
hash = SStrHash("", SSTR_HASH_CASESENSITIVE, 0);
|
||||
CHECK(hash == 0x7FED7FED);
|
||||
}
|
||||
|
||||
SECTION("hashing empty string with custom seed returns that seed") {
|
||||
auto seed = GENERATE(1, 123, 0x7FED7FED, 0xFFFFFFFF);
|
||||
|
||||
auto hash = SStrHash("", 0, seed);
|
||||
CHECK(hash == seed);
|
||||
|
||||
hash = SStrHash("", SSTR_HASH_CASESENSITIVE, seed);
|
||||
CHECK(hash == seed);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("SStrHashHT", "[string]") {
|
||||
SECTION("hashes simple string correctly") {
|
||||
auto hash = SStrHashHT("foo");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue