From 5dc612aa54181d8041f8038dd161c46820993eaf Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 3 Aug 2022 10:21:05 +0200 Subject: [PATCH] Replace ciCompareLen with ciStartsWith where possible `ciCompareLen(a, b, b.size()) == 0` expression is an equivalent of checking for equality of `a` prefix with size `b.size()` with `b`. `ciCompareLen(a, b, a.size()) == 0` is also the same thing but `a` is a prefix `b` should start with. --- apps/openmw/mwclass/misc.cpp | 2 +- apps/openmw/mwscript/containerextensions.cpp | 2 +- apps/openmw/mwworld/store.cpp | 5 +-- .../openmw_test_suite/misc/test_stringops.cpp | 31 +++++++++++++++++++ components/misc/strings/algorithm.hpp | 5 +++ components/nifbullet/bulletnifloader.cpp | 2 +- components/sceneutil/attach.cpp | 7 +++-- components/sceneutil/visitor.cpp | 3 +- 8 files changed, 45 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 7144c51242..fdb5f1fe12 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -205,7 +205,7 @@ namespace MWClass { const std::string_view soulgemPrefix = "misc_soulgem"; - if (::Misc::StringUtils::ciCompareLen(ptr.getCellRef().getRefId(), soulgemPrefix, soulgemPrefix.length()) == 0) + if (Misc::StringUtils::ciStartsWith(ptr.getCellRef().getRefId(), soulgemPrefix)) return std::make_unique(ptr); return std::make_unique(); diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 7014d14265..c042727edb 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -309,7 +309,7 @@ namespace MWScript const std::string soulgemPrefix = "misc_soulgem"; - if (::Misc::StringUtils::ciCompareLen(item, soulgemPrefix, soulgemPrefix.length()) == 0) + if (Misc::StringUtils::ciStartsWith(item, soulgemPrefix)) { it = invStore.end(); diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index 2b98eb2921..a84f4d9de5 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -147,10 +147,7 @@ namespace MWWorld { std::vector results; std::copy_if(mShared.begin(), mShared.end(), std::back_inserter(results), - [&id](const T* item) - { - return Misc::StringUtils::ciCompareLen(id, item->mId, id.size()) == 0; - }); + [&id](const T* item) { return Misc::StringUtils::ciStartsWith(item->mId, id); }); if(!results.empty()) return results[Misc::Rng::rollDice(results.size(), prng)]; return nullptr; diff --git a/apps/openmw_test_suite/misc/test_stringops.cpp b/apps/openmw_test_suite/misc/test_stringops.cpp index 539956d8a0..9df5b0114b 100644 --- a/apps/openmw_test_suite/misc/test_stringops.cpp +++ b/apps/openmw_test_suite/misc/test_stringops.cpp @@ -151,4 +151,35 @@ namespace { EXPECT_FALSE(ciEqual(std::string("a"), std::string("aa"))); } + + TEST(MiscStringsCiStartsWith, empty_string_should_start_with_empty_prefix) + { + EXPECT_TRUE(ciStartsWith(std::string_view(), std::string_view())); + } + + TEST(MiscStringsCiStartsWith, string_should_start_with_empty_prefix) + { + EXPECT_TRUE(ciStartsWith("foo", std::string_view())); + } + + TEST(MiscStringsCiStartsWith, string_should_start_with_own_prefix) + { + std::string string = "some string"; + EXPECT_TRUE(ciStartsWith(string, string.substr(0, 4))); + } + + TEST(MiscStringsCiStartsWith, string_should_start_with_the_same_value) + { + EXPECT_TRUE(ciStartsWith("foo", "foo")); + } + + TEST(MiscStringsCiStartsWith, string_should_not_start_with_not_its_prefix) + { + EXPECT_FALSE(ciStartsWith("some string", "foo")); + } + + TEST(MiscStringsCiStartsWith, string_should_not_start_with_longer_string_having_matching_prefix) + { + EXPECT_FALSE(ciStartsWith("foo", "foo bar")); + } } diff --git a/components/misc/strings/algorithm.hpp b/components/misc/strings/algorithm.hpp index 0b6e2ef9bd..3fcaf12709 100644 --- a/components/misc/strings/algorithm.hpp +++ b/components/misc/strings/algorithm.hpp @@ -28,6 +28,11 @@ namespace Misc::StringUtils [] (char l, char r) { return toLower(l) == toLower(r); }); } + inline bool ciStartsWith(std::string_view value, std::string_view prefix) + { + return ciEqual(value.substr(0, prefix.size()), prefix); + } + inline int ciCompareLen(std::string_view x, std::string_view y, std::size_t len) { std::string_view::const_iterator xit = x.begin(); diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index 80f7672c20..bb087a65d8 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -373,7 +373,7 @@ void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node& n // affecting the entire subtree of this node Nif::NiStringExtraData *sd = (Nif::NiStringExtraData*)e.getPtr(); - if (Misc::StringUtils::ciCompareLen(sd->string, "NC", 2) == 0) + if (Misc::StringUtils::ciStartsWith(sd->string, "NC")) { // NCC flag in vanilla is partly case sensitive: prefix NC is case insensitive but second C needs be uppercase if (sd->string.length() > 2 && sd->string[2] == 'C') diff --git a/components/sceneutil/attach.cpp b/components/sceneutil/attach.cpp index ee2b53c62e..0bcb9630d5 100644 --- a/components/sceneutil/attach.cpp +++ b/components/sceneutil/attach.cpp @@ -72,10 +72,11 @@ namespace SceneUtil bool filterMatches(std::string_view name) const { - if (Misc::StringUtils::ciCompareLen(name, mFilter, mFilter.size()) == 0) + if (Misc::StringUtils::ciStartsWith(name, mFilter)) return true; - if (Misc::StringUtils::ciCompareLen(name, "tri ", 4) == 0) - return Misc::StringUtils::ciCompareLen(name.substr(4), mFilter, mFilter.size()) == 0; + constexpr std::string_view prefix = "tri "; + if (Misc::StringUtils::ciStartsWith(name, prefix)) + return Misc::StringUtils::ciStartsWith(name.substr(prefix.size()), mFilter); return false; } diff --git a/components/sceneutil/visitor.cpp b/components/sceneutil/visitor.cpp index 47bb9dbf5d..e3530d2c3b 100644 --- a/components/sceneutil/visitor.cpp +++ b/components/sceneutil/visitor.cpp @@ -144,8 +144,7 @@ namespace SceneUtil void RemoveTriBipVisitor::applyImpl(osg::Node& node) { - const std::string_view toFind = "tri bip"; - if (Misc::StringUtils::ciCompareLen(node.getName(), toFind, toFind.size()) == 0) + if (Misc::StringUtils::ciStartsWith(node.getName(), "tri bip")) { osg::Group* parent = static_cast(*(getNodePath().end()-2)); // Not safe to remove in apply(), since the visitor is still iterating the child list