1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-05-10 09:11:29 +00:00

Pass std::string_view instead of const std::string&

* Starting with Actor::getBodyPartMesh and ending with
  Misc::StringUtils::ciEqual.
* Add tests for Misc::StringUtils::ciEqual.
This commit is contained in:
elsid 2021-09-04 18:07:23 +02:00
parent 149241daae
commit 6b7434ca69
No known key found for this signature in database
GPG key ID: D27B8E8D10A2896B
20 changed files with 170 additions and 42 deletions

View file

@ -145,8 +145,7 @@ namespace CSMWorld
return {}; return {};
} }
const std::string& partName = it->second.first; return it->second.first;
return partName;
} }
bool ActorAdapter::ActorData::hasDependency(const std::string& id) const bool ActorAdapter::ActorData::hasDependency(const std::string& id) const

View file

@ -9,6 +9,7 @@
#include <string> #include <string>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <string_view>
#include <QVariant> #include <QVariant>
@ -153,7 +154,7 @@ namespace CSMWorld
///< Change the state of a record from base to modified, if it is not already. ///< Change the state of a record from base to modified, if it is not already.
/// \return True if the record was changed. /// \return True if the record was changed.
int searchId (const std::string& id) const override; int searchId(std::string_view id) const override;
////< Search record with \a id. ////< Search record with \a id.
/// \return index of record (if found) or -1 (not found) /// \return index of record (if found) or -1 (not found)
@ -476,7 +477,7 @@ namespace CSMWorld
} }
template<typename ESXRecordT, typename IdAccessorT> template<typename ESXRecordT, typename IdAccessorT>
int Collection<ESXRecordT, IdAccessorT>::searchId (const std::string& id) const int Collection<ESXRecordT, IdAccessorT>::searchId(std::string_view id) const
{ {
std::string id2 = Misc::StringUtils::lowerCase(id); std::string id2 = Misc::StringUtils::lowerCase(id);

View file

@ -4,6 +4,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <memory> #include <memory>
#include <string_view>
#include "universalid.hpp" #include "universalid.hpp"
#include "columns.hpp" #include "columns.hpp"
@ -61,7 +62,7 @@ namespace CSMWorld
UniversalId::Type type = UniversalId::Type_None) = 0; UniversalId::Type type = UniversalId::Type_None) = 0;
///< \param type Will be ignored, unless the collection supports multiple record types ///< \param type Will be ignored, unless the collection supports multiple record types
virtual int searchId (const std::string& id) const = 0; virtual int searchId(std::string_view id) const = 0;
////< Search record with \a id. ////< Search record with \a id.
/// \return index of record (if found) or -1 (not found) /// \return index of record (if found) or -1 (not found)

View file

@ -391,7 +391,7 @@ int CSMWorld::Columns::getId (const std::string& name)
std::string name2 = Misc::StringUtils::lowerCase (name); std::string name2 = Misc::StringUtils::lowerCase (name);
for (int i=0; sNames[i].mName; ++i) for (int i=0; sNames[i].mName; ++i)
if (Misc::StringUtils::ciEqual(sNames[i].mName, name2)) if (Misc::StringUtils::ciEqual(std::string_view(sNames[i].mName), name2))
return sNames[i].mId; return sNames[i].mId;
return -1; return -1;

View file

