1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-03-31 04:36:40 +00:00

fixed info record ordering and performance problems by determining topic ranges in the record collection instead of in the index collection

This commit is contained in:
Marc Zinnschlag 2013-11-10 13:00:46 +01:00
parent ec6018928c
commit 583f1ae9c2
3 changed files with 42 additions and 36 deletions

View file

@ -55,6 +55,8 @@ namespace CSMWorld
const std::map<std::string, int>& getIdMap() const;
const std::vector<Record<ESXRecordT> >& getRecords() const;
public:
Collection();
@ -138,6 +140,12 @@ namespace CSMWorld
return mIndex;
}
template<typename ESXRecordT, typename IdAccessorT>
const std::vector<Record<ESXRecordT> >& Collection<ESXRecordT, IdAccessorT>::getRecords() const
{
return mRecords;
}
template<typename ESXRecordT, typename IdAccessorT>
Collection<ESXRecordT, IdAccessorT>::Collection()
{}

View file

@ -39,20 +39,9 @@ void CSMWorld::InfoCollection::load (const Info& record, bool base)
if (index==-1)
{
std::pair<MapConstIterator, MapConstIterator> range = getTopicRange (topic);
Range range = getTopicRange (topic);
if (range.first==range.second)
index = getIdMap().size();
else
{
for (; range.first!=range.second; ++range.first)
{
if (range.first->second>index)
index = range.first->second;
}
++index;
}
index = std::distance (getRecords().begin(), range.second);
}
insertRecord (record2, index);
@ -75,11 +64,11 @@ int CSMWorld::InfoCollection::getIndex (const std::string& id, const std::string
{
std::string fullId = Misc::StringUtils::lowerCase (topic) + "#" + id;
std::pair<MapConstIterator, MapConstIterator> range = getTopicRange (topic);
std::pair<RecordConstIterator, RecordConstIterator> range = getTopicRange (topic);
for (; range.first!=range.second; ++range.first)
if (range.first->first==fullId)
return std::distance (getIdMap().begin(), range.first);
if (Misc::StringUtils::lowerCase (range.first->get().mId)==fullId)
return std::distance (getRecords().begin(), range.first);
return -1;
}
@ -91,18 +80,12 @@ int CSMWorld::InfoCollection::getAppendIndex (const std::string& id, UniversalId
if (separator==std::string::npos)
throw std::runtime_error ("invalid info ID: " + id);
std::pair<MapConstIterator, MapConstIterator> range = getTopicRange (id.substr (0, separator));
std::pair<RecordConstIterator, RecordConstIterator> range = getTopicRange (id.substr (0, separator));
if (range.first==range.second)
return Collection<Info, IdAccessor<Info> >::getAppendIndex (id, type);
int index = 0;
for (; range.first!=range.second; ++range.first)
if (range.first->second>index)
index = range.first->second;
return index+1;
return std::distance (getRecords().begin(), range.second);
}
void CSMWorld::InfoCollection::load (ESM::ESMReader& reader, bool base, const ESM::Dialogue& dialogue)
@ -146,25 +129,40 @@ void CSMWorld::InfoCollection::load (ESM::ESMReader& reader, bool base, const ES
}
}
std::pair<CSMWorld::InfoCollection::MapConstIterator, CSMWorld::InfoCollection::MapConstIterator>
CSMWorld::InfoCollection::getTopicRange (const std::string& topic) const
CSMWorld::InfoCollection::Range CSMWorld::InfoCollection::getTopicRange (const std::string& topic)
const
{
std::string topic2 = Misc::StringUtils::lowerCase (topic);
MapConstIterator begin = getIdMap().lower_bound (topic2);
std::map<std::string, int>::const_iterator iter = getIdMap().lower_bound (topic2);
// Skip invalid records: The beginning of a topic string could be identical to another topic
// string.
for (; begin!=getIdMap().end(); ++begin)
if (Misc::StringUtils::lowerCase (getRecord (begin->second).get().mTopicId)==topic2)
for (; iter!=getIdMap().end(); ++iter)
{
std::string testTopicId =
Misc::StringUtils::lowerCase (getRecord (iter->second).get().mTopicId);
if (testTopicId==topic2)
break;
std::size_t size = topic2.size();
if (testTopicId.size()<size || testTopicId.substr (0, size)!=topic2)
return Range (getRecords().end(), getRecords().end());
}
if (iter==getIdMap().end())
return Range (getRecords().end(), getRecords().end());
RecordConstIterator begin = getRecords().begin()+iter->second;
// Find end
MapConstIterator end = begin;
RecordConstIterator end = begin;
for (; end!=getIdMap().end(); ++end)
if (Misc::StringUtils::lowerCase (getRecord (end->second).get().mTopicId)!=topic2)
for (; end!=getRecords().end(); ++end)
if (Misc::StringUtils::lowerCase (end->get().mTopicId)!=topic2)
break;
return std::make_pair (begin, end);
return Range (begin, end);
}

View file

@ -15,7 +15,8 @@ namespace CSMWorld
{
public:
typedef std::map<std::string, int>::const_iterator MapConstIterator;
typedef std::vector<Record<Info> >::const_iterator RecordConstIterator;
typedef std::pair<RecordConstIterator, RecordConstIterator> Range;
private:
@ -34,8 +35,7 @@ namespace CSMWorld
void load (ESM::ESMReader& reader, bool base, const ESM::Dialogue& dialogue);
std::pair<MapConstIterator, MapConstIterator> getTopicRange (const std::string& topic)
const;
Range getTopicRange (const std::string& topic) const;
///< Return iterators that point to the beginning and past the end of the range for
/// the given topic.
};