mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-04-01 00:36:46 +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:
parent
ec6018928c
commit
583f1ae9c2
3 changed files with 42 additions and 36 deletions
|
@ -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()
|
||||||
{}
|
{}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
|
@ -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.
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue