Add asset loader for localize files

This commit is contained in:
Jan 2021-03-23 17:16:36 +01:00
parent 3ed63415a7
commit 79c1284193
50 changed files with 609 additions and 23 deletions

View File

@ -0,0 +1,10 @@
#include "LocalizeFile.h"
LocalizeFileEntry::LocalizeFileEntry()
= default;
LocalizeFileEntry::LocalizeFileEntry(std::string key, std::string value)
: m_key(std::move(key)),
m_value(std::move(value))
{
}

View File

@ -0,0 +1,12 @@
#pragma once
#include <string>
class LocalizeFileEntry
{
public:
std::string m_key;
std::string m_value;
LocalizeFileEntry();
LocalizeFileEntry(std::string key, std::string value);
};

View File

@ -59,14 +59,14 @@ XAssetInfoGeneric* AssetLoadingManager::LoadIgnoredDependency(const asset_type_t
XAssetInfoGeneric* AssetLoadingManager::LoadAssetDependency(const asset_type_t assetType, const std::string& assetName, IAssetLoader* loader) XAssetInfoGeneric* AssetLoadingManager::LoadAssetDependency(const asset_type_t assetType, const std::string& assetName, IAssetLoader* loader)
{ {
if (loader->CanLoadFromGdt() && loader->LoadFromGdt(assetName, &m_context, m_context.m_zone->GetMemory(), this)) if (loader->CanLoadFromGdt() && loader->LoadFromGdt(assetName, &m_context, m_context.m_zone->GetMemory(), this, m_context.m_zone))
{ {
auto* lastDependency = m_last_dependency_loaded; auto* lastDependency = m_last_dependency_loaded;
m_last_dependency_loaded = nullptr; m_last_dependency_loaded = nullptr;
return lastDependency; return lastDependency;
} }
if (loader->CanLoadFromRaw() && loader->LoadFromRaw(assetName, m_context.m_raw_search_path, m_context.m_zone->GetMemory(), this)) if (loader->CanLoadFromRaw() && loader->LoadFromRaw(assetName, m_context.m_raw_search_path, m_context.m_zone->GetMemory(), this, m_context.m_zone))
{ {
auto* lastDependency = m_last_dependency_loaded; auto* lastDependency = m_last_dependency_loaded;
m_last_dependency_loaded = nullptr; m_last_dependency_loaded = nullptr;

View File

@ -36,12 +36,12 @@ public:
return false; return false;
} }
virtual bool LoadFromGdt(const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager) const virtual bool LoadFromGdt(const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{ {
return false; return false;
} }
virtual bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) const virtual bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{ {
return false; return false;
} }

View File

@ -20,7 +20,7 @@ bool AssetLoaderRawFile::CanLoadFromRaw() const
return true; return true;
} }
bool AssetLoaderRawFile::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) const bool AssetLoaderRawFile::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{ {
const auto file = searchPath->Open(assetName); const auto file = searchPath->Open(assetName);
if (!file.IsOpen()) if (!file.IsOpen())

View File

@ -11,6 +11,6 @@ namespace IW4
public: public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override; _NODISCARD bool CanLoadFromRaw() const override;
bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) const override; bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
}; };
} }

View File