@ -97,7 +97,7 @@ void CSMWorld::InfoCollection::load (const Info& record, bool base)
} }
} }
int CSMWorld::InfoCollection::getInfoIndex (const std::string& id, const std::string& topic) const int CSMWorld::InfoCollection::getInfoIndex(std::string_view id, std::string_view topic) const
{ {
// find the topic first // find the topic first
std::unordered_map<std::string, std::vector<std::pair<std::string, int> > >::const_iterator iter std::unordered_map<std::string, std::vector<std::pair<std::string, int> > >::const_iterator iter
@ -345,12 +345,12 @@ void CSMWorld::InfoCollection::appendBlankRecord (const std::string& id, Univer
insertRecord(std::move(record2), getInsertIndex(id, type, nullptr), type); // call InfoCollection::insertRecord() insertRecord(std::move(record2), getInsertIndex(id, type, nullptr), type); // call InfoCollection::insertRecord()
} }
int CSMWorld::InfoCollection::searchId (const std::string& id) const int CSMWorld::InfoCollection::searchId(std::string_view id) const
{ {
std::string::size_type separator = id.find_last_of('#'); std::string::size_type separator = id.find_last_of('#');
if (separator == std::string::npos) if (separator == std::string::npos)
throw std::runtime_error("invalid info ID: " + id); throw std::runtime_error("invalid info ID: " + std::string(id));
return getInfoIndex(id.substr(separator+1), id.substr(0, separator)); return getInfoIndex(id.substr(separator+1), id.substr(0, separator));
} }

View file

@ -2,6 +2,7 @@
#define CSM_WOLRD_INFOCOLLECTION_H #define CSM_WOLRD_INFOCOLLECTION_H
#include <unordered_map> #include <unordered_map>
#include <string_view>
#include "collection.hpp" #include "collection.hpp"
#include "info.hpp" #include "info.hpp"
@ -43,7 +44,7 @@ namespace CSMWorld
void load (const Info& record, bool base); void load (const Info& record, bool base);
int getInfoIndex (const std::string& id, const std::string& topic) const; int getInfoIndex(std::string_view id, std::string_view topic) const;
///< Return index for record \a id or -1 (if not present; deleted records are considered) ///< Return index for record \a id or -1 (if not present; deleted records are considered)
/// ///
/// \param id info ID without topic prefix /// \param id info ID without topic prefix
@ -79,7 +80,7 @@ namespace CSMWorld
void appendBlankRecord (const std::string& id, void appendBlankRecord (const std::string& id,
UniversalId::Type type = UniversalId::Type_None) override; UniversalId::Type type = UniversalId::Type_None) override;
int searchId (const std::string& id) const override; int searchId(std::string_view id) const override;
void appendRecord (std::unique_ptr<RecordBase> record, void appendRecord (std::unique_ptr<RecordBase> record,
UniversalId::Type type = UniversalId::Type_None) override; UniversalId::Type type = UniversalId::Type_None) override;

View file

@ -7,6 +7,8 @@
#include "universalid.hpp" #include "universalid.hpp"
#include "record.hpp" #include "record.hpp"
#include <string_view>
namespace CSMWorld namespace CSMWorld
{ {
template<> template<>
@ -261,7 +263,7 @@ void CSMWorld::RefCollection::cloneRecord (const std::string& origin,
insertRecord(std::move(copy), getAppendIndex(destination, type)); // call RefCollection::insertRecord() insertRecord(std::move(copy), getAppendIndex(destination, type)); // call RefCollection::insertRecord()
} }
int CSMWorld::RefCollection::searchId (const std::string& id) const int CSMWorld::RefCollection::searchId(std::string_view id) const
{ {
return searchId(extractIdNum(id)); return searchId(extractIdNum(id));
} }

View file

@ -2,6 +2,7 @@
#define CSM_WOLRD_REFCOLLECTION_H #define CSM_WOLRD_REFCOLLECTION_H
#include <map> #include <map>
#include <string_view>
#include "../doc/stage.hpp" #include "../doc/stage.hpp"
@ -56,7 +57,7 @@ namespace CSMWorld
const std::string& destination, const std::string& destination,
const UniversalId::Type type); const UniversalId::Type type);
virtual int searchId (const std::string& id) const; virtual int searchId(std::string_view id) const;
virtual void appendRecord (std::unique_ptr<RecordBase> record, virtual void appendRecord (std::unique_ptr<RecordBase> record,
UniversalId::Type type = UniversalId::Type_None); UniversalId::Type type = UniversalId::Type_None);

View file

