#ifndef OPENMW_MWWORLD_STORE_H #define OPENMW_MWWORLD_STORE_H #include #include #include #include #include #include namespace MWWorld { std::string lowerCase(const std::string &in) { std::string out = in; std::transform( in.begin(), in.end(), out.begin(), (int (*)(int)) std::tolower ); return out; } struct CICompareString { struct ci { bool operator()(int x, int y) { return std::tolower(x) < std::tolower(y); } }; bool operator()(const std::string &x, const std::string &y) { return std::lexicographical_compare( x.begin(), x.end(), y.begin(), y.end(), ci() ); } }; struct StoreBase { class Compare { bool mCaseInsensitive; public: Compare() : mCaseInsensitive(false) {} Compare(bool ci) : mCaseInsensitive(ci) {} Compare(const Compare &orig) : mCaseInsensitive(orig.mCaseInsensitive) {} template bool operator()(const T &x, const T &y) { if (mCaseInsensitive) { return CICompareString()(x.mId, y.mId); } return x.mId < y.mId; } bool isCaseInsensitive() const { return mCaseInsensitive; } bool equalString(const std::string &x, const std::string &y) const { if (!mCaseInsensitive) { return x == y; } if (x.length() != y.length()) { return false; } std::string::iterator xit = x.begin(); std::string::iterator yit = y.begin(); for (; xit != x.end(); ++xit, ++yit) { if (std::tolower(*xit) != std::tolower(*yit)) { return false; } } return true; } }; virtual ~StoreBase() {} virtual void setUp() {} virtual void listIdentifier(std::vector &list) const {} virtual int getSize() const = 0; virtual void load(ESM::ESMReader &esm, const std::string &id) = 0; }; template class SharedIterator { typedef typename std::vector::const_iterator Iter; Iter mIter; public: SharedIterator() {} SharedIterator(const SharedIterator &orig) : mIter(orig.mIter) {} SharedIterator(const Iter &iter) : mIter(iter) {} SharedIterator &operator++() { ++mIter; return *this; } SharedIterator operator++(int) { SharedIterator iter = *this; mIter++; return iter; } SharedIterator &operator--() { --mIter; return *this; } SharedIterator operator--(int) { SharedIterator iter = *this; mIter--; return iter; } SharedIterator operator==(const SharedIterator &x) const { return mIter == x.mIter; } SharedIterator operator!=(const SharedIterator &x) const { return !(*this == x); } const T &operator*() const { return **mIter; } const T *operator->() const { return &(**mIter); } }; template class Store : public StoreBase { Compare mComp; std::vector mData; std::vector mShared; public: Store() {} Store(bool ci) : mComp(ci) {} Store(const Store &orig) : mComp(orig.mComp), mData(orig.mData) {} typedef SharedIterator iterator; const T* search(const std::string &id) const { T item; item.mId = lowerCase(id); typename std::vector::const_iterator it = std::lower_bound(mData.begin(), mData.end(), item, mComp); if (it != mData.end() && mComp.equalString(it->mId, item.mId)) { return &(*it); } return 0; } const T *find(const std::string &id) const { const T *ptr = search(id); if (ptr == 0) { throw std::runtime_error("object '" + id + "' not found"); } return ptr; } void setUp() { std::sort(mData.begin(), mData.end(), mComp); mShared.reserve(mData.size()); typename std::vector::iterator it = mData.begin(); for (; it != mData.end(); ++it) { mShared.push_back(&(*it)); } } iterator begin() { return mShared.begin(); } iterator end() { return mShared.end(); } }; template <> class Store : public StoreBase { std::vector mData; public: Store() { mData.reserve(128); } typedef std::vector::const_iterator iterator; const ESM::LandTexture *search(size_t index) const { if (index < mData.size()) { return &mData.at(index); } return 0; } const ESM::LandTexture *find(size_t index) const { ESM::LandTexture *ptr = search(index); if (ptr == 0) { throw std::runtime_error( "Land texture with index " + index " not found" ); } return ptr; } int getSize() const { return mData.size(); } int load(ESM::ESMReader &esm, const std::string &id) { ESM::LandTexture ltex; ltex.load(esm); if (ltex.mIndex >= (int) mData.size()) { mData.resize(ltex.mIndex + 1); } mData[ltex.mIndex] = ltex; mData[ltex.mIndex].mId = id; } iterator begin() { return mData.begin(); } iterator end() { return mData.end(); } }; template <> class Store : public StoreBase { std::vector mData; struct Compare { bool operator()(const ESM::Land &x, const ESM::Land &y) { if (x.mX == y.mX) { return x.mY < y.mY; } return x.mX < y.mX; } }; public: typedef typename std::vector::const_iterator iterator; int getSize() const { return mData.size(); } iterator begin() { return mData.begin(); } iterator end() { return mData.end(); } ESM::Land *search(int x, int y) const { ESM::Land land; land.mX = x, land.mY = y; std::vector::iterator it = std::lower_bound(mData.begin(), mData.end(), land, Compare()); if (it != mData.end() && it->mX == x && it->mY == y) { return &(*it); } return 0; } ESM::Land *find(int x, int y) const { ESM::Land *ptr = search(x, y); if (ptr == 0) { throw std::runtime_error( "Land at (" + x + ", " + y + ") not found" ); } return ptr; } void load(ESM::ESMReader &esm, const std::string &id) { mData.push_back(ESM::Land()); mData.back().load(esm); } void setUp() { std::sort(mData.begin(), mData.end(), Compare()); } }; template <> class Store : public StoreBase { Compare mIntCmp; std::vector mInt; std::vector mExt; public: Store() : mIntCmp(true) {} typedef std::vector::const_iterator iterator; const ESM::Cell *search(const std::string &id) const { ESM::Cell cell; iterator it = std::lower_bound(mInt.begin(), mInt.end(), cell, mIntCmp); if (it != mInt.end() && mIntCmp.equalString(it->mId, id)) { return &(*it); } return 0; } const ESM::Cell *search(int x, int y) const { return 0; } const ESM::Cell *find(const std::string &id) const { ESM::Cell *ptr = search(id); if (ptr == 0) { throw std::runtime_error( "Interior cell '" + id + "' not found" ); } return ptr; } const ESM::Cell *find(int x, int y) const { ESM::Cell *ptr = search(x, y); if (ptr == 0) { throw std::runtime_error( "Exterior cell at (" + x + ", " + y + ") not found" ); } return ptr; } }; template <> class Store : public StoreBase { }; template <> class Store { }; } //end namespace #endif