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"
const std::string ParserLine::EMPTY_STRING;
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)
: m_filename(filename),
ParserLine::ParserLine(std::shared_ptr<std::string> filename, const int lineNumber, std::string line)
: m_filename(std::move(filename)),
m_line_number(lineNumber),
m_line(std::move(line))
{

View File

@ -2,20 +2,19 @@
#include <string>
#include <functional>
#include <memory>
#include "Utils/ClassUtils.h"
class ParserLine
{
static const std::string EMPTY_STRING;
public:
std::reference_wrapper<const std::string> m_filename;
std::shared_ptr<std::string> m_filename;
int m_line_number;
std::string m_line;
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;
};

View File

@ -2,7 +2,7 @@
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)

View File

@ -100,7 +100,7 @@ protected:
_NODISCARD TokenPos GetPreviousCharacterPos() const
{
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()
@ -109,10 +109,10 @@ protected:
if (m_current_line_offset + 1 >= currentLine.m_line.size())
{
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)
{
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] == '\"')
break;
@ -189,7 +189,7 @@ protected:
auto exponent = false;
if (*currentCharacter == '-' || *currentCharacter == '+')
currentCharacter++;
++currentCharacter;
while (*currentCharacter)
{
@ -208,7 +208,7 @@ protected:
if (exponent)
throw ParsingException(GetPreviousCharacterPos(), "Invalid number");
if (currentCharacter[1] == '-')
currentCharacter++;
++currentCharacter;
exponent = true;
isInteger = false;
}
@ -221,7 +221,7 @@ protected:
break;
}
currentCharacter++;
++currentCharacter;
}
return isInteger;
@ -290,7 +290,6 @@ protected:
public:
const TokenType& GetToken(unsigned index) override
{
assert(index >= 0);
while (index >= m_token_cache.size())
m_token_cache.emplace_back(GetNextToken());
@ -307,7 +306,7 @@ public:
const auto& lastToken = m_token_cache.back();
while (!m_line_cache.empty()
&& (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_index--;
@ -319,7 +318,7 @@ public:
m_token_cache.erase(m_token_cache.begin(), m_token_cache.begin() + amount);
const auto& firstToken = m_token_cache.front();
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_index--;
@ -341,7 +340,7 @@ public:
{
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)
return line;
}

View File

@ -70,7 +70,7 @@ bool IncludingStreamProxy::MatchIncludeDirective(const ParserLine& line, const u
unsigned 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)
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)))
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 existingPath = m_included_files.find(absolutePathStr);

View File

@ -15,7 +15,7 @@ class IncludingStreamProxy final : public AbstractDirectiveStreamProxy
IParserLineStream* const m_stream;
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 MatchPragmaOnceDirective(const ParserLine& line, unsigned directiveStartPos, unsigned directiveEndPos);
_NODISCARD bool MatchDirectives(const ParserLine& line);

View File

@ -2,6 +2,7 @@
#include <stack>
#include "Utils/ClassUtils.h"
#include "AbstractDirectiveStreamProxy.h"
#include "Parsing/IPackValueSupplier.h"
#include "Parsing/IParserLineStream.h"
@ -32,5 +33,5 @@ public:
_NODISCARD bool IsOpen() 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;
ParserFilesystemStream::FileInfo::FileInfo(std::string filePath)
: m_file_path(std::move(filePath)),
m_stream(m_file_path),
: m_file_path(std::make_shared<std::string>(std::move(filePath))),
m_stream(*m_file_path),
m_line_number(1)
{
}
ParserFilesystemStream::ParserFilesystemStream(std::string path)
ParserFilesystemStream::ParserFilesystemStream(const std::string& path)
{
const auto absolutePath = absolute(fs::path(path));
m_files.emplace(FileInfo(absolutePath.string()));
@ -74,7 +74,7 @@ bool ParserFilesystemStream::IncludeFile(const std::string& filename)
if (m_files.empty())
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 = absolute(newFilePath);

View File

@ -10,7 +10,7 @@ class ParserFilesystemStream final : public IParserLineStream
class FileInfo
{
public:
std::string m_file_path;
std::shared_ptr<std::string> m_file_path;
std::ifstream m_stream;
int m_line_number;
@ -19,7 +19,7 @@ class ParserFilesystemStream final : public IParserLineStream
std::stack<FileInfo> m_files;
public:
explicit ParserFilesystemStream(std::string path);
explicit ParserFilesystemStream(const std::string& path);
ParserLine NextLine() 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)
: m_owned_stream(std::move(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)
{
}
ParserMultiInputStream::FileInfo::FileInfo(std::istream& stream, std::string filePath)
: m_stream(stream),
m_file_path(std::move(filePath)),
m_file_path(std::make_shared<std::string>(std::move(filePath))),
m_line_number(1)
{
}
@ -79,7 +79,7 @@ bool ParserMultiInputStream::IncludeFile(const std::string& filename)
if (!m_include_callback)
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)
return false;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -27,21 +27,21 @@ namespace test::parsing::impl::including_stream_proxy
{
auto line = proxy.NextLine();
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");
}
{
auto line = proxy.NextLine();
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");
}
{
auto line = proxy.NextLine();
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");
}
@ -70,21 +70,21 @@ namespace test::parsing::impl::including_stream_proxy
{
auto line = proxy.NextLine();
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");
}
{
auto line = proxy.NextLine();
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");
}
{
auto line = proxy.NextLine();
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");
}
@ -113,21 +113,21 @@ namespace test::parsing::impl::including_stream_proxy
{
auto line = proxy.NextLine();
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");
}
{
auto line = proxy.NextLine();
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");
}
{
auto line = proxy.NextLine();
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");
}
@ -158,21 +158,21 @@ namespace test::parsing::impl::including_stream_proxy
{
auto line = proxy.NextLine();
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");
}
{
auto line = proxy.NextLine();
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");
}
{
auto line = proxy.NextLine();
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");
}