@ -2,6 +2,7 @@
#include <stdexcept> #include <stdexcept>
#include <memory> #include <memory>
#include <string_view>
#include <components/esm/esmreader.hpp> #include <components/esm/esmreader.hpp>
@ -787,7 +788,7 @@ void CSMWorld::RefIdCollection::appendBlankRecord (const std::string& id, Univer
mData.appendRecord (type, id, false); mData.appendRecord (type, id, false);
} }
int CSMWorld::RefIdCollection::searchId (const std::string& id) const int CSMWorld::RefIdCollection::searchId(std::string_view id) const
{ {
RefIdData::LocalIndex localIndex = mData.searchId (id); RefIdData::LocalIndex localIndex = mData.searchId (id);

View file

@ -4,6 +4,7 @@
#include <vector> #include <vector>
#include <map> #include <map>
#include <deque> #include <deque>
#include <string_view>
#include "columnbase.hpp" #include "columnbase.hpp"
#include "collectionbase.hpp" #include "collectionbase.hpp"
@ -85,7 +86,7 @@ namespace CSMWorld
void appendBlankRecord (const std::string& id, UniversalId::Type type) override; void appendBlankRecord (const std::string& id, UniversalId::Type type) override;
///< \param type Will be ignored, unless the collection supports multiple record types ///< \param type Will be ignored, unless the collection supports multiple record types
int searchId (const std::string& id) const override; int searchId(std::string_view id) const override;
////< Search record with \a id. ////< Search record with \a id.
/// \return index of record (if found) or -1 (not found) /// \return index of record (if found) or -1 (not found)

View file

@ -2,6 +2,7 @@
#include <cassert> #include <cassert>
#include <memory> #include <memory>
#include <string_view>
CSMWorld::RefIdDataContainerBase::~RefIdDataContainerBase() {} CSMWorld::RefIdDataContainerBase::~RefIdDataContainerBase() {}
@ -74,8 +75,7 @@ int CSMWorld::RefIdData::localToGlobalIndex (const LocalIndex& index)
return globalIndex; return globalIndex;
} }
CSMWorld::RefIdData::LocalIndex CSMWorld::RefIdData::searchId ( CSMWorld::RefIdData::LocalIndex CSMWorld::RefIdData::searchId(std::string_view id) const
const std::string& id) const
{ {
std::string id2 = Misc::StringUtils::lowerCase (id); std::string id2 = Misc::StringUtils::lowerCase (id);

View file

@ -5,6 +5,7 @@
#include <map> #include <map>
#include <memory> #include <memory>
#include <cassert> #include <cassert>
#include <string_view>
#include <components/esm/loadacti.hpp> #include <components/esm/loadacti.hpp>
#include <components/esm/loadalch.hpp> #include <components/esm/loadalch.hpp>
@ -277,7 +278,7 @@ namespace CSMWorld
int localToGlobalIndex (const LocalIndex& index) const; int localToGlobalIndex (const LocalIndex& index) const;
LocalIndex searchId (const std::string& id) const; LocalIndex searchId(std::string_view id) const;
void erase (int index, int count); void erase (int index, int count);

View file

@ -3,6 +3,7 @@
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
#include <algorithm> #include <algorithm>
#include <string_view>
#include <components/vfs/manager.hpp> #include <components/vfs/manager.hpp>
@ -83,7 +84,7 @@ int CSMWorld::Resources::getIndex (const std::string& id) const
return index; return index;
} }
int CSMWorld::Resources::searchId (const std::string& id) const int CSMWorld::Resources::searchId(std::string_view id) const
{ {
std::string id2 = Misc::StringUtils::lowerCase (id); std::string id2 = Misc::StringUtils::lowerCase (id);

View file

@ -4,6 +4,7 @@
#include <string> #include <string>
#include <map> #include <map>
#include <vector> #include <vector>
#include <string_view>
#include "universalid.hpp" #include "universalid.hpp"
@ -35,7 +36,7 @@ namespace CSMWorld
int getIndex (const std::string& id) const; int getIndex (const std::string& id) const;
int searchId (const std::string& id) const; int searchId(std::string_view id) const;
UniversalId::Type getType() const; UniversalId::Type getType() const;
}; };

View file

