1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-01 02:45:38 +00:00

Rework RefIdData code. Update the index map when a new record is loaded

(cherry picked from commit 5e623a2a1d)
This commit is contained in:
Stanislav Bas 2015-07-14 16:18:33 +03:00 committed by cc9cii
parent 82e1b0563c
commit 0979d88b0c
2 changed files with 55 additions and 48 deletions

View file

@ -3,10 +3,20 @@
#include <cassert> #include <cassert>
#include <memory> #include <memory>
#include <components/misc/stringops.hpp>
CSMWorld::RefIdDataContainerBase::~RefIdDataContainerBase() {} CSMWorld::RefIdDataContainerBase::~RefIdDataContainerBase() {}
std::string CSMWorld::RefIdData::getRecordId(const CSMWorld::RefIdData::LocalIndex &index) const
{
std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator found =
mRecordContainers.find (index.second);
if (found == mRecordContainers.end())
throw std::logic_error ("invalid local index type");
return found->second->getId(index.first);
}
CSMWorld::RefIdData::RefIdData() CSMWorld::RefIdData::RefIdData()
{ {
mRecordContainers.insert (std::make_pair (UniversalId::Type_Activator, &mActivators)); mRecordContainers.insert (std::make_pair (UniversalId::Type_Activator, &mActivators));
@ -167,9 +177,21 @@ void CSMWorld::RefIdData::load (ESM::ESMReader& reader, bool base, CSMWorld::Uni
mRecordContainers.find (type); mRecordContainers.find (type);
if (found == mRecordContainers.end()) if (found == mRecordContainers.end())
throw std::logic_error ("Invalid type for an Object (Reference ID)"); throw std::logic_error ("Invalid Referenceable ID type");
found->second->load(reader, base); int index = found->second->load(reader, base);
if (index != -1)
{
LocalIndex localIndex = LocalIndex(index, type);
if (base && getRecord(localIndex).mState == RecordBase::State_Deleted)
{
erase(localIndex, 1);
}
else
{
mIndex[Misc::StringUtils::lowerCase(getRecordId(localIndex))] = localIndex;
}
}
} }
void CSMWorld::RefIdData::erase (const LocalIndex& index, int count) void CSMWorld::RefIdData::erase (const LocalIndex& index, int count)

View file

@ -25,6 +25,8 @@
#include <components/esm/loadmisc.hpp> #include <components/esm/loadmisc.hpp>
#include <components/esm/esmwriter.hpp> #include <components/esm/esmwriter.hpp>
#include <components/misc/stringops.hpp>
#include "record.hpp" #include "record.hpp"
#include "universalid.hpp" #include "universalid.hpp"
@ -49,7 +51,8 @@ namespace CSMWorld
virtual void insertRecord (RecordBase& record) = 0; virtual void insertRecord (RecordBase& record) = 0;
virtual void load (ESM::ESMReader& reader, bool base) = 0; virtual int load (ESM::ESMReader& reader, bool base) = 0;
///< \return index of a loaded record or -1 if no record was loaded
virtual void erase (int index, int count) = 0; virtual void erase (int index, int count) = 0;
@ -73,7 +76,8 @@ namespace CSMWorld
virtual void insertRecord (RecordBase& record); virtual void insertRecord (RecordBase& record);
virtual void load (ESM::ESMReader& reader, bool base); virtual int load (ESM::ESMReader& reader, bool base);
///< \return index of a loaded record or -1 if no record was loaded
virtual void erase (int index, int count); virtual void erase (int index, int count);
@ -122,15 +126,16 @@ namespace CSMWorld
} }
template<typename RecordT> template<typename RecordT>
void RefIdDataContainer<RecordT>::load (ESM::ESMReader& reader, bool base) int RefIdDataContainer<RecordT>::load (ESM::ESMReader& reader, bool base)
{ {
RecordT record; RecordT record;
record.load(reader); record.load(reader);
typename std::vector<Record<RecordT> >::iterator found = mContainer.begin(); int index = 0;
for (; found != mContainer.end(); ++found) int numRecords = static_cast<int>(mContainer.size());
for (; index < numRecords; ++index)
{ {
if (found->get().mId == record.mId) if (Misc::StringUtils::ciEqual(mContainer[index].get().mId, record.mId))
{ {
break; break;
} }
@ -138,26 +143,21 @@ namespace CSMWorld
if (record.mIsDeleted) if (record.mIsDeleted)
{ {
if (found == mContainer.end()) if (index == numRecords)
{ {
// deleting a record that does not exist // deleting a record that does not exist
// ignore it for now // ignore it for now
/// \todo report the problem to the user /// \todo report the problem to the user
return; return -1;
} }
if (base) // Flag the record as Deleted even for a base content file.
{ // RefIdData is responsible for its erasure.
mContainer.erase(found); mContainer[index].mState = RecordBase::State_Deleted;
}
else
{
found->mState = RecordBase::State_Deleted;
}
} }
else else
{ {
if (found == mContainer.end()) if (index == numRecords)
{ {
appendRecord(record.mId, base); appendRecord(record.mId, base);
if (base) if (base)
@ -169,20 +169,13 @@ namespace CSMWorld
mContainer.back().mModified = record; mContainer.back().mModified = record;
} }
} }
else else if (!base)
{ {
if (!base) mContainer[index].setModified(record);
{
if (found->mState == RecordBase::State_Erased)
{
throw std::logic_error("Attempt to access a deleted record");
}
found->mState = RecordBase::State_Modified;
found->mModified = record;
}
} }
} }
return index;
} }
template<typename RecordT> template<typename RecordT>
@ -204,25 +197,15 @@ namespace CSMWorld
void RefIdDataContainer<RecordT>::save (int index, ESM::ESMWriter& writer) const void RefIdDataContainer<RecordT>::save (int index, ESM::ESMWriter& writer) const
{ {
Record<RecordT> record = mContainer.at(index); Record<RecordT> record = mContainer.at(index);
RecordT esmRecord; RecordT esmRecord = record.get();
switch (record.mState) if (record.isModified() || record.mState == RecordBase::State_Deleted)
{ {
case RecordBase::State_Modified: esmRecord.mIsDeleted = (record.mState == RecordBase::State_Deleted);
case RecordBase::State_ModifiedOnly: writer.startRecord(esmRecord.sRecordId);
esmRecord = record.mModified; esmRecord.save(writer);
break; writer.endRecord(esmRecord.sRecordId);
case RecordBase::State_Deleted:
esmRecord = record.mBase;
esmRecord.mIsDeleted = true;
break;
default:
break;
} }
writer.startRecord(esmRecord.sRecordId);
esmRecord.save(writer);
writer.endRecord(esmRecord.sRecordId);
} }
@ -262,6 +245,8 @@ namespace CSMWorld
void erase (const LocalIndex& index, int count); void erase (const LocalIndex& index, int count);
///< Must not spill over into another type. ///< Must not spill over into another type.
std::string getRecordId(const LocalIndex &index) const;
public: public:
RefIdData(); RefIdData();