1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-03-29 15:36:41 +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::map<std::string, int>& getIdMap() const;
const std::vector<Record<ESXRecordT> >& getRecords() const;
public: public:
Collection(); Collection();
@ -138,6 +140,12 @@ namespace CSMWorld
return mIndex; return mIndex;
} }
template<typename ESXRecordT, typename IdAccessorT>
const std::vector<Record<ESXRecordT> >& Collection<ESXRecordT, IdAccessorT>::getRecords() const
{
return mRecords;
}
template<typename ESXRecordT, typename IdAccessorT> template<typename ESXRecordT, typename IdAccessorT>
Collection<ESXRecordT, IdAccessorT>::Collection() Collection<ESXRecordT, IdAccessorT>::Collection()
{} {}

View file

@ -39,20 +39,9 @@ void CSMWorld::InfoCollection::load (const Info& record, bool base)
if (index==-1) if (index==-1)
{ {
std::pair<MapConstIterator, MapConstIterator> range = getTopicRange (topic); Range range = getTopicRange (topic);
if (range.first==range.second) index = std::distance (getRecords().begin(), range.second);
index = getIdMap().size();
else
{
for (; range.first!=range.second; ++range.first)
{
if (range.first->second>index)
index = range.first->second;
}
++index;
}
} }
insertRecord (record2, index); 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::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) for (; range.first!=range.second; ++range.first)
if (range.first->first==fullId) if (Misc::StringUtils::lowerCase (range.first->get().mId)==fullId)
return std::distance (getIdMap().begin(), range.first); return std::distance (getRecords().begin(), range.first);
return -1; return -1;
} }
@ -91,18 +80,12 @@ int CSMWorld::InfoCollection::getAppendIndex (const std::string& id, UniversalId
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: " + 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) if (range.first==range.second)
return Collection<Info, IdAccessor<Info> >::getAppendIndex (id, type); return Collection<Info, IdAccessor<Info> >::getAppendIndex (id, type);
int index = 0; return std::distance (getRecords().begin(), range.second);
for (; range.first!=range.second; ++range.first)
if (range.first->second>index)
index = range.first->second;
return index+1;
} }
void CSMWorld::InfoCollection::load (ESM::ESMReader& reader, bool base, const ESM::Dialogue& dialogue) 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::Range CSMWorld::InfoCollection::getTopicRange (const std::string& topic)
CSMWorld::InfoCollection::getTopicRange (const std::string& topic) const const
{ {
std::string topic2 = Misc::StringUtils::lowerCase (topic); 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 // Skip invalid records: The beginning of a topic string could be identical to another topic
// string. // string.
for (; begin!=getIdMap().end(); ++begin) for (; iter!=getIdMap().end(); ++iter)
if (Misc::StringUtils::lowerCase (getRecord (begin->second).get().mTopicId)==topic2) {
std::string testTopicId =
Misc::StringUtils::lowerCase (getRecord (iter->second).get().mTopicId);
if (testTopicId==topic2)
break; 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 // Find end
MapConstIterator end = begin; RecordConstIterator end = begin;
for (; end!=getIdMap().end(); ++end) for (; end!=getRecords().end(); ++end)
if (Misc::StringUtils::lowerCase (getRecord (end->second).get().mTopicId)!=topic2) if (Misc::StringUtils::lowerCase (end->get().mTopicId)!=topic2)
break; break;
return std::make_pair (begin, end); return Range (begin, end);
} }

View file

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