Use shared ptr for line filenames to be able to still use filenames when original file has been closed

This commit is contained in:
Jan 2021-11-22 10:52:43 +01:00
parent 6b7a71a1bb
commit a8f0fbd3bb
16 changed files with 50 additions and 55 deletions

View File

@ -1,15 +1,12 @@
#include "IParserLineStream.h" #include "IParserLineStream.h"
const std::string ParserLine::EMPTY_STRING;
ParserLine::ParserLine() ParserLine::ParserLine()
: m_filename(EMPTY_STRING), : m_line_number(0)
m_line_number(0)
{ {
} }
ParserLine::ParserLine(const std::string& filename, const int lineNumber, std::string line) ParserLine::ParserLine(std::shared_ptr<std::string> filename, const int lineNumber, std::string line)
: m_filename(filename), : m_filename(std::move(filename)),
m_line_number(lineNumber), m_line_number(lineNumber),
m_line(std::move(line)) m_line(std::move(line))
{ {

View File

@ -2,20 +2,19 @@
#include <string> #include <string>
#include <functional> #include <functional>
#include <memory>
#include "Utils/ClassUtils.h" #include "Utils/ClassUtils.h"
class ParserLine class ParserLine
{ {
static const std::string EMPTY_STRING;
public: public:
std::reference_wrapper<const std::string> m_filename; std::shared_ptr<std::string> m_filename;
int m_line_number; int m_line_number;
std::string m_line; std::string m_line;
ParserLine(); ParserLine();
ParserLine(const std::string& filename, int lineNumber, std::string line); ParserLine(std::shared_ptr<std::string> filename, int lineNumber, std::string line);
_NODISCARD bool IsEof() const; _NODISCARD bool IsEof() const;
}; };

View File

@ -2,7 +2,7 @@
TokenPos AbstractDirectiveStreamProxy::CreatePos(const ParserLine& line, const unsigned position) TokenPos AbstractDirectiveStreamProxy::CreatePos(const ParserLine& line, const unsigned position)
{ {
return TokenPos(line.m_filename.get(), line.m_line_number, static_cast<int>(position + 1)); return TokenPos(*line.m_filename, line.m_line_number, static_cast<int>(position + 1));
} }
bool AbstractDirectiveStreamProxy::SkipWhitespace(const ParserLine& line, unsigned& position) bool AbstractDirectiveStreamProxy::SkipWhitespace(const ParserLine& line, unsigned& position)

View File

@ -100,7 +100,7 @@ protected:
_NODISCARD TokenPos GetPreviousCharacterPos() const _NODISCARD TokenPos GetPreviousCharacterPos() const
{ {
const auto& currentLine = CurrentLine(); const auto& currentLine = CurrentLine();
return TokenPos(currentLine.m_filename, currentLine.m_line_number, m_current_line_offset); return TokenPos(*currentLine.m_filename, currentLine.m_line_number, m_current_line_offset);
} }
_NODISCARD TokenPos GetNextCharacterPos() _NODISCARD TokenPos GetNextCharacterPos()
@ -109,10 +109,10 @@ protected:
if (m_current_line_offset + 1 >= currentLine.m_line.size()) if (m_current_line_offset + 1 >= currentLine.m_line.size())
{ {
PeekChar(); PeekChar();
return TokenPos(m_line_cache.back().m_filename, m_line_cache.back().m_line_number, 1); return TokenPos(*m_line_cache.back().m_filename, m_line_cache.back().m_line_number, 1);
} }
return TokenPos(currentLine.m_filename, currentLine.m_line_number, m_current_line_offset + 1); return TokenPos(*currentLine.m_filename, currentLine.m_line_number, m_current_line_offset + 1);
} }
/** /**
@ -155,7 +155,7 @@ protected:
while (true) while (true)
{ {
if (m_current_line_offset >= lineSize) if (m_current_line_offset >= lineSize)
throw ParsingException(TokenPos(currentLine.m_filename, currentLine.m_line_number, m_current_line_offset), "Unclosed string"); throw ParsingException(TokenPos(*currentLine.m_filename, currentLine.m_line_number, m_current_line_offset), "Unclosed string");
if (currentLine.m_line[m_current_line_offset] == '\"') if (currentLine.m_line[m_current_line_offset] == '\"')
break; break;
@ -189,7 +189,7 @@ protected:
auto exponent = false; auto exponent = false;
if (*currentCharacter == '-' || *currentCharacter == '+') if (*currentCharacter == '-' || *currentCharacter == '+')
currentCharacter++; ++currentCharacter;
while (*currentCharacter) while (*currentCharacter)
{ {
@ -208,7 +208,7 @@ protected:
if (exponent) if (exponent)
throw ParsingException(GetPreviousCharacterPos(), "Invalid number"); throw ParsingException(GetPreviousCharacterPos(), "Invalid number");
if (currentCharacter[1] == '-') if (currentCharacter[1] == '-')
currentCharacter++; ++currentCharacter;
exponent = true; exponent = true;
isInteger = false; isInteger = false;
} }
@ -221,7 +221,7 @@ protected:
break; break;
} }
currentCharacter++; ++currentCharacter;
} }
return isInteger; return isInteger;
@ -290,7 +290,6 @@ protected:
public: public:
const TokenType& GetToken(unsigned index) override const TokenType& GetToken(unsigned index) override
{ {
assert(index >= 0);
while (index >= m_token_cache.size()) while (index >= m_token_cache.size())
m_token_cache.emplace_back(GetNextToken()); m_token_cache.emplace_back(GetNextToken());
@ -307,7 +306,7 @@ public:
const auto& lastToken = m_token_cache.back(); const auto& lastToken = m_token_cache.back();
while (!m_line_cache.empty() while (!m_line_cache.empty()
&& (m_line_cache.front().m_line_number != lastToken.GetPos().m_line && (m_line_cache.front().m_line_number != lastToken.GetPos().m_line
|| m_line_cache.front().m_filename.get() != lastToken.GetPos().m_filename.get())) || *m_line_cache.front().m_filename != lastToken.GetPos().m_filename.get()))
{ {
m_line_cache.pop_front(); m_line_cache.pop_front();
m_line_index--; m_line_index--;
@ -319,7 +318,7 @@ public:
m_token_cache.erase(m_token_cache.begin(), m_token_cache.begin() + amount); m_token_cache.erase(m_token_cache.begin(), m_token_cache.begin() + amount);
const auto& firstToken = m_token_cache.front(); const auto& firstToken = m_token_cache.front();
while (m_line_cache.front().m_line_number != firstToken.GetPos().m_line while (m_line_cache.front().m_line_number != firstToken.GetPos().m_line
|| m_line_cache.front().m_filename.get() != firstToken.GetPos().m_filename.get()) || *m_line_cache.front().m_filename != firstToken.GetPos().m_filename.get())
{ {
m_line_cache.pop_front(); m_line_cache.pop_front();
m_line_index--; m_line_index--;
@ -341,7 +340,7 @@ public:
{ {
for (const auto& line : m_line_cache) for (const auto& line : m_line_cache)
{ {
if (line.m_filename.get() == pos.m_filename.get() if (*line.m_filename == pos.m_filename.get()
&& line.m_line_number == pos.m_line) && line.m_line_number == pos.m_line)
return line; return line;
} }

View File

@ -70,7 +70,7 @@ bool IncludingStreamProxy::MatchIncludeDirective(const ParserLine& line, const u
unsigned filenameStart, filenameEnd; unsigned filenameStart, filenameEnd;
if (!ExtractIncludeFilename(line, currentPos, filenameStart, filenameEnd)) if (!ExtractIncludeFilename(line, currentPos, filenameStart, filenameEnd))
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, static_cast<int>(currentPos)), INCLUDE_QUOTES_ERROR); throw ParsingException(TokenPos(*line.m_filename, line.m_line_number, static_cast<int>(currentPos)), INCLUDE_QUOTES_ERROR);
if (filenameEnd <= filenameStart) if (filenameEnd <= filenameStart)
throw ParsingException(CreatePos(line, currentPos), "No filename specified"); throw ParsingException(CreatePos(line, currentPos), "No filename specified");
@ -103,7 +103,7 @@ bool IncludingStreamProxy::MatchPragmaOnceDirective(const ParserLine& line, cons
if (!MatchString(line, currentPos, ONCE_PRAGMA_COMMAND, std::char_traits<char>::length(ONCE_PRAGMA_COMMAND))) if (!MatchString(line, currentPos, ONCE_PRAGMA_COMMAND, std::char_traits<char>::length(ONCE_PRAGMA_COMMAND)))
return false; return false;
const auto absolutePath = absolute(fs::path(line.m_filename.get())); const auto absolutePath = absolute(fs::path(*line.m_filename));
const auto absolutePathStr = absolutePath.string(); const auto absolutePathStr = absolutePath.string();
const auto existingPath = m_included_files.find(absolutePathStr); const auto existingPath = m_included_files.find(absolutePathStr);

View File

@ -15,7 +15,7 @@ class IncludingStreamProxy final : public AbstractDirectiveStreamProxy
IParserLineStream* const m_stream; IParserLineStream* const m_stream;
std::set<std::string> m_included_files; std::set<std::string> m_included_files;
_NODISCARD static bool ExtractIncludeFilename(const ParserLine& line, unsigned includeDirectivePosition, unsigned& directiveStartPos, unsigned& filenameEndPos); _NODISCARD static bool ExtractIncludeFilename(const ParserLine& line, unsigned includeDirectivePosition, unsigned& filenameStartPosition, unsigned& filenameEndPosition);
_NODISCARD bool MatchIncludeDirective(const ParserLine& line, unsigned directiveStartPos, unsigned directiveEndPos) const; _NODISCARD bool MatchIncludeDirective(const ParserLine& line, unsigned directiveStartPos, unsigned directiveEndPos) const;
_NODISCARD bool MatchPragmaOnceDirective(const ParserLine& line, unsigned directiveStartPos, unsigned directiveEndPos); _NODISCARD bool MatchPragmaOnceDirective(const ParserLine& line, unsigned directiveStartPos, unsigned directiveEndPos);
_NODISCARD bool MatchDirectives(const ParserLine& line); _NODISCARD bool MatchDirectives(const ParserLine& line);

View File

@ -2,6 +2,7 @@
#include <stack> #include <stack>
#include "Utils/ClassUtils.h"
#include "AbstractDirectiveStreamProxy.h" #include "AbstractDirectiveStreamProxy.h"
#include "Parsing/IPackValueSupplier.h" #include "Parsing/IPackValueSupplier.h"
#include "Parsing/IParserLineStream.h" #include "Parsing/IParserLineStream.h"
@ -32,5 +33,5 @@ public:
_NODISCARD bool IsOpen() const override; _NODISCARD bool IsOpen() const override;
_NODISCARD bool Eof() const override; _NODISCARD bool Eof() const override;
int GetCurrentPack() const override; _NODISCARD int GetCurrentPack() const override;
}; };

View File

@ -6,13 +6,13 @@
namespace fs = std::filesystem; namespace fs = std::filesystem;
ParserFilesystemStream::FileInfo::FileInfo(std::string filePath) ParserFilesystemStream::FileInfo::FileInfo(std::string filePath)
: m_file_path(std::move(filePath)), : m_file_path(std::make_shared<std::string>(std::move(filePath))),
m_stream(m_file_path), m_stream(*m_file_path),
m_line_number(1) m_line_number(1)
{ {
} }
ParserFilesystemStream::ParserFilesystemStream(std::string path) ParserFilesystemStream::ParserFilesystemStream(const std::string& path)
{ {
const auto absolutePath = absolute(fs::path(path)); const auto absolutePath = absolute(fs::path(path));
m_files.emplace(FileInfo(absolutePath.string())); m_files.emplace(FileInfo(absolutePath.string()));
@ -74,7 +74,7 @@ bool ParserFilesystemStream::IncludeFile(const std::string& filename)
if (m_files.empty()) if (m_files.empty())
return false; return false;
auto newFilePath = fs::path(m_files.top().m_file_path); auto newFilePath = fs::path(*m_files.top().m_file_path);
newFilePath.remove_filename().concat(filename); newFilePath.remove_filename().concat(filename);
newFilePath = absolute(newFilePath); newFilePath = absolute(newFilePath);

View File

@ -10,7 +10,7 @@ class ParserFilesystemStream final : public IParserLineStream
class FileInfo class FileInfo
{ {
public: public:
std::string m_file_path; std::shared_ptr<std::string> m_file_path;
std::ifstream m_stream; std::ifstream m_stream;
int m_line_number; int m_line_number;
@ -19,7 +19,7 @@ class ParserFilesystemStream final : public IParserLineStream
std::stack<FileInfo> m_files; std::stack<FileInfo> m_files;
public: public:
explicit ParserFilesystemStream(std::string path); explicit ParserFilesystemStream(const std::string& path);
ParserLine NextLine() override; ParserLine NextLine() override;
bool IncludeFile(const std::string& filename) override; bool IncludeFile(const std::string& filename) override;

View File

@ -5,14 +5,14 @@
ParserMultiInputStream::FileInfo::FileInfo(std::unique_ptr<std::istream> stream, std::string filePath) ParserMultiInputStream::FileInfo::FileInfo(std::unique_ptr<std::istream> stream, std::string filePath)
: m_owned_stream(std::move(stream)), : m_owned_stream(std::move(stream)),
m_stream(*m_owned_stream), m_stream(*m_owned_stream),
m_file_path(std::move(filePath)), m_file_path(std::make_shared<std::string>(std::move(filePath))),
m_line_number(1) m_line_number(1)
{ {
} }
ParserMultiInputStream::FileInfo::FileInfo(std::istream& stream, std::string filePath) ParserMultiInputStream::FileInfo::FileInfo(std::istream& stream, std::string filePath)
: m_stream(stream), : m_stream(stream),
m_file_path(std::move(filePath)), m_file_path(std::make_shared<std::string>(std::move(filePath))),
m_line_number(1) m_line_number(1)
{ {
} }
@ -79,7 +79,7 @@ bool ParserMultiInputStream::IncludeFile(const std::string& filename)
if (!m_include_callback) if (!m_include_callback)
return false; return false;
auto newFile = m_include_callback(filename, m_files.empty() ? "" : m_files.top().m_file_path); auto newFile = m_include_callback(filename, m_files.empty() ? "" : *m_files.top().m_file_path);
if (!newFile) if (!newFile)
return false; return false;

View File

@ -18,7 +18,7 @@ private:
public: public:
std::unique_ptr<std::istream> m_owned_stream; std::unique_ptr<std::istream> m_owned_stream;
std::istream& m_stream; std::istream& m_stream;
std::string m_file_path; std::shared_ptr<std::string> m_file_path;
int m_line_number; int m_line_number;
FileInfo(std::unique_ptr<std::istream> stream, std::string filePath); FileInfo(std::unique_ptr<std::istream> stream, std::string filePath);

View File

@ -4,7 +4,7 @@
ParserSingleInputStream::ParserSingleInputStream(std::istream& stream, std::string fileName) ParserSingleInputStream::ParserSingleInputStream(std::istream& stream, std::string fileName)
: m_stream(stream), : m_stream(stream),
m_file_name(std::move(fileName)), m_file_name(std::make_shared<std::string>(std::move(fileName))),
m_line_number(1) m_line_number(1)
{ {
} }

View File

@ -1,13 +1,14 @@
#pragma once #pragma once
#include <istream> #include <istream>
#include <memory>
#include "Parsing/IParserLineStream.h" #include "Parsing/IParserLineStream.h"
class ParserSingleInputStream final : public IParserLineStream class ParserSingleInputStream final : public IParserLineStream
{ {
std::istream& m_stream; std::istream& m_stream;
std::string m_file_name; std::shared_ptr<std::string> m_file_name;
int m_line_number; int m_line_number;
public: public:

View File

@ -2,8 +2,6 @@
#include <algorithm> #include <algorithm>
const std::string MockParserLineStream::MOCK_FILENAME = "Mockfile";
MockParserLineStream::MockParserLineStream(const std::vector<std::string>& lines) MockParserLineStream::MockParserLineStream(const std::vector<std::string>& lines)
{ {
AddIncludeLines(MOCK_FILENAME, lines); AddIncludeLines(MOCK_FILENAME, lines);
@ -11,7 +9,7 @@ MockParserLineStream::MockParserLineStream(const std::vector<std::string>& lines
} }
MockParserLineStream::IncludePos::IncludePos(std::string filename, const std::vector<std::string>& lines) MockParserLineStream::IncludePos::IncludePos(std::string filename, const std::vector<std::string>& lines)
: m_filename(std::move(filename)), : m_filename(std::make_shared<std::string>(std::move(filename))),
m_lines(lines), m_lines(lines),
m_pos(0) m_pos(0)
{ {

View File

@ -8,13 +8,13 @@
class MockParserLineStream final : public IParserLineStream class MockParserLineStream final : public IParserLineStream
{ {
public: public:
static const std::string MOCK_FILENAME; static constexpr const char* MOCK_FILENAME = "MockFile";
private: private:
class IncludePos class IncludePos
{ {
public: public:
std::string m_filename; std::shared_ptr<std::string> m_filename;
const std::vector<std::string>& m_lines; const std::vector<std::string>& m_lines;
unsigned m_pos; unsigned m_pos;

View File

@ -27,21 +27,21 @@ namespace test::parsing::impl::including_stream_proxy
{ {
auto line = proxy.NextLine(); auto line = proxy.NextLine();
REQUIRE(line.m_line_number == 1); REQUIRE(line.m_line_number == 1);
REQUIRE(line.m_filename.get() == MockParserLineStream::MOCK_FILENAME); REQUIRE(*line.m_filename == MockParserLineStream::MOCK_FILENAME);
REQUIRE(line.m_line == "Hello world"); REQUIRE(line.m_line == "Hello world");
} }
{ {
auto line = proxy.NextLine(); auto line = proxy.NextLine();
REQUIRE(line.m_line_number == 1); REQUIRE(line.m_line_number == 1);
REQUIRE(line.m_filename.get() == "ASDF.txt"); REQUIRE(*line.m_filename == "ASDF.txt");
REQUIRE(line.m_line == "Hello galaxy"); REQUIRE(line.m_line == "Hello galaxy");
} }
{ {
auto line = proxy.NextLine(); auto line = proxy.NextLine();
REQUIRE(line.m_line_number == 3); REQUIRE(line.m_line_number == 3);
REQUIRE(line.m_filename.get() == MockParserLineStream::MOCK_FILENAME); REQUIRE(*line.m_filename == MockParserLineStream::MOCK_FILENAME);
REQUIRE(line.m_line == "and bye"); REQUIRE(line.m_line == "and bye");
} }
@ -70,21 +70,21 @@ namespace test::parsing::impl::including_stream_proxy
{ {
auto line = proxy.NextLine(); auto line = proxy.NextLine();
REQUIRE(line.m_line_number == 1); REQUIRE(line.m_line_number == 1);
REQUIRE(line.m_filename.get() == MockParserLineStream::MOCK_FILENAME); REQUIRE(*line.m_filename == MockParserLineStream::MOCK_FILENAME);
REQUIRE(line.m_line == "Hello world"); REQUIRE(line.m_line == "Hello world");
} }
{ {
auto line = proxy.NextLine(); auto line = proxy.NextLine();
REQUIRE(line.m_line_number == 1); REQUIRE(line.m_line_number == 1);
REQUIRE(line.m_filename.get() == "ASDF.txt"); REQUIRE(*line.m_filename == "ASDF.txt");
REQUIRE(line.m_line == "Hello galaxy"); REQUIRE(line.m_line == "Hello galaxy");
} }
{ {
auto line = proxy.NextLine(); auto line = proxy.NextLine();
REQUIRE(line.m_line_number == 3); REQUIRE(line.m_line_number == 3);
REQUIRE(line.m_filename.get() == MockParserLineStream::MOCK_FILENAME); REQUIRE(*line.m_filename == MockParserLineStream::MOCK_FILENAME);
REQUIRE(line.m_line == "and bye"); REQUIRE(line.m_line == "and bye");
} }
@ -113,21 +113,21 @@ namespace test::parsing::impl::including_stream_proxy
{ {
auto line = proxy.NextLine(); auto line = proxy.NextLine();
REQUIRE(line.m_line_number == 1); REQUIRE(line.m_line_number == 1);
REQUIRE(line.m_filename.get() == MockParserLineStream::MOCK_FILENAME); REQUIRE(*line.m_filename == MockParserLineStream::MOCK_FILENAME);
REQUIRE(line.m_line == "Hello world"); REQUIRE(line.m_line == "Hello world");
} }
{ {
auto line = proxy.NextLine(); auto line = proxy.NextLine();
REQUIRE(line.m_line_number == 1); REQUIRE(line.m_line_number == 1);
REQUIRE(line.m_filename.get() == "ASDF.txt"); REQUIRE(*line.m_filename == "ASDF.txt");
REQUIRE(line.m_line == "Hello galaxy"); REQUIRE(line.m_line == "Hello galaxy");
} }
{ {
auto line = proxy.NextLine(); auto line = proxy.NextLine();
REQUIRE(line.m_line_number == 3); REQUIRE(line.m_line_number == 3);
REQUIRE(line.m_filename.get() == MockParserLineStream::MOCK_FILENAME); REQUIRE(*line.m_filename == MockParserLineStream::MOCK_FILENAME);
REQUIRE(line.m_line == "and bye"); REQUIRE(line.m_line == "and bye");
} }
@ -158,21 +158,21 @@ namespace test::parsing::impl::including_stream_proxy
{ {
auto line = proxy.NextLine(); auto line = proxy.NextLine();
REQUIRE(line.m_line_number == 1); REQUIRE(line.m_line_number == 1);
REQUIRE(line.m_filename.get() == MockParserLineStream::MOCK_FILENAME); REQUIRE(*line.m_filename == MockParserLineStream::MOCK_FILENAME);
REQUIRE(line.m_line == "Hello world"); REQUIRE(line.m_line == "Hello world");
} }
{ {
auto line = proxy.NextLine(); auto line = proxy.NextLine();
REQUIRE(line.m_line_number == 2); REQUIRE(line.m_line_number == 2);
REQUIRE(line.m_filename.get() == "ASDF.txt"); REQUIRE(*line.m_filename == "ASDF.txt");
REQUIRE(line.m_line == "Hello galaxy"); REQUIRE(line.m_line == "Hello galaxy");
} }
{ {
auto line = proxy.NextLine(); auto line = proxy.NextLine();
REQUIRE(line.m_line_number == 4); REQUIRE(line.m_line_number == 4);
REQUIRE(line.m_filename.get() == MockParserLineStream::MOCK_FILENAME); REQUIRE(*line.m_filename == MockParserLineStream::MOCK_FILENAME);
REQUIRE(line.m_line == "and bye"); REQUIRE(line.m_line == "and bye");
} }