#include "StdAfx.h" #include "StringTable.h" StringTable::StringTable(void) { } // Load string table from a binary blob, filling out with the current localisation data only StringTable::StringTable(PBYTE pbData, DWORD dwSize) { src = byteArray(pbData, dwSize); ProcessStringTableData(); } StringTable::~StringTable(void) { Reset(); } void StringTable::Reset(void) { m_stringsMap.clear(); m_stringsVec.clear(); m_langSizeMap.clear(); isStatic = false; currentLanguage.clear(); } void StringTable::ReloadStringTable() { Reset(); ProcessStringTableData(); } void StringTable::ProcessStringTableData(void) { if (src.length > 0 && src.data != nullptr) { ByteArrayInputStream bais(src); DataInputStream dis(&bais); ReadAllFromStream(&dis); dis.close(); bais.reset(); } } void StringTable::ReadAllFromStream(DataInputStream* dis) { int versionNumber = dis->readInt(); int languagesCount = dis->readInt(); m_langSizeMap.clear(); for(int i = 0; i < languagesCount; ++i) { wstring langId = dis->readUTF(); int langSize = dis->readInt(); m_langSizeMap.push_back(make_pair(langId, langSize)); } int64_t bytesToSkip = 0; int dataSize = 0; if(FindLanguage(currentLanguage, bytesToSkip, dataSize)) { dis->skip(bytesToSkip); ReadLanguageFromStream(dis, dataSize); } else { isStatic = false; } } bool StringTable::FindLanguage(wstring& outLangId, int64_t& outBytesToSkip, int& outDataSize) { vector locales; app.getLocale(locales); outBytesToSkip = 0; for (auto it_locales = locales.begin(); it_locales != locales.end(); ++it_locales) { outBytesToSkip = 0; for(auto& it : m_langSizeMap) { if(it.first.compare(*it_locales) == 0) { app.DebugPrintf("StringTable:: Found language '%ls'.\n", it_locales->c_str()); outDataSize = it.second; outLangId = *it_locales; return true; } outBytesToSkip += it.second; } app.DebugPrintf("StringTable:: Can't find language '%ls'.\n", it_locales->c_str()); } app.DebugPrintf("Failed to get language\n"); return false; } void StringTable::ReadLanguageFromStream(DataInputStream* dis, int dataSize) { byteArray langData(dataSize); dis->read(langData); ByteArrayInputStream bais2(langData); DataInputStream dis2(&bais2); // Read the language file for the selected language int langVersion = dis2.readInt(); isStatic = false; if (langVersion > 0) isStatic = dis2.readBoolean(); wstring langId = dis2.readUTF(); int totalStrings = dis2.readInt(); app.DebugPrintf("IsStatic=%s totalStrings = %d\n", isStatic ? "TRUE" : "FALSE", totalStrings); if (!isStatic) { for(int i = 0; i < totalStrings; ++i) { wstring stringId = dis2.readUTF(); wstring stringValue = dis2.readUTF(); m_stringsMap.insert(unordered_map::value_type(stringId, stringValue)); } } else { for(int i = 0; i < totalStrings; ++i) { m_stringsVec.push_back(dis2.readUTF()); } } dis2.close(); bais2.reset(); } void StringTable::write(DataOutputStream* dos) { dos->writeInt(1); dos->writeInt(1); int langVersion = 1; dos->writeInt(langVersion); dos->writeBoolean(isStatic); dos->writeUTF(currentLanguage.empty() ? L"en_US" : currentLanguage); if (!isStatic) { dos->writeInt(m_stringsMap.size()); for (auto const& [key, val] : m_stringsMap) { dos->writeUTF(key); dos->writeUTF(val); } } else { dos->writeInt(m_stringsVec.size()); for (auto const& val : m_stringsVec) { dos->writeUTF(val); } } } void StringTable::getData(PBYTE *ppData, UINT *pSize) { *ppData = src.data; *pSize = src.length; } LPCWSTR StringTable::getString(const wstring &id) { auto it = m_stringsMap.find(id); if(it != m_stringsMap.end()) { return it->second.c_str(); } else { return L""; } } LPCWSTR StringTable::getString(int id) { if (id >= 0 && id < m_stringsVec.size()) { LPCWSTR pwchString=m_stringsVec.at(id).c_str(); return pwchString; } else return L""; }