2013-05-06 12:11:55 +00:00
|
|
|
|
|
|
|
#include "refiddata.hpp"
|
|
|
|
|
|
|
|
#include <cassert>
|
|
|
|
|
|
|
|
#include <components/misc/stringops.hpp>
|
|
|
|
|
|
|
|
CSMWorld::RefIdDataContainerBase::~RefIdDataContainerBase() {}
|
|
|
|
|
|
|
|
CSMWorld::RefIdData::RefIdData()
|
|
|
|
{
|
2013-12-27 21:13:55 +00:00
|
|
|
mRecordContainers.insert(std::make_pair(UniversalId::Type_Activator, &mActivators));
|
|
|
|
mRecordContainers.insert(std::make_pair(UniversalId::Type_Potion, &mPotions));
|
|
|
|
mRecordContainers.insert(std::make_pair(UniversalId::Type_Apparatus, &mApparati));
|
|
|
|
mRecordContainers.insert(std::make_pair(UniversalId::Type_Armor, &mArmors));
|
|
|
|
mRecordContainers.insert(std::make_pair(UniversalId::Type_Book, &mBooks));
|
|
|
|
mRecordContainers.insert(std::make_pair(UniversalId::Type_Clothing, &mClothing));
|
|
|
|
mRecordContainers.insert(std::make_pair(UniversalId::Type_Container, &mContainers));
|
|
|
|
mRecordContainers.insert(std::make_pair(UniversalId::Type_Creature, &mCreatures));
|
|
|
|
mRecordContainers.insert(std::make_pair(UniversalId::Type_Door, &mDoors));
|
|
|
|
mRecordContainers.insert(std::make_pair(UniversalId::Type_Ingredient, &mIngredients));
|
|
|
|
mRecordContainers.insert(std::make_pair(UniversalId::Type_CreatureLevelledList,
|
|
|
|
&mCreatureLevelledLists));
|
|
|
|
mRecordContainers.insert(std::make_pair(UniversalId::Type_ItemLevelledList, &mItemLevelledLists));
|
|
|
|
mRecordContainers.insert(std::make_pair(UniversalId::Type_Light, &mLights));
|
|
|
|
mRecordContainers.insert(std::make_pair(UniversalId::Type_Lockpick, &mLockpicks));
|
|
|
|
mRecordContainers.insert(std::make_pair(UniversalId::Type_Miscellaneous, &mMiscellaneous));
|
|
|
|
mRecordContainers.insert(std::make_pair(UniversalId::Type_Npc, &mNpcs));
|
|
|
|
mRecordContainers.insert(std::make_pair(UniversalId::Type_Probe, &mProbes));
|
|
|
|
mRecordContainers.insert(std::make_pair(UniversalId::Type_Repair, &mRepairs));
|
|
|
|
mRecordContainers.insert(std::make_pair(UniversalId::Type_Static, &mStatics));
|
|
|
|
mRecordContainers.insert(std::make_pair(UniversalId::Type_Weapon, &mWeapons));
|
2013-05-06 12:11:55 +00:00
|
|
|
}
|
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
CSMWorld::RefIdData::LocalIndex CSMWorld::RefIdData::globalToLocalIndex(int index) const
|
2013-05-06 12:11:55 +00:00
|
|
|
{
|
2013-12-27 21:13:55 +00:00
|
|
|
for (std::map<UniversalId::Type, RefIdDataContainerBase*>::const_iterator iter(
|
|
|
|
mRecordContainers.begin()); iter != mRecordContainers.end(); ++iter)
|
2013-05-06 12:11:55 +00:00
|
|
|
{
|
2013-12-27 21:13:55 +00:00
|
|
|
if (index < iter->second->getSize())
|
|
|
|
return LocalIndex(index, iter->first);
|
2013-05-06 12:11:55 +00:00
|
|
|
|
|
|
|
index -= iter->second->getSize();
|
|
|
|
}
|
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
throw std::runtime_error("RefIdData index out of range");
|
2013-05-06 12:11:55 +00:00
|
|
|
}
|
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
int CSMWorld::RefIdData::localToGlobalIndex(const LocalIndex& index)
|
|
|
|
const
|
2013-05-06 12:11:55 +00:00
|
|
|
{
|
2013-12-27 21:13:55 +00:00
|
|
|
std::map<UniversalId::Type, RefIdDataContainerBase*>::const_iterator end =
|
|
|
|
mRecordContainers.find(index.second);
|
2013-05-06 12:11:55 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
if (end == mRecordContainers.end())
|
|
|
|
throw std::logic_error("invalid local index type");
|
2013-05-06 12:11:55 +00:00
|
|
|
|
|
|
|
int globalIndex = index.first;
|
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
for (std::map<UniversalId::Type, RefIdDataContainerBase*>::const_iterator iter(
|
|
|
|
mRecordContainers.begin()); iter != end; ++iter)
|
2013-05-06 12:11:55 +00:00
|
|
|
globalIndex += iter->second->getSize();
|
|
|
|
|
|
|
|
return globalIndex;
|
|
|
|
}
|
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
CSMWorld::RefIdData::LocalIndex CSMWorld::RefIdData::searchId(
|
2013-05-06 12:11:55 +00:00
|
|
|
const std::string& id) const
|
|
|
|
{
|
2013-12-27 21:13:55 +00:00
|
|
|
std::string id2 = Misc::StringUtils::lowerCase(id);
|
2013-05-06 12:11:55 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
std::map<std::string, std::pair<int, UniversalId::Type> >::const_iterator iter = mIndex.find(id2);
|
2013-05-06 12:11:55 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
if (iter == mIndex.end())
|
|
|
|
return std::make_pair(-1, CSMWorld::UniversalId::Type_None);
|
2013-05-06 12:11:55 +00:00
|
|
|
|
|
|
|
return iter->second;
|
|
|
|
}
|
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
void CSMWorld::RefIdData::erase(int index, int count)
|
2013-05-06 12:11:55 +00:00
|
|
|
{
|
2013-12-27 21:13:55 +00:00
|
|
|
LocalIndex localIndex = globalToLocalIndex(index);
|
2013-05-06 12:11:55 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
std::map<UniversalId::Type, RefIdDataContainerBase*>::const_iterator iter =
|
|
|
|
mRecordContainers.find(localIndex.second);
|
2013-05-06 12:11:55 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
while (count > 0 && iter != mRecordContainers.end())
|
2013-05-06 12:11:55 +00:00
|
|
|
{
|
|
|
|
int size = iter->second->getSize();
|
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
if (localIndex.first + count > size)
|
2013-05-06 12:11:55 +00:00
|
|
|
{
|
2013-12-27 21:13:55 +00:00
|
|
|
erase(localIndex, size - localIndex.first);
|
|
|
|
count -= size - localIndex.first;
|
2013-05-06 12:11:55 +00:00
|
|
|
|
|
|
|
++iter;
|
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
if (iter == mRecordContainers.end())
|
|
|
|
throw std::runtime_error("invalid count value for erase operation");
|
2013-05-06 12:11:55 +00:00
|
|
|
|
|
|
|
localIndex.first = 0;
|
|
|
|
localIndex.second = iter->first;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-12-27 21:13:55 +00:00
|
|
|
erase(localIndex, count);
|
2013-05-06 12:11:55 +00:00
|
|
|
count = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
const CSMWorld::RecordBase& CSMWorld::RefIdData::getRecord(const LocalIndex& index) const
|
2013-05-06 12:11:55 +00:00
|
|
|
{
|
2013-12-27 21:13:55 +00:00
|
|
|
std::map<UniversalId::Type, RefIdDataContainerBase*>::const_iterator iter =
|
|
|
|
mRecordContainers.find(index.second);
|
2013-05-06 12:11:55 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
if (iter == mRecordContainers.end())
|
|
|
|
throw std::logic_error("invalid local index type");
|
2013-05-06 12:11:55 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
return iter->second->getRecord(index.first);
|
2013-05-06 12:11:55 +00:00
|
|
|
}
|
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
CSMWorld::RecordBase& CSMWorld::RefIdData::getRecord(const LocalIndex& index)
|
2013-05-06 12:11:55 +00:00
|
|
|
{
|
2013-12-27 21:13:55 +00:00
|
|
|
std::map<UniversalId::Type, RefIdDataContainerBase*>::iterator iter =
|
|
|
|
mRecordContainers.find(index.second);
|
2013-05-06 12:11:55 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
if (iter == mRecordContainers.end())
|
|
|
|
throw std::logic_error("invalid local index type");
|
2013-05-06 12:11:55 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
return iter->second->getRecord(index.first);
|
2013-05-06 12:11:55 +00:00
|
|
|
}
|
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
void CSMWorld::RefIdData::appendRecord(UniversalId::Type type, const std::string& id)
|
2013-05-06 12:11:55 +00:00
|
|
|
{
|
2013-12-27 21:13:55 +00:00
|
|
|
std::map<UniversalId::Type, RefIdDataContainerBase*>::iterator iter =
|
|
|
|
mRecordContainers.find(type);
|
2013-05-06 12:11:55 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
if (iter == mRecordContainers.end())
|
|
|
|
throw std::logic_error("invalid local index type");
|
2013-05-06 12:11:55 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
iter->second->appendRecord(id);
|
2013-05-06 12:11:55 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
mIndex.insert(std::make_pair(Misc::StringUtils::lowerCase(id),
|
|
|
|
LocalIndex(iter->second->getSize() - 1, type)));
|
2013-05-06 12:11:55 +00:00
|
|
|
}
|
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
int CSMWorld::RefIdData::getAppendIndex(UniversalId::Type type) const
|
2013-05-06 12:11:55 +00:00
|
|
|
{
|
|
|
|
int index = 0;
|
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
for (std::map<UniversalId::Type, RefIdDataContainerBase*>::const_iterator iter(
|
|
|
|
mRecordContainers.begin()); iter != mRecordContainers.end(); ++iter)
|
2013-05-06 12:11:55 +00:00
|
|
|
{
|
|
|
|
index += iter->second->getSize();
|
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
if (type == iter->first)
|
2013-05-06 12:11:55 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
void CSMWorld::RefIdData::load(const LocalIndex& index, ESM::ESMReader& reader, bool base)
|
2013-05-06 12:11:55 +00:00
|
|
|
{
|
2013-12-27 21:13:55 +00:00
|
|
|
std::map<UniversalId::Type, RefIdDataContainerBase*>::iterator iter =
|
|
|
|
mRecordContainers.find(index.second);
|
2013-05-06 12:11:55 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
if (iter == mRecordContainers.end())
|
|
|
|
throw std::logic_error("invalid local index type");
|
2013-05-06 12:11:55 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
iter->second->load(index.first, reader, base);
|
2013-05-06 12:11:55 +00:00
|
|
|
}
|
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
void CSMWorld::RefIdData::erase(const LocalIndex& index, int count)
|
2013-05-06 12:11:55 +00:00
|
|
|
{
|
2013-12-27 21:13:55 +00:00
|
|
|
std::map<UniversalId::Type, RefIdDataContainerBase*>::iterator iter =
|
|
|
|
mRecordContainers.find(index.second);
|
2013-05-06 12:11:55 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
if (iter == mRecordContainers.end())
|
|
|
|
throw std::logic_error("invalid local index type");
|
2013-05-06 12:11:55 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
for (int i = index.first; i < index.first + count; ++i)
|
2013-05-06 12:11:55 +00:00
|
|
|
{
|
|
|
|
std::map<std::string, LocalIndex>::iterator result =
|
2013-12-27 21:13:55 +00:00
|
|
|
mIndex.find(Misc::StringUtils::lowerCase(iter->second->getId(i)));
|
2013-05-06 12:11:55 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
if (result != mIndex.end())
|
|
|
|
mIndex.erase(result);
|
2013-05-06 12:11:55 +00:00
|
|
|
}
|
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
iter->second->erase(index.first, count);
|
2013-05-06 12:11:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int CSMWorld::RefIdData::getSize() const
|
|
|
|
{
|
|
|
|
return mIndex.size();
|
|
|
|
}
|
2013-09-19 10:11:27 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
std::vector<std::string> CSMWorld::RefIdData::getIds(bool listDeleted) const
|
2013-09-19 10:11:27 +00:00
|
|
|
{
|
|
|
|
std::vector<std::string> ids;
|
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
for (std::map<std::string, LocalIndex>::const_iterator iter(mIndex.begin()); iter != mIndex.end();
|
|
|
|
++iter)
|
2013-09-19 10:11:27 +00:00
|
|
|
{
|
2013-12-27 21:13:55 +00:00
|
|
|
if (listDeleted || !getRecord(iter->second).isDeleted())
|
2013-09-19 10:11:27 +00:00
|
|
|
{
|
2013-12-27 21:13:55 +00:00
|
|
|
std::map<UniversalId::Type, RefIdDataContainerBase*>::const_iterator container =
|
|
|
|
mRecordContainers.find(iter->second.second);
|
2013-09-19 10:11:27 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
if (container == mRecordContainers.end())
|
|
|
|
throw std::logic_error("Invalid referenceable ID type");
|
2013-09-19 10:11:27 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
ids.push_back(container->second->getId(iter->second.first));
|
2013-09-19 10:11:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ids;
|
|
|
|
}
|
2013-09-24 11:53:19 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
void CSMWorld::RefIdData::save(int index, ESM::ESMWriter& writer) const
|
2013-09-24 11:53:19 +00:00
|
|
|
{
|
2013-12-27 21:13:55 +00:00
|
|
|
LocalIndex localIndex = globalToLocalIndex(index);
|
2013-09-24 11:53:19 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
std::map<UniversalId::Type, RefIdDataContainerBase*>::const_iterator iter =
|
|
|
|
mRecordContainers.find(localIndex.second);
|
2013-09-24 11:53:19 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
if (iter == mRecordContainers.end())
|
|
|
|
throw std::logic_error("invalid local index type");
|
2013-09-24 11:53:19 +00:00
|
|
|
|
2013-12-27 21:13:55 +00:00
|
|
|
iter->second->save(localIndex.first, writer);
|
2013-12-20 19:02:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const CSMWorld::RefIdDataContainer< ESM::Book >& CSMWorld::RefIdData::getBooks() const
|
|
|
|
{
|
|
|
|
return mBooks;
|
|
|
|
}
|
2013-12-20 21:31:17 +00:00
|
|
|
|
2013-12-21 09:59:13 +00:00
|
|
|
const CSMWorld::RefIdDataContainer< ESM::Activator >& CSMWorld::RefIdData::getActivators() const
|
2013-12-20 21:31:17 +00:00
|
|
|
{
|
|
|
|
return mActivators;
|
|
|
|
}
|
2013-12-21 09:58:05 +00:00
|
|
|
|
|
|
|
const CSMWorld::RefIdDataContainer< ESM::Potion >& CSMWorld::RefIdData::getPotions() const
|
|
|
|
{
|
|
|
|
return mPotions;
|
|
|
|
}
|
2013-12-21 11:07:40 +00:00
|
|
|
|
|
|
|
const CSMWorld::RefIdDataContainer< ESM::Apparatus >& CSMWorld::RefIdData::getApparati() const
|
|
|
|
{
|
|
|
|
return mApparati;
|
|
|
|
}
|
2013-12-22 13:22:03 +00:00
|
|
|
|
|
|
|
const CSMWorld::RefIdDataContainer< ESM::Armor >& CSMWorld::RefIdData::getArmors() const
|
|
|
|
{
|
|
|
|
return mArmors;
|
|
|
|
}
|
2013-12-22 13:32:42 +00:00
|
|
|
|
|
|
|
const CSMWorld::RefIdDataContainer< ESM::Clothing >& CSMWorld::RefIdData::getClothing() const
|
|
|
|
{
|
|
|
|
return mClothing;
|
|
|
|
}
|
2013-12-22 13:34:29 +00:00
|
|
|
|
|
|
|
const CSMWorld::RefIdDataContainer< ESM::Container >& CSMWorld::RefIdData::getContainers() const
|
|
|
|
{
|
|
|
|
return mContainers;
|
|
|
|
}
|
2013-12-22 13:44:22 +00:00
|
|
|
|
|
|
|
const CSMWorld::RefIdDataContainer< ESM::Creature >& CSMWorld::RefIdData::getCreatures() const
|
|
|
|
{
|
|
|
|
return mCreatures;
|
|
|
|
}
|
2013-12-26 11:59:43 +00:00
|
|
|
|
|
|
|
const CSMWorld::RefIdDataContainer< ESM::Door >& CSMWorld::RefIdData::getDoors() const
|
|
|
|
{
|
|
|
|
return mDoors;
|
|
|
|
}
|
|
|
|
|
2013-12-26 14:24:52 +00:00
|
|
|
const CSMWorld::RefIdDataContainer< ESM::Ingredient >& CSMWorld::RefIdData::getIngredients() const
|
|
|
|
{
|
|
|
|
return mIngredients;
|
|
|
|
}
|
2013-12-26 14:35:58 +00:00
|
|
|
|
|
|
|
const CSMWorld::RefIdDataContainer< ESM::CreatureLevList >& CSMWorld::RefIdData::getCreatureLevelledLists() const
|
|
|
|
{
|
|
|
|
return mCreatureLevelledLists;
|
|
|
|
}
|
2013-12-26 17:28:24 +00:00
|
|
|
|
|
|
|
const CSMWorld::RefIdDataContainer< ESM::ItemLevList >& CSMWorld::RefIdData::getItemLevelledList() const
|
|
|
|
{
|
|
|
|
return mItemLevelledLists;
|
|
|
|
}
|
2013-12-26 17:40:47 +00:00
|
|
|
|
|
|
|
const CSMWorld::RefIdDataContainer< ESM::Light >& CSMWorld::RefIdData::getLights() const
|
|
|
|
{
|
|
|
|
return mLights;
|
|
|
|
}
|
2013-12-27 21:13:55 +00:00
|
|
|
|
|
|
|
const CSMWorld::RefIdDataContainer< ESM::Lockpick >& CSMWorld::RefIdData::getLocpicks() const
|
|
|
|
{
|
|
|
|
return mLockpicks;
|
|
|
|
}
|
|
|
|
|
|
|
|
const CSMWorld::RefIdDataContainer< ESM::Miscellaneous >& CSMWorld::RefIdData::getMiscellaneous() const
|
|
|
|
{
|
|
|
|
return mMiscellaneous;
|
|
|
|
}
|
|
|
|
|
|
|
|
const CSMWorld::RefIdDataContainer< ESM::NPC >& CSMWorld::RefIdData::getNPCs() const
|
|
|
|
{
|
|
|
|
return mNpcs;
|
|
|
|
}
|