@ -0,0 +1,52 @@
#include "AssetLoaderLocalizeEntry.h"
#include <sstream>
#include "Localize/LocalizeCommon.h"
#include "Parsing/LocalizeFile/LocalizeFileReader.h"
using namespace T6;
XAssetInfoGeneric* AssetLoaderLocalizeEntry::LoadFromGlobalAssetPools(const std::string& assetName) const
{
return nullptr;
}
void* AssetLoaderLocalizeEntry::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
{
return nullptr;
}
bool AssetLoaderLocalizeEntry::CanLoadFromRaw() const
{
return true;
}
bool AssetLoaderLocalizeEntry::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
std::string fileName;
{
std::ostringstream str;
str << LocalizeCommon::GetNameOfLanguage(zone->m_language) << "/localizedstrings/" << assetName << ".str";
fileName = str.str();
}
const auto file = searchPath->Open(fileName);
if (!file.IsOpen())
return false;
LocalizeFileReader reader(*file.m_stream, assetName, zone->m_language);
const auto localizeEntries = reader.ReadLocalizeFile();
for(const auto& entry : localizeEntries)
{
auto* localizeEntry = memory->Create<LocalizeEntry>();
localizeEntry->name = memory->Dup(entry.m_key.c_str());
localizeEntry->value = memory->Dup(entry.m_value.c_str());
manager->AddAsset(ASSET_TYPE_LOCALIZE_ENTRY, entry.m_key, localizeEntry);
}
return true;
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "Game/T6/T6.h"
#include "AssetLoading/BasicAssetLoader.h"
#include "AssetLoading/IAssetLoadingManager.h"
#include "SearchPath/ISearchPath.h"
namespace T6
{
class AssetLoaderLocalizeEntry final : public BasicAssetLoader<ASSET_TYPE_LOCALIZE_ENTRY, LocalizeEntry>
{
public:
_NODISCARD XAssetInfoGeneric* LoadFromGlobalAssetPools(const std::string& assetName) const override;
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override;
bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
};
}

View File

@ -20,7 +20,7 @@ bool AssetLoaderQdb::CanLoadFromRaw() const
return true; return true;
} }
bool AssetLoaderQdb::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) const bool AssetLoaderQdb::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{ {
const auto file = searchPath->Open(assetName); const auto file = searchPath->Open(assetName);
if (!file.IsOpen()) if (!file.IsOpen())

View File

@ -11,6 +11,6 @@ namespace T6
public: public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override; _NODISCARD bool CanLoadFromRaw() const override;
bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) const override; bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
}; };
} }

View File

@ -20,7 +20,7 @@ bool AssetLoaderRawFile::CanLoadFromRaw() const
return true; return true;
} }
bool AssetLoaderRawFile::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) const bool AssetLoaderRawFile::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{ {
const auto file = searchPath->Open(assetName); const auto file = searchPath->Open(assetName);
if (!file.IsOpen()) if (!file.IsOpen())

View File

@ -11,6 +11,6 @@ namespace T6
public: public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override; _NODISCARD bool CanLoadFromRaw() const override;
bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) const override; bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
}; };
} }

View File

@ -20,7 +20,7 @@ bool AssetLoaderScriptParseTree::CanLoadFromRaw() const
return true; return true;
} }
bool AssetLoaderScriptParseTree::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) const bool AssetLoaderScriptParseTree::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{ {
const auto file = searchPath->Open(assetName); const auto file = searchPath->Open(assetName);
if (!file.IsOpen()) if (!file.IsOpen())

View File

@ -11,6 +11,6 @@ namespace T6
public: public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override; _NODISCARD bool CanLoadFromRaw() const override;
bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) const override; bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
}; };
} }

View File

@ -20,7 +20,7 @@ bool AssetLoaderSlug::CanLoadFromRaw() const
return true; return true;
} }
bool AssetLoaderSlug::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) const bool AssetLoaderSlug::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{ {
const auto file = searchPath->Open(assetName); const auto file = searchPath->Open(assetName);
if (!file.IsOpen()) if (!file.IsOpen())

View File

@ -11,6 +11,6 @@ namespace T6
public: public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override; _NODISCARD bool CanLoadFromRaw() const override;
bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) const override; bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
}; };
} }

View File

@ -22,7 +22,7 @@ bool AssetLoaderStringTable::CanLoadFromRaw() const
return true; return true;
} }
bool AssetLoaderStringTable::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) const bool AssetLoaderStringTable::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{ {
const auto file = searchPath->Open(assetName); const auto file = searchPath->Open(assetName);
if (!file.IsOpen()) if (!file.IsOpen())

View File

@ -11,6 +11,6 @@ namespace T6
public: public:
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
_NODISCARD bool CanLoadFromRaw() const override; _NODISCARD bool CanLoadFromRaw() const override;
bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) const override; bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
}; };
} }

View File

