From 4c0dcd46a19fea65c1c8bd31f82fbbe9103b7429 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 24 Nov 2012 11:01:53 +0100 Subject: [PATCH] added UniversalId class --- apps/opencs/CMakeLists.txt | 4 + apps/opencs/model/world/universalid.cpp | 161 ++++++++++++++++++++++++ apps/opencs/model/world/universalid.hpp | 80 ++++++++++++ 3 files changed, 245 insertions(+) create mode 100644 apps/opencs/model/world/universalid.cpp create mode 100644 apps/opencs/model/world/universalid.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 66b9f4942..cb721ac54 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -4,6 +4,8 @@ set (OPENCS_SRC model/doc/documentmanager.cpp model/doc/document.cpp + model/world/universalid.cpp + view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp ) @@ -12,6 +14,8 @@ set (OPENCS_HDR model/doc/documentmanager.hpp model/doc/document.hpp + model/world/universalid.hpp + view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp ) diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp new file mode 100644 index 000000000..b56a336a6 --- /dev/null +++ b/apps/opencs/model/world/universalid.cpp @@ -0,0 +1,161 @@ + +#include "universalid.hpp" + +#include +#include +#include + +namespace +{ + struct TypeData + { + CSMWorld::UniversalId::Class mClass; + CSMWorld::UniversalId::Type mType; + const char *mName; + }; + + static const TypeData sNoArg[] = + { + { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "empty" }, + + { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker + }; + + static const TypeData sIdArg[] = + { + + { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker + }; + + static const TypeData sIndexArg[] = + { + + { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker + }; +} + +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; + } +} + +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; + + stream << getTypeName(); + + switch (mArgumentType) + { + case ArgumentType_None: break; + case ArgumentType_Id: stream << " " << mId; + case ArgumentType_Index: stream << " " << mIndex; + } + + return stream.str(); +} + +bool operator== (const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right) +{ + return left.isEqual (right); +} + +bool operator!= (const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right) +{ + return !left.isEqual (right); +} + +std::ostream& operator< (std::ostream& stream, const CSMWorld::UniversalId& universalId) +{ + return stream << universalId.toString(); +} \ No newline at end of file diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp new file mode 100644 index 000000000..6f085cfc2 --- /dev/null +++ b/apps/opencs/model/world/universalid.hpp @@ -0,0 +1,80 @@ +#ifndef CSM_WOLRD_UNIVERSALID_H +#define CSM_WOLRD_UNIVERSALID_H + +#include +#include + +namespace CSMWorld +{ + class UniversalId + { + public: + + enum Class + { + Class_None = 0, + Class_Record, + Class_SubRecord, + Class_RecordList, + Class_Collection, // multiple types of records combined + Class_Transient, // not part of the world data or the project data + Class_NonRecord // record like data that is not part of the world + }; + + enum ArgumentType + { + ArgumentType_None, + ArgumentType_Id, + ArgumentType_Index + }; + + enum Type + { + Type_None + }; + + private: + + Class mClass; + ArgumentType mArgumentType; + Type mType; + std::string mId; + int mIndex; + + public: + + UniversalId (Type type = Type_None); + ///< Using a type for a non-argument-less UniversalId will throw an exception. + + UniversalId (Type type, const std::string& id); + ///< Using a type for a non-ID-argument UniversalId will throw an exception. + + UniversalId (Type type, int index); + ///< Using a type for a non-index-argument UniversalId will throw an exception. + + Class getClass() const; + + ArgumentType getArgumentType() const; + + Type getType() const; + + const std::string& getId() const; + ///< Calling this function for a non-ID type will throw an exception. + + int getIndex() const; + ///< Calling this function for a non-index type will throw an exception. + + bool isEqual (const UniversalId& universalId) const; + + std::string getTypeName() const; + + std::string toString() const; + }; + + bool operator== (const UniversalId& left, const UniversalId& right); + bool operator!= (const UniversalId& left, const UniversalId& right); + + std::ostream& operator< (std::ostream& stream, const UniversalId& universalId); +} + +#endif