diff --git a/src/common/utils.cpp b/src/common/utils.cpp index 007b4e60f13..cc380a9e8b6 100644 --- a/src/common/utils.cpp +++ b/src/common/utils.cpp @@ -926,14 +926,32 @@ std::unique_ptr utils::openFile(std::string const& path, std::string const return std::unique_ptr(fopen(path.c_str(), mode.c_str())); } +auto utils::isPrintableASCII(unsigned char ch, ASCIIMode mode) -> bool +{ + if (mode == ASCIIMode::IncludeSpace) + { + return ch >= 0x20 && ch < 0x7F; + } + else // ASCIIMode::ExcludeSpace + { + return ch > 0x20 && ch < 0x7F; + } +} + +auto utils::isStringPrintable(const std::string& str, ASCIIMode mode) -> bool +{ + // clang-format off + return std::all_of(str.begin(), str.end(), [mode](unsigned char ch) { return isPrintableASCII(ch, mode); }); + // clang-format on +} + std::string utils::toASCII(std::string const& target, unsigned char replacement) { std::string out; out.reserve(target.size()); for (unsigned char ch : target) { - bool isLetter = ch >= 0x20 && ch < 0x7F; - out += isLetter ? ch : replacement; + out += isPrintableASCII(ch, ASCIIMode::IncludeSpace) ? ch : replacement; } return out; } diff --git a/src/common/utils.h b/src/common/utils.h index b98a5b525f1..799e0dcc7ec 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -139,6 +139,15 @@ std::set sorted_directory_iterator(std::string path_name) namespace utils { auto openFile(std::string const& path, std::string const& mode) -> std::unique_ptr; + + enum class ASCIIMode + { + IncludeSpace, + ExcludeSpace, + }; + + auto isPrintableASCII(unsigned char ch, ASCIIMode mode) -> bool; + auto isStringPrintable(const std::string& str, ASCIIMode mode) -> bool; auto toASCII(std::string const& target, unsigned char replacement = '\0') -> std::string; } // namespace utils diff --git a/src/map/lua/luautils.cpp b/src/map/lua/luautils.cpp index 300c28f5c69..d7c2d87dbbb 100644 --- a/src/map/lua/luautils.cpp +++ b/src/map/lua/luautils.cpp @@ -831,28 +831,14 @@ namespace luautils std::string filename; if (PEntity->objtype == TYPE_NPC) { - // clang-format off - auto isNamePrintable = [](const std::string& name) - { - // Match non-printable ASCII - for (const char& c : name) - { - if ((c >= 0 && c <= 0x20) || c >= 0x7F) - { - return false; - } - } - return true; - }; - // clang-format on - // Don't bother even trying to load the script if the NPC name is non printable, // and therefore impossible for a filesystem to load. // TODO: Change name to "0x%X" instead so non-printables could get a script? - if (!isNamePrintable(PEntity->getName())) + if (!utils::isPrintableString(PEntity->getName(), ASCIIMode::ExcludeSpace)) { return; } + std::string zone_name = PEntity->loc.zone->getName(); std::string npc_name = PEntity->getName(); filename = fmt::format("./scripts/zones/{}/npcs/{}.lua", zone_name, npc_name);