diff options
Diffstat (limited to 'src/server/shared')
24 files changed, 650 insertions, 1370 deletions
diff --git a/src/server/shared/DataStores/DBCDatabaseLoader.cpp b/src/server/shared/DataStores/DBCDatabaseLoader.cpp new file mode 100644 index 00000000000..3ef3e8f64c0 --- /dev/null +++ b/src/server/shared/DataStores/DBCDatabaseLoader.cpp @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> + * + * 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 "DBCDatabaseLoader.h" +#include "Common.h" +#include "DatabaseEnv.h" +#include "Errors.h" +#include "Log.h" +#include <sstream> + +DBCDatabaseLoader::DBCDatabaseLoader(std::string const& storageName, std::string const& dbFormatString, std::string const& primaryKey, char const* dbcFormatString) + : _formatString(dbFormatString), _indexName(primaryKey), _sqlTableName(storageName), _dbcFormat(dbcFormatString), _sqlIndexPos(0), _recordSize(0) +{ + // Convert dbc file name to sql table name + std::transform(_sqlTableName.begin(), _sqlTableName.end(), _sqlTableName.begin(), ::tolower); + for (char& c : _sqlTableName) + if (c == '.') + c = '_'; + + // Get sql index position + int32 indexPos = -1; + _recordSize = DBCFileLoader::GetFormatRecordSize(_dbcFormat, &indexPos); + ASSERT(indexPos >= 0); + ASSERT(_recordSize); + + uint32 uindexPos = uint32(indexPos); + for (uint32 x = 0; x < _formatString.size(); ++x) + { + // Count only fields present in sql + if (_formatString[x] == FT_SQL_PRESENT) + { + if (x == uindexPos) + break; + ++_sqlIndexPos; + } + } +} + +static char const* nullStr = ""; + +char* DBCDatabaseLoader::Load(uint32& records, char**& indexTable) +{ + std::ostringstream queryBuilder; + queryBuilder << "SELECT * FROM " << _sqlTableName + << " ORDER BY " << _indexName << " DESC;"; + + // no error if empty set + QueryResult result = WorldDatabase.Query(queryBuilder.str().c_str()); + if (!result) + return nullptr; + + // Check if sql index pos is valid + if (int32(result->GetFieldCount() - 1) < _sqlIndexPos) + { + ASSERT(false, "Invalid index pos for dbc:'%s'", _sqlTableName.c_str()); + return nullptr; + } + + // Resize index table + // database query *MUST* contain ORDER BY `index_field` DESC clause + uint32 indexTableSize = std::max(records, (*result)[_sqlIndexPos].GetUInt32() + 1); + if (indexTableSize > records) + { + char** tmpIdxTable = new char*[indexTableSize]; + memset(tmpIdxTable, 0, indexTableSize * sizeof(char*)); + memcpy(tmpIdxTable, indexTable, records * sizeof(char*)); + delete[] indexTable; + indexTable = tmpIdxTable; + } + + std::unique_ptr<char[]> dataTable = Trinity::make_unique<char[]>(result->GetRowCount() * _recordSize); + std::unique_ptr<uint32[]> newIndexes = Trinity::make_unique<uint32[]>(result->GetRowCount()); + uint32 newRecords = 0; + + // Insert sql data into the data array + do + { + Field* fields = result->Fetch(); + uint32 offset = 0; + + uint32 indexValue = fields[_sqlIndexPos].GetUInt32(); + + char* dataValue = indexTable[indexValue]; + if (!dataValue) + { + newIndexes[newRecords] = indexValue; + dataValue = &dataTable[newRecords++ * _recordSize]; + } + else + { + // Attempt to overwrite existing data + ASSERT(false, "Index %d already exists in dbc:'%s'", indexValue, _sqlTableName.c_str()); + return nullptr; + } + + uint32 columnNumber = 0; + uint32 sqlColumnNumber = 0; + + for (; columnNumber < _formatString.size(); ++columnNumber) + { + if (_formatString[columnNumber] == FT_SQL_ABSENT) + { + switch (_dbcFormat[columnNumber]) + { + case FT_FLOAT: + *reinterpret_cast<float*>(&dataValue[offset]) = 0.0f; + offset += 4; + break; + case FT_IND: + case FT_INT: + *reinterpret_cast<uint32*>(&dataValue[offset]) = uint32(0); + offset += 4; + break; + case FT_BYTE: + *reinterpret_cast<uint8*>(&dataValue[offset]) = uint8(0); + offset += 1; + break; + case FT_STRING: + *reinterpret_cast<char**>(&dataValue[offset]) = const_cast<char*>(nullStr); + offset += sizeof(char*); + break; + } + } + else if (_formatString[columnNumber] == FT_SQL_PRESENT) + { + bool validSqlColumn = true; + switch (_dbcFormat[columnNumber]) + { + case FT_FLOAT: + *reinterpret_cast<float*>(&dataValue[offset]) = fields[sqlColumnNumber].GetFloat(); + offset += 4; + break; + case FT_IND: + case FT_INT: + *reinterpret_cast<uint32*>(&dataValue[offset]) = fields[sqlColumnNumber].GetUInt32(); + offset += 4; + break; + case FT_BYTE: + *reinterpret_cast<uint8*>(&dataValue[offset]) = fields[sqlColumnNumber].GetUInt8(); + offset += 1; + break; + case FT_STRING: + ASSERT(false, "Unsupported data type in table '%s' at char %d", _sqlTableName.c_str(), columnNumber); + return nullptr; + case FT_SORT: + break; + default: + validSqlColumn = false; + break; + } + if (validSqlColumn && (columnNumber != (_formatString.size() - 1))) + sqlColumnNumber++; + } + else + { + ASSERT(false, "Incorrect sql format string '%s' at char %d", _sqlTableName.c_str(), columnNumber); + break; + } + } + + if (sqlColumnNumber != (result->GetFieldCount() - 1)) + { + ASSERT(false, "SQL and DBC format strings are not matching for table: '%s'", _sqlTableName.c_str()); + return nullptr; + } + + ASSERT(offset == _recordSize); + } while (result->NextRow()); + + ASSERT(newRecords == result->GetRowCount()); + + // insert new records to index table + for (uint32 i = 0; i < newRecords; ++i) + indexTable[newIndexes[i]] = &dataTable[i * _recordSize]; + + records = indexTableSize; + + return dataTable.release(); +} diff --git a/src/server/shared/DataStores/DBCDatabaseLoader.h b/src/server/shared/DataStores/DBCDatabaseLoader.h new file mode 100644 index 00000000000..153a0eb4dcb --- /dev/null +++ b/src/server/shared/DataStores/DBCDatabaseLoader.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> + * + * 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 DBCDatabaseLoader_h__ +#define DBCDatabaseLoader_h__ + +#include "DBCFileLoader.h" +#include <string> +#include <vector> + +struct TC_SHARED_API DBCDatabaseLoader +{ + DBCDatabaseLoader(std::string const& storageName, std::string const& dbFormatString, std::string const& primaryKey, char const* dbcFormatString); + + char* Load(uint32& records, char**& indexTable); + +private: + std::string const& _formatString; + std::string const& _indexName; + std::string _sqlTableName; + char const* _dbcFormat; + int32 _sqlIndexPos; + uint32 _recordSize; + + DBCDatabaseLoader(DBCDatabaseLoader const& right) = delete; + DBCDatabaseLoader& operator=(DBCDatabaseLoader const& right) = delete; +}; + +#endif // DBCDatabaseLoader_h__ diff --git a/src/server/shared/DataStores/DBCFileLoader.cpp b/src/server/shared/DataStores/DBCFileLoader.cpp deleted file mode 100644 index 8c92260e62d..00000000000 --- a/src/server/shared/DataStores/DBCFileLoader.cpp +++ /dev/null @@ -1,322 +0,0 @@ -/* - * 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(NULL), data(NULL), stringTable(NULL) { } - -bool DBCFileLoader::Load(const char* filename, const char* fmt) -{ - uint32 header; - if (data) - { - delete [] data; - data = NULL; - } - - 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(const char* 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(const char* format, uint32& records, char**& indexTable, uint32 sqlRecordCount, uint32 sqlHighestIndex, char*& sqlDataTable) -{ - /* - 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 NULL; - - //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; - } - - // If higher index avalible from sql - use it instead of dbcs - if (sqlHighestIndex > maxi) - maxi = sqlHighestIndex; - - ++maxi; - records = maxi; - indexTable = new ptr[maxi]; - memset(indexTable, 0, maxi * sizeof(ptr)); - } - else - { - records = recordCount + sqlRecordCount; - indexTable = new ptr[recordCount + sqlRecordCount]; - } - - char* dataTable = new char[(recordCount + sqlRecordCount) * 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])) = NULL; // 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; - } - } - } - - sqlDataTable = dataTable + offset; - - return dataTable; -} - -char* DBCFileLoader::AutoProduceStrings(const char* format, char* dataTable) -{ - if (strlen(format) != fieldCount) - return NULL; - - 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-(const char*)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/server/shared/DataStores/DBCFileLoader.h b/src/server/shared/DataStores/DBCFileLoader.h deleted file mode 100644 index 1c005a9e670..00000000000 --- a/src/server/shared/DataStores/DBCFileLoader.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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_SHARED_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 != NULL && id < fieldCount) ? fieldsOffset[id] : 0; } - bool IsLoaded() const { return data != NULL; } - char* AutoProduceData(const char* fmt, uint32& count, char**& indexTable, uint32 sqlRecordCount, uint32 sqlHighestIndex, char *& sqlDataTable); - char* AutoProduceStrings(const char* fmt, char* dataTable); - static uint32 GetFormatRecordSize(const char * format, int32 * index_pos = NULL); - 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 diff --git a/src/server/shared/DataStores/DBCStorageIterator.h b/src/server/shared/DataStores/DBCStorageIterator.h new file mode 100644 index 00000000000..be1e58db967 --- /dev/null +++ b/src/server/shared/DataStores/DBCStorageIterator.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> + * + * 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 DBCStorageIterator_h__ +#define DBCStorageIterator_h__ + +#include "Define.h" +#include <iterator> + +template <class T> +class DBCStorageIterator : public std::iterator<std::forward_iterator_tag, T> +{ + public: + DBCStorageIterator() : _index(nullptr), _pos(0), _end(0) { } + DBCStorageIterator(T** index, uint32 size, uint32 pos = 0) : _index(index), _pos(pos), _end(size) + { + if (_pos < _end) + { + while (_pos < _end && !_index[_pos]) + ++_pos; + } + } + + T const* operator->() { return _index[_pos]; } + T const* operator*() { return _index[_pos]; } + + bool operator==(DBCStorageIterator const& right) const { /*ASSERT(_index == right._index, "Iterator belongs to a different container")*/ return _pos == right._pos; } + bool operator!=(DBCStorageIterator const& right) const { return !(*this == right); } + + DBCStorageIterator& operator++() + { + if (_pos < _end) + { + do + ++_pos; + while (_pos < _end && !_index[_pos]); + } + + return *this; + } + + DBCStorageIterator operator++(int) + { + DBCStorageIterator tmp = *this; + ++*this; + return tmp; + } + + private: + T** _index; + uint32 _pos; + uint32 _end; +}; + +#endif // DBCStorageIterator_h__ diff --git a/src/server/shared/DataStores/DBCStore.cpp b/src/server/shared/DataStores/DBCStore.cpp new file mode 100644 index 00000000000..30cae057f90 --- /dev/null +++ b/src/server/shared/DataStores/DBCStore.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> + * + * 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 "DBCStore.h" +#include "DBCDatabaseLoader.h" + +DBCStorageBase::DBCStorageBase(char const* fmt) : _fieldCount(0), _fileFormat(fmt), _dataTable(nullptr), _indexTableSize(0) +{ +} + +DBCStorageBase::~DBCStorageBase() +{ + delete[] _dataTable; + delete[] _dataTableEx; + for (char* strings : _stringPool) + delete[] strings; +} + +bool DBCStorageBase::Load(std::string const& path, char**& indexTable) +{ + indexTable = nullptr; + + DBCFileLoader dbc; + // Check if load was sucessful, only then continue + if (!dbc.Load(path.c_str(), _fileFormat)) + return false; + + _fieldCount = dbc.GetCols(); + + // load raw non-string data + _dataTable = dbc.AutoProduceData(_fileFormat, _indexTableSize, indexTable); + + // load strings from dbc data + if (char* stringBlock = dbc.AutoProduceStrings(_fileFormat, _dataTable)) + _stringPool.push_back(stringBlock); + + // error in dbc file at loading if NULL + return indexTable != nullptr; +} + +bool DBCStorageBase::LoadStringsFrom(std::string const& path, char** indexTable) +{ + // DBC must be already loaded using Load + if (!indexTable) + return false; + + DBCFileLoader dbc; + // Check if load was successful, only then continue + if (!dbc.Load(path.c_str(), _fileFormat)) + return false; + + // load strings from another locale dbc data + if (char* stringBlock = dbc.AutoProduceStrings(_fileFormat, _dataTable)) + _stringPool.push_back(stringBlock); + + return true; +} + +void DBCStorageBase::LoadFromDB(std::string const& path, std::string const& dbFormat, std::string const& primaryKey, char**& indexTable) +{ + _dataTableEx = DBCDatabaseLoader(path, dbFormat, primaryKey, _fileFormat).Load(_indexTableSize, indexTable); +} diff --git a/src/server/shared/DataStores/DBCStore.h b/src/server/shared/DataStores/DBCStore.h index b11bb0b74d4..e04f434cf89 100644 --- a/src/server/shared/DataStores/DBCStore.h +++ b/src/server/shared/DataStores/DBCStore.h @@ -19,289 +19,83 @@ #ifndef DBCSTORE_H #define DBCSTORE_H -#include "DBCFileLoader.h" -#include "Logging/Log.h" -#include "Field.h" -#include "DatabaseWorkerPool.h" -#include "Implementation/WorldDatabase.h" -#include "DatabaseEnv.h" +#include "Common.h" +#include "DBCStorageIterator.h" +#include <vector> -struct SqlDbc + /// Interface class for common access +class TC_SHARED_API DBCStorageBase { - std::string const* formatString; - std::string const* indexName; - std::string sqlTableName; - int32 indexPos; - int32 sqlIndexPos; - SqlDbc(std::string const* _filename, std::string const* _format, std::string const* _idname, char const* fmt) - : formatString(_format), indexName (_idname), sqlIndexPos(0) - { - // Convert dbc file name to sql table name - sqlTableName = *_filename; - for (uint32 i = 0; i< sqlTableName.size(); ++i) - { - if (isalpha(sqlTableName[i])) - sqlTableName[i] = char(tolower(sqlTableName[i])); - else if (sqlTableName[i] == '.') - sqlTableName[i] = '_'; - } - - // Get sql index position - DBCFileLoader::GetFormatRecordSize(fmt, &indexPos); - if (indexPos >= 0) - { - uint32 uindexPos = uint32(indexPos); - for (uint32 x = 0; x < formatString->size(); ++x) - { - // Count only fields present in sql - if ((*formatString)[x] == FT_SQL_PRESENT) - { - if (x == uindexPos) - break; - ++sqlIndexPos; - } - } - } - } - -private: - SqlDbc(SqlDbc const& right) = delete; - SqlDbc& operator=(SqlDbc const& right) = delete; + public: + DBCStorageBase(char const* fmt); + virtual ~DBCStorageBase(); + + char const* GetFormat() const { return _fileFormat; } + uint32 GetFieldCount() const { return _fieldCount; } + + virtual bool Load(std::string const& path) = 0; + virtual bool LoadStringsFrom(std::string const& path) = 0; + virtual void LoadFromDB(std::string const& path, std::string const& dbFormat, std::string const& primaryKey) = 0; + + protected: + bool Load(std::string const& path, char**& indexTable); + bool LoadStringsFrom(std::string const& path, char** indexTable); + void LoadFromDB(std::string const& path, std::string const& dbFormat, std::string const& primaryKey, char**& indexTable); + + uint32 _fieldCount; + char const* _fileFormat; + char* _dataTable; + char* _dataTableEx; + std::vector<char*> _stringPool; + uint32 _indexTableSize; }; -template<class T> -class DBCStorage +template <class T> +class DBCStorage : public DBCStorageBase { - typedef std::list<char*> StringPoolList; public: - explicit DBCStorage(char const* f) - : fmt(f), nCount(0), fieldCount(0), dataTable(NULL) - { - indexTable.asT = NULL; - } + typedef DBCStorageIterator<T> iterator; - ~DBCStorage() { Clear(); } - - T const* LookupEntry(uint32 id) const + explicit DBCStorage(char const* fmt) : DBCStorageBase(fmt) { - return (id >= nCount) ? NULL : indexTable.asT[id]; + _indexTable.AsT = nullptr; } - T const* AssertEntry(uint32 id) const + ~DBCStorage() { - T const* entry = LookupEntry(id); - ASSERT(entry); - return entry; + delete[] reinterpret_cast<char*>(_indexTable.AsT); } - uint32 GetNumRows() const { return nCount; } - char const* GetFormat() const { return fmt; } - uint32 GetFieldCount() const { return fieldCount; } - - bool Load(char const* fn, SqlDbc* sql) - { - DBCFileLoader dbc; - // Check if load was sucessful, only then continue - if (!dbc.Load(fn, fmt)) - return false; - - uint32 sqlRecordCount = 0; - uint32 sqlHighestIndex = 0; - Field* fields = NULL; - QueryResult result = QueryResult(NULL); - // Load data from sql - if (sql) - { - std::string query = "SELECT * FROM " + sql->sqlTableName; - if (sql->indexPos >= 0) - query +=" ORDER BY " + *sql->indexName + " DESC"; - query += ';'; - - - result = WorldDatabase.Query(query.c_str()); - if (result) - { - sqlRecordCount = uint32(result->GetRowCount()); - if (sql->indexPos >= 0) - { - fields = result->Fetch(); - sqlHighestIndex = fields[sql->sqlIndexPos].GetUInt32(); - } - - // Check if sql index pos is valid - if (int32(result->GetFieldCount() - 1) < sql->sqlIndexPos) - { - TC_LOG_ERROR("server.loading", "Invalid index pos for dbc:'%s'", sql->sqlTableName.c_str()); - return false; - } - } - } - - char* sqlDataTable = NULL; - fieldCount = dbc.GetCols(); - - dataTable = reinterpret_cast<T*>(dbc.AutoProduceData(fmt, nCount, indexTable.asChar, - sqlRecordCount, sqlHighestIndex, sqlDataTable)); + T const* LookupEntry(uint32 id) const { return (id >= _indexTableSize) ? nullptr : _indexTable.AsT[id]; } + T const* AssertEntry(uint32 id) const { return ASSERT_NOTNULL(LookupEntry(id)); } - stringPoolList.push_back(dbc.AutoProduceStrings(fmt, reinterpret_cast<char*>(dataTable))); + uint32 GetNumRows() const { return _indexTableSize; } - // Insert sql data into arrays - if (result) - { - if (indexTable.asT) - { - uint32 offset = 0; - uint32 rowIndex = dbc.GetNumRows(); - do - { - if (!fields) - fields = result->Fetch(); - - if (sql->indexPos >= 0) - { - uint32 id = fields[sql->sqlIndexPos].GetUInt32(); - if (indexTable.asT[id]) - { - TC_LOG_ERROR("server.loading", "Index %d already exists in dbc:'%s'", id, sql->sqlTableName.c_str()); - return false; - } - - indexTable.asT[id] = reinterpret_cast<T*>(&sqlDataTable[offset]); - } - else - indexTable.asT[rowIndex]= reinterpret_cast<T*>(&sqlDataTable[offset]); - - uint32 columnNumber = 0; - uint32 sqlColumnNumber = 0; - - for (; columnNumber < sql->formatString->size(); ++columnNumber) - { - if ((*sql->formatString)[columnNumber] == FT_SQL_ABSENT) - { - switch (fmt[columnNumber]) - { - case FT_FLOAT: - *reinterpret_cast<float*>(&sqlDataTable[offset]) = 0.0f; - offset += 4; - break; - case FT_IND: - case FT_INT: - *reinterpret_cast<uint32*>(&sqlDataTable[offset]) = uint32(0); - offset += 4; - break; - case FT_BYTE: - *reinterpret_cast<uint8*>(&sqlDataTable[offset]) = uint8(0); - offset += 1; - break; - case FT_STRING: - // Beginning of the pool - empty string - *reinterpret_cast<char**>(&sqlDataTable[offset]) = stringPoolList.back(); - offset += sizeof(char*); - break; - } - } - else if ((*sql->formatString)[columnNumber] == FT_SQL_PRESENT) - { - bool validSqlColumn = true; - switch (fmt[columnNumber]) - { - case FT_FLOAT: - *reinterpret_cast<float*>(&sqlDataTable[offset]) = fields[sqlColumnNumber].GetFloat(); - offset += 4; - break; - case FT_IND: - case FT_INT: - *reinterpret_cast<uint32*>(&sqlDataTable[offset]) = fields[sqlColumnNumber].GetUInt32(); - offset += 4; - break; - case FT_BYTE: - *reinterpret_cast<uint8*>(&sqlDataTable[offset]) = fields[sqlColumnNumber].GetUInt8(); - offset += 1; - break; - case FT_STRING: - TC_LOG_ERROR("server.loading", "Unsupported data type in table '%s' at char %d", sql->sqlTableName.c_str(), columnNumber); - return false; - case FT_SORT: - break; - default: - validSqlColumn = false; - break; - } - if (validSqlColumn && (columnNumber != (sql->formatString->size()-1))) - sqlColumnNumber++; - } - else - { - TC_LOG_ERROR("server.loading", "Incorrect sql format string '%s' at char %d", sql->sqlTableName.c_str(), columnNumber); - return false; - } - } - - if (sqlColumnNumber != (result->GetFieldCount() - 1)) - { - TC_LOG_ERROR("server.loading", "SQL and DBC format strings are not matching for table: '%s'", sql->sqlTableName.c_str()); - return false; - } - - fields = NULL; - ++rowIndex; - } while (result->NextRow()); - } - } - - // error in dbc file at loading if NULL - return indexTable.asT != NULL; + bool Load(std::string const& path) override + { + return DBCStorageBase::Load(path, _indexTable.AsChar); } - bool LoadStringsFrom(char const* fn) + bool LoadStringsFrom(std::string const& path) override { - // DBC must be already loaded using Load - if (!indexTable.asT) - return false; - - DBCFileLoader dbc; - // Check if load was successful, only then continue - if (!dbc.Load(fn, fmt)) - return false; - - stringPoolList.push_back(dbc.AutoProduceStrings(fmt, reinterpret_cast<char*>(dataTable))); - - return true; + return DBCStorageBase::LoadStringsFrom(path, _indexTable.AsChar); } - void Clear() + void LoadFromDB(std::string const& path, std::string const& dbFormat, std::string const& primaryKey) override { - if (!indexTable.asT) - return; - - delete[] reinterpret_cast<char*>(indexTable.asT); - indexTable.asT = NULL; - delete[] reinterpret_cast<char*>(dataTable); - dataTable = NULL; - - while (!stringPoolList.empty()) - { - delete[] stringPoolList.front(); - stringPoolList.pop_front(); - } - - nCount = 0; + DBCStorageBase::LoadFromDB(path, dbFormat, primaryKey, _indexTable.AsChar); } - private: - char const* fmt; - uint32 nCount; - uint32 fieldCount; + iterator begin() { return iterator(_indexTable.AsT, _indexTableSize); } + iterator end() { return iterator(_indexTable.AsT, _indexTableSize, _indexTableSize); } + private: union { - T** asT; - char** asChar; + T** AsT; + char** AsChar; } - indexTable; - - T* dataTable; - StringPoolList stringPoolList; + _indexTable; DBCStorage(DBCStorage const& right) = delete; DBCStorage& operator=(DBCStorage const& right) = delete; diff --git a/src/server/shared/Dynamic/FactoryHolder.h b/src/server/shared/Dynamic/FactoryHolder.h index 9c9e2ada5e0..9e67fe11467 100644 --- a/src/server/shared/Dynamic/FactoryHolder.h +++ b/src/server/shared/Dynamic/FactoryHolder.h @@ -20,8 +20,8 @@ #define TRINITY_FACTORY_HOLDER #include "Define.h" -#include "Dynamic/TypeList.h" #include "ObjectRegistry.h" +#include "TypeList.h" /** FactoryHolder holds a factory object of a specific type */ diff --git a/src/server/shared/Dynamic/LinkedList.h b/src/server/shared/Dynamic/LinkedList.h index 0d64c337cbe..74f4ca553f4 100644 --- a/src/server/shared/Dynamic/LinkedList.h +++ b/src/server/shared/Dynamic/LinkedList.h @@ -165,13 +165,13 @@ class LinkedListHead { // construct with node pointer _Pnode } - Iterator& operator=(Iterator const &_Right) + Iterator& operator=(Iterator const& _Right) { _Ptr = _Right._Ptr; return *this; } - Iterator& operator=(const_pointer const &_Right) + Iterator& operator=(const_pointer const& _Right) { _Ptr = pointer(_Right); return *this; @@ -213,22 +213,22 @@ class LinkedListHead return (_Tmp); } - bool operator==(Iterator const &_Right) const + bool operator==(Iterator const& _Right) const { // test for iterator equality return (_Ptr == _Right._Ptr); } - bool operator!=(Iterator const &_Right) const + bool operator!=(Iterator const& _Right) const { // test for iterator inequality return (!(*this == _Right)); } - bool operator==(pointer const &_Right) const + bool operator==(pointer const& _Right) const { // test for pointer equality return (_Ptr != _Right); } - bool operator!=(pointer const &_Right) const + bool operator!=(pointer const& _Right) const { // test for pointer equality return (!(*this == _Right)); } diff --git a/src/server/shared/Dynamic/LinkedReference/Reference.h b/src/server/shared/Dynamic/LinkedReference/Reference.h index c0c4ec21a80..4002de2d584 100644 --- a/src/server/shared/Dynamic/LinkedReference/Reference.h +++ b/src/server/shared/Dynamic/LinkedReference/Reference.h @@ -40,7 +40,7 @@ template <class TO, class FROM> class Reference : public LinkedListElement // Tell our refFrom (source) object, that the link is cut (Target destroyed) virtual void sourceObjectDestroyLink() = 0; public: - Reference() { iRefTo = NULL; iRefFrom = NULL; } + Reference() { iRefTo = nullptr; iRefFrom = nullptr; } virtual ~Reference() { } // Create new link @@ -49,7 +49,7 @@ template <class TO, class FROM> class Reference : public LinkedListElement ASSERT(fromObj); // fromObj MUST not be NULL if (isValid()) unlink(); - if (toObj != NULL) + if (toObj != nullptr) { iRefTo = toObj; iRefFrom = fromObj; @@ -63,8 +63,8 @@ template <class TO, class FROM> class Reference : public LinkedListElement { targetObjectDestroyLink(); delink(); - iRefTo = NULL; - iRefFrom = NULL; + iRefTo = nullptr; + iRefFrom = nullptr; } // Link is invalid due to destruction of referenced target object. Call comes from the refTo object @@ -73,12 +73,12 @@ template <class TO, class FROM> class Reference : public LinkedListElement { sourceObjectDestroyLink(); delink(); - iRefTo = NULL; + iRefTo = nullptr; } bool isValid() const // Only check the iRefTo { - return iRefTo != NULL; + return iRefTo != nullptr; } Reference<TO, FROM> * next() { return((Reference<TO, FROM> *) LinkedListElement::next()); } diff --git a/src/server/shared/Dynamic/ObjectRegistry.h b/src/server/shared/Dynamic/ObjectRegistry.h index 5f614819b13..8ed72c476e8 100644 --- a/src/server/shared/Dynamic/ObjectRegistry.h +++ b/src/server/shared/Dynamic/ObjectRegistry.h @@ -82,6 +82,8 @@ class ObjectRegistry final // non instanceable, only static ObjectRegistry() { } ~ObjectRegistry() { } + ObjectRegistry(ObjectRegistry const&) = delete; + ObjectRegistry& operator=(ObjectRegistry const&) = delete; }; #endif diff --git a/src/server/shared/Dynamic/TypeContainer.h b/src/server/shared/Dynamic/TypeContainer.h deleted file mode 100644 index 7e825136755..00000000000 --- a/src/server/shared/Dynamic/TypeContainer.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * 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 TRINITY_TYPECONTAINER_H -#define TRINITY_TYPECONTAINER_H - -/* - * Here, you'll find a series of containers that allow you to hold multiple - * types of object at the same time. - */ - -#include <map> -#include <unordered_map> -#include <vector> -#include "Define.h" -#include "Dynamic/TypeList.h" -#include "GridRefManager.h" - -/* - * @class ContainerMapList is a mulit-type container for map elements - * By itself its meaningless but collaborate along with TypeContainers, - * it become the most powerfully container in the whole system. - */ -template<class OBJECT> -struct ContainerMapList -{ - //std::map<OBJECT_HANDLE, OBJECT *> _element; - GridRefManager<OBJECT> _element; -}; - -template<> -struct ContainerMapList<TypeNull> /* nothing is in type null */ -{ -}; - -template<class H, class T> -struct ContainerMapList<TypeList<H, T> > -{ - ContainerMapList<H> _elements; - ContainerMapList<T> _TailElements; -}; - -template<class OBJECT, class KEY_TYPE> -struct ContainerUnorderedMap -{ - std::unordered_map<KEY_TYPE, OBJECT*> _element; -}; - -template<class KEY_TYPE> -struct ContainerUnorderedMap<TypeNull, KEY_TYPE> -{ -}; - -template<class H, class T, class KEY_TYPE> -struct ContainerUnorderedMap<TypeList<H, T>, KEY_TYPE> -{ - ContainerUnorderedMap<H, KEY_TYPE> _elements; - ContainerUnorderedMap<T, KEY_TYPE> _TailElements; -}; - -#include "TypeContainerFunctions.h" - -/* - * @class TypeMapContainer contains a fixed number of types and is - * determined at compile time. This is probably the most complicated - * class and do its simplest thing, that is, holds objects - * of different types. - */ - -template<class OBJECT_TYPES> -class TypeMapContainer -{ - public: - template<class SPECIFIC_TYPE> size_t Count() const { return Trinity::Count(i_elements, (SPECIFIC_TYPE*)NULL); } - - /// inserts a specific object into the container - template<class SPECIFIC_TYPE> - bool insert(SPECIFIC_TYPE *obj) - { - SPECIFIC_TYPE* t = Trinity::Insert(i_elements, obj); - return (t != NULL); - } - - /// Removes the object from the container, and returns the removed object - //template<class SPECIFIC_TYPE> - //bool remove(SPECIFIC_TYPE* obj) - //{ - // SPECIFIC_TYPE* t = Trinity::Remove(i_elements, obj); - // return (t != NULL); - //} - - ContainerMapList<OBJECT_TYPES> & GetElements(void) { return i_elements; } - const ContainerMapList<OBJECT_TYPES> & GetElements(void) const { return i_elements;} - - private: - ContainerMapList<OBJECT_TYPES> i_elements; -}; - -template<class OBJECT_TYPES, class KEY_TYPE> -class TypeUnorderedMapContainer -{ -public: - template<class SPECIFIC_TYPE> - bool Insert(KEY_TYPE const& handle, SPECIFIC_TYPE* obj) - { - return Trinity::Insert(_elements, handle, obj); - } - - template<class SPECIFIC_TYPE> - bool Remove(KEY_TYPE const& handle) - { - return Trinity::Remove(_elements, handle, (SPECIFIC_TYPE*)NULL); - } - - template<class SPECIFIC_TYPE> - SPECIFIC_TYPE* Find(KEY_TYPE const& handle) - { - return Trinity::Find(_elements, handle, (SPECIFIC_TYPE*)NULL); - } - - ContainerUnorderedMap<OBJECT_TYPES, KEY_TYPE>& GetElements() { return _elements; } - ContainerUnorderedMap<OBJECT_TYPES, KEY_TYPE> const& GetElements() const { return _elements; } - -private: - ContainerUnorderedMap<OBJECT_TYPES, KEY_TYPE> _elements; -}; - -#endif diff --git a/src/server/shared/Dynamic/TypeContainerFunctions.h b/src/server/shared/Dynamic/TypeContainerFunctions.h deleted file mode 100644 index 97d20922a05..00000000000 --- a/src/server/shared/Dynamic/TypeContainerFunctions.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - * 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 TYPECONTAINER_FUNCTIONS_H -#define TYPECONTAINER_FUNCTIONS_H - -/* - * Here you'll find a list of helper functions to make - * the TypeContainer usefull. Without it, its hard - * to access or mutate the container. - */ - -#include "Define.h" -#include "Dynamic/TypeList.h" -#include <map> -#include <unordered_map> - -namespace Trinity -{ - // Helpers - // Insert helpers - template<class SPECIFIC_TYPE, class KEY_TYPE> - bool Insert(ContainerUnorderedMap<SPECIFIC_TYPE, KEY_TYPE>& elements, KEY_TYPE const& handle, SPECIFIC_TYPE* obj) - { - auto i = elements._element.find(handle); - if (i == elements._element.end()) - { - elements._element[handle] = obj; - return true; - } - else - { - ASSERT(i->second == obj, "Object with certain key already in but objects are different!"); - return false; - } - } - - template<class SPECIFIC_TYPE, class KEY_TYPE> - bool Insert(ContainerUnorderedMap<TypeNull, KEY_TYPE>& /*elements*/, KEY_TYPE const& /*handle*/, SPECIFIC_TYPE* /*obj*/) - { - return false; - } - - template<class SPECIFIC_TYPE, class KEY_TYPE, class T> - bool Insert(ContainerUnorderedMap<T, KEY_TYPE>& /*elements*/, KEY_TYPE const& /*handle*/, SPECIFIC_TYPE* /*obj*/) - { - return false; - } - - template<class SPECIFIC_TYPE, class KEY_TYPE, class H, class T> - bool Insert(ContainerUnorderedMap<TypeList<H, T>, KEY_TYPE>& elements, KEY_TYPE const& handle, SPECIFIC_TYPE* obj) - { - bool ret = Insert(elements._elements, handle, obj); - return ret ? ret : Insert(elements._TailElements, handle, obj); - } - - // Find helpers - template<class SPECIFIC_TYPE, class KEY_TYPE> - SPECIFIC_TYPE* Find(ContainerUnorderedMap<SPECIFIC_TYPE, KEY_TYPE> const& elements, KEY_TYPE const& handle, SPECIFIC_TYPE* /*obj*/) - { - auto i = elements._element.find(handle); - if (i == elements._element.end()) - return nullptr; - else - return i->second; - } - - template<class SPECIFIC_TYPE, class KEY_TYPE> - SPECIFIC_TYPE* Find(ContainerUnorderedMap<TypeNull, KEY_TYPE> const& /*elements*/, KEY_TYPE const& /*handle*/, SPECIFIC_TYPE* /*obj*/) - { - return nullptr; - } - - template<class SPECIFIC_TYPE, class KEY_TYPE, class T> - SPECIFIC_TYPE* Find(ContainerUnorderedMap<T, KEY_TYPE> const& /*elements*/, KEY_TYPE const& /*handle*/, SPECIFIC_TYPE* /*obj*/) - { - return nullptr; - } - - template<class SPECIFIC_TYPE, class KEY_TYPE, class H, class T> - SPECIFIC_TYPE* Find(ContainerUnorderedMap<TypeList<H, T>, KEY_TYPE> const& elements, KEY_TYPE const& handle, SPECIFIC_TYPE* /*obj*/) - { - SPECIFIC_TYPE* ret = Find(elements._elements, handle, (SPECIFIC_TYPE*)nullptr); - return ret ? ret : Find(elements._TailElements, handle, (SPECIFIC_TYPE*)nullptr); - } - - // Erase helpers - template<class SPECIFIC_TYPE, class KEY_TYPE> - bool Remove(ContainerUnorderedMap<SPECIFIC_TYPE, KEY_TYPE>& elements, KEY_TYPE const& handle, SPECIFIC_TYPE* /*obj*/) - { - elements._element.erase(handle); - return true; - } - - template<class SPECIFIC_TYPE, class KEY_TYPE> - bool Remove(ContainerUnorderedMap<TypeNull, KEY_TYPE>& /*elements*/, KEY_TYPE const& /*handle*/, SPECIFIC_TYPE* /*obj*/) - { - return false; - } - - template<class SPECIFIC_TYPE, class KEY_TYPE, class T> - bool Remove(ContainerUnorderedMap<T, KEY_TYPE>& /*elements*/, KEY_TYPE const& /*handle*/, SPECIFIC_TYPE* /*obj*/) - { - return false; - } - - template<class SPECIFIC_TYPE, class KEY_TYPE, class H, class T> - bool Remove(ContainerUnorderedMap<TypeList<H, T>, KEY_TYPE>& elements, KEY_TYPE const& handle, SPECIFIC_TYPE* /*obj*/) - { - bool ret = Remove(elements._elements, handle, (SPECIFIC_TYPE*)nullptr); - return ret ? ret : Remove(elements._TailElements, handle, (SPECIFIC_TYPE*)nullptr); - } - - /* ContainerMapList Helpers */ - // count functions - template<class SPECIFIC_TYPE> - size_t Count(ContainerMapList<SPECIFIC_TYPE> const& elements, SPECIFIC_TYPE* /*fake*/) - { - return elements._element.getSize(); - } - - template<class SPECIFIC_TYPE> - size_t Count(ContainerMapList<TypeNull> const& /*elements*/, SPECIFIC_TYPE* /*fake*/) - { - return 0; - } - - template<class SPECIFIC_TYPE, class T> - size_t Count(ContainerMapList<T> const& /*elements*/, SPECIFIC_TYPE* /*fake*/) - { - return 0; - } - - template<class SPECIFIC_TYPE, class T> - size_t Count(ContainerMapList<TypeList<SPECIFIC_TYPE, T>> const& elements, SPECIFIC_TYPE* fake) - { - return Count(elements._elements, fake); - } - - template<class SPECIFIC_TYPE, class H, class T> - size_t Count(ContainerMapList<TypeList<H, T>> const& elements, SPECIFIC_TYPE* fake) - { - return Count(elements._TailElements, fake); - } - - // non-const insert functions - template<class SPECIFIC_TYPE> - SPECIFIC_TYPE* Insert(ContainerMapList<SPECIFIC_TYPE>& elements, SPECIFIC_TYPE* obj) - { - //elements._element[hdl] = obj; - obj->AddToGrid(elements._element); - return obj; - } - - template<class SPECIFIC_TYPE> - SPECIFIC_TYPE* Insert(ContainerMapList<TypeNull>& /*elements*/, SPECIFIC_TYPE* /*obj*/) - { - return nullptr; - } - - // this is a missed - template<class SPECIFIC_TYPE, class T> - SPECIFIC_TYPE* Insert(ContainerMapList<T>& /*elements*/, SPECIFIC_TYPE* /*obj*/) - { - return nullptr; // a missed - } - - // Recursion - template<class SPECIFIC_TYPE, class H, class T> - SPECIFIC_TYPE* Insert(ContainerMapList<TypeList<H, T>>& elements, SPECIFIC_TYPE* obj) - { - SPECIFIC_TYPE* t = Insert(elements._elements, obj); - return (t != nullptr ? t : Insert(elements._TailElements, obj)); - } - - //// non-const remove method - //template<class SPECIFIC_TYPE> SPECIFIC_TYPE* Remove(ContainerMapList<SPECIFIC_TYPE> & /*elements*/, SPECIFIC_TYPE *obj) - //{ - // obj->GetGridRef().unlink(); - // return obj; - //} - - //template<class SPECIFIC_TYPE> SPECIFIC_TYPE* Remove(ContainerMapList<TypeNull> &/*elements*/, SPECIFIC_TYPE * /*obj*/) - //{ - // return nullptr; - //} - - //// this is a missed - //template<class SPECIFIC_TYPE, class T> SPECIFIC_TYPE* Remove(ContainerMapList<T> &/*elements*/, SPECIFIC_TYPE * /*obj*/) - //{ - // return nullptr; // a missed - //} - - //template<class SPECIFIC_TYPE, class T, class H> SPECIFIC_TYPE* Remove(ContainerMapList<TypeList<H, T> > &elements, SPECIFIC_TYPE *obj) - //{ - // // The head element is bad - // SPECIFIC_TYPE* t = Remove(elements._elements, obj); - // return (t != nullptr ? t : Remove(elements._TailElements, obj)); - //} -} -#endif - diff --git a/src/server/shared/Dynamic/TypeContainerVisitor.h b/src/server/shared/Dynamic/TypeContainerVisitor.h deleted file mode 100644 index f15cfe66758..00000000000 --- a/src/server/shared/Dynamic/TypeContainerVisitor.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 TRINITY_TYPECONTAINERVISITOR_H -#define TRINITY_TYPECONTAINERVISITOR_H - -/* - * @class TypeContainerVisitor is implemented as a visitor pattern. It is - * a visitor to the TypeContainerList or TypeContainerMapList. The visitor has - * to overload its types as a visit method is called. - */ - -#include "Define.h" -#include "Dynamic/TypeContainer.h" - -// forward declaration -template<class T, class Y> class TypeContainerVisitor; - -// visitor helper -template<class VISITOR, class TYPE_CONTAINER> void VisitorHelper(VISITOR &v, TYPE_CONTAINER &c) -{ - v.Visit(c); -} - -// terminate condition container map list -template<class VISITOR> void VisitorHelper(VISITOR &/*v*/, ContainerMapList<TypeNull> &/*c*/) { } - -template<class VISITOR, class T> void VisitorHelper(VISITOR &v, ContainerMapList<T> &c) -{ - v.Visit(c._element); -} - -// recursion container map list -template<class VISITOR, class H, class T> void VisitorHelper(VISITOR &v, ContainerMapList<TypeList<H, T> > &c) -{ - VisitorHelper(v, c._elements); - VisitorHelper(v, c._TailElements); -} - -// for TypeMapContainer -template<class VISITOR, class OBJECT_TYPES> void VisitorHelper(VISITOR &v, TypeMapContainer<OBJECT_TYPES> &c) -{ - VisitorHelper(v, c.GetElements()); -} - -// TypeUnorderedMapContainer -template<class VISITOR, class KEY_TYPE> -void VisitorHelper(VISITOR& /*v*/, ContainerUnorderedMap<TypeNull, KEY_TYPE>& /*c*/) { } - -template<class VISITOR, class KEY_TYPE, class T> -void VisitorHelper(VISITOR& v, ContainerUnorderedMap<T, KEY_TYPE>& c) -{ - v.Visit(c._element); -} - -template<class VISITOR, class KEY_TYPE, class H, class T> -void VisitorHelper(VISITOR& v, ContainerUnorderedMap<TypeList<H, T>, KEY_TYPE>& c) -{ - VisitorHelper(v, c._elements); - VisitorHelper(v, c._TailElements); -} - -template<class VISITOR, class OBJECT_TYPES, class KEY_TYPE> -void VisitorHelper(VISITOR& v, TypeUnorderedMapContainer<OBJECT_TYPES, KEY_TYPE>& c) -{ - VisitorHelper(v, c.GetElements()); -} - -template<class VISITOR, class TYPE_CONTAINER> -class TypeContainerVisitor -{ - public: - TypeContainerVisitor(VISITOR &v) : i_visitor(v) { } - - void Visit(TYPE_CONTAINER &c) - { - VisitorHelper(i_visitor, c); - } - - void Visit(const TYPE_CONTAINER &c) const - { - VisitorHelper(i_visitor, c); - } - - private: - VISITOR &i_visitor; -}; -#endif - diff --git a/src/server/shared/Memory.h b/src/server/shared/Memory.h index 7aeb4dc3f0a..e41e4baf025 100644 --- a/src/server/shared/Memory.h +++ b/src/server/shared/Memory.h @@ -1,4 +1,19 @@ - +/* + * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> + * + * 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 _MEMORY_H #define _MEMORY_H diff --git a/src/server/shared/Networking/AsyncAcceptor.h b/src/server/shared/Networking/AsyncAcceptor.h index 7c827ec4454..dc6c5332c23 100644 --- a/src/server/shared/Networking/AsyncAcceptor.h +++ b/src/server/shared/Networking/AsyncAcceptor.h @@ -19,7 +19,8 @@ #define __ASYNCACCEPT_H_ #include "Log.h" -#include <boost/asio.hpp> +#include <boost/asio/ip/tcp.hpp> +#include <boost/asio/ip/address.hpp> #include <functional> #include <atomic> diff --git a/src/server/shared/Packets/ByteBuffer.cpp b/src/server/shared/Packets/ByteBuffer.cpp index f9860f273ed..a4ab6e1daf7 100644 --- a/src/server/shared/Packets/ByteBuffer.cpp +++ b/src/server/shared/Packets/ByteBuffer.cpp @@ -17,11 +17,13 @@ */ #include "ByteBuffer.h" +#include "Errors.h" #include "MessageBuffer.h" #include "Common.h" #include "Log.h" - +#include "Util.h" #include <sstream> +#include <ctime> ByteBuffer::ByteBuffer(MessageBuffer&& buffer) : _rpos(0), _wpos(0), _storage(buffer.Move()) { @@ -51,6 +53,78 @@ ByteBufferSourceException::ByteBufferSourceException(size_t pos, size_t size, message().assign(ss.str()); } +ByteBuffer& ByteBuffer::operator>>(float& value) +{ + value = read<float>(); + if (!std::isfinite(value)) + throw ByteBufferException(); + return *this; +} + +ByteBuffer& ByteBuffer::operator>>(double& value) +{ + value = read<double>(); + if (!std::isfinite(value)) + throw ByteBufferException(); + return *this; +} + +uint32 ByteBuffer::ReadPackedTime() +{ + uint32 packedDate = read<uint32>(); + tm lt = tm(); + + lt.tm_min = packedDate & 0x3F; + lt.tm_hour = (packedDate >> 6) & 0x1F; + //lt.tm_wday = (packedDate >> 11) & 7; + lt.tm_mday = ((packedDate >> 14) & 0x3F) + 1; + lt.tm_mon = (packedDate >> 20) & 0xF; + lt.tm_year = ((packedDate >> 24) & 0x1F) + 100; + + return uint32(mktime(<)); +} + +void ByteBuffer::append(uint8 const* src, size_t cnt) +{ + ASSERT(src, "Attempted to put a NULL-pointer in ByteBuffer (pos: " SZFMTD " size: " SZFMTD ")", _wpos, size()); + ASSERT(cnt, "Attempted to put a zero-sized value in ByteBuffer (pos: " SZFMTD " size: " SZFMTD ")", _wpos, size()); + ASSERT(size() < 10000000); + + size_t const newSize = _wpos + cnt; + if (_storage.capacity() < newSize) // custom memory allocation rules + { + if (newSize < 100) + _storage.reserve(300); + else if (newSize < 750) + _storage.reserve(2500); + else if (newSize < 6000) + _storage.reserve(10000); + else + _storage.reserve(400000); + } + + if (_storage.size() < newSize) + _storage.resize(newSize); + std::memcpy(&_storage[_wpos], src, cnt); + _wpos = newSize; +} + +void ByteBuffer::AppendPackedTime(time_t time) +{ + tm lt; + localtime_r(&time, <); + append<uint32>((lt.tm_year - 100) << 24 | lt.tm_mon << 20 | (lt.tm_mday - 1) << 14 | lt.tm_wday << 11 | lt.tm_hour << 6 | lt.tm_min); +} + +void ByteBuffer::put(size_t pos, uint8 const* src, size_t cnt) +{ + ASSERT(pos + cnt <= size(), "Attempted to put value with size: " SZFMTD " in ByteBuffer (pos: " SZFMTD " size: " SZFMTD ")", cnt, pos, size()); + ASSERT(src, "Attempted to put a NULL-pointer in ByteBuffer (pos: " SZFMTD " size: " SZFMTD ")", pos, size()); + ASSERT(cnt, "Attempted to put a zero-sized value in ByteBuffer (pos: " SZFMTD " size: " SZFMTD ")", pos, size()); + + std::memcpy(&_storage[pos], src, cnt); +} + void ByteBuffer::print_storage() const { if (!sLog->ShouldLog("network", LOG_LEVEL_TRACE)) // optimize disabled trace output diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h index 1dc5fee6a12..77f09455cc7 100644 --- a/src/server/shared/Packets/ByteBuffer.h +++ b/src/server/shared/Packets/ByteBuffer.h @@ -20,9 +20,9 @@ #define _BYTEBUFFER_H #include "Define.h" -#include "Errors.h" #include "ByteConverter.h" -#include "Util.h" +#include <string> +#include <vector> #include <cstring> class MessageBuffer; @@ -109,7 +109,8 @@ class TC_SHARED_API ByteBuffer append((uint8 *)&value, sizeof(value)); } - template <typename T> void put(size_t pos, T value) + template <typename T> + void put(std::size_t pos, T value) { static_assert(std::is_fundamental<T>::value, "append(compound)"); EndianConvert(value); @@ -249,21 +250,8 @@ class TC_SHARED_API ByteBuffer return *this; } - ByteBuffer &operator>>(float &value) - { - value = read<float>(); - if (!std::isfinite(value)) - throw ByteBufferException(); - return *this; - } - - ByteBuffer &operator>>(double &value) - { - value = read<double>(); - if (!std::isfinite(value)) - throw ByteBufferException(); - return *this; - } + ByteBuffer &operator>>(float &value); + ByteBuffer &operator>>(double &value); ByteBuffer &operator>>(std::string& value) { @@ -371,20 +359,7 @@ class TC_SHARED_API ByteBuffer } } - uint32 ReadPackedTime() - { - uint32 packedDate = read<uint32>(); - tm lt = tm(); - - lt.tm_min = packedDate & 0x3F; - lt.tm_hour = (packedDate >> 6) & 0x1F; - //lt.tm_wday = (packedDate >> 11) & 7; - lt.tm_mday = ((packedDate >> 14) & 0x3F) + 1; - lt.tm_mon = (packedDate >> 20) & 0xF; - lt.tm_year = ((packedDate >> 24) & 0x1F) + 100; - - return uint32(mktime(<)); - } + uint32 ReadPackedTime(); ByteBuffer& ReadPackedTime(uint32& time) { @@ -432,36 +407,9 @@ class TC_SHARED_API ByteBuffer return append((const uint8 *)src, cnt * sizeof(T)); } - void append(const uint8 *src, size_t cnt) - { - if (!cnt) - throw ByteBufferSourceException(_wpos, size(), cnt); - - if (!src) - throw ByteBufferSourceException(_wpos, size(), cnt); + void append(uint8 const* src, size_t cnt); - ASSERT(size() < 10000000); - - size_t const newSize = _wpos + cnt; - if (_storage.capacity() < newSize) // custom memory allocation rules - { - if (newSize < 100) - _storage.reserve(300); - else if (newSize < 750) - _storage.reserve(2500); - else if (newSize < 6000) - _storage.reserve(10000); - else - _storage.reserve(400000); - } - - if (_storage.size() < newSize) - _storage.resize(newSize); - std::memcpy(&_storage[_wpos], src, cnt); - _wpos = newSize; - } - - void append(const ByteBuffer& buffer) + void append(ByteBuffer const& buffer) { if (buffer.wpos()) append(buffer.contents(), buffer.wpos()); @@ -496,23 +444,9 @@ class TC_SHARED_API ByteBuffer append(packGUID, size); } - void AppendPackedTime(time_t time) - { - tm lt; - localtime_r(&time, <); - append<uint32>((lt.tm_year - 100) << 24 | lt.tm_mon << 20 | (lt.tm_mday - 1) << 14 | lt.tm_wday << 11 | lt.tm_hour << 6 | lt.tm_min); - } + void AppendPackedTime(time_t time); - void put(size_t pos, const uint8 *src, size_t cnt) - { - if (pos + cnt > size()) - throw ByteBufferPositionException(true, pos, cnt, size()); - - if (!src) - throw ByteBufferSourceException(_wpos, size(), cnt); - - std::memcpy(&_storage[pos], src, cnt); - } + void put(size_t pos, const uint8 *src, size_t cnt); void print_storage() const; @@ -525,85 +459,6 @@ class TC_SHARED_API ByteBuffer std::vector<uint8> _storage; }; -template <typename T> -inline ByteBuffer &operator<<(ByteBuffer &b, std::vector<T> v) -{ - b << (uint32)v.size(); - for (typename std::vector<T>::iterator i = v.begin(); i != v.end(); ++i) - { - b << *i; - } - return b; -} - -template <typename T> -inline ByteBuffer &operator>>(ByteBuffer &b, std::vector<T> &v) -{ - uint32 vsize; - b >> vsize; - v.clear(); - while (vsize--) - { - T t; - b >> t; - v.push_back(t); - } - return b; -} - -template <typename T> -inline ByteBuffer &operator<<(ByteBuffer &b, std::list<T> v) -{ - b << (uint32)v.size(); - for (typename std::list<T>::iterator i = v.begin(); i != v.end(); ++i) - { - b << *i; - } - return b; -} - -template <typename T> -inline ByteBuffer &operator>>(ByteBuffer &b, std::list<T> &v) -{ - uint32 vsize; - b >> vsize; - v.clear(); - while (vsize--) - { - T t; - b >> t; - v.push_back(t); - } - return b; -} - -template <typename K, typename V> -inline ByteBuffer &operator<<(ByteBuffer &b, std::map<K, V> &m) -{ - b << (uint32)m.size(); - for (typename std::map<K, V>::iterator i = m.begin(); i != m.end(); ++i) - { - b << i->first << i->second; - } - return b; -} - -template <typename K, typename V> -inline ByteBuffer &operator>>(ByteBuffer &b, std::map<K, V> &m) -{ - uint32 msize; - b >> msize; - m.clear(); - while (msize--) - { - K k; - V v; - b >> k >> v; - m.insert(make_pair(k, v)); - } - return b; -} - /// @todo Make a ByteBuffer.cpp and move all this inlining to it. template<> inline std::string ByteBuffer::read<std::string>() { diff --git a/src/server/shared/PrecompiledHeaders/sharedPCH.cpp b/src/server/shared/PrecompiledHeaders/sharedPCH.cpp index 36eb3a877f0..3b045ac537a 100644 --- a/src/server/shared/PrecompiledHeaders/sharedPCH.cpp +++ b/src/server/shared/PrecompiledHeaders/sharedPCH.cpp @@ -1 +1,18 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> + * + * 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 "sharedPCH.h" diff --git a/src/server/shared/PrecompiledHeaders/sharedPCH.h b/src/server/shared/PrecompiledHeaders/sharedPCH.h index f864674d5ad..436b0453c30 100644 --- a/src/server/shared/PrecompiledHeaders/sharedPCH.h +++ b/src/server/shared/PrecompiledHeaders/sharedPCH.h @@ -1,4 +1,28 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> + * + * 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/>. + */ + //add here most rarely modified headers to speed up debug build compilation -#include "TypeList.h" -#include "GitRevision.h" +#include "Common.h" +#include "Define.h" +#include "Errors.h" +#include "Log.h" +#include <boost/asio/ip/tcp.hpp> +#include <atomic> +#include <memory> +#include <string> +#include <vector> diff --git a/src/server/shared/Realm/Realm.cpp b/src/server/shared/Realm/Realm.cpp index 2768e17848b..571e798cc76 100644 --- a/src/server/shared/Realm/Realm.cpp +++ b/src/server/shared/Realm/Realm.cpp @@ -16,8 +16,9 @@ */ #include "Realm.h" +#include <boost/asio/ip/basic_endpoint.hpp> -boost::asio::ip::tcp::endpoint Realm::GetAddressForClient(boost::asio::ip::address const& clientAddr) const +boost::asio::ip::tcp_endpoint Realm::GetAddressForClient(boost::asio::ip::address const& clientAddr) const { boost::asio::ip::address realmIp; @@ -25,29 +26,27 @@ boost::asio::ip::tcp::endpoint Realm::GetAddressForClient(boost::asio::ip::addre if (clientAddr.is_loopback()) { // Try guessing if realm is also connected locally - if (LocalAddress.is_loopback() || ExternalAddress.is_loopback()) + if (LocalAddress->is_loopback() || ExternalAddress->is_loopback()) realmIp = clientAddr; else { // Assume that user connecting from the machine that bnetserver is located on // has all realms available in his local network - realmIp = LocalAddress; + realmIp = *LocalAddress; } } else { if (clientAddr.is_v4() && - (clientAddr.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong()) == - (LocalAddress.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong())) + (clientAddr.to_v4().to_ulong() & LocalSubnetMask->to_v4().to_ulong()) == + (LocalAddress->to_v4().to_ulong() & LocalSubnetMask->to_v4().to_ulong())) { - realmIp = LocalAddress; + realmIp = *LocalAddress; } else - realmIp = ExternalAddress; + realmIp = *ExternalAddress; } - boost::asio::ip::tcp::endpoint endpoint(realmIp, Port); - // Return external IP - return endpoint; + return boost::asio::ip::tcp_endpoint(realmIp, Port); } diff --git a/src/server/shared/Realm/Realm.h b/src/server/shared/Realm/Realm.h index e3cf181c120..b9b70592f0f 100644 --- a/src/server/shared/Realm/Realm.h +++ b/src/server/shared/Realm/Realm.h @@ -19,8 +19,7 @@ #define Realm_h__ #include "Common.h" -#include <boost/asio/ip/address.hpp> -#include <boost/asio/ip/tcp.hpp> +#include "AsioHacksFwd.h" enum RealmFlags { @@ -68,9 +67,9 @@ struct TC_SHARED_API Realm { RealmHandle Id; uint32 Build; - boost::asio::ip::address ExternalAddress; - boost::asio::ip::address LocalAddress; - boost::asio::ip::address LocalSubnetMask; + std::unique_ptr<boost::asio::ip::address> ExternalAddress; + std::unique_ptr<boost::asio::ip::address> LocalAddress; + std::unique_ptr<boost::asio::ip::address> LocalSubnetMask; uint16 Port; std::string Name; uint8 Type; @@ -79,7 +78,7 @@ struct TC_SHARED_API Realm AccountTypes AllowedSecurityLevel; float PopulationLevel; - boost::asio::ip::tcp::endpoint GetAddressForClient(boost::asio::ip::address const& clientAddr) const; + boost::asio::ip::tcp_endpoint GetAddressForClient(boost::asio::ip::address const& clientAddr) const; }; #endif // Realm_h__ diff --git a/src/server/shared/Realm/RealmList.cpp b/src/server/shared/Realm/RealmList.cpp index 37dd6bbaa17..a4a92ce0ec0 100644 --- a/src/server/shared/Realm/RealmList.cpp +++ b/src/server/shared/Realm/RealmList.cpp @@ -17,16 +17,18 @@ */ #include "RealmList.h" -#include "Database/DatabaseEnv.h" +#include "DatabaseEnv.h" +#include "Log.h" #include "Util.h" +#include <boost/asio/deadline_timer.hpp> +#include <boost/asio/ip/tcp.hpp> -RealmList::RealmList() : _updateInterval(0), _updateTimer(nullptr), _resolver(nullptr) +RealmList::RealmList() : _updateInterval(0) { } RealmList::~RealmList() { - delete _updateTimer; } RealmList* RealmList::Instance() @@ -39,8 +41,8 @@ RealmList* RealmList::Instance() void RealmList::Initialize(boost::asio::io_service& ioService, uint32 updateInterval) { _updateInterval = updateInterval; - _updateTimer = new boost::asio::deadline_timer(ioService); - _resolver = new boost::asio::ip::tcp::resolver(ioService); + _updateTimer = Trinity::make_unique<boost::asio::deadline_timer>(ioService); + _resolver = Trinity::make_unique<boost::asio::ip::tcp::resolver>(ioService); // Get the content of the realmlist table in the database UpdateRealms(boost::system::error_code()); @@ -51,9 +53,9 @@ void RealmList::Close() _updateTimer->cancel(); } -void RealmList::UpdateRealm(RealmHandle const& id, uint32 build, const std::string& name, boost::asio::ip::address const& address, boost::asio::ip::address const& localAddr, - boost::asio::ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, - float population) +void RealmList::UpdateRealm(RealmHandle const& id, uint32 build, std::string const& name, + boost::asio::ip::address const& address, boost::asio::ip::address const& localAddr, boost::asio::ip::address const& localSubmask, + uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population) { // Create new if not exist or update existed Realm& realm = _realms[id]; @@ -66,9 +68,12 @@ void RealmList::UpdateRealm(RealmHandle const& id, uint32 build, const std::stri realm.Timezone = timezone; realm.AllowedSecurityLevel = allowedSecurityLevel; realm.PopulationLevel = population; - realm.ExternalAddress = address; - realm.LocalAddress = localAddr; - realm.LocalSubnetMask = localSubmask; + if (!realm.ExternalAddress || *realm.ExternalAddress != address) + realm.ExternalAddress = Trinity::make_unique<boost::asio::ip::address>(address); + if (!realm.LocalAddress || *realm.LocalAddress != localAddr) + realm.LocalAddress = Trinity::make_unique<boost::asio::ip::address>(localAddr); + if (!realm.LocalSubnetMask || *realm.LocalSubnetMask != localSubmask) + realm.LocalSubnetMask = Trinity::make_unique<boost::asio::ip::address>(localSubmask); realm.Port = port; } @@ -110,7 +115,7 @@ void RealmList::UpdateRealms(boost::system::error_code const& error) continue; } - boost::asio::ip::address externalAddress = (*endPoint).endpoint().address(); + boost::asio::ip::address externalAddress = endPoint->endpoint().address(); boost::asio::ip::tcp::resolver::query localAddressQuery(boost::asio::ip::tcp::v4(), fields[3].GetString(), ""); endPoint = _resolver->resolve(localAddressQuery, ec); @@ -120,7 +125,7 @@ void RealmList::UpdateRealms(boost::system::error_code const& error) continue; } - boost::asio::ip::address localAddress = (*endPoint).endpoint().address(); + boost::asio::ip::address localAddress = endPoint->endpoint().address(); boost::asio::ip::tcp::resolver::query localSubmaskQuery(boost::asio::ip::tcp::v4(), fields[4].GetString(), ""); endPoint = _resolver->resolve(localSubmaskQuery, ec); @@ -130,7 +135,7 @@ void RealmList::UpdateRealms(boost::system::error_code const& error) continue; } - boost::asio::ip::address localSubmask = (*endPoint).endpoint().address(); + boost::asio::ip::address localSubmask = endPoint->endpoint().address(); uint16 port = fields[5].GetUInt16(); uint8 icon = fields[6].GetUInt8(); @@ -181,5 +186,5 @@ Realm const* RealmList::GetRealm(RealmHandle const& id) const if (itr != _realms.end()) return &itr->second; - return NULL; + return nullptr; } diff --git a/src/server/shared/Realm/RealmList.h b/src/server/shared/Realm/RealmList.h index 7878779b736..5d6d2c16151 100644 --- a/src/server/shared/Realm/RealmList.h +++ b/src/server/shared/Realm/RealmList.h @@ -19,12 +19,24 @@ #ifndef _REALMLIST_H #define _REALMLIST_H -#include "Common.h" -#include "Realm/Realm.h" -#include <boost/asio/ip/address.hpp> -#include <boost/asio/ip/tcp.hpp> -#include <boost/asio/io_service.hpp> -#include <boost/asio/deadline_timer.hpp> +#include "Define.h" +#include "Realm.h" +#include <map> +#include <vector> +#include <unordered_set> + +namespace boost +{ + namespace asio + { + class io_service; + } + + namespace system + { + class error_code; + } +} /// Storage object for the list of realms on the server class TC_SHARED_API RealmList @@ -46,13 +58,14 @@ private: RealmList(); void UpdateRealms(boost::system::error_code const& error); - void UpdateRealm(RealmHandle const& id, uint32 build, const std::string& name, boost::asio::ip::address const& address, boost::asio::ip::address const& localAddr, - boost::asio::ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population); + void UpdateRealm(RealmHandle const& id, uint32 build, std::string const& name, + boost::asio::ip::address const& address, boost::asio::ip::address const& localAddr, boost::asio::ip::address const& localSubmask, + uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population); RealmMap _realms; uint32 _updateInterval; - boost::asio::deadline_timer* _updateTimer; - boost::asio::ip::tcp::resolver* _resolver; + std::unique_ptr<boost::asio::deadline_timer> _updateTimer; + std::unique_ptr<boost::asio::ip::tcp_resolver> _resolver; }; #define sRealmList RealmList::Instance() |