diff options
| author | ariel- <ariel-@users.noreply.github.com> | 2017-06-19 23:20:06 -0300 |
|---|---|---|
| committer | ariel- <ariel-@users.noreply.github.com> | 2017-06-19 23:20:06 -0300 |
| commit | 85a7d5ce9ac68b30da2277cc91d4b70358f1880d (patch) | |
| tree | df3d2084ee2e35008903c03178039b9c986e2d08 /src/common/DataStores | |
| parent | 052fc24315ace866ea1cf610e85df119b68100c9 (diff) | |
Core: ported headers cleanup from master branch
Diffstat (limited to 'src/common/DataStores')
| -rw-r--r-- | src/common/DataStores/DBCFileLoader.cpp | 316 | ||||
| -rw-r--r-- | src/common/DataStores/DBCFileLoader.h | 114 |
2 files changed, 430 insertions, 0 deletions
diff --git a/src/common/DataStores/DBCFileLoader.cpp b/src/common/DataStores/DBCFileLoader.cpp new file mode 100644 index 00000000000..c1102c25d8c --- /dev/null +++ b/src/common/DataStores/DBCFileLoader.cpp @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 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 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 <http://www.gnu.org/licenses/>. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "DBCFileLoader.h" +#include "Errors.h" + +DBCFileLoader::DBCFileLoader() : recordSize(0), recordCount(0), fieldCount(0), stringSize(0), fieldsOffset(nullptr), data(nullptr), stringTable(nullptr) { } + +bool DBCFileLoader::Load(char const* filename, char const* fmt) +{ + uint32 header; + if (data) + { + delete [] data; + data = nullptr; + } + + FILE* f = fopen(filename, "rb"); + if (!f) + return false; + + if (fread(&header, 4, 1, f) != 1) // Number of records + { + fclose(f); + return false; + } + + + EndianConvert(header); + + if (header != 0x43424457) //'WDBC' + { + fclose(f); + return false; + } + + if (fread(&recordCount, 4, 1, f) != 1) // Number of records + { + fclose(f); + return false; + } + + EndianConvert(recordCount); + + if (fread(&fieldCount, 4, 1, f) != 1) // Number of fields + { + fclose(f); + return false; + } + + EndianConvert(fieldCount); + + if (fread(&recordSize, 4, 1, f) != 1) // Size of a record + { + fclose(f); + return false; + } + + EndianConvert(recordSize); + + if (fread(&stringSize, 4, 1, f) != 1) // String size + { + fclose(f); + return false; + } + + EndianConvert(stringSize); + + fieldsOffset = new uint32[fieldCount]; + fieldsOffset[0] = 0; + for (uint32 i = 1; i < fieldCount; ++i) + { + fieldsOffset[i] = fieldsOffset[i - 1]; + if (fmt[i - 1] == 'b' || fmt[i - 1] == 'X') // byte fields + fieldsOffset[i] += sizeof(uint8); + else // 4 byte fields (int32/float/strings) + fieldsOffset[i] += sizeof(uint32); + } + + data = new unsigned char[recordSize * recordCount + stringSize]; + stringTable = data + recordSize*recordCount; + + if (fread(data, recordSize * recordCount + stringSize, 1, f) != 1) + { + fclose(f); + return false; + } + + fclose(f); + + return true; +} + +DBCFileLoader::~DBCFileLoader() +{ + delete[] data; + + delete[] fieldsOffset; +} + +DBCFileLoader::Record DBCFileLoader::getRecord(size_t id) +{ + assert(data); + return Record(*this, data + id * recordSize); +} + +uint32 DBCFileLoader::GetFormatRecordSize(char const* format, int32* index_pos) +{ + uint32 recordsize = 0; + int32 i = -1; + for (uint32 x = 0; format[x]; ++x) + { + switch (format[x]) + { + case FT_FLOAT: + recordsize += sizeof(float); + break; + case FT_INT: + recordsize += sizeof(uint32); + break; + case FT_STRING: + recordsize += sizeof(char*); + break; + case FT_SORT: + i = x; + break; + case FT_IND: + i = x; + recordsize += sizeof(uint32); + break; + case FT_BYTE: + recordsize += sizeof(uint8); + break; + case FT_NA: + case FT_NA_BYTE: + break; + case FT_LOGIC: + ASSERT(false && "Attempted to load DBC files that do not have field types that match what is in the core. Check DBCfmt.h or your DBC files."); + break; + default: + ASSERT(false && "Unknown field format character in DBCfmt.h"); + break; + } + } + + if (index_pos) + *index_pos = i; + + return recordsize; +} + +char* DBCFileLoader::AutoProduceData(char const* format, uint32& records, char**& indexTable) +{ + /* + format STRING, NA, FLOAT, NA, INT <=> + struct{ + char* field0, + float field1, + int field2 + }entry; + + this func will generate entry[rows] data; + */ + + typedef char* ptr; + if (strlen(format) != fieldCount) + return nullptr; + + //get struct size and index pos + int32 i; + uint32 recordsize = GetFormatRecordSize(format, &i); + + if (i >= 0) + { + uint32 maxi = 0; + //find max index + for (uint32 y = 0; y < recordCount; ++y) + { + uint32 ind = getRecord(y).getUInt(i); + if (ind > maxi) + maxi = ind; + } + + ++maxi; + records = maxi; + indexTable = new ptr[maxi]; + memset(indexTable, 0, maxi * sizeof(ptr)); + } + else + { + records = recordCount; + indexTable = new ptr[recordCount]; + } + + char* dataTable = new char[recordCount * recordsize]; + + uint32 offset = 0; + + for (uint32 y = 0; y < recordCount; ++y) + { + if (i >= 0) + indexTable[getRecord(y).getUInt(i)] = &dataTable[offset]; + else + indexTable[y] = &dataTable[offset]; + + for (uint32 x=0; x < fieldCount; ++x) + { + switch (format[x]) + { + case FT_FLOAT: + *((float*)(&dataTable[offset])) = getRecord(y).getFloat(x); + offset += sizeof(float); + break; + case FT_IND: + case FT_INT: + *((uint32*)(&dataTable[offset])) = getRecord(y).getUInt(x); + offset += sizeof(uint32); + break; + case FT_BYTE: + *((uint8*)(&dataTable[offset])) = getRecord(y).getUInt8(x); + offset += sizeof(uint8); + break; + case FT_STRING: + *((char**)(&dataTable[offset])) = nullptr; // will replace non-empty or "" strings in AutoProduceStrings + offset += sizeof(char*); + break; + case FT_LOGIC: + ASSERT(false && "Attempted to load DBC files that do not have field types that match what is in the core. Check DBCfmt.h or your DBC files."); + break; + case FT_NA: + case FT_NA_BYTE: + case FT_SORT: + break; + default: + ASSERT(false && "Unknown field format character in DBCfmt.h"); + break; + } + } + } + + return dataTable; +} + +char* DBCFileLoader::AutoProduceStrings(char const* format, char* dataTable) +{ + if (strlen(format) != fieldCount) + return nullptr; + + char* stringPool = new char[stringSize]; + memcpy(stringPool, stringTable, stringSize); + + uint32 offset = 0; + + for (uint32 y = 0; y < recordCount; ++y) + { + for (uint32 x = 0; x < fieldCount; ++x) + { + switch (format[x]) + { + case FT_FLOAT: + offset += sizeof(float); + break; + case FT_IND: + case FT_INT: + offset += sizeof(uint32); + break; + case FT_BYTE: + offset += sizeof(uint8); + break; + case FT_STRING: + { + // fill only not filled entries + char** slot = (char**)(&dataTable[offset]); + if (!*slot || !**slot) + { + const char * st = getRecord(y).getString(x); + *slot = stringPool + (st - (char const*)stringTable); + } + offset += sizeof(char*); + break; + } + case FT_LOGIC: + ASSERT(false && "Attempted to load DBC files that does not have field types that match what is in the core. Check DBCfmt.h or your DBC files."); + break; + case FT_NA: + case FT_NA_BYTE: + case FT_SORT: + break; + default: + ASSERT(false && "Unknown field format character in DBCfmt.h"); + break; + } + } + } + + return stringPool; +} diff --git a/src/common/DataStores/DBCFileLoader.h b/src/common/DataStores/DBCFileLoader.h new file mode 100644 index 00000000000..85cad0d9e7b --- /dev/null +++ b/src/common/DataStores/DBCFileLoader.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 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 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef DBC_FILE_LOADER_H +#define DBC_FILE_LOADER_H + +#include "Define.h" +#include "Utilities/ByteConverter.h" +#include <cassert> + +enum DbcFieldFormat +{ + FT_NA='x', //not used or unknown, 4 byte size + FT_NA_BYTE='X', //not used or unknown, byte + FT_STRING='s', //char* + FT_FLOAT='f', //float + FT_INT='i', //uint32 + FT_BYTE='b', //uint8 + FT_SORT='d', //sorted by this field, field is not included + FT_IND='n', //the same, but parsed to data + FT_LOGIC='l', //Logical (boolean) + FT_SQL_PRESENT='p', //Used in sql format to mark column present in sql dbc + FT_SQL_ABSENT='a' //Used in sql format to mark column absent in sql dbc +}; + +class TC_COMMON_API DBCFileLoader +{ + public: + DBCFileLoader(); + ~DBCFileLoader(); + + bool Load(const char *filename, const char *fmt); + + class Record + { + public: + float getFloat(size_t field) const + { + assert(field < file.fieldCount); + float val = *reinterpret_cast<float*>(offset+file.GetOffset(field)); + EndianConvert(val); + return val; + } + uint32 getUInt(size_t field) const + { + assert(field < file.fieldCount); + uint32 val = *reinterpret_cast<uint32*>(offset+file.GetOffset(field)); + EndianConvert(val); + return val; + } + uint8 getUInt8(size_t field) const + { + assert(field < file.fieldCount); + return *reinterpret_cast<uint8*>(offset+file.GetOffset(field)); + } + + const char *getString(size_t field) const + { + assert(field < file.fieldCount); + size_t stringOffset = getUInt(field); + assert(stringOffset < file.stringSize); + return reinterpret_cast<char*>(file.stringTable + stringOffset); + } + + private: + Record(DBCFileLoader &file_, unsigned char *offset_): offset(offset_), file(file_) { } + unsigned char *offset; + DBCFileLoader &file; + + friend class DBCFileLoader; + + }; + + // Get record by id + Record getRecord(size_t id); + /// Get begin iterator over records + + uint32 GetNumRows() const { return recordCount; } + uint32 GetRowSize() const { return recordSize; } + uint32 GetCols() const { return fieldCount; } + uint32 GetOffset(size_t id) const { return (fieldsOffset != nullptr && id < fieldCount) ? fieldsOffset[id] : 0; } + bool IsLoaded() const { return data != nullptr; } + char* AutoProduceData(char const* fmt, uint32& count, char**& indexTable); + char* AutoProduceStrings(char const* fmt, char* dataTable); + static uint32 GetFormatRecordSize(const char * format, int32 * index_pos = nullptr); + private: + + uint32 recordSize; + uint32 recordCount; + uint32 fieldCount; + uint32 stringSize; + uint32 *fieldsOffset; + unsigned char *data; + unsigned char *stringTable; + + DBCFileLoader(DBCFileLoader const& right) = delete; + DBCFileLoader& operator=(DBCFileLoader const& right) = delete; +}; +#endif |
