/* * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Affero General Public License as published by the * Free Software Foundation; either version 3 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #ifndef DBCFILE_H #define DBCFILE_H #include #include class DBCFile { public: DBCFile(std::string filename); ~DBCFile(); // Open database. It must be openened before it can be used. bool open(); /// @todo: Add a close function? // Database exceptions class Exception { public: Exception(std::string message): message(std::move(message)) { } virtual ~Exception() = default; const std::string& getMessage() {return message;} private: std::string message; }; // class NotFound: public Exception { public: NotFound(): Exception("Key was not found") { } }; // Iteration over database class Iterator; class Record { public: Record& operator= (const Record& r) { file = r.file; offset = r.offset; return *this; } [[nodiscard]] float getFloat(std::size_t field) const { assert(field < file.fieldCount); return *reinterpret_cast(offset + field * 4); } [[nodiscard]] unsigned int getUInt(std::size_t field) const { assert(field < file.fieldCount); return *reinterpret_cast(offset + (field * 4)); } [[nodiscard]] int getInt(std::size_t field) const { assert(field < file.fieldCount); return *reinterpret_cast(offset + field * 4); } [[nodiscard]] unsigned char getByte(std::size_t ofs) const { assert(ofs < file.recordSize); return *reinterpret_cast(offset + ofs); } [[nodiscard]] const char* getString(std::size_t field) const { assert(field < file.fieldCount); std::size_t stringOffset = getUInt(field); assert(stringOffset < file.stringSize); //char * tmp = (char*)file.stringTable + stringOffset; //unsigned char * tmp2 = file.stringTable + stringOffset; return reinterpret_cast(file.stringTable + stringOffset); } private: Record(DBCFile& file, unsigned char* offset): file(file), offset(offset) {} DBCFile& file; unsigned char* offset; friend class DBCFile; friend class Iterator; }; /* Iterator that iterates over records */ class Iterator { public: Iterator(DBCFile& file, unsigned char* offset): record(file, offset) {} /// Advance (prefix only) Iterator& operator++() { record.offset += record.file.recordSize; return *this; } /// Return address of current instance Record const& operator*() const { return record; } const Record* operator->() const { return &record; } /// Comparison bool operator==(const Iterator& b) const { return record.offset == b.record.offset; } bool operator!=(const Iterator& b) const { return record.offset != b.record.offset; } private: Record record; }; // Get record by id Record getRecord(std::size_t id); /// Get begin iterator over records Iterator begin(); /// Get begin iterator over records Iterator end(); /// Trivial [[nodiscard]] std::size_t getRecordCount() const { return recordCount;} [[nodiscard]] std::size_t getFieldCount() const { return fieldCount; } private: std::string filename; std::size_t recordSize; std::size_t recordCount; std::size_t fieldCount; std::size_t stringSize; unsigned char* data; unsigned char* stringTable; }; #endif