diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderStringTable.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderStringTable.cpp index 642a60a8..e7335004 100644 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderStringTable.cpp +++ b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderStringTable.cpp @@ -5,6 +5,7 @@ #include "Game/IW4/IW4.h" #include "ObjLoading.h" #include "Pool/GlobalAssetPool.h" +#include "StringTable/StringTableLoader.h" #include @@ -30,49 +31,8 @@ bool AssetLoaderStringTable::LoadFromRaw( if (!file.IsOpen()) return false; - auto* stringTable = memory->Create(); - stringTable->name = memory->Dup(assetName.c_str()); - - std::vector> csvLines; - std::vector currentLine; - auto maxCols = 0u; - const CsvInputStream csv(*file.m_stream); - - while (csv.NextRow(currentLine)) - { - if (currentLine.size() > maxCols) - maxCols = currentLine.size(); - csvLines.emplace_back(std::move(currentLine)); - currentLine = std::vector(); - } - - stringTable->columnCount = static_cast(maxCols); - stringTable->rowCount = static_cast(csvLines.size()); - const auto cellCount = static_cast(stringTable->rowCount) * static_cast(stringTable->columnCount); - - if (cellCount) - { - stringTable->values = static_cast(memory->Alloc(sizeof(StringTableCell) * cellCount)); - - for (auto row = 0u; row < csvLines.size(); row++) - { - const auto& rowValues = csvLines[row]; - for (auto col = 0u; col < maxCols; col++) - { - auto& cell = stringTable->values[row * maxCols + col]; - if (col >= rowValues.size() || rowValues[col].empty()) - cell.string = ""; - else - cell.string = memory->Dup(rowValues[col].c_str()); - - cell.hash = Common::StringTable_HashString(cell.string); - } - } - } - else - { - stringTable->values = nullptr; - } + string_table::StringTableLoaderV2 loader; + auto* stringTable = loader.LoadFromStream(assetName, *memory, *file.m_stream); manager->AddAsset(ASSET_TYPE_STRINGTABLE, assetName, stringTable); diff --git a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderStringTable.cpp b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderStringTable.cpp index 9c9eb6e2..ece65461 100644 --- a/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderStringTable.cpp +++ b/src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderStringTable.cpp @@ -5,6 +5,7 @@ #include "Game/IW5/IW5.h" #include "ObjLoading.h" #include "Pool/GlobalAssetPool.h" +#include "StringTable/StringTableLoader.h" #include @@ -30,49 +31,8 @@ bool AssetLoaderStringTable::LoadFromRaw( if (!file.IsOpen()) return false; - auto* stringTable = memory->Create(); - stringTable->name = memory->Dup(assetName.c_str()); - - std::vector> csvLines; - std::vector currentLine; - auto maxCols = 0u; - const CsvInputStream csv(*file.m_stream); - - while (csv.NextRow(currentLine)) - { - if (currentLine.size() > maxCols) - maxCols = currentLine.size(); - csvLines.emplace_back(std::move(currentLine)); - currentLine = std::vector(); - } - - stringTable->columnCount = static_cast(maxCols); - stringTable->rowCount = static_cast(csvLines.size()); - const auto cellCount = static_cast(stringTable->rowCount) * static_cast(stringTable->columnCount); - - if (cellCount) - { - stringTable->values = static_cast(memory->Alloc(sizeof(StringTableCell) * cellCount)); - - for (auto row = 0u; row < csvLines.size(); row++) - { - const auto& rowValues = csvLines[row]; - for (auto col = 0u; col < maxCols; col++) - { - auto& cell = stringTable->values[row * maxCols + col]; - if (col >= rowValues.size() || rowValues[col].empty()) - cell.string = ""; - else - cell.string = memory->Dup(rowValues[col].c_str()); - - cell.hash = Common::StringTable_HashString(cell.string); - } - } - } - else - { - stringTable->values = nullptr; - } + string_table::StringTableLoaderV2 loader; + auto* stringTable = loader.LoadFromStream(assetName, *memory, *file.m_stream); manager->AddAsset(ASSET_TYPE_STRINGTABLE, assetName, stringTable); diff --git a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderStringTable.cpp b/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderStringTable.cpp index 8261df56..d8785dc7 100644 --- a/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderStringTable.cpp +++ b/src/ObjLoading/Game/T5/AssetLoaders/AssetLoaderStringTable.cpp @@ -4,6 +4,7 @@ #include "Game/T5/CommonT5.h" #include "Game/T5/T5.h" #include "Pool/GlobalAssetPool.h" +#include "StringTable/StringTableLoader.h" #include @@ -29,65 +30,8 @@ bool AssetLoaderStringTable::LoadFromRaw( if (!file.IsOpen()) return false; - auto* stringTable = memory->Create(); - stringTable->name = memory->Dup(assetName.c_str()); - - std::vector> csvLines; - std::vector currentLine; - auto maxCols = 0u; - const CsvInputStream csv(*file.m_stream); - - while (csv.NextRow(currentLine)) - { - if (currentLine.size() > maxCols) - maxCols = currentLine.size(); - csvLines.emplace_back(std::move(currentLine)); - currentLine = std::vector(); - } - - stringTable->columnCount = static_cast(maxCols); - stringTable->rowCount = static_cast(csvLines.size()); - const auto cellCount = static_cast(stringTable->rowCount) * static_cast(stringTable->columnCount); - - if (cellCount) - { - stringTable->values = static_cast(memory->Alloc(sizeof(StringTableCell) * cellCount)); - stringTable->cellIndex = static_cast(memory->Alloc(sizeof(int16_t) * cellCount)); - - for (auto c = 0u; c < cellCount; c++) - stringTable->cellIndex[c] = static_cast(c); - - for (auto row = 0u; row < csvLines.size(); row++) - { - const auto& rowValues = csvLines[row]; - for (auto col = 0u; col < maxCols; col++) - { - auto& cell = stringTable->values[row * maxCols + col]; - if (col >= rowValues.size() || rowValues[col].empty()) - cell.string = ""; - else - cell.string = memory->Dup(rowValues[col].c_str()); - - cell.hash = Common::Com_HashString(cell.string); - } - } - - std::sort(&stringTable->cellIndex[0], - &stringTable->cellIndex[cellCount - 1], - [stringTable, maxCols](const int16_t a, const int16_t b) - { - auto compareResult = stringTable->values[a].hash - stringTable->values[b].hash; - if (compareResult == 0) - compareResult = a % maxCols - b % maxCols; - return compareResult < 0; - }); - } - - else - { - stringTable->values = nullptr; - stringTable->cellIndex = nullptr; - } + string_table::StringTableLoaderV3 loader; + auto* stringTable = loader.LoadFromStream(assetName, *memory, *file.m_stream); manager->AddAsset(ASSET_TYPE_STRINGTABLE, assetName, stringTable); diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderStringTable.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderStringTable.cpp index 150431f1..e77cc4bb 100644 --- a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderStringTable.cpp +++ b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderStringTable.cpp @@ -4,6 +4,7 @@ #include "Game/T6/CommonT6.h" #include "Game/T6/T6.h" #include "Pool/GlobalAssetPool.h" +#include "StringTable/StringTableLoader.h" #include @@ -29,65 +30,8 @@ bool AssetLoaderStringTable::LoadFromRaw( if (!file.IsOpen()) return false; - auto* stringTable = memory->Create(); - stringTable->name = memory->Dup(assetName.c_str()); - - std::vector> csvLines; - std::vector currentLine; - auto maxCols = 0u; - const CsvInputStream csv(*file.m_stream); - - while (csv.NextRow(currentLine)) - { - if (currentLine.size() > maxCols) - maxCols = currentLine.size(); - csvLines.emplace_back(std::move(currentLine)); - currentLine = std::vector(); - } - - stringTable->columnCount = static_cast(maxCols); - stringTable->rowCount = static_cast(csvLines.size()); - const auto cellCount = static_cast(stringTable->rowCount) * static_cast(stringTable->columnCount); - - if (cellCount) - { - stringTable->values = static_cast(memory->Alloc(sizeof(StringTableCell) * cellCount)); - stringTable->cellIndex = static_cast(memory->Alloc(sizeof(int16_t) * cellCount)); - - for (auto c = 0u; c < cellCount; c++) - stringTable->cellIndex[c] = static_cast(c); - - for (auto row = 0u; row < csvLines.size(); row++) - { - const auto& rowValues = csvLines[row]; - for (auto col = 0u; col < maxCols; col++) - { - auto& cell = stringTable->values[row * maxCols + col]; - if (col >= rowValues.size() || rowValues[col].empty()) - cell.string = ""; - else - cell.string = memory->Dup(rowValues[col].c_str()); - - cell.hash = Common::Com_HashString(cell.string); - } - } - - std::sort(&stringTable->cellIndex[0], - &stringTable->cellIndex[cellCount - 1], - [stringTable, maxCols](const int16_t a, const int16_t b) - { - auto compareResult = stringTable->values[a].hash - stringTable->values[b].hash; - if (compareResult == 0) - compareResult = a % maxCols - b % maxCols; - return compareResult < 0; - }); - } - - else - { - stringTable->values = nullptr; - stringTable->cellIndex = nullptr; - } + string_table::StringTableLoaderV3 loader; + auto* stringTable = loader.LoadFromStream(assetName, *memory, *file.m_stream); manager->AddAsset(ASSET_TYPE_STRINGTABLE, assetName, stringTable); diff --git a/src/ObjLoading/StringTable/StringTableLoader.h b/src/ObjLoading/StringTable/StringTableLoader.h index b685030b..fae42fc4 100644 --- a/src/ObjLoading/StringTable/StringTableLoader.h +++ b/src/ObjLoading/StringTable/StringTableLoader.h @@ -86,4 +86,60 @@ namespace string_table cell = content; } }; + + // ================================= + // V2: IW4, IW5 + // - Cells are a struct and have a hash + // ================================= + template + class StringTableLoaderV2 final : public AbstractStringTableLoader> + { + using CellType_t = decltype(*StringTableType::values); + + protected: + void SetCellContent(CellType_t& cell, const char* content) override + { + cell.string = content; + cell.hash = HashFunc(content); + } + }; + + // ================================= + // V3: T5, T6 + // - Cells are a struct and have a hash + // - StringTable has an index array for binary search + // ================================= + template + class StringTableLoaderV3 final : public AbstractStringTableLoader> + { + using CellType_t = decltype(*StringTableType::values); + + protected: + void SetCellContent(CellType_t& cell, const char* content) override + { + cell.string = content; + cell.hash = HashFunc(content); + } + + void PostProcessStringTable(StringTableType* stringTable, const unsigned cellCount, MemoryManager& memory) override + { + if (!cellCount) + { + stringTable->cellIndex = nullptr; + return; + } + + stringTable->cellIndex = static_cast(memory.Alloc(sizeof(int16_t) * cellCount)); + + std::sort(&stringTable->cellIndex[0], + &stringTable->cellIndex[cellCount - 1], + [stringTable](const int16_t a, const int16_t b) + { + auto compareResult = stringTable->values[a].hash - stringTable->values[b].hash; + if (compareResult == 0) + compareResult = (a % stringTable->columnCount) - (b % stringTable->columnCount); + return compareResult < 0; + }); + } + }; } // namespace string_table