fix: terrorist behaviour on ES maps with buyzone. (fixes #155).
fix: help commands causing host overflow when translated. crlib: use fnv1a for string hashes. crlib: add hash () method to String & StringRef classes.
This commit is contained in:
parent
e173accc13
commit
8acd84fdc8
6 changed files with 35 additions and 48 deletions
|
|
@ -26,37 +26,19 @@ template <typename T> struct Hash;
|
|||
|
||||
template <> struct Hash <String> {
|
||||
uint32 operator () (const String &key) const noexcept {
|
||||
auto str = const_cast <char *> (key.chars ());
|
||||
uint32 hash = 0;
|
||||
|
||||
while (*str++) {
|
||||
hash = ((hash << 5) + hash) + *str;
|
||||
}
|
||||
return hash;
|
||||
return key.hash ();
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct Hash <StringRef> {
|
||||
uint32 operator () (const StringRef &key) const noexcept {
|
||||
auto str = const_cast <char *> (key.chars ());
|
||||
uint32 hash = 0;
|
||||
|
||||
while (*str++) {
|
||||
hash = ((hash << 5) + hash) + *str;
|
||||
}
|
||||
return hash;
|
||||
return key.hash ();
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct Hash <const char *> {
|
||||
uint32 operator () (const char *key) const noexcept {
|
||||
auto str = const_cast <char *> (key);
|
||||
uint32 hash = 0;
|
||||
|
||||
while (*str++) {
|
||||
hash = ((hash << 5) + hash) + *str;
|
||||
}
|
||||
return hash;
|
||||
return StringRef::fnv1a32 (key);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -59,14 +59,13 @@ CR_EXPOSE_GLOBAL_SINGLETON (SNPrintfWrap, fmtwrap);
|
|||
// simple non-owning string class like std::string_view
|
||||
class StringRef {
|
||||
private:
|
||||
static constexpr size_t strLength (const char *cstr) {
|
||||
size_t length = 0;
|
||||
static constexpr size_t len (const char *str) noexcept {
|
||||
return !*str ? 0 : 1 + len (str + 1);
|
||||
}
|
||||
|
||||
while (*cstr != kNullChar) {
|
||||
length++;
|
||||
cstr++;
|
||||
}
|
||||
return length;
|
||||
public:
|
||||
static constexpr uint32 fnv1a32 (const char *str, uint32 hash = 0x811c9dc5) {
|
||||
return !*str ? hash : fnv1a32 (str + 1, (hash ^ static_cast <uint8> (*str)) * 0x01000193);
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
@ -81,7 +80,7 @@ private:
|
|||
public:
|
||||
constexpr StringRef () noexcept = default;
|
||||
|
||||
constexpr StringRef (const char *chars) : chars_ (chars), length_ (chars ? strLength (chars) : 0)
|
||||
constexpr StringRef (const char *chars) : chars_ (chars), length_ (chars ? len (chars) : 0)
|
||||
{ }
|
||||
|
||||
constexpr StringRef (const char *chars, size_t length) : chars_ (chars), length_ (length)
|
||||
|
|
@ -133,6 +132,10 @@ public:
|
|||
return *this == rhs;
|
||||
}
|
||||
|
||||
constexpr uint32 hash () const {
|
||||
return fnv1a32 (chars ());
|
||||
}
|
||||
|
||||
public:
|
||||
int32 int_ () const {
|
||||
return atoi (chars ());
|
||||
|
|
@ -606,6 +609,10 @@ public:
|
|||
}
|
||||
|
||||
public:
|
||||
uint32 hash () const {
|
||||
return str ().hash ();
|
||||
}
|
||||
|
||||
bool contains (StringRef rhs) const {
|
||||
return str ().contains (rhs);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ private:
|
|||
};
|
||||
|
||||
// hash the lang string, only the letters
|
||||
uint32 hashLangString (const char *input);
|
||||
uint32 hashLangString (StringRef str);
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
|||
|
|
@ -1064,7 +1064,7 @@ void Bot::checkMsgQueue () {
|
|||
|
||||
// prevent terrorists from buying on es maps
|
||||
if (game.mapIs (MapFlags::Escape) && m_team == Team::Terrorist) {
|
||||
m_buyState = 6;
|
||||
m_buyState = BuyState::Done;;
|
||||
}
|
||||
|
||||
// prevent teams from buying on fun maps
|
||||
|
|
|
|||
|
|
@ -764,23 +764,17 @@ const char *BotConfig::translate (StringRef input) {
|
|||
return input.chars (); // nothing found
|
||||
}
|
||||
|
||||
uint32 BotConfig::hashLangString (const char *input) {
|
||||
auto str = reinterpret_cast <uint8 *> (const_cast <char *> (input));
|
||||
uint32_t hash = 0;
|
||||
uint32 BotConfig::hashLangString (StringRef str) {
|
||||
auto test = [] (const char ch) {
|
||||
return (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
|
||||
};
|
||||
String res;
|
||||
|
||||
for (; *str; ++str) {
|
||||
if (!isalnum (*str)) {
|
||||
for (const auto &ch : str) {
|
||||
if (!test (ch)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hash += *str;
|
||||
hash += (hash << 10);
|
||||
hash ^= (hash >> 6);
|
||||
res += ch;
|
||||
}
|
||||
|
||||
hash += (hash << 3);
|
||||
hash ^= (hash >> 11);
|
||||
hash += (hash << 15);
|
||||
|
||||
return hash;
|
||||
return res.empty () ? 0 : res.hash ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -360,7 +360,9 @@ int BotControl::cmdNode () {
|
|||
if (strValue (cmd) == "help" && hasArg (cmd2) && commands.has (strValue (cmd2))) {
|
||||
auto &item = commands[strValue (cmd2)];
|
||||
|
||||
msg ("Command: \"%s %s %s\"\nFormat: %s\nHelp: %s", m_args[root], m_args[alias], item.name, item.format, conf.translate (item.help));
|
||||
msg ("Command: \"%s %s %s\"", m_args[root], m_args[alias], item.name);
|
||||
msg ("Format: %s", item.format);
|
||||
msg ("Help: %s", conf.translate (item.help));
|
||||
}
|
||||
else {
|
||||
for (auto &desc : descriptions) {
|
||||
|
|
@ -1583,7 +1585,9 @@ bool BotControl::executeCommands () {
|
|||
}
|
||||
|
||||
if ((hasSecondArg && aliasMatch (item.name, m_args[2], cmd)) || !hasSecondArg) {
|
||||
msg ("Command: \"%s %s\"\nFormat: %s\nHelp: %s", prefix, cmd, item.format, conf.translate (item.help));
|
||||
msg ("Command: \"%s %s\"", prefix, cmd);
|
||||
msg ("Format: %s", item.format);
|
||||
msg ("Help: %s", conf.translate (item.help));
|
||||
|
||||
auto aliases = item.name.split ("/");
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue