diff --git a/src/ObjLoading/Parsing/LocalizeFile/LocalizeFileReader.cpp b/src/ObjLoading/Parsing/LocalizeFile/LocalizeFileReader.cpp index 289131f0..dde66961 100644 --- a/src/ObjLoading/Parsing/LocalizeFile/LocalizeFileReader.cpp +++ b/src/ObjLoading/Parsing/LocalizeFile/LocalizeFileReader.cpp @@ -2,7 +2,7 @@ #include "LocalizeFileParser.h" #include "Parsing/Impl/CommentRemovingStreamProxy.h" -#include "Parsing/Impl/ParserInputStream.h" +#include "Parsing/Impl/ParserSingleInputStream.h" LocalizeFileReader::LocalizeFileReader(std::istream& stream, std::string fileName, GameLanguage language) : m_file_name(std::move(fileName)), @@ -16,7 +16,7 @@ LocalizeFileReader::LocalizeFileReader(std::istream& stream, std::string fileNam bool LocalizeFileReader::OpenBaseStream(std::istream& stream) { - m_open_streams.emplace_back(std::make_unique(stream, m_file_name)); + m_open_streams.emplace_back(std::make_unique(stream, m_file_name)); return true; } diff --git a/src/ObjWriting/Menu/AbstractMenuDumper.cpp b/src/ObjWriting/Menu/AbstractMenuDumper.cpp index 14a2764f..104ed5cb 100644 --- a/src/ObjWriting/Menu/AbstractMenuDumper.cpp +++ b/src/ObjWriting/Menu/AbstractMenuDumper.cpp @@ -4,7 +4,7 @@ #include #include -#include "Parsing/Impl/ParserInputStream.h" +#include "Parsing/Impl/ParserSingleInputStream.h" #include "Parsing/Simple/SimpleLexer.h" AbstractMenuDumper::AbstractMenuDumper(std::ostream& stream) @@ -65,7 +65,7 @@ std::vector AbstractMenuDumper::CreateScriptTokenList(const char* s { const std::string scriptString(script); std::istringstream stringStream(scriptString); - ParserInputStream inputStream(stringStream, "MenuScript"); + ParserSingleInputStream inputStream(stringStream, "MenuScript"); SimpleLexer lexer(&inputStream, SimpleLexer::Config{false, true, false}); std::vector result; diff --git a/src/Parser/Parsing/Impl/IncludingStreamProxy.cpp b/src/Parser/Parsing/Impl/IncludingStreamProxy.cpp index fa6e2991..d8110a1d 100644 --- a/src/Parser/Parsing/Impl/IncludingStreamProxy.cpp +++ b/src/Parser/Parsing/Impl/IncludingStreamProxy.cpp @@ -65,7 +65,7 @@ bool IncludingStreamProxy::MatchIncludeDirective(const ParserLine& line, unsigne unsigned filenameStart, filenameEnd; if (!ExtractIncludeFilename(line, directivePosition, filenameStart, filenameEnd)) - throw ParsingException(TokenPos(line.m_filename, line.m_line_number, directivePosition), INCLUDE_QUOTES_ERROR); + throw ParsingException(TokenPos(line.m_filename, line.m_line_number, static_cast(directivePosition)), INCLUDE_QUOTES_ERROR); if (filenameEnd <= filenameStart) throw ParsingException(CreatePos(line, directivePosition), "No filename specified"); diff --git a/src/Parser/Parsing/Impl/ParserMultiInputStream.cpp b/src/Parser/Parsing/Impl/ParserMultiInputStream.cpp new file mode 100644 index 00000000..859027b2 --- /dev/null +++ b/src/Parser/Parsing/Impl/ParserMultiInputStream.cpp @@ -0,0 +1,104 @@ +#include "ParserMultiInputStream.h" + +#include + +ParserMultiInputStream::FileInfo::FileInfo(std::unique_ptr stream, std::string filePath) + : m_owned_stream(std::move(stream)), + m_stream(*m_owned_stream), + m_file_path(std::move(filePath)), + m_line_number(1) +{ +} + +ParserMultiInputStream::FileInfo::FileInfo(std::istream& stream, std::string filePath) + : m_stream(stream), + m_file_path(std::move(filePath)), + m_line_number(1) +{ +} + +ParserMultiInputStream::ParserMultiInputStream(std::unique_ptr stream, std::string fileName, include_callback_t includeCallback) + : m_include_callback(std::move(includeCallback)) +{ + m_files.emplace(std::move(stream), std::move(fileName)); +} + +ParserMultiInputStream::ParserMultiInputStream(std::istream& stream, std::string fileName, include_callback_t includeCallback) + : m_include_callback(std::move(includeCallback)) +{ + m_files.emplace(stream, std::move(fileName)); +} + +ParserLine ParserMultiInputStream::NextLine() +{ + std::ostringstream str; + auto hasLength = false; + + if (m_files.empty()) + return ParserLine(); + + while (!m_files.empty()) + { + auto& fileInfo = m_files.top(); + + auto c = fileInfo.m_stream.get(); + while (c != EOF) + { + switch (c) + { + case '\r': + c = fileInfo.m_stream.get(); + if (c == '\n') + return ParserLine(fileInfo.m_file_path, fileInfo.m_line_number++, str.str()); + str << '\r'; + hasLength = true; + continue; + + case '\n': + return ParserLine(fileInfo.m_file_path, fileInfo.m_line_number++, str.str()); + + default: + str << static_cast(c); + hasLength = true; + break; + } + + c = fileInfo.m_stream.get(); + } + + if (hasLength) + return ParserLine(fileInfo.m_file_path, fileInfo.m_line_number, str.str()); + m_files.pop(); + } + + return ParserLine(); +} + +bool ParserMultiInputStream::IncludeFile(const std::string& filename) +{ + if (!m_include_callback) + return false; + + auto newFile = m_include_callback(filename); + if (!newFile) + return false; + + m_files.emplace(std::move(newFile), filename); + return true; +} + +void ParserMultiInputStream::PopCurrentFile() +{ + if (!m_files.empty()) + m_files.pop(); +} + +bool ParserMultiInputStream::IsOpen() const +{ + return !m_files.empty(); +} + +bool ParserMultiInputStream::Eof() const +{ + return m_files.empty(); +} diff --git a/src/Parser/Parsing/Impl/ParserMultiInputStream.h b/src/Parser/Parsing/Impl/ParserMultiInputStream.h new file mode 100644 index 00000000..40c362ba --- /dev/null +++ b/src/Parser/Parsing/Impl/ParserMultiInputStream.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include +#include + +#include "Parsing/IParserLineStream.h" + +class ParserMultiInputStream final : public IParserLineStream +{ +public: + using include_callback_t = std::function(const std::string& filename)>; + +private: + class FileInfo + { + public: + std::unique_ptr m_owned_stream; + std::istream& m_stream; + std::string m_file_path; + int m_line_number; + + FileInfo(std::unique_ptr stream, std::string filePath); + FileInfo(std::istream& stream, std::string filePath); + }; + + const include_callback_t m_include_callback; + std::stack m_files; + +public: + ParserMultiInputStream(std::unique_ptr stream, std::string fileName, include_callback_t includeCallback); + ParserMultiInputStream(std::istream& stream, std::string fileName, include_callback_t includeCallback); + + ParserLine NextLine() override; + bool IncludeFile(const std::string& filename) override; + void PopCurrentFile() override; + _NODISCARD bool IsOpen() const override; + _NODISCARD bool Eof() const override; +}; \ No newline at end of file diff --git a/src/Parser/Parsing/Impl/ParserInputStream.cpp b/src/Parser/Parsing/Impl/ParserSingleInputStream.cpp similarity index 71% rename from src/Parser/Parsing/Impl/ParserInputStream.cpp rename to src/Parser/Parsing/Impl/ParserSingleInputStream.cpp index 06a338eb..efb965a1 100644 --- a/src/Parser/Parsing/Impl/ParserInputStream.cpp +++ b/src/Parser/Parsing/Impl/ParserSingleInputStream.cpp @@ -1,15 +1,15 @@ -#include "ParserInputStream.h" +#include "ParserSingleInputStream.h" #include -ParserInputStream::ParserInputStream(std::istream& stream, std::string fileName) +ParserSingleInputStream::ParserSingleInputStream(std::istream& stream, std::string fileName) : m_stream(stream), m_file_name(std::move(fileName)), m_line_number(1) { } -ParserLine ParserInputStream::NextLine() +ParserLine ParserSingleInputStream::NextLine() { std::ostringstream str; auto hasLength = false; @@ -45,21 +45,21 @@ ParserLine ParserInputStream::NextLine() return ParserLine(); } -bool ParserInputStream::IncludeFile(const std::string& filename) +bool ParserSingleInputStream::IncludeFile(const std::string& filename) { return false; } -void ParserInputStream::PopCurrentFile() +void ParserSingleInputStream::PopCurrentFile() { } -bool ParserInputStream::IsOpen() const +bool ParserSingleInputStream::IsOpen() const { return !m_stream.eof(); } -bool ParserInputStream::Eof() const +bool ParserSingleInputStream::Eof() const { return !m_stream.eof(); } diff --git a/src/Parser/Parsing/Impl/ParserInputStream.h b/src/Parser/Parsing/Impl/ParserSingleInputStream.h similarity index 73% rename from src/Parser/Parsing/Impl/ParserInputStream.h rename to src/Parser/Parsing/Impl/ParserSingleInputStream.h index 87e78398..4af10424 100644 --- a/src/Parser/Parsing/Impl/ParserInputStream.h +++ b/src/Parser/Parsing/Impl/ParserSingleInputStream.h @@ -4,14 +4,14 @@ #include "Parsing/IParserLineStream.h" -class ParserInputStream final : public IParserLineStream +class ParserSingleInputStream final : public IParserLineStream { std::istream& m_stream; std::string m_file_name; int m_line_number; public: - ParserInputStream(std::istream& stream, std::string fileName); + ParserSingleInputStream(std::istream& stream, std::string fileName); ParserLine NextLine() override; bool IncludeFile(const std::string& filename) override; diff --git a/src/ZoneCommon/Zone/Definition/ZoneDefinitionStream.cpp b/src/ZoneCommon/Zone/Definition/ZoneDefinitionStream.cpp index e172bfaf..e2a4774d 100644 --- a/src/ZoneCommon/Zone/Definition/ZoneDefinitionStream.cpp +++ b/src/ZoneCommon/Zone/Definition/ZoneDefinitionStream.cpp @@ -2,7 +2,7 @@ #include -#include "Parsing/Impl/ParserInputStream.h" +#include "Parsing/Impl/ParserSingleInputStream.h" #include #include "Parsing/Impl/DefinesStreamProxy.h" @@ -22,7 +22,7 @@ ZoneDefinitionInputStream::ZoneDefinitionInputStream(std::istream& stream, std:: bool ZoneDefinitionInputStream::OpenBaseStream(std::istream& stream) { - m_open_streams.emplace_back(std::make_unique(stream, m_file_name)); + m_open_streams.emplace_back(std::make_unique(stream, m_file_name)); return true; }