@ -4,6 +4,7 @@
#include "Game/T6/GameAssetPoolT6.h" #include "Game/T6/GameAssetPoolT6.h"
#include "ObjContainer/IPak/IPak.h" #include "ObjContainer/IPak/IPak.h"
#include "ObjLoading.h" #include "ObjLoading.h"
#include "AssetLoaders/AssetLoaderLocalizeEntry.h"
#include "AssetLoaders/AssetLoaderQdb.h" #include "AssetLoaders/AssetLoaderQdb.h"
#include "AssetLoaders/AssetLoaderRawFile.h" #include "AssetLoaders/AssetLoaderRawFile.h"
#include "AssetLoaders/AssetLoaderScriptParseTree.h" #include "AssetLoaders/AssetLoaderScriptParseTree.h"
@ -46,7 +47,7 @@ namespace T6
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_FONTICON, FontIcon)) REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_FONTICON, FontIcon))
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_MENULIST, MenuList)) REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_MENULIST, MenuList))
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_MENU, menuDef_t)) REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_MENU, menuDef_t))
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_LOCALIZE_ENTRY, LocalizeEntry)) REGISTER_ASSET_LOADER(AssetLoaderLocalizeEntry)
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_WEAPON, WeaponVariantDef)) REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_WEAPON, WeaponVariantDef))
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_ATTACHMENT, WeaponAttachment)) REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_ATTACHMENT, WeaponAttachment))
REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_ATTACHMENT_UNIQUE, WeaponAttachmentUnique)) REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_ATTACHMENT_UNIQUE, WeaponAttachmentUnique))

View File

@ -0,0 +1,9 @@
#include "LocalizeFileLexer.h"
LocalizeFileLexer::LocalizeFileLexer(IParserLineStream* stream)
: SimpleLexer(stream)
{
SetShouldEmitNewLineTokens(true);
SetShouldReadNumbers(false);
SetShouldReadStrings(true);
}

View File

@ -0,0 +1,9 @@
#pragma once
#include "Parsing/Simple/SimpleLexer.h"
class LocalizeFileLexer final : public SimpleLexer
{
public:
explicit LocalizeFileLexer(IParserLineStream* stream);
};

View File

