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

openmw-38
Stanislav Bas 10 years ago
parent b55a4999ca
commit 5e623a2a1d

@ -3,10 +3,20 @@
#include <cassert>
#include <components/misc/stringops.hpp>
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()
{
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);
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)

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

Loading…
Cancel
Save