2012-11-24 10:01:53 +00:00
|
|
|
|
|
|
|
#include "universalid.hpp"
|
|
|
|
|
|
|
|
#include <ostream>
|
|
|
|
#include <stdexcept>
|
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
struct TypeData
|
|
|
|
{
|
|
|
|
CSMWorld::UniversalId::Class mClass;
|
|
|
|
CSMWorld::UniversalId::Type mType;
|
|
|
|
const char *mName;
|
2013-07-29 14:21:42 +00:00
|
|
|
const char *mIcon;
|
2012-11-24 10:01:53 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const TypeData sNoArg[] =
|
|
|
|
{
|
2013-07-29 14:21:42 +00:00
|
|
|
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "empty", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Factions, "Factions", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Races, "Races", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Sounds, "Sounds", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Scripts, "Scripts", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells", 0 },
|
2013-04-23 09:21:21 +00:00
|
|
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables,
|
2013-07-29 14:21:42 +00:00
|
|
|
"Referenceables", 0 },
|
2013-07-06 15:03:18 +00:00
|
|
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_References,
|
2013-07-29 14:21:42 +00:00
|
|
|
"References", 0 },
|
2013-07-08 11:12:50 +00:00
|
|
|
{ CSMWorld::UniversalId::Class_NonRecord, CSMWorld::UniversalId::Type_RegionMap,
|
2013-07-29 14:21:42 +00:00
|
|
|
"Region Map", 0 },
|
2013-07-30 13:55:50 +00:00
|
|
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Filters, "Filters", 0 },
|
2012-11-24 10:01:53 +00:00
|
|
|
|
2013-07-29 14:21:42 +00:00
|
|
|
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
|
2012-11-24 10:01:53 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const TypeData sIdArg[] =
|
|
|
|
{
|
2013-07-29 14:21:42 +00:00
|
|
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables", 0 },
|
|
|
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":./activator.png" },
|
|
|
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":./potion.png" },
|
|
|
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Apparatus, "Apparatus", ":./apparatus.png" },
|
|
|
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Armor, "Armor", ":./armor.png" },
|
|
|
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Book, "Book", ":./book.png" },
|
|
|
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Clothing, "Clothing", ":./clothing.png" },
|
|
|
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Container, "Container", ":./container.png" },
|
|
|
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Creature, "Creature", ":./creature.png" },
|
|
|
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Door, "Door", ":./door.png" },
|
|
|
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Ingredient, "Ingredient", ":./ingredient.png" },
|
|
|
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_CreatureLevelledList,
|
|
|
|
"Creature Levelled List", ":./creature.png" },
|
|
|
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_ItemLevelledList,
|
2013-07-30 10:55:02 +00:00
|
|
|
"Item Levelled List", ":./leveled-item.png" },
|
2013-07-29 14:21:42 +00:00
|
|
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Light, "Light", ":./light.png" },
|
|
|
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Lockpick, "Lockpick", ":./lockpick.png" },
|
|
|
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Miscellaneous,
|
2013-07-30 10:55:02 +00:00
|
|
|
"Miscellaneous", ":./miscellaneous.png" },
|
2013-07-29 14:21:42 +00:00
|
|
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Npc, "NPC", ":./npc.png" },
|
|
|
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Probe, "Probe", ":./probe.png" },
|
|
|
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Repair, "Repair", ":./repair.png" },
|
|
|
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Static, "Static", ":./static.png" },
|
|
|
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":./weapon.png" },
|
|
|
|
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Reference", 0 },
|
|
|
|
|
|
|
|
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
|
2012-11-24 10:01:53 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const TypeData sIndexArg[] =
|
|
|
|
{
|
2013-07-29 14:21:42 +00:00
|
|
|
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, "Verification Results", 0 },
|
2012-11-24 10:01:53 +00:00
|
|
|
|
2013-07-29 14:21:42 +00:00
|
|
|
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
|
2012-11-24 10:01:53 +00:00
|
|
|
};
|
2013-06-30 12:43:58 +00:00
|
|
|
|
|
|
|
static const unsigned int IDARG_SIZE = sizeof (sIdArg) / sizeof (TypeData);
|
2012-11-24 10:01:53 +00:00
|
|
|
}
|
|
|
|
|
2012-12-08 22:27:59 +00:00
|
|
|
CSMWorld::UniversalId::UniversalId (const std::string& universalId)
|
|
|
|
{
|
|
|
|
std::string::size_type index = universalId.find (':');
|
|
|
|
|
2013-03-25 10:04:41 +00:00
|
|
|
if (index!=std::string::npos)
|
2012-12-08 22:27:59 +00:00
|
|
|
{
|
|
|
|
std::string type = universalId.substr (0, index);
|
|
|
|
|
2013-04-06 17:20:46 +00:00
|
|
|
for (int i=0; sIdArg[i].mName; ++i)
|
|
|
|
if (type==sIdArg[i].mName)
|
|
|
|
{
|
|
|
|
mArgumentType = ArgumentType_Id;
|
|
|
|
mType = sIdArg[i].mType;
|
|
|
|
mClass = sIdArg[i].mClass;
|
|
|
|
mId = universalId.substr (index+2);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i=0; sIndexArg[i].mName; ++i)
|
|
|
|
if (type==sIndexArg[i].mName)
|
|
|
|
{
|
|
|
|
mArgumentType = ArgumentType_Index;
|
|
|
|
mType = sIndexArg[i].mType;
|
|
|
|
mClass = sIndexArg[i].mClass;
|
|
|
|
|
|
|
|
std::istringstream stream (universalId.substr (index+2));
|
|
|
|
|
|
|
|
if (stream >> mIndex)
|
2012-12-09 10:10:35 +00:00
|
|
|
return;
|
|
|
|
|
2013-04-06 17:20:46 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (int i=0; sNoArg[i].mName; ++i)
|
|
|
|
if (universalId==sNoArg[i].mName)
|
|
|
|
{
|
|
|
|
mArgumentType = ArgumentType_None;
|
|
|
|
mType = sNoArg[i].mType;
|
|
|
|
mClass = sNoArg[i].mClass;
|
|
|
|
return;
|
|
|
|
}
|
2012-12-08 22:27:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
throw std::runtime_error ("invalid UniversalId: " + universalId);
|
|
|
|
}
|
|
|
|
|
2012-11-24 10:01:53 +00:00
|
|
|
CSMWorld::UniversalId::UniversalId (Type type) : mArgumentType (ArgumentType_None), mType (type), mIndex (0)
|
|
|
|
{
|
|
|
|
for (int i=0; sNoArg[i].mName; ++i)
|
|
|
|
if (type==sNoArg[i].mType)
|
|
|
|
{
|
|
|
|
mClass = sNoArg[i].mClass;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
throw std::logic_error ("invalid argument-less UniversalId type");
|
|
|
|
}
|
|
|
|
|
|
|
|
CSMWorld::UniversalId::UniversalId (Type type, const std::string& id)
|
|
|
|
: mArgumentType (ArgumentType_Id), mType (type), mId (id), mIndex (0)
|
|
|
|
{
|
|
|
|
for (int i=0; sIdArg[i].mName; ++i)
|
|
|
|
if (type==sIdArg[i].mType)
|
|
|
|
{
|
|
|
|
mClass = sIdArg[i].mClass;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
throw std::logic_error ("invalid ID argument UniversalId type");
|
|
|
|
}
|
|
|
|
|
|
|
|
CSMWorld::UniversalId::UniversalId (Type type, int index)
|
|
|
|
: mArgumentType (ArgumentType_Index), mType (type), mIndex (index)
|
|
|
|
{
|
|
|
|
for (int i=0; sIndexArg[i].mName; ++i)
|
|
|
|
if (type==sIndexArg[i].mType)
|
|
|
|
{
|
|
|
|
mClass = sIndexArg[i].mClass;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
throw std::logic_error ("invalid index argument UniversalId type");
|
|
|
|
}
|
|
|
|
|
|
|
|
CSMWorld::UniversalId::Class CSMWorld::UniversalId::getClass() const
|
|
|
|
{
|
|
|
|
return mClass;
|
|
|
|
}
|
|
|
|
|
|
|
|
CSMWorld::UniversalId::ArgumentType CSMWorld::UniversalId::getArgumentType() const
|
|
|
|
{
|
|
|
|
return mArgumentType;
|
|
|
|
}
|
|
|
|
|
|
|
|
CSMWorld::UniversalId::Type CSMWorld::UniversalId::getType() const
|
|
|
|
{
|
|
|
|
return mType;
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::string& CSMWorld::UniversalId::getId() const
|
|
|
|
{
|
|
|
|
if (mArgumentType!=ArgumentType_Id)
|
|
|
|
throw std::logic_error ("invalid access to ID of non-ID UniversalId");
|
|
|
|
|
|
|
|
return mId;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CSMWorld::UniversalId::getIndex() const
|
|
|
|
{
|
|
|
|
if (mArgumentType!=ArgumentType_Index)
|
|
|
|
throw std::logic_error ("invalid access to index of non-index UniversalId");
|
|
|
|
|
|
|
|
return mIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CSMWorld::UniversalId::isEqual (const UniversalId& universalId) const
|
|
|
|
{
|
|
|
|
if (mClass!=universalId.mClass || mArgumentType!=universalId.mArgumentType || mType!=universalId.mType)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
switch (mArgumentType)
|
|
|
|
{
|
|
|
|
case ArgumentType_Id: return mId==universalId.mId;
|
|
|
|
case ArgumentType_Index: return mIndex==universalId.mIndex;
|
|
|
|
|
|
|
|
default: return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-26 11:29:22 +00:00
|
|
|
bool CSMWorld::UniversalId::isLess (const UniversalId& universalId) const
|
|
|
|
{
|
|
|
|
if (mType<universalId.mType)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (mType>universalId.mType)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
switch (mArgumentType)
|
|
|
|
{
|
|
|
|
case ArgumentType_Id: return mId<universalId.mId;
|
|
|
|
case ArgumentType_Index: return mIndex<universalId.mIndex;
|
|
|
|
|
|
|
|
default: return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-24 10:01:53 +00:00
|
|
|
std::string CSMWorld::UniversalId::getTypeName() const
|
|
|
|
{
|
|
|
|
const TypeData *typeData = mArgumentType==ArgumentType_None ? sNoArg :
|
|
|
|
(mArgumentType==ArgumentType_Id ? sIdArg : sIndexArg);
|
|
|
|
|
|
|
|
for (int i=0; typeData[i].mName; ++i)
|
|
|
|
if (typeData[i].mType==mType)
|
|
|
|
return typeData[i].mName;
|
|
|
|
|
|
|
|
throw std::logic_error ("failed to retrieve UniversalId type name");
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string CSMWorld::UniversalId::toString() const
|
|
|
|
{
|
|
|
|
std::ostringstream stream;
|
|
|
|
|
2012-12-09 10:10:35 +00:00
|
|
|
stream << getTypeName();
|
2012-11-24 10:01:53 +00:00
|
|
|
|
|
|
|
switch (mArgumentType)
|
|
|
|
{
|
|
|
|
case ArgumentType_None: break;
|
2012-12-13 12:35:08 +00:00
|
|
|
case ArgumentType_Id: stream << ": " << mId; break;
|
|
|
|
case ArgumentType_Index: stream << ": " << mIndex; break;
|
2012-11-24 10:01:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return stream.str();
|
|
|
|
}
|
|
|
|
|
2013-07-29 14:21:42 +00:00
|
|
|
std::string CSMWorld::UniversalId::getIcon() const
|
|
|
|
{
|
|
|
|
const TypeData *typeData = mArgumentType==ArgumentType_None ? sNoArg :
|
|
|
|
(mArgumentType==ArgumentType_Id ? sIdArg : sIndexArg);
|
|
|
|
|
|
|
|
for (int i=0; typeData[i].mName; ++i)
|
|
|
|
if (typeData[i].mType==mType)
|
|
|
|
return typeData[i].mIcon ? typeData[i].mIcon : "";
|
|
|
|
|
|
|
|
throw std::logic_error ("failed to retrieve UniversalId type icon");
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<CSMWorld::UniversalId::Type> CSMWorld::UniversalId::listReferenceableTypes()
|
|
|
|
{
|
|
|
|
std::vector<CSMWorld::UniversalId::Type> list;
|
|
|
|
|
|
|
|
for (int i=0; sIdArg[i].mName; ++i)
|
|
|
|
if (sIdArg[i].mClass==Class_RefRecord)
|
|
|
|
list.push_back (sIdArg[i].mType);
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
2013-06-30 12:43:58 +00:00
|
|
|
|
|
|
|
std::pair<int, const char *> CSMWorld::UniversalId::getIdArgPair (unsigned int index)
|
|
|
|
{
|
|
|
|
std::pair<int, const char *> retPair;
|
|
|
|
|
|
|
|
if ( index < IDARG_SIZE )
|
|
|
|
{
|
|
|
|
retPair.first = sIdArg[index].mType;
|
|
|
|
retPair.second = sIdArg[index].mName;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retPair;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int CSMWorld::UniversalId::getIdArgSize()
|
|
|
|
{
|
|
|
|
return IDARG_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-11-26 11:29:22 +00:00
|
|
|
bool CSMWorld::operator== (const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right)
|
2012-11-24 10:01:53 +00:00
|
|
|
{
|
|
|
|
return left.isEqual (right);
|
|
|
|
}
|
|
|
|
|
2012-11-26 11:29:22 +00:00
|
|
|
bool CSMWorld::operator!= (const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right)
|
2012-11-24 10:01:53 +00:00
|
|
|
{
|
|
|
|
return !left.isEqual (right);
|
|
|
|
}
|
|
|
|
|
2012-11-26 11:29:22 +00:00
|
|
|
bool CSMWorld::operator< (const UniversalId& left, const UniversalId& right)
|
|
|
|
{
|
|
|
|
return left.isLess (right);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::ostream& CSMWorld::operator< (std::ostream& stream, const CSMWorld::UniversalId& universalId)
|
2012-11-24 10:01:53 +00:00
|
|
|
{
|
|
|
|
return stream << universalId.toString();
|
2013-06-30 12:43:58 +00:00
|
|
|
}
|