#ifndef CSM_WOLRD_RECORD_H #define CSM_WOLRD_RECORD_H #include namespace CSMWorld { struct RecordBase { enum State { State_BaseOnly = 0, // defined in base only State_Modified = 1, // exists in base, but has been modified State_ModifiedOnly = 2, // newly created in modified State_Deleted = 3, // exists in base, but has been deleted State_Erased = 4 // does not exist at all (we mostly treat that the same way as deleted) }; State mState; virtual ~RecordBase(); virtual RecordBase *clone() const = 0; virtual RecordBase *modifiedCopy() const = 0; virtual void assign (const RecordBase& record) = 0; ///< Will throw an exception if the types don't match. bool isDeleted() const; bool isErased() const; bool isModified() const; }; template struct Record : public RecordBase { ESXRecordT mBase; ESXRecordT mModified; Record(); Record(State state, const ESXRecordT *base = 0, const ESXRecordT *modified = 0); virtual RecordBase *clone() const; virtual RecordBase *modifiedCopy() const; virtual void assign (const RecordBase& record); const ESXRecordT& get() const; ///< Throws an exception, if the record is deleted. ESXRecordT& get(); ///< Throws an exception, if the record is deleted. const ESXRecordT& getBase() const; ///< Throws an exception, if the record is deleted. Returns modified, if there is no base. void setModified (const ESXRecordT& modified); ///< Throws an exception, if the record is deleted. void merge(); ///< Merge modified into base. }; template Record::Record() : mBase(), mModified() { } template Record::Record(State state, const ESXRecordT *base, const ESXRecordT *modified) { if(base) mBase = *base; if(modified) mModified = *modified; this->mState = state; } template RecordBase *Record::modifiedCopy() const { return new Record (State_ModifiedOnly, 0, &(this->get())); } template RecordBase *Record::clone() const { return new Record (*this); } template void Record::assign (const RecordBase& record) { *this = dynamic_cast& > (record); } template const ESXRecordT& Record::get() const { if (mState==State_Erased) throw std::logic_error ("attempt to access a deleted record"); return mState==State_BaseOnly || mState==State_Deleted ? mBase : mModified; } template ESXRecordT& Record::get() { if (mState==State_Erased) throw std::logic_error ("attempt to access a deleted record"); return mState==State_BaseOnly || mState==State_Deleted ? mBase : mModified; } template const ESXRecordT& Record::getBase() const { if (mState==State_Erased) throw std::logic_error ("attempt to access a deleted record"); return mState==State_ModifiedOnly ? mModified : mBase; } template void Record::setModified (const ESXRecordT& modified) { if (mState==State_Erased) throw std::logic_error ("attempt to modify a deleted record"); mModified = modified; if (mState!=State_ModifiedOnly) mState = State_Modified; } template void Record::merge() { if (isModified()) { mBase = mModified; mState = State_BaseOnly; } else if (mState==State_Deleted) { mState = State_Erased; } } } #endif