@ -96,7 +96,7 @@ namespace CSVRender
for (int i = 0; i < ESM::PRT_Count; ++i) for (int i = 0; i < ESM::PRT_Count; ++i)
{ {
auto type = (ESM::PartReferenceType) i; auto type = (ESM::PartReferenceType) i;
const std::string partId(mActorData->getPart(type)); const std::string_view partId = mActorData->getPart(type);
attachBodyPart(type, getBodyPartMesh(partId)); attachBodyPart(type, getBodyPartMesh(partId));
} }
} }
@ -115,7 +115,7 @@ namespace CSVRender
} }
} }
std::string Actor::getBodyPartMesh(const std::string& bodyPartId) std::string Actor::getBodyPartMesh(std::string_view bodyPartId)
{ {
const auto& bodyParts = mData.getBodyParts(); const auto& bodyParts = mData.getBodyParts();

View file

@ -2,6 +2,7 @@
#define OPENCS_VIEW_RENDER_ACTOR_H #define OPENCS_VIEW_RENDER_ACTOR_H
#include <string> #include <string>
#include <string_view>
#include <osg/ref_ptr> #include <osg/ref_ptr>
@ -54,7 +55,7 @@ namespace CSVRender
void loadBodyParts(); void loadBodyParts();
void attachBodyPart(ESM::PartReferenceType, const std::string& mesh); void attachBodyPart(ESM::PartReferenceType, const std::string& mesh);
std::string getBodyPartMesh(const std::string& bodyPartId); std::string getBodyPartMesh(std::string_view bodyPartId);
static const std::string MeshPrefix; static const std::string MeshPrefix;

View file

@ -376,7 +376,9 @@ namespace MWGui
{ {
for (const std::string& keyword : keywords) for (const std::string& keyword : keywords)
{ {
if(Misc::StringUtils::ciEqual(MyGUI::LanguageManager::getInstance().replaceTags("#{" + keyword + "}"), button->getCaption())) if (Misc::StringUtils::ciEqual(
MyGUI::LanguageManager::getInstance().replaceTags("#{" + keyword + "}").asUTF8(),
button->getCaption().asUTF8()))
{ {
return button; return button;
} }

View file

@ -1,6 +1,10 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "components/misc/stringops.hpp" #include "components/misc/stringops.hpp"
#include <string>
#include <string_view>
#include <type_traits>
struct PartialBinarySearchTest : public ::testing::Test struct PartialBinarySearchTest : public ::testing::Test
{ {
protected: protected:
@ -12,10 +16,6 @@ struct PartialBinarySearchTest : public ::testing::Test
std::sort(mDataVec.begin(), mDataVec.end(), Misc::StringUtils::ciLess); std::sort(mDataVec.begin(), mDataVec.end(), Misc::StringUtils::ciLess);
} }
void TearDown() override
{
}
bool matches(const std::string& keyword) bool matches(const std::string& keyword)
{ {
return Misc::StringUtils::partialBinarySearch(mDataVec.begin(), mDataVec.end(), keyword) != mDataVec.end(); return Misc::StringUtils::partialBinarySearch(mDataVec.begin(), mDataVec.end(), keyword) != mDataVec.end();
@ -51,3 +51,97 @@ TEST_F (PartialBinarySearchTest, ci_test)
std::string unicode1 = "\u04151 \u0418"; // CYRILLIC CAPITAL LETTER IE, CYRILLIC CAPITAL LETTER I std::string unicode1 = "\u04151 \u0418"; // CYRILLIC CAPITAL LETTER IE, CYRILLIC CAPITAL LETTER I
EXPECT_TRUE( Misc::StringUtils::lowerCase(unicode1) == unicode1 ); EXPECT_TRUE( Misc::StringUtils::lowerCase(unicode1) == unicode1 );
} }
namespace
{
using ::Misc::StringUtils;
using namespace ::testing;
template <class T>
struct MiscStringUtilsCiEqualEmptyTest : Test {};
TYPED_TEST_SUITE_P(MiscStringUtilsCiEqualEmptyTest);
TYPED_TEST_P(MiscStringUtilsCiEqualEmptyTest, empty_strings_should_be_equal)
{
EXPECT_TRUE(StringUtils::ciEqual(typename TypeParam::first_type {}, typename TypeParam::second_type {}));
}
REGISTER_TYPED_TEST_SUITE_P(MiscStringUtilsCiEqualEmptyTest,
empty_strings_should_be_equal
);
using EmptyStringTypePairsTypes = Types<
std::pair<std::string, std::string>,
std::pair<std::string, std::string_view>,
std::pair<std::string, const char[1]>,
std::pair<std::string_view, std::string>,
std::pair<std::string_view, std::string_view>,
std::pair<std::string_view, const char[1]>,
std::pair<const char[1], std::string>,
std::pair<const char[1], std::string_view>,
std::pair<const char[1], const char[1]>
>;
INSTANTIATE_TYPED_TEST_SUITE_P(EmptyStringTypePairs, MiscStringUtilsCiEqualEmptyTest, EmptyStringTypePairsTypes);
template <class T>
struct MiscStringUtilsCiEqualNotEmptyTest : Test {};
TYPED_TEST_SUITE_P(MiscStringUtilsCiEqualNotEmptyTest);
using RawValue = const char[4];
constexpr RawValue foo = "foo";
constexpr RawValue fooUpper = "FOO";
constexpr RawValue bar = "bar";
template <typename T>
using Value = std::conditional_t<std::is_same_v<T, RawValue>, RawValue&, T>;
TYPED_TEST_P(MiscStringUtilsCiEqualNotEmptyTest, same_strings_should_be_equal)
{
const Value<typename TypeParam::first_type> a {foo};
const Value<typename TypeParam::second_type> b {foo};
EXPECT_TRUE(StringUtils::ciEqual(a, b)) << a << "\n" << b;
}
TYPED_TEST_P(MiscStringUtilsCiEqualNotEmptyTest, same_strings_with_different_case_sensetivity_should_be_equal)
{
const Value<typename TypeParam::first_type> a {foo};
const Value<typename TypeParam::second_type> b {fooUpper};
EXPECT_TRUE(StringUtils::ciEqual(a, b)) << a << "\n" << b;
}
TYPED_TEST_P(MiscStringUtilsCiEqualNotEmptyTest, different_strings_content_should_not_be_equal)
{
const Value<typename TypeParam::first_type> a {foo};
const Value<typename TypeParam::second_type> b {bar};
EXPECT_FALSE(StringUtils::ciEqual(a, b)) << a << "\n" << b;
}
REGISTER_TYPED_TEST_SUITE_P(MiscStringUtilsCiEqualNotEmptyTest,
same_strings_should_be_equal,
same_strings_with_different_case_sensetivity_should_be_equal,
different_strings_content_should_not_be_equal
);
using NotEmptyStringTypePairsTypes = Types<
std::pair<std::string, std::string>,
std::pair<std::string, std::string_view>,
std::pair<std::string, const char[4]>,
std::pair<std::string_view, std::string>,
std::pair<std::string_view, std::string_view>,
std::pair<std::string_view, const char[4]>,
std::pair<const char[4], std::string>,
std::pair<const char[4], std::string_view>,
std::pair<const char[4], const char[4]>
>;
INSTANTIATE_TYPED_TEST_SUITE_P(NotEmptyStringTypePairs, MiscStringUtilsCiEqualNotEmptyTest, NotEmptyStringTypePairsTypes);
TEST(MiscStringUtilsCiEqualTest, string_with_different_length_should_not_be_equal)
{
EXPECT_FALSE(StringUtils::ciEqual(std::string("a"), std::string("aa")));
}
}

View file

@ -4,6 +4,8 @@
#include <cctype> #include <cctype>
#include <string> #include <string>
#include <algorithm> #include <algorithm>
#include <string_view>
#include <iterator>
#include "utf8stream.hpp" #include "utf8stream.hpp"
@ -109,18 +111,34 @@ public:
return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end(), ci()); return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end(), ci());
} }
static bool ciEqual(const std::string &x, const std::string &y) { template <class X, class Y>
if (x.size() != y.size()) { static bool ciEqual(const X& x, const Y& y)
{
if (std::size(x) != std::size(y))
return false; return false;
} return std::equal(std::begin(x), std::end(x), std::begin(y),
std::string::const_iterator xit = x.begin(); [] (char l, char r) { return toLower(l) == toLower(r); });
std::string::const_iterator yit = y.begin(); }
for (; xit != x.end(); ++xit, ++yit) {
if (toLower(*xit) != toLower(*yit)) { template <std::size_t n>
return false; static auto ciEqual(const char(& x)[n], const char(& y)[n])
} {
} static_assert(n > 0);
return true; return ciEqual(std::string_view(x, n - 1), std::string_view(y, n - 1));
}
template <std::size_t n, class T>
static auto ciEqual(const char(& x)[n], const T& y)
{
static_assert(n > 0);
return ciEqual(std::string_view(x, n - 1), y);
}
template <std::size_t n, class T>
static auto ciEqual(const T& x, const char(& y)[n])
{
static_assert(n > 0);
return ciEqual(x, std::string_view(y, n - 1));
} }
static int ciCompareLen(const std::string &x, const std::string &y, size_t len) static int ciCompareLen(const std::string &x, const std::string &y, size_t len)
@ -157,9 +175,9 @@ public:
} }
/// Returns lower case copy of input string /// Returns lower case copy of input string
static std::string lowerCase(const std::string &in) static std::string lowerCase(std::string_view in)
{ {
std::string out = in; std::string out(in);
lowerCaseInPlace(out); lowerCaseInPlace(out);
return out; return out;
} }

View file

@ -9,6 +9,9 @@
#include <components/misc/stringops.hpp> #include <components/misc/stringops.hpp>
#include <cstring>
#include <string_view>
namespace SceneUtil namespace SceneUtil
{ {
@ -24,7 +27,7 @@ namespace SceneUtil
void FindByClassVisitor::apply(osg::Node &node) void FindByClassVisitor::apply(osg::Node &node)
{ {
if (Misc::StringUtils::ciEqual(node.className(), mNameToFind)) if (Misc::StringUtils::ciEqual(std::string_view(node.className()), mNameToFind))
mFoundNodes.push_back(&node); mFoundNodes.push_back(&node);
traverse(node); traverse(node);