@ -0,0 +1,38 @@
#include "LocalizeFileParser.h"
#include "Sequence/SequenceLocalizeFileConfig.h"
#include "Sequence/SequenceLocalizeFileConsumeEmptyLines.h"
#include "Sequence/SequenceLocalizeFileEndMarker.h"
#include "Sequence/SequenceLocalizeFileLanguageValue.h"
#include "Sequence/SequenceLocalizeFileNotes.h"
#include "Sequence/SequenceLocalizeFileReference.h"
#include "Sequence/SequenceLocalizeFileVersion.h"
LocalizeFileParser::LocalizeFileParser(SimpleLexer* lexer, GameLanguage language)
: AbstractParser(lexer, std::make_unique<LocalizeFileParserState>(language))
{
}
const std::vector<AbstractParser<SimpleParserValue, LocalizeFileParserState>::sequence_t*>& LocalizeFileParser::GetTestsForState()
{
static std::vector<sequence_t*> tests({
new SequenceLocalizeFileReference(),
new SequenceLocalizeFileConfig(),
new SequenceLocalizeFileNotes(),
new SequenceLocalizeFileVersion(),
new SequenceLocalizeFileEndMarker(),
new SequenceLocalizeFileLanguageValue(),
new SequenceLocalizeFileConsumeEmptyLines()
});
static std::vector<sequence_t*> noTests({
new SequenceLocalizeFileConsumeEmptyLines()
});
return !m_state->m_end ? tests : noTests;
}
std::vector<LocalizeFileEntry> LocalizeFileParser::GetParsedValues()
{
return std::move(m_state->m_entries);
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "LocalizeFileParserState.h"
#include "Game/GameLanguage.h"
#include "Parsing/Simple/SimpleLexer.h"
#include "Parsing/Simple/SimpleParserValue.h"
#include "Parsing/Impl/AbstractParser.h"
class LocalizeFileParser final : public AbstractParser<SimpleParserValue, LocalizeFileParserState>
{
protected:
const std::vector<sequence_t*>& GetTestsForState() override;
public:
LocalizeFileParser(SimpleLexer* lexer, GameLanguage language);
std::vector<LocalizeFileEntry> GetParsedValues();
};

View File

@ -0,0 +1,12 @@
#include "LocalizeFileParserState.h"
#include "Localize/LocalizeCommon.h"
LocalizeFileParserState::LocalizeFileParserState(const GameLanguage language)
: m_end(false),
m_language(language)
{
m_language_name_caps = LocalizeCommon::GetNameOfLanguage(m_language);
for (auto& c : m_language_name_caps)
c = static_cast<char>(toupper(c));
}

View File

@ -0,0 +1,22 @@
#pragma once
#include <unordered_set>
#include <vector>
#include "Game/GameLanguage.h"
#include "Localize/LocalizeFile.h"
class LocalizeFileParserState
{
public:
bool m_end;
std::vector<LocalizeFileEntry> m_entries;
GameLanguage m_language;
std::string m_language_name_caps;
std::string m_current_reference;
std::unordered_set<std::string> m_current_reference_languages;
explicit LocalizeFileParserState(GameLanguage language);
};

View File

@ -0,0 +1,41 @@
#include "LocalizeFileReader.h"
#include "LocalizeFileLexer.h"
#include "LocalizeFileParser.h"
#include "Parsing/Impl/CommentRemovingStreamProxy.h"
#include "Parsing/Impl/ParserInputStream.h"
LocalizeFileReader::LocalizeFileReader(std::istream& stream, std::string fileName, GameLanguage language)
: m_file_name(std::move(fileName)),
m_stream(nullptr),
m_language(language)
{
OpenBaseStream(stream);
SetupStreamProxies();
m_stream = m_open_streams.back().get();
}
bool LocalizeFileReader::OpenBaseStream(std::istream& stream)
{
m_open_streams.emplace_back(std::make_unique<ParserInputStream>(stream, m_file_name));
return true;
}
void LocalizeFileReader::SetupStreamProxies()
{
m_open_streams.emplace_back(std::make_unique<CommentRemovingStreamProxy>(m_open_streams.back().get()));
m_stream = m_open_streams.back().get();
}
std::vector<LocalizeFileEntry> LocalizeFileReader::ReadLocalizeFile()
{
const auto lexer = std::make_unique<LocalizeFileLexer>(m_stream);
const auto parser = std::make_unique<LocalizeFileParser>(lexer.get(), m_language);
if (parser->Parse())
return parser->GetParsedValues();
std::cout << "Parsing localization file failed!" << std::endl;
return std::vector<LocalizeFileEntry>();
}

View File

@ -0,0 +1,25 @@
#pragma once
#include <memory>
#include <string>
#include <vector>
#include "Game/GameLanguage.h"
#include "Localize/LocalizeFile.h"
#include "Parsing/IParserLineStream.h"
class LocalizeFileReader
{
std::string m_file_name;
IParserLineStream* m_stream;
std::vector<std::unique_ptr<IParserLineStream>> m_open_streams;
GameLanguage m_language;
bool OpenBaseStream(std::istream& stream);
void SetupStreamProxies();
public:
LocalizeFileReader(std::istream& stream, std::string fileName, GameLanguage language);
std::vector<LocalizeFileEntry> ReadLocalizeFile();
};

View File

@ -0,0 +1,18 @@
#include "SequenceLocalizeFileConfig.h"
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
SequenceLocalizeFileConfig::SequenceLocalizeFileConfig()
{
const SimpleMatcherFactory create(this);
AddMatchers({
create.Keyword("CONFIG"),
create.String(),
create.Type(SimpleParserValueType::NEW_LINE)
});
}
void SequenceLocalizeFileConfig::ProcessMatch(LocalizeFileParserState* state, SequenceResult<SimpleParserValue>& result) const
{
}

View File

@ -0,0 +1,12 @@
#pragma once
#include "Parsing/LocalizeFile/LocalizeFileParser.h"
class SequenceLocalizeFileConfig final : public LocalizeFileParser::sequence_t
{
protected:
void ProcessMatch(LocalizeFileParserState* state, SequenceResult<SimpleParserValue>& result) const override;
public:
SequenceLocalizeFileConfig();
};

View File

@ -0,0 +1,16 @@
#include "SequenceLocalizeFileConsumeEmptyLines.h"
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
SequenceLocalizeFileConsumeEmptyLines::SequenceLocalizeFileConsumeEmptyLines()
{
const SimpleMatcherFactory create(this);
AddMatchers({
create.Type(SimpleParserValueType::NEW_LINE)
});
}
void SequenceLocalizeFileConsumeEmptyLines::ProcessMatch(LocalizeFileParserState* state, SequenceResult<SimpleParserValue>& result) const
{
}

View File

@ -0,0 +1,12 @@
#pragma once
#include "Parsing/LocalizeFile/LocalizeFileParser.h"
class SequenceLocalizeFileConsumeEmptyLines final : public LocalizeFileParser::sequence_t
{
protected:
void ProcessMatch(LocalizeFileParserState* state, SequenceResult<SimpleParserValue>& result) const override;
public:
SequenceLocalizeFileConsumeEmptyLines();
};

View File

@ -0,0 +1,17 @@
#include "SequenceLocalizeFileEndMarker.h"
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
SequenceLocalizeFileEndMarker::SequenceLocalizeFileEndMarker()
{
const SimpleMatcherFactory create(this);
AddMatchers({
create.Keyword("ENDMARKER")
});
}
void SequenceLocalizeFileEndMarker::ProcessMatch(LocalizeFileParserState* state, SequenceResult<SimpleParserValue>& result) const
{
state->m_end = true;
}

View File

@ -0,0 +1,12 @@
#pragma once
#include "Parsing/LocalizeFile/LocalizeFileParser.h"
class SequenceLocalizeFileEndMarker final : public LocalizeFileParser::sequence_t
{
protected:
void ProcessMatch(LocalizeFileParserState* state, SequenceResult<SimpleParserValue>& result) const override;
public:
SequenceLocalizeFileEndMarker();
};

View File

@ -0,0 +1,72 @@
#include "SequenceLocalizeFileLanguageValue.h"
#include <sstream>
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
SequenceLocalizeFileLanguageValue::SequenceLocalizeFileLanguageValue()
{
const SimpleMatcherFactory create(this);
AddMatchers({
create.KeywordPrefix("LANG_").Capture(CAPTURE_LANGUAGE_NAME),
create.String().Capture(CAPTURE_ENTRY_VALUE),
create.Type(SimpleParserValueType::NEW_LINE)
});
}
std::string SequenceLocalizeFileLanguageValue::UnescapeValue(const std::string& value)
{
std::ostringstream str;
auto isEscaped = false;
for(auto c : value)
{
if(isEscaped)
{
switch(c)
{
case 'n':
str << '\n';
break;
case 'r':
str << '\r';
break;
default:
str << c;
break;
}
}
else if(c == '\\')
{
isEscaped = true;
}
else
{
str << c;
}
}
return str.str();
}
void SequenceLocalizeFileLanguageValue::ProcessMatch(LocalizeFileParserState* state, SequenceResult<SimpleParserValue>& result) const
{
const auto& langToken = result.NextCapture(CAPTURE_LANGUAGE_NAME);
const auto& valueToken = result.NextCapture(CAPTURE_ENTRY_VALUE);
const auto langName = langToken.IdentifierValue().substr(std::char_traits<char>::length("LANG_"));
const auto alreadyDefinedLanguage = state->m_current_reference_languages.find(langName);
if(alreadyDefinedLanguage != state->m_current_reference_languages.end())
{
std::ostringstream str;
str << "Value for reference \"" << state->m_current_reference << "\" already defined for language \"" << langToken.IdentifierValue() << "\"";
throw ParsingException(langToken.GetPos(), str.str());
}
state->m_current_reference_languages.emplace(langName);
if(langName == state->m_language_name_caps)
state->m_entries.emplace_back(state->m_current_reference, UnescapeValue(valueToken.StringValue()));
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "Parsing/LocalizeFile/LocalizeFileParser.h"
class SequenceLocalizeFileLanguageValue final : public LocalizeFileParser::sequence_t
{
static constexpr auto CAPTURE_LANGUAGE_NAME = 1;
static constexpr auto CAPTURE_ENTRY_VALUE = 2;
static std::string UnescapeValue(const std::string& value);
protected:
void ProcessMatch(LocalizeFileParserState* state, SequenceResult<SimpleParserValue>& result) const override;
public:
SequenceLocalizeFileLanguageValue();
};

View File

@ -0,0 +1,18 @@
#include "SequenceLocalizeFileNotes.h"
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
SequenceLocalizeFileNotes::SequenceLocalizeFileNotes()
{
const SimpleMatcherFactory create(this);
AddMatchers({
create.Keyword("FILENOTES"),
create.String(),
create.Type(SimpleParserValueType::NEW_LINE)
});
}
void SequenceLocalizeFileNotes::ProcessMatch(LocalizeFileParserState* state, SequenceResult<SimpleParserValue>& result) const
{
}

View File

@ -0,0 +1,12 @@
#pragma once
#include "Parsing/LocalizeFile/LocalizeFileParser.h"
class SequenceLocalizeFileNotes final : public LocalizeFileParser::sequence_t
{
protected:
void ProcessMatch(LocalizeFileParserState* state, SequenceResult<SimpleParserValue>& result) const override;
public:
SequenceLocalizeFileNotes();
};

View File

@ -0,0 +1,20 @@
#include "SequenceLocalizeFileReference.h"
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
SequenceLocalizeFileReference::SequenceLocalizeFileReference()
{
const SimpleMatcherFactory create(this);
AddMatchers({
create.Keyword("REFERENCE"),
create.Identifier().Capture(CAPTURE_REFERENCE_NAME),
create.Type(SimpleParserValueType::NEW_LINE)
});
}
void SequenceLocalizeFileReference::ProcessMatch(LocalizeFileParserState* state, SequenceResult<SimpleParserValue>& result) const
{
state->m_current_reference = result.NextCapture(CAPTURE_REFERENCE_NAME).IdentifierValue();
state->m_current_reference_languages.clear();
}

View File

@ -0,0 +1,14 @@
#pragma once
#include "Parsing/LocalizeFile/LocalizeFileParser.h"
class SequenceLocalizeFileReference final : public LocalizeFileParser::sequence_t
{
static constexpr auto CAPTURE_REFERENCE_NAME = 1;
protected:
void ProcessMatch(LocalizeFileParserState* state, SequenceResult<SimpleParserValue>& result) const override;
public:
SequenceLocalizeFileReference();
};

View File

@ -0,0 +1,23 @@
#include "SequenceLocalizeFileVersion.h"
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
SequenceLocalizeFileVersion::SequenceLocalizeFileVersion()
{
const SimpleMatcherFactory create(this);
AddMatchers({
create.Keyword("VERSION"),
create.String().Capture(CAPTURE_VERSION),
create.Type(SimpleParserValueType::NEW_LINE)
});
}
void SequenceLocalizeFileVersion::ProcessMatch(LocalizeFileParserState* state, SequenceResult<SimpleParserValue>& result) const
{
const auto& versionCapture = result.NextCapture(CAPTURE_VERSION);
if(versionCapture.StringValue() != "1")
{
throw ParsingException(versionCapture.GetPos(), "Localize file needs to be version 1");
}
}

View File

@ -0,0 +1,14 @@
#pragma once
#include "Parsing/LocalizeFile/LocalizeFileParser.h"
class SequenceLocalizeFileVersion final : public LocalizeFileParser::sequence_t
{
static constexpr auto CAPTURE_VERSION = 1;
protected:
void ProcessMatch(LocalizeFileParserState* state, SequenceResult<SimpleParserValue>& result) const override;
public:
SequenceLocalizeFileVersion();
};

View File

@ -44,7 +44,8 @@ void StringFileDumper::WriteLocalizeEntry(const std::string& reference, const st
m_stream << "\n"; m_stream << "\n";
m_stream << "REFERENCE " << reference <<"\n"; m_stream << "REFERENCE " << reference <<"\n";
const auto escapedValue = std::regex_replace(value, std::regex("\n"), "\\n"); auto escapedValue = std::regex_replace(value, std::regex("\n"), "\\n");
escapedValue = std::regex_replace(escapedValue, std::regex("\r"), "\\r");
const auto valueSpacing = std::string(15 - m_language_caps.length(), ' '); const auto valueSpacing = std::string(15 - m_language_caps.length(), ' ');
m_stream << "LANG_" << m_language_caps << valueSpacing << "\"" << escapedValue << "\"\n"; m_stream << "LANG_" << m_language_caps << valueSpacing << "\"" << escapedValue << "\"\n";

View File

@ -3,7 +3,7 @@
#include <fstream> #include <fstream>
#include <filesystem> #include <filesystem>
#include "Dumping/Localize/LocalizeCommon.h" #include "Localize/LocalizeCommon.h"
#include "Dumping/Localize/StringFileDumper.h" #include "Dumping/Localize/StringFileDumper.h"
using namespace IW4; using namespace IW4;

View File

@ -3,7 +3,7 @@
#include <fstream> #include <fstream>
#include <filesystem> #include <filesystem>
#include "Dumping/Localize/LocalizeCommon.h" #include "Localize/LocalizeCommon.h"
#include "Dumping/Localize/StringFileDumper.h" #include "Dumping/Localize/StringFileDumper.h"
using namespace T6; using namespace T6;
@ -17,13 +17,12 @@ void AssetDumperLocalizeEntry::DumpPool(AssetDumpingContext& context, AssetPool<
const auto language = LocalizeCommon::GetNameOfLanguage(context.m_zone->m_language); const auto language = LocalizeCommon::GetNameOfLanguage(context.m_zone->m_language);
fs::path stringsPath(context.m_base_path); fs::path stringsPath(context.m_base_path);
stringsPath.append(language); stringsPath.append(language);
stringsPath.append("/localizedstrings"); stringsPath.append("localizedstrings");
create_directories(stringsPath); create_directories(stringsPath);
auto stringFilePath(stringsPath); auto stringFilePath(stringsPath);
stringFilePath.append(context.m_zone->m_name); stringFilePath.append(context.m_zone->m_name + ".str");
stringFilePath.append(".str");
std::ofstream stringFile(stringFilePath, std::fstream::out | std::ofstream::binary); std::ofstream stringFile(stringFilePath, std::fstream::out | std::ofstream::binary);

View File

@ -3,6 +3,7 @@
#include "SimpleMatcherAnyCharacterBesides.h" #include "SimpleMatcherAnyCharacterBesides.h"
#include "SimpleMatcherCharacter.h" #include "SimpleMatcherCharacter.h"
#include "SimpleMatcherKeyword.h" #include "SimpleMatcherKeyword.h"
#include "SimpleMatcherKeywordPrefix.h"
#include "SimpleMatcherValueType.h" #include "SimpleMatcherValueType.h"
SimpleMatcherFactory::SimpleMatcherFactory(const IMatcherForLabelSupplier<SimpleParserValue>* labelSupplier) SimpleMatcherFactory::SimpleMatcherFactory(const IMatcherForLabelSupplier<SimpleParserValue>* labelSupplier)
@ -20,11 +21,21 @@ MatcherFactoryWrapper<SimpleParserValue> SimpleMatcherFactory::Keyword(std::stri
return MatcherFactoryWrapper<SimpleParserValue>(std::make_unique<SimpleMatcherKeyword>(std::move(value))); return MatcherFactoryWrapper<SimpleParserValue>(std::make_unique<SimpleMatcherKeyword>(std::move(value)));
} }
MatcherFactoryWrapper<SimpleParserValue> SimpleMatcherFactory::KeywordPrefix(std::string value) const
{
return MatcherFactoryWrapper<SimpleParserValue>(std::make_unique<SimpleMatcherKeywordPrefix>(std::move(value)));
}
MatcherFactoryWrapper<SimpleParserValue> SimpleMatcherFactory::Identifier() const MatcherFactoryWrapper<SimpleParserValue> SimpleMatcherFactory::Identifier() const
{ {
return MatcherFactoryWrapper<SimpleParserValue>(std::make_unique<SimpleMatcherValueType>(SimpleParserValueType::IDENTIFIER)); return MatcherFactoryWrapper<SimpleParserValue>(std::make_unique<SimpleMatcherValueType>(SimpleParserValueType::IDENTIFIER));
} }
MatcherFactoryWrapper<SimpleParserValue> SimpleMatcherFactory::String() const
{
return MatcherFactoryWrapper<SimpleParserValue>(std::make_unique<SimpleMatcherValueType>(SimpleParserValueType::STRING));
}
MatcherFactoryWrapper<SimpleParserValue> SimpleMatcherFactory::Integer() const MatcherFactoryWrapper<SimpleParserValue> SimpleMatcherFactory::Integer() const
{ {
return MatcherFactoryWrapper<SimpleParserValue>(std::make_unique<SimpleMatcherValueType>(SimpleParserValueType::INTEGER)); return MatcherFactoryWrapper<SimpleParserValue>(std::make_unique<SimpleMatcherValueType>(SimpleParserValueType::INTEGER));

View File

@ -12,7 +12,9 @@ public:
_NODISCARD MatcherFactoryWrapper<SimpleParserValue> Type(SimpleParserValueType type) const; _NODISCARD MatcherFactoryWrapper<SimpleParserValue> Type(SimpleParserValueType type) const;
_NODISCARD MatcherFactoryWrapper<SimpleParserValue> Keyword(std::string value) const; _NODISCARD MatcherFactoryWrapper<SimpleParserValue> Keyword(std::string value) const;
_NODISCARD MatcherFactoryWrapper<SimpleParserValue> KeywordPrefix(std::string value) const;
_NODISCARD MatcherFactoryWrapper<SimpleParserValue> Identifier() const; _NODISCARD MatcherFactoryWrapper<SimpleParserValue> Identifier() const;
_NODISCARD MatcherFactoryWrapper<SimpleParserValue> String() const;
_NODISCARD MatcherFactoryWrapper<SimpleParserValue> Integer() const; _NODISCARD MatcherFactoryWrapper<SimpleParserValue> Integer() const;
_NODISCARD MatcherFactoryWrapper<SimpleParserValue> FloatingPoint() const; _NODISCARD MatcherFactoryWrapper<SimpleParserValue> FloatingPoint() const;
_NODISCARD MatcherFactoryWrapper<SimpleParserValue> Char(char c) const; _NODISCARD MatcherFactoryWrapper<SimpleParserValue> Char(char c) const;

View File

@ -0,0 +1,14 @@
#include "SimpleMatcherKeywordPrefix.h"
SimpleMatcherKeywordPrefix::SimpleMatcherKeywordPrefix(std::string value)
: m_value(std::move(value))
{
}
MatcherResult<SimpleParserValue> SimpleMatcherKeywordPrefix::CanMatch(ILexer<SimpleParserValue>* lexer, const unsigned tokenOffset)
{
const auto& token = lexer->GetToken(tokenOffset);
return token.m_type == SimpleParserValueType::IDENTIFIER && token.IdentifierValue().compare(0, m_value.size(), m_value) == 0
? MatcherResult<SimpleParserValue>::Match(1)
: MatcherResult<SimpleParserValue>::NoMatch();
}

View File

@ -0,0 +1,17 @@
#pragma once
#include <string>
#include "Parsing/Simple/SimpleParserValue.h"
#include "Parsing/Matcher/AbstractMatcher.h"
class SimpleMatcherKeywordPrefix final : public AbstractMatcher<SimpleParserValue>
{
std::string m_value;
protected:
MatcherResult<SimpleParserValue> CanMatch(ILexer<SimpleParserValue>* lexer, unsigned tokenOffset) override;
public:
explicit SimpleMatcherKeywordPrefix(std::